diff --git a/src/common/Common.h b/src/common/Common.h index 1a8139e2..5c9f1d57 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -504,6 +504,7 @@ namespace Sapphire::Common enum class UnlockEntry : uint16_t { Return = 1, + InnRoom = 2, Teleport = 4, GearSets = 6, MateriaMelding = 11, diff --git a/src/scripts/ScriptLoader.cpp.in b/src/scripts/ScriptLoader.cpp.in index 18b44e64..05ea7b31 100644 --- a/src/scripts/ScriptLoader.cpp.in +++ b/src/scripts/ScriptLoader.cpp.in @@ -14,6 +14,11 @@ const Sapphire::ScriptAPI::ScriptObject* ptrs[] = }; #ifdef _WIN32 +namespace Sapphire +{ + class InstanceObjectCache; +} + namespace Sapphire::Data { class ExdData; @@ -44,6 +49,11 @@ extern "C" EXPORT void win32initWarpMgr( std::shared_ptr< Sapphire::World::Manag { Sapphire::Common::Service< Sapphire::World::Manager::WarpMgr >::set( warpMgr ); } + +extern "C" EXPORT void win32initIObjectCache( std::shared_ptr< Sapphire::InstanceObjectCache > ioCache ) +{ + Sapphire::Common::Service< Sapphire::InstanceObjectCache >::set( ioCache ); +} #endif extern "C" EXPORT const Sapphire::ScriptAPI::ScriptObject** getScripts() diff --git a/src/scripts/common/aethernet/Aetheryte.cpp b/src/scripts/common/aethernet/Aetheryte.cpp index e4e61520..80e509c2 100644 --- a/src/scripts/common/aethernet/Aetheryte.cpp +++ b/src/scripts/common/aethernet/Aetheryte.cpp @@ -94,7 +94,7 @@ public: { player.registerAetheryte( eventId & 0xFFFF ); - if( player.isActionLearned( Common::UnlockEntry::Teleport ) ) + if( player.hasReward( Common::UnlockEntry::Teleport ) ) { eventMgr().sendEventNotice( player, eventId, 0, 2, 0, 0 ); } diff --git a/src/scripts/common/warptaxi/WarpInnGridania.cpp b/src/scripts/common/warptaxi/WarpInnGridania.cpp new file mode 100644 index 00000000..a5f634ff --- /dev/null +++ b/src/scripts/common/warptaxi/WarpInnGridania.cpp @@ -0,0 +1,61 @@ +#include +#include + +#include +#include + +#include "Territory/InstanceObjectCache.h" +#include "Territory/Territory.h" + +#include +#include +#include + +using namespace Sapphire; + +class WarpInnGridania : public Sapphire::ScriptAPI::EventScript +{ +public: + constexpr static auto InnTerritoryType = 179; + + WarpInnGridania() : + Sapphire::ScriptAPI::EventScript( 131080 ) + { + } + + void onTalk( uint32_t eventId, Entity::Player& player, uint64_t actorId ) override + { + auto& exdData = Common::Service< Sapphire::Data::ExdData >::ref(); + + auto warp = exdData.getRow< Excel::Warp >( eventId ); + if( !warp ) + return; + + auto qualifiedPreResult = [ this ]( Entity::Player& player, const Event::SceneResult& result ) + { + auto warpChoice = [ this ]( Entity::Player& player, const Event::SceneResult& result ) + { + auto warp = this->exdData().getRow< Excel::Warp >( result.eventId ); + if( warp ) + { + auto popRangeInfo = instanceObjectCache().getPopRangeInfo( warp->data().PopRange ); + if( popRangeInfo ) + { + auto pTeri = teriMgr().getZoneByTerritoryTypeId( popRangeInfo->m_territoryTypeId ); + warpMgr().requestMoveTerritory( player, Sapphire::Common::WARP_TYPE_TOWN_TRANSLATE, + pTeri->getGuId(), popRangeInfo->m_pos, popRangeInfo->m_rotation ); + } + } + }; + + eventMgr().playScene( player, result.eventId, 1, HIDE_HOTBAR, { 1 }, warpChoice ); + }; + + if( player.hasReward( Common::UnlockEntry::InnRoom ) ) + eventMgr().playScene( player, eventId, 0, HIDE_HOTBAR, { 1 }, qualifiedPreResult ); + else + eventMgr().playScene( player, eventId, 2, HIDE_HOTBAR, { 1 }, nullptr ); + } +}; + +EXPOSE_SCRIPT( WarpInnGridania ); \ No newline at end of file diff --git a/src/scripts/common/warptaxi/WarpTaxi.cpp b/src/scripts/common/warptaxi/WarpTaxi.cpp index c62ac3ce..abe69479 100644 --- a/src/scripts/common/warptaxi/WarpTaxi.cpp +++ b/src/scripts/common/warptaxi/WarpTaxi.cpp @@ -5,6 +5,7 @@ #include #include "Territory/InstanceObjectCache.h" +#include "Territory/Territory.h" #include #include @@ -16,76 +17,38 @@ class WarpTaxi : public Sapphire::ScriptAPI::EventScript { public: WarpTaxi() : - Sapphire::ScriptAPI::EventScript( 0x0002005a ) + Sapphire::ScriptAPI::EventScript( 0x00020000 ) { } - void inner( Entity::Player& player, const Event::SceneResult& result ) - { -/* if( result.numOfResults == 1 ) // exit - { - eventMgr().eventFinish( player, 1310721, 0 ); - eventMgr().eventFinish( player, getId(), 1 ); - } - else if( result.numOfResults == 2 ) // teleport to ward - { - eventMgr().eventFinish( player, 1310721, 0 ); - eventMgr().eventFinish( player, getId(), 1 ); - - auto& exdData = Common::Service< Data::ExdData >::ref(); - auto& popRange = Common::Service< Sapphire::InstanceObjectCache >::ref(); - - auto warp = exdData.getRow< Excel::Warp >( getId() ); - if( !warp ) - return; - - auto& playerMgr = Common::Service< Sapphire::World::Manager::PlayerMgr >::ref(); - - // EXD TODO: This was TerritoryType from warp before... - auto pPop = popRange.getPopRange( player.getTerritoryTypeId(), warp->data().PopRange ); - - if( !pPop ) - { - std::cout << "not found..."; - } - else - { - std::cout << "found!!"; - } - - playerMgr.movePlayerToLandDestination( player, warp->data().PopRange, result.getResult( 1 ) ); - } - else - { - eventMgr().playScene( player, 1310721, 0, HIDE_HOTBAR, { 1, 341 }, - std::bind( &WarpTaxi::inner, this, std::placeholders::_1, std::placeholders::_2 ) ); - }*/ - } - - void inner2( Entity::Player& player, uint64_t actorId ) - { - /* eventMgr().playScene( player, getId(), 0, HIDE_HOTBAR, { 32529 }, - [this, actorId]( Entity::Player& player, const Event::SceneResult& result ) - { - eventMgr().eventStart( player, actorId, 1310721, Event::EventHandler::Nest, 1, 0 ); - - eventMgr().playScene( player, 1310721, 0, HIDE_HOTBAR, { 1, 341 }, - std::bind( &WarpTaxi::inner, this, std::placeholders::_1, std::placeholders::_2 ) ); - } );*/ - } - void onTalk( uint32_t eventId, Entity::Player& player, uint64_t actorId ) override { -/* auto& exdData = Common::Service< Sapphire::Data::ExdData >::ref(); + auto& exdData = Common::Service< Sapphire::Data::ExdData >::ref(); auto warp = exdData.getRow< Excel::Warp >( eventId ); if( !warp ) return; - // EXD TODO: Not sure Warpcondition is correct here - eventMgr().eventStart( player, actorId, warp->data().WarpCondition, Event::EventHandler::Nest, 0, 0, - std::bind( &WarpTaxi::inner2, this, std::placeholders::_1, std::placeholders::_2 ) ); - eventMgr().playScene( player, warp->data().WarpCondition, 0, HIDE_HOTBAR, { 7 }, nullptr );*/ + auto qualifiedPreResult = [ this ]( Entity::Player& player, const Event::SceneResult& result ) + { + //eventMgr().playScene( player, result.eventId, 1, HIDE_HOTBAR, { 1 }, nullptr ); + if( result.getResult( 0 ) == 1 && result.errorCode != Common::EventSceneError::EVENT_SCENE_ERROR_LUA_ERRRUN ) + { + auto warp = this->exdData().getRow< Excel::Warp >( result.eventId ); + if( warp ) + { + auto popRangeInfo = instanceObjectCache().getPopRangeInfo( warp->data().PopRange ); + if( popRangeInfo ) + { + auto pTeri = teriMgr().getZoneByTerritoryTypeId( popRangeInfo->m_territoryTypeId ); + warpMgr().requestMoveTerritory( player, Sapphire::Common::WARP_TYPE_TOWN_TRANSLATE, + pTeri->getGuId(), popRangeInfo->m_pos, popRangeInfo->m_rotation ); + } + } + } + }; + + eventMgr().playScene( player, eventId, 0, HIDE_HOTBAR, { 1 }, qualifiedPreResult ); } }; diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index 808a34ae..f6d1af23 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -415,7 +415,7 @@ void Player::teleport( uint16_t aetheryteId, uint8_t type ) const auto& data = aetherData->data(); auto& instanceObjectCache = Common::Service< InstanceObjectCache >::ref(); - auto pop = instanceObjectCache.getPopRange( data.TerritoryType, data.PopRange[ 0 ] ); + auto pop = instanceObjectCache.getPopRangeInfo( data.PopRange[ 0 ] ); Common::FFXIVARR_POSITION3 pos{ 0.f, 0.f, 0.f }; @@ -424,10 +424,8 @@ void Player::teleport( uint16_t aetheryteId, uint8_t type ) if( pop ) { PlayerMgr::sendDebug( *this, "Teleport: popRange {0} found!", data.PopRange[ 0 ] ); - const auto& transform = pop->header.transform; - pos = Common::FFXIVARR_POSITION3{ transform.translation.x, transform.translation.y, transform.translation.z }; - auto targetRot = Common::FFXIVARR_POSITION3{ transform.rotation.x, transform.rotation.y, transform.rotation.z }; - rot = Common::Util::eulerToDirection( targetRot ); + pos = pop->m_pos; + rot = pop->m_rotation; } else { @@ -674,7 +672,7 @@ void Player::learnSong( uint8_t songId, uint32_t itemId ) Service< World::Manager::PlayerMgr >::ref().onUnlockOrchestrion( *this, songId, itemId ); } -bool Player::isActionLearned( Common::UnlockEntry unlockId ) const +bool Player::hasReward( Common::UnlockEntry unlockId ) const { uint16_t index; uint8_t value; @@ -1506,7 +1504,7 @@ void Player::sendZonePackets() //setStateFlag( PlayerStateFlag::BetweenAreas ); //setStateFlag( PlayerStateFlag::BetweenAreas1 ); - if( isActionLearned( Common::UnlockEntry::HuntingLog ) ) + if( hasReward( Common::UnlockEntry::HuntingLog ) ) sendHuntingLog(); sendStats(); diff --git a/src/world/Actor/Player.h b/src/world/Actor/Player.h index a69fa174..10dfe28c 100644 --- a/src/world/Actor/Player.h +++ b/src/world/Actor/Player.h @@ -438,7 +438,7 @@ namespace Sapphire::Entity void learnSong( uint8_t songId, uint32_t itemId ); /*! check if an action is already unlocked in the bitmask. */ - bool isActionLearned( Common::UnlockEntry unlockId ) const; + bool hasReward( Common::UnlockEntry unlockId ) const; /*! return a const pointer to the unlock bitmask array */ const UnlockList& getUnlockBitmask() const; diff --git a/src/world/Manager/EventMgr.cpp b/src/world/Manager/EventMgr.cpp index 9750b263..412d32da 100644 --- a/src/world/Manager/EventMgr.cpp +++ b/src/world/Manager/EventMgr.cpp @@ -109,8 +109,18 @@ std::string EventMgr::getEventName( uint32_t eventId ) { auto warpInfo = exdData.getRow< Excel::Warp >( eventId ); if( warpInfo ) - return "WarpTaxi"; - return unknown + "ChocoboWarp"; //who know + { + auto warpLogic = exdData.getRow< Excel::WarpLogic >( warpInfo->data().Logic ); + if( warpLogic ) + { + if( warpLogic->getString( warpLogic->data().Script ).empty() ) + return "WarpTaxi"; + else + return warpLogic->getString( warpLogic->data().Script ); + } + } + + return unknown + "Warp"; //who know } case Event::EventHandler::EventHandlerType::Shop: diff --git a/src/world/Manager/PlayerMgr.cpp b/src/world/Manager/PlayerMgr.cpp index 304d799f..67b59495 100644 --- a/src/world/Manager/PlayerMgr.cpp +++ b/src/world/Manager/PlayerMgr.cpp @@ -204,7 +204,7 @@ void PlayerMgr::onMobKill( Entity::Player& player, uint16_t nameId, uint32_t lay auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref(); scriptMgr.onBNpcKill( player, nameId, layoutId ); - if( player.isActionLearned( Common::UnlockEntry::HuntingLog ) ) + if( player.hasReward( Common::UnlockEntry::HuntingLog ) ) { player.updateHuntingLog( nameId ); } diff --git a/src/world/Network/Handlers/PacketHandlers.cpp b/src/world/Network/Handlers/PacketHandlers.cpp index db84ce36..86a258f3 100644 --- a/src/world/Network/Handlers/PacketHandlers.cpp +++ b/src/world/Network/Handlers/PacketHandlers.cpp @@ -314,30 +314,13 @@ void Sapphire::Network::GameConnection::zoneJumpHandler( const Packets::FFXIVARR if( pExitRange ) { - auto pPopRange = instanceObjectCache.getPopRange( pExitRange->data.destTerritoryType, - pExitRange->data.destInstanceObjectId ); + auto pPopRange = instanceObjectCache.getPopRangeInfo( pExitRange->data.destInstanceObjectId ); if( pPopRange ) { targetZone = pExitRange->data.destTerritoryType; - - - targetPos = Common::FFXIVARR_POSITION3 { pPopRange->header.transform.translation.x, - pPopRange->header.transform.translation.y, - pPopRange->header.transform.translation.z }; - - targetRot = Common::FFXIVARR_POSITION3 { pPopRange->header.transform.rotation.x, - pPopRange->header.transform.rotation.y, - pPopRange->header.transform.rotation.z }; - - rotation = Util::eulerToDirection( targetRot ); - - - PlayerMgr::sendDebug( player, "ZoneLine #{0} found. Rotation: {1} {2} {3} - {4}", exitBoxId, - pPopRange->header.transform.rotation.x, - pPopRange->header.transform.rotation.y, - pPopRange->header.transform.rotation.z, - rotation ); - + targetPos = pPopRange->m_pos; + rotation = pPopRange->m_rotation; + PlayerMgr::sendDebug( player, "ZoneLine #{0} found. Rotation: {1}, Zone: #{2} ", exitBoxId, rotation, targetZone ); } } diff --git a/src/world/Script/NativeScriptApi.h b/src/world/Script/NativeScriptApi.h index 4d5153de..150f5465 100644 --- a/src/world/Script/NativeScriptApi.h +++ b/src/world/Script/NativeScriptApi.h @@ -9,6 +9,8 @@ #include "Manager/PlayerMgr.h" #include "Manager/TerritoryMgr.h" #include "Manager/WarpMgr.h" +#include "Exd/ExdData.h" +#include "Territory/InstanceObjectCache.h" #include "Service.h" #ifdef _MSC_VER @@ -173,6 +175,10 @@ namespace Sapphire::ScriptAPI virtual void onEObjHit( Sapphire::Entity::Player& player, uint64_t actorId, uint32_t actionId ); + Data::ExdData& exdData() + { + return Common::Service< Data::ExdData >::ref(); + } World::Manager::EventMgr& eventMgr() { @@ -188,6 +194,21 @@ namespace Sapphire::ScriptAPI { return Common::Service< World::Manager::PlayerMgr >::ref(); } + + World::Manager::WarpMgr& warpMgr() + { + return Common::Service< World::Manager::WarpMgr >::ref(); + } + + Sapphire::InstanceObjectCache& instanceObjectCache() + { + return Common::Service< Sapphire::InstanceObjectCache >::ref(); + } + + World::Manager::TerritoryMgr& teriMgr() + { + return Common::Service< World::Manager::TerritoryMgr >::ref(); + } }; class QuestScript : public ScriptObject diff --git a/src/world/Script/ScriptLoader.cpp b/src/world/Script/ScriptLoader.cpp index 9acec86a..7247c834 100644 --- a/src/world/Script/ScriptLoader.cpp +++ b/src/world/Script/ScriptLoader.cpp @@ -7,6 +7,10 @@ #ifdef _WIN32 #include +namespace Sapphire +{ + class InstanceObjectCache; +} namespace Sapphire::Data { class ExdData; @@ -118,10 +122,24 @@ Sapphire::ScriptAPI::ScriptObject** Sapphire::Scripting::ScriptLoader::getScript using win32initFuncTeri = void(*)( std::shared_ptr< Sapphire::World::Manager::TerritoryMgr > ); using win32initFuncLinkshell = void(*)( std::shared_ptr< Sapphire::World::Manager::LinkshellMgr > ); using win32initFuncWarpMgr = void(*)( std::shared_ptr< Sapphire::World::Manager::WarpMgr > ); + using win32initIObjectCache = void(*)( std::shared_ptr< Sapphire::InstanceObjectCache > ); + auto win32init = reinterpret_cast< win32initFunc >( GetProcAddress( handle, "win32initExd" ) ); auto win32initTeri = reinterpret_cast< win32initFuncTeri >( GetProcAddress( handle, "win32initTeri" ) ); auto win32initLinkshell = reinterpret_cast< win32initFuncLinkshell >( GetProcAddress( handle, "win32initLinkshell" ) ); auto win32initWarp = reinterpret_cast< win32initFuncWarpMgr >( GetProcAddress( handle, "win32initWarpMgr" ) ); + auto win32initIObject = reinterpret_cast< win32initIObjectCache >( GetProcAddress( handle, "win32initIObjectCache" ) ); + + if( win32initIObject ) + { + auto ioCache = Common::Service< Sapphire::InstanceObjectCache >::get(); + auto ptr = ioCache.lock(); + win32initIObject( ptr ); + } + else + { + Logger::warn( "did not find a win32initIObjectCache export on a windows script target - the server will likely crash!" ); + } if( win32init ) { diff --git a/src/world/Script/ScriptMgr.cpp b/src/world/Script/ScriptMgr.cpp index 49a741fb..69c85548 100644 --- a/src/world/Script/ScriptMgr.cpp +++ b/src/world/Script/ScriptMgr.cpp @@ -764,4 +764,5 @@ bool Sapphire::Scripting::ScriptMgr::onSay( Sapphire::Entity::Player& player, ui } return true; } + return false; } diff --git a/src/world/Territory/InstanceObjectCache.cpp b/src/world/Territory/InstanceObjectCache.cpp index 14821166..a61f9da4 100644 --- a/src/world/Territory/InstanceObjectCache.cpp +++ b/src/world/Territory/InstanceObjectCache.cpp @@ -13,6 +13,7 @@ #include #include +#include Sapphire::InstanceObjectCache::InstanceObjectCache() { @@ -146,9 +147,9 @@ Sapphire::InstanceObjectCache::ExitRangePtr } Sapphire::InstanceObjectCache::PopRangePtr - Sapphire::InstanceObjectCache::getPopRange( uint16_t zoneId, uint32_t popRangeId ) + Sapphire::InstanceObjectCache::getPopRange( uint32_t popRangeId ) { - return m_popRangeCache.get( zoneId, popRangeId ); + return m_popRangeCache.get( 0, popRangeId ); } Sapphire::InstanceObjectCache::EObjPtr @@ -167,3 +168,29 @@ Sapphire::InstanceObjectCache::EventRangePtr Sapphire::InstanceObjectCache::getE { return m_eventRangeCache.get( 0, eventRangeId ); } + +std::shared_ptr< Sapphire::InstanceObjectCache::PopRangeInfo > Sapphire::InstanceObjectCache::getPopRangeInfo( uint32_t popRangeId ) +{ + auto popRange = getPopRange( popRangeId ); + if( !popRange ) + return nullptr; + + auto popInfo = std::make_shared< Sapphire::InstanceObjectCache::PopRangeInfo >(); + + popInfo->m_pos = Common::FFXIVARR_POSITION3 { popRange->header.transform.translation.x, + popRange->header.transform.translation.y, + popRange->header.transform.translation.z }; + + auto targetRot = Common::FFXIVARR_POSITION3 { popRange->header.transform.rotation.x, + popRange->header.transform.rotation.y, + popRange->header.transform.rotation.z }; + + popInfo->m_rotation = Common::Util::eulerToDirection( targetRot ); + + auto& exdData = Common::Service< Sapphire::Data::ExdData >::ref(); + auto levelData = exdData.getRow< Excel::Level >( popRangeId ); + if( levelData ) + popInfo->m_territoryTypeId = levelData->data().TerritoryType; + + return popInfo; +} diff --git a/src/world/Territory/InstanceObjectCache.h b/src/world/Territory/InstanceObjectCache.h index 2c54bd6c..a8b24dc6 100644 --- a/src/world/Territory/InstanceObjectCache.h +++ b/src/world/Territory/InstanceObjectCache.h @@ -3,6 +3,7 @@ #include #include +#include struct LGB_MAP_RANGE_ENTRY; struct LGB_EXIT_RANGE_ENTRY; @@ -29,11 +30,10 @@ namespace Sapphire public: ObjectPtr get( uint16_t zoneId, uint32_t id ) { - auto it = m_objectCache.find( zoneId ); - if( it != m_objectCache.end() ) + for( auto& entry : m_objectCache ) { - auto rangeIt = it->second.find( id ); - if( rangeIt != it->second.end() ) + auto rangeIt = entry.second.find( id ); + if( rangeIt != entry.second.end() ) { return rangeIt->second; } @@ -76,12 +76,23 @@ namespace Sapphire using ENpcPtr = std::shared_ptr< LGB_ENPC_ENTRY >; using EventRangePtr = std::shared_ptr< LGB_EVENT_RANGE_ENTRY >; + struct PopRangeInfo + { + Common::FFXIVARR_POSITION3 m_pos; + float m_rotation; + uint16_t m_territoryTypeId; + }; + InstanceObjectCache(); ~InstanceObjectCache() = default; MapRangePtr getMapRange( uint16_t zoneId, uint32_t mapRangeId ); ExitRangePtr getExitRange( uint16_t zoneId, uint32_t exitRangeId ); - PopRangePtr getPopRange( uint16_t zoneId, uint32_t popRangeId ); + PopRangePtr getPopRange( uint32_t popRangeId ); + + std::shared_ptr< PopRangeInfo > getPopRangeInfo( uint32_t popRangeId ); + + EObjPtr getEObj( uint32_t eObjId ); ENpcPtr getENpc( uint32_t eNpcId ); EventRangePtr getEventRange( uint32_t eventRangeId ); @@ -93,6 +104,7 @@ namespace Sapphire ObjectCache< LGB_EOBJ_ENTRY > m_eobjCache; ObjectCache< LGB_ENPC_ENTRY > m_enpcCache; ObjectCache< LGB_EVENT_RANGE_ENTRY > m_eventRangeCache; + std::shared_ptr< Framework > m_pFramework; };