diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index 5258a3d2..3899a0a5 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -1318,8 +1318,8 @@ struct FFXIVIpcObjectSpawn : FFXIVIpcBasePacket { uint8_t count; uint8_t objKind; - uint8_t unknown2; uint8_t state; + uint8_t unknown2; uint32_t objId; uint32_t actorId; uint32_t levelId; diff --git a/src/servers/sapphire_zone/Actor/Actor.cpp b/src/servers/sapphire_zone/Actor/Actor.cpp index acefabbc..f1db8533 100644 --- a/src/servers/sapphire_zone/Actor/Actor.cpp +++ b/src/servers/sapphire_zone/Actor/Actor.cpp @@ -29,6 +29,11 @@ uint32_t Core::Entity::Actor::getId() const return m_id; } +void Core::Entity::Actor::setId( uint32_t id ) +{ + m_id = id; +} + Core::Entity::Actor::ObjKind Core::Entity::Actor::getObjKind() const { return m_objKind; @@ -152,7 +157,7 @@ void Core::Entity::Actor::addInRangeActor( ActorPtr pActor ) { auto pPlayer = pActor->getAsPlayer(); - pPlayer->spawn( getAsPlayer() ); + spawn( pPlayer ); // if actor is a player, add it to the in range player set m_inRangePlayers.insert( pPlayer ); diff --git a/src/servers/sapphire_zone/Actor/Actor.h b/src/servers/sapphire_zone/Actor/Actor.h index 647af43e..94502c0d 100644 --- a/src/servers/sapphire_zone/Actor/Actor.h +++ b/src/servers/sapphire_zone/Actor/Actor.h @@ -68,6 +68,7 @@ namespace Entity { virtual void despawn( PlayerPtr pTarget ) {} uint32_t getId() const; + void setId( uint32_t id ); ObjKind getObjKind() const; diff --git a/src/servers/sapphire_zone/Actor/EventObject.cpp b/src/servers/sapphire_zone/Actor/EventObject.cpp index 6f361889..1162e9c1 100644 --- a/src/servers/sapphire_zone/Actor/EventObject.cpp +++ b/src/servers/sapphire_zone/Actor/EventObject.cpp @@ -1,18 +1,33 @@ #include "EventObject.h" -#include "Zone/InstanceContent.h" -Core::Entity::EventObject::EventObject( uint32_t objectId, uint32_t mapLinkId ) : +#include "Zone/InstanceContent.h" +#include "Actor/Player.h" + +#include +#include +#include +#include +#include +#include + +using namespace Core::Common; +using namespace Core::Network::Packets; +using namespace Core::Network::Packets::Server; + +extern Core::Logger g_log; + + +Core::Entity::EventObject::EventObject( uint32_t objectId, uint32_t mapLinkId, + uint8_t initialState, Common::FFXIVARR_POSITION3 pos ) : Core::Entity::Actor( ObjKind::EventObj ), m_mapLinkId( mapLinkId ), - m_state( 0 ) + m_state( initialState ), + m_objectId( objectId ) { m_id = objectId; -} - -Core::Entity::EventObject::EventObject( uint32_t objectId, uint32_t mapLinkId, Common::FFXIVARR_POSITION3 pos ) : - EventObject( objectId, mapLinkId ) -{ - + m_pos.x = pos.x; + m_pos.y = pos.y; + m_pos.z = pos.z; } uint32_t Core::Entity::EventObject::getMapLinkId() const @@ -20,6 +35,11 @@ uint32_t Core::Entity::EventObject::getMapLinkId() const return m_mapLinkId; } +uint32_t Core::Entity::EventObject::getObjectId() const +{ + return m_objectId; +} + void Core::Entity::EventObject::setMapLinkId( uint32_t mapLinkId ) { m_mapLinkId = mapLinkId; @@ -45,4 +65,23 @@ void Core::Entity::EventObject::setParentInstance( Core::InstanceContentPtr inst Core::InstanceContentPtr Core::Entity::EventObject::getParentInstance() const { return m_parentInstance; +} + +void Core::Entity::EventObject::spawn( Core::Entity::PlayerPtr pTarget ) +{ + g_log.debug( "spawn eobj: " + std::to_string( getId() ) ); + ZoneChannelPacket< FFXIVIpcObjectSpawn > eobjStatePacket( getId(), pTarget->getId() ); + eobjStatePacket.data().count = pTarget->getNextObjCount(); + eobjStatePacket.data().objKind = getObjKind(); + eobjStatePacket.data().state = getState(); + eobjStatePacket.data().objId = getId(); + eobjStatePacket.data().hierachyId = getMapLinkId(); + eobjStatePacket.data().position = getPos(); + pTarget->queuePacket( eobjStatePacket ); +} + + +void Core::Entity::EventObject::despawn( Core::Entity::PlayerPtr pTarget ) +{ + g_log.debug( "despawn eobj: " + std::to_string( getId() ) ); } \ No newline at end of file diff --git a/src/servers/sapphire_zone/Actor/EventObject.h b/src/servers/sapphire_zone/Actor/EventObject.h index 49df8e18..1c48b72d 100644 --- a/src/servers/sapphire_zone/Actor/EventObject.h +++ b/src/servers/sapphire_zone/Actor/EventObject.h @@ -10,8 +10,7 @@ namespace Entity class EventObject : public Actor { public: - EventObject( uint32_t objectId, uint32_t mapLinkId ); - EventObject( uint32_t objectId, uint32_t mapLinkId, Common::FFXIVARR_POSITION3 pos ); + EventObject( uint32_t objectId, uint32_t mapLinkId, uint8_t initialState, Common::FFXIVARR_POSITION3 pos ); uint32_t getMapLinkId() const; void setMapLinkId( uint32_t mapLinkId ); @@ -19,11 +18,17 @@ namespace Entity uint8_t getState() const; void setState( uint8_t state ); + uint32_t getObjectId() const; + InstanceContentPtr getParentInstance() const; void setParentInstance( InstanceContentPtr instance ); + void spawn( PlayerPtr pTarget ) override; + void despawn( PlayerPtr pTarget ) override; + protected: uint32_t m_mapLinkId; + uint32_t m_objectId; uint8_t m_state; InstanceContentPtr m_parentInstance; }; diff --git a/src/servers/sapphire_zone/Actor/Player.cpp b/src/servers/sapphire_zone/Actor/Player.cpp index 44d990e7..5b44a401 100644 --- a/src/servers/sapphire_zone/Actor/Player.cpp +++ b/src/servers/sapphire_zone/Actor/Player.cpp @@ -72,7 +72,8 @@ Core::Entity::Player::Player() : m_bAutoattack( false ), m_markedForRemoval( false ), m_mount( 0 ), - m_directorInitialized( false ) + m_directorInitialized( false ), + m_objCount( 0 ) { m_id = 0; m_currentStance = Stance::Passive; @@ -1491,6 +1492,8 @@ uint32_t Core::Entity::Player::getTerritoryId() const void Core::Entity::Player::sendZonePackets() { + getCurrentZone()->onBeforeEnterTerritory( *this ); + ZoneChannelPacket< FFXIVIpcInit > initPacket( getId() ); initPacket.data().charId = getId(); queuePacket( initPacket ); @@ -1651,3 +1654,8 @@ void Player::teleportQuery( uint16_t aetheryteId ) } } } + +uint8_t Player::getNextObjCount() +{ + return m_objCount++; +} \ No newline at end of file diff --git a/src/servers/sapphire_zone/Actor/Player.h b/src/servers/sapphire_zone/Actor/Player.h index e1f57e1d..a5681055 100644 --- a/src/servers/sapphire_zone/Actor/Player.h +++ b/src/servers/sapphire_zone/Actor/Player.h @@ -559,6 +559,8 @@ public: void setMarkedForRemoval(); bool isMarkedForRemoval() const; + uint8_t getNextObjCount(); + private: uint32_t m_lastWrite; uint32_t m_lastPing; @@ -669,6 +671,9 @@ private: uint32_t m_cfPenaltyUntil; // unix time uint8_t m_mount; + + // counter used to index objects spawned for the player + uint8_t m_objCount; }; } diff --git a/src/servers/sapphire_zone/Script/NativeScriptApi.h b/src/servers/sapphire_zone/Script/NativeScriptApi.h index 1d5e5b22..045d734f 100644 --- a/src/servers/sapphire_zone/Script/NativeScriptApi.h +++ b/src/servers/sapphire_zone/Script/NativeScriptApi.h @@ -120,8 +120,8 @@ public: ScriptObject( instanceContentId, typeid( InstanceContentScript ).hash_code() ) { } - virtual void onInit( InstanceContent& instance ) { } - virtual void onUpdate( InstanceContent& instance, uint32_t currTime ) { } + virtual void onInit( InstanceContentPtr instance ) { } + virtual void onUpdate( InstanceContentPtr instance, uint32_t currTime ) { } }; #endif \ No newline at end of file diff --git a/src/servers/sapphire_zone/Script/ScriptManager.cpp b/src/servers/sapphire_zone/Script/ScriptManager.cpp index 51e50e77..4e96a2a8 100644 --- a/src/servers/sapphire_zone/Script/ScriptManager.cpp +++ b/src/servers/sapphire_zone/Script/ScriptManager.cpp @@ -335,9 +335,9 @@ bool Core::Scripting::ScriptManager::onZoneInit( ZonePtr pZone ) return false; } -bool Core::Scripting::ScriptManager::onInstanceInit( InstanceContent& instance ) +bool Core::Scripting::ScriptManager::onInstanceInit( InstanceContentPtr instance ) { - auto script = m_nativeScriptManager->getScript< InstanceContentScript >( instance.getInstanceContentId() ); + auto script = m_nativeScriptManager->getScript< InstanceContentScript >( instance->getInstanceContentId() ); if( script ) { script->onInit( instance ); @@ -347,9 +347,9 @@ bool Core::Scripting::ScriptManager::onInstanceInit( InstanceContent& instance ) return false; } -bool Core::Scripting::ScriptManager::onInstanceUpdate( InstanceContent& instance, uint32_t currTime ) +bool Core::Scripting::ScriptManager::onInstanceUpdate( InstanceContentPtr instance, uint32_t currTime ) { - auto script = m_nativeScriptManager->getScript< InstanceContentScript >( instance.getInstanceContentId() ); + auto script = m_nativeScriptManager->getScript< InstanceContentScript >( instance->getInstanceContentId() ); if( script ) { script->onUpdate( instance, currTime ); diff --git a/src/servers/sapphire_zone/Script/ScriptManager.h b/src/servers/sapphire_zone/Script/ScriptManager.h index c06fc626..39b702cb 100644 --- a/src/servers/sapphire_zone/Script/ScriptManager.h +++ b/src/servers/sapphire_zone/Script/ScriptManager.h @@ -57,8 +57,8 @@ namespace Core bool onEventHandlerReturn( Entity::Player& player, uint32_t eventId, uint16_t subEvent, uint16_t param1, uint16_t param2, uint16_t param3 ); bool onEventHandlerTradeReturn( Entity::Player& player, uint32_t eventId, uint16_t subEvent, uint16_t param, uint32_t catalogId ); - bool onInstanceInit( InstanceContent& instance ); - bool onInstanceUpdate( InstanceContent& instance, uint32_t currTime ); + bool onInstanceInit( InstanceContentPtr instance ); + bool onInstanceUpdate( InstanceContentPtr instance, uint32_t currTime ); void loadDir( const std::string& dirname, std::set &files, const std::string& ext ); diff --git a/src/servers/sapphire_zone/Script/Scripts/instances/trials/TheNavel.cpp b/src/servers/sapphire_zone/Script/Scripts/instances/trials/TheNavel.cpp index bc176fb4..1a04204d 100644 --- a/src/servers/sapphire_zone/Script/Scripts/instances/trials/TheNavel.cpp +++ b/src/servers/sapphire_zone/Script/Scripts/instances/trials/TheNavel.cpp @@ -7,16 +7,16 @@ public: TheNavel() : InstanceContentScript( 20002 ) { } - void onInit( InstanceContent& instance ) override + void onInit( InstanceContentPtr instance ) override { - auto exit = new Entity::EventObject( EXIT_OBJECT, 0, { 0, 0, -10 } ); - instance.registerEObj(Entity::EventObjectPtr(exit)); + auto exit = Entity::EventObjectPtr( new Entity::EventObject( EXIT_OBJECT, 0, 4, { 0, 0, -10 } ) ); + instance->registerEObj( exit ); - auto start = new Entity::EventObject( START_CIRCLE, 4236868, { 0, 0, 24 } ); - instance.registerEObj(Entity::EventObjectPtr(start)); + auto start = Entity::EventObjectPtr( new Entity::EventObject( START_CIRCLE, 4236868, 5, { 0, 0, 24 } ) ); + instance->registerEObj( start ); } - void onUpdate( InstanceContent& instance, uint32_t currTime ) override + void onUpdate( InstanceContentPtr instance, uint32_t currTime ) override { } diff --git a/src/servers/sapphire_zone/Zone/InstanceContent.cpp b/src/servers/sapphire_zone/Zone/InstanceContent.cpp index c4fc6514..b7572a9a 100644 --- a/src/servers/sapphire_zone/Zone/InstanceContent.cpp +++ b/src/servers/sapphire_zone/Zone/InstanceContent.cpp @@ -29,11 +29,20 @@ Core::InstanceContent::InstanceContent( boost::shared_ptr< Core::Data::InstanceC Director( Event::Director::InstanceContent, instanceContentId ), m_instanceContentInfo( pInstanceContent ), m_instanceContentId( instanceContentId ), - m_state( Created ) + m_state( Created ), + m_pEntranceEObj( nullptr ) { - g_scriptMgr.onInstanceInit( *this ); + } +bool Core::InstanceContent::init() +{ + g_scriptMgr.onInstanceInit( getAsInstanceContent() ); + + return true; +} + + Core::InstanceContent::~InstanceContent() { @@ -121,7 +130,7 @@ void Core::InstanceContent::onUpdate( uint32_t currTime ) break; } - g_scriptMgr.onInstanceUpdate( *this, currTime ); + g_scriptMgr.onInstanceUpdate( getAsInstanceContent(), currTime ); } void Core::InstanceContent::onFinishLoading( Entity::Player& player ) @@ -210,4 +219,20 @@ void Core::InstanceContent::setVar( uint8_t index, uint8_t value ) { sendDirectorVars( *playerIt.second ); } -} \ No newline at end of file +} + +void Core::InstanceContent::onRegisterEObj( Entity::EventObjectPtr object ) +{ + if( object->getObjectId() == 2000182 ) // start + m_pEntranceEObj = object; +} + +void Core::InstanceContent::onBeforeEnterTerritory( Core::Entity::Player &player ) +{ + if( m_pEntranceEObj != nullptr ) + player.setPos( m_pEntranceEObj->getPos() ); + else + player.setPos( { 0.f, 0.f, 0.f } ); +} + + diff --git a/src/servers/sapphire_zone/Zone/InstanceContent.h b/src/servers/sapphire_zone/Zone/InstanceContent.h index 318b82c7..1b150800 100644 --- a/src/servers/sapphire_zone/Zone/InstanceContent.h +++ b/src/servers/sapphire_zone/Zone/InstanceContent.h @@ -9,7 +9,7 @@ namespace Core { -class InstanceContent : public Zone, Event::Director +class InstanceContent : public Event::Director, public Zone { public: enum InstanceContentState @@ -27,12 +27,16 @@ public: uint32_t instanceContentId ); virtual ~InstanceContent(); + bool init() override; + void onBeforeEnterTerritory( Entity::Player& player ) override; void onEnterTerritory( Entity::Player& player ) override; void onLeaveTerritory( Entity::Player& player ) override; void onFinishLoading( Entity::Player& player ) override; void onInitDirector( Entity::Player& player ) override; void onUpdate( uint32_t currTime ) override; + void onRegisterEObj( Entity::EventObjectPtr object ) override; + void setVar( uint8_t index, uint8_t value ); Core::Data::ExdDataGenerated::InstanceContentPtr getInstanceContentInfo() const; @@ -46,6 +50,8 @@ private: InstanceContentState m_state; int64_t m_instanceExpireTime; + + Entity::EventObjectPtr m_pEntranceEObj; }; } diff --git a/src/servers/sapphire_zone/Zone/TerritoryMgr.cpp b/src/servers/sapphire_zone/Zone/TerritoryMgr.cpp index 879d47ae..18ae16c2 100644 --- a/src/servers/sapphire_zone/Zone/TerritoryMgr.cpp +++ b/src/servers/sapphire_zone/Zone/TerritoryMgr.cpp @@ -181,7 +181,7 @@ Core::ZonePtr Core::TerritoryMgr::createInstanceContent( uint32_t instanceConten m_instanceContentToInstanceMap[instanceContentId][pZone->getGuId()] = pZone; m_instanceIdToZonePtrMap[pZone->getGuId()] = pZone; - m_instanceZoneSet.insert( { pZone } ); + m_instanceZoneSet.insert( pZone ); return pZone; } @@ -313,6 +313,8 @@ bool Core::TerritoryMgr::movePlayer( ZonePtr pZone, Core::Entity::PlayerPtr pPla return false; } + pPlayer->initSpawnIdQueue(); + pPlayer->setTerritoryId( pZone->getTerritoryId() ); // mark character as zoning in progress diff --git a/src/servers/sapphire_zone/Zone/Zone.cpp b/src/servers/sapphire_zone/Zone/Zone.cpp index 7125b32d..ff016078 100644 --- a/src/servers/sapphire_zone/Zone/Zone.cpp +++ b/src/servers/sapphire_zone/Zone/Zone.cpp @@ -13,6 +13,7 @@ #include #include "Zone.h" +#include "InstanceContent.h" #include "TerritoryMgr.h" #include "Session.h" @@ -48,7 +49,8 @@ Core::Zone::Zone() : m_currentWeather( Weather::FairSkies ), m_weatherOverride( Weather::None ), m_lastMobUpdate( 0 ), - m_currentFestivalId( 0 ) + m_currentFestivalId( 0 ), + m_nextEObjId( 0x400D0000 ) { } @@ -658,10 +660,13 @@ void Core::Zone::registerEObj( Entity::EventObjectPtr object ) if( !object ) return; - //object->setParentInstance( InstanceContentPtr( this ) ); + object->setId( getNextEObjId() ); + pushActor( object ); m_eventObjects[object->getId()] = object; + onRegisterEObj( object ); + g_log.debug( "Registered instance eobj: " + std::to_string( object->getId() ) ); } @@ -701,3 +706,13 @@ void Core::Zone::updateEObj( Entity::EventObjectPtr object ) playerIt.second->queuePacket( eobjStatePacket ); } } + +Core::InstanceContentPtr Core::Zone::getAsInstanceContent() +{ + return boost::dynamic_pointer_cast< InstanceContent, Zone >( shared_from_this() ); +} + +uint32_t Core::Zone::getNextEObjId() +{ + return ++m_nextEObjId; +} diff --git a/src/servers/sapphire_zone/Zone/Zone.h b/src/servers/sapphire_zone/Zone/Zone.h index 8802ff2a..c90290f6 100644 --- a/src/servers/sapphire_zone/Zone/Zone.h +++ b/src/servers/sapphire_zone/Zone/Zone.h @@ -48,14 +48,14 @@ protected: std::map< uint8_t, int32_t> m_weatherRateMap; + uint32_t m_nextEObjId; + public: Zone(); Zone( uint16_t territoryId, uint32_t guId, const std::string& internalName, const std::string& placeName ); virtual ~Zone(); - bool init(); - /*! overrides the zone's weather, set to 0 to unlock */ void setWeatherOverride( Common::Weather weather ); @@ -64,13 +64,17 @@ public: uint16_t getCurrentFestival() const; void setCurrentFestival( uint16_t festivalId ); + virtual bool init(); + virtual void loadCellCache(); virtual uint32_t getTerritoryId() const; + virtual void onBeforeEnterTerritory( Entity::Player& player ) {}; virtual void onEnterTerritory( Entity::Player& player ); virtual void onFinishLoading( Entity::Player& player ); virtual void onInitDirector( Entity::Player& player ); virtual void onLeaveTerritory( Entity::Player& player ); virtual void onUpdate( uint32_t currTime ); + virtual void onRegisterEObj( Entity::EventObjectPtr object ) {}; Common::Weather getNextWeather(); @@ -90,6 +94,8 @@ public: uint32_t getGuId() const; + uint32_t getNextEObjId(); + const std::string& getName() const; const std::string& getInternalName() const;