From e8ab570502fe96e48978ff32d02e5d5e8ed96b1a Mon Sep 17 00:00:00 2001 From: Mordred Date: Wed, 14 Feb 2018 20:44:35 +0100 Subject: [PATCH 01/69] refactoring of session update loop in zone --- src/servers/sapphire_zone/Zone/Zone.cpp | 28 ++++++++++++++----------- src/servers/sapphire_zone/Zone/Zone.h | 2 ++ 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/servers/sapphire_zone/Zone/Zone.cpp b/src/servers/sapphire_zone/Zone/Zone.cpp index 4f24f064..eee90859 100644 --- a/src/servers/sapphire_zone/Zone/Zone.cpp +++ b/src/servers/sapphire_zone/Zone/Zone.cpp @@ -481,8 +481,18 @@ bool Core::Zone::update( uint32_t currTime ) { int64_t tickCount = Util::getTimeMs(); + //TODO: this should be moved to a updateWeather call and pulled out of updateSessions bool changedWeather = checkWeather(); + updateSessions( changedWeather ); + updateBnpcs( tickCount ); + onUpdate( currTime ); + + return true; +} + +void Core::Zone::updateSessions( bool changedWeather ) +{ auto it = m_sessionSet.begin(); // update sessions in this zone @@ -493,24 +503,24 @@ bool Core::Zone::update( uint32_t currTime ) if( !pSession ) { - it = m_sessionSet.erase( it ); + it = m_sessionSet.erase(it ); continue; } // this session is not linked to this area anymore, remove it from zone session list - if( ( !pSession->getPlayer()->getCurrentZone() ) - || ( pSession->getPlayer()->getCurrentZone() != shared_from_this() ) ) + if( ( !pSession->getPlayer()->getCurrentZone() ) || + ( pSession->getPlayer()->getCurrentZone() != shared_from_this() ) ) { if( pSession->getPlayer()->getCell() ) - removeActor( pSession->getPlayer() ); + removeActor(pSession->getPlayer() ); - it = m_sessionSet.erase( it ); + it = m_sessionSet.erase(it ); continue; } if( changedWeather ) { - Network::Packets::ZoneChannelPacket< Network::Packets::Server::FFXIVIpcWeatherChange > + Core::Network::Packets::ZoneChannelPacket< Core::Network::Packets::Server::FFXIVIpcWeatherChange > weatherChangePacket( pSession->getPlayer()->getId() ); weatherChangePacket.data().weatherId = m_currentWeather; weatherChangePacket.data().delay = 5.0f; @@ -521,12 +531,6 @@ bool Core::Zone::update( uint32_t currTime ) pSession->update(); ++it; } - - updateBnpcs( tickCount ); - - onUpdate( currTime ); - - return true; } bool Core::Zone::isCellActive( uint32_t x, uint32_t y ) diff --git a/src/servers/sapphire_zone/Zone/Zone.h b/src/servers/sapphire_zone/Zone/Zone.h index dedf6e3a..a9b09ecc 100644 --- a/src/servers/sapphire_zone/Zone/Zone.h +++ b/src/servers/sapphire_zone/Zone/Zone.h @@ -111,6 +111,8 @@ public: bool update( uint32_t currTime ); + void updateSessions( bool changedWeather ); + void registerInstanceObj( Entity::InstanceObjectPtr object ); Entity::InstanceObjectPtr getInstanceObject( uint32_t objId ); void updateInstanceObj( Entity::InstanceObjectPtr object ); From ddb424758872ad8c226f71aa38f2f230c8349879 Mon Sep 17 00:00:00 2001 From: Mordred Date: Wed, 14 Feb 2018 21:11:23 +0100 Subject: [PATCH 02/69] More zone refactoring, general style fixes --- src/common/CommonGen.h | 1 + .../Network/Handlers/GMCommandHandlers.cpp | 48 +++++++++---------- src/servers/sapphire_zone/Zone/Zone.cpp | 47 +++++++++++------- src/servers/sapphire_zone/Zone/Zone.h | 11 +++-- 4 files changed, 61 insertions(+), 46 deletions(-) diff --git a/src/common/CommonGen.h b/src/common/CommonGen.h index e0005ada..5e9bf149 100644 --- a/src/common/CommonGen.h +++ b/src/common/CommonGen.h @@ -463,6 +463,7 @@ namespace Common { //Weather.exd enum class Weather : uint8_t { + None = 0, ClearSkies = 1, FairSkies = 2, Clouds = 3, diff --git a/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp b/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp index 9ba5c2b9..865ffdc1 100644 --- a/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp @@ -139,7 +139,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac player.sendNotice( "Race for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) ); targetPlayer->spawn( targetPlayer ); auto inRange = targetPlayer->getInRangeActors(); - for ( auto actor : inRange ) + for( auto actor : inRange ) { targetPlayer->despawn( actor->getAsPlayer() ); targetPlayer->spawn( actor->getAsPlayer() ); @@ -152,7 +152,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac player.sendNotice( "Tribe for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) ); targetPlayer->spawn( targetPlayer ); auto inRange = targetPlayer->getInRangeActors(); - for ( auto actor : inRange ) + for( auto actor : inRange ) { targetPlayer->despawn( actor->getAsPlayer() ); targetPlayer->spawn( actor->getAsPlayer() ); @@ -165,7 +165,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac player.sendNotice( "Sex for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) ); targetPlayer->spawn( targetPlayer ); auto inRange = targetActor->getInRangeActors(); - for ( auto actor : inRange ) + for( auto actor : inRange ) { targetPlayer->despawn( actor->getAsPlayer() ); targetPlayer->spawn( actor->getAsPlayer() ); @@ -180,14 +180,14 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac } case GmCommand::Weather: { - targetPlayer->getCurrentZone()->setWeatherOverride( param1 ); + targetPlayer->getCurrentZone()->setWeatherOverride( static_cast< Common::Weather >( param1 ) ); player.sendNotice( "Weather in Zone \"" + targetPlayer->getCurrentZone()->getName() + "\" of " + targetPlayer->getName() + " set in range." ); break; } case GmCommand::Call: { - if ( targetPlayer->getZoneId() != player.getZoneId() ) + if( targetPlayer->getZoneId() != player.getZoneId() ) targetPlayer->setZone( player.getZoneId() ); targetPlayer->changePosition( player.getPos().x, player.getPos().y, player.getPos().z, @@ -266,7 +266,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac } case GmCommand::Inv: { - if ( targetActor->getInvincibilityType() == Common::InvincibilityType::InvincibilityRefill ) + if( targetActor->getInvincibilityType() == Common::InvincibilityType::InvincibilityRefill ) targetActor->setInvincibilityType( Common::InvincibilityType::InvincibilityNone ); else targetActor->setInvincibilityType( Common::InvincibilityType::InvincibilityRefill ); @@ -277,11 +277,11 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac } case GmCommand::Orchestrion: { - if ( param1 == 1 ) + if( param1 == 1 ) { - if ( param2 == 0 ) + if( param2 == 0 ) { - for ( uint8_t i = 0; i < 255; i++ ) + for( uint8_t i = 0; i < 255; i++ ) targetActor->getAsPlayer()->learnSong( i, 0 ); player.sendNotice( "All Songs for " + targetPlayer->getName() + @@ -324,7 +324,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac { uint32_t gil = targetPlayer->getCurrency( 1 ); - if ( gil < param1 ) + if( gil < param1 ) { player.sendUrgent( "Player does not have enough Gil(" + std::to_string( gil ) + ")" ); } @@ -379,11 +379,11 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac } case GmCommand::Aetheryte: { - if ( param1 == 0 ) + if( param1 == 0 ) { - if ( param2 == 0 ) + if( param2 == 0 ) { - for ( uint8_t i = 0; i < 255; i++ ) + for( uint8_t i = 0; i < 255; i++ ) targetActor->getAsPlayer()->registerAetheryte( i ); player.sendNotice( "All Aetherytes for " + targetPlayer->getName() + @@ -427,23 +427,23 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac } case GmCommand::TeriInfo: { + auto pCurrentZone = player.getCurrentZone(); player.sendNotice( "ZoneId: " + std::to_string( player.getZoneId() ) + "\nName: " + - player.getCurrentZone()->getName() + "\nInternalName: " + - player.getCurrentZone()->getInternalName() + "\nPopCount: " + - std::to_string( player.getCurrentZone()->getPopCount() ) + - "\nCurrentWeather:" + std::to_string( player.getCurrentZone()->getCurrentWeather() ) + - "\nNextWeather:" + std::to_string( player.getCurrentZone()->getNextWeather() ) ); + pCurrentZone->getName() + "\nInternalName: " + + pCurrentZone->getInternalName() + "\nPopCount: " + + std::to_string( pCurrentZone->getPopCount() ) + + "\nCurrentWeather:" + std::to_string( static_cast< uint8_t >( pCurrentZone->getCurrentWeather() ) ) + + "\nNextWeather:" + std::to_string( static_cast< uint8_t >( pCurrentZone->getNextWeather() ) ) ); break; } case GmCommand::Jump: { auto inRange = player.getInRangeActors(); - for( auto actor : inRange ) - { - player.changePosition( targetActor->getPos().x, targetActor->getPos().y, targetActor->getPos().z, - targetActor->getRotation() ); - } + + player.changePosition( targetActor->getPos().x, targetActor->getPos().y, targetActor->getPos().z, + targetActor->getRotation() ); + player.sendNotice( "Jumping to " + targetPlayer->getName() + " in range." ); break; } @@ -517,7 +517,7 @@ void Core::Network::GameConnection::gm2Handler( const Packets::GamePacket& inPac } case GmCommand::Call: { - if ( targetPlayer->getZoneId() != player.getZoneId() ) + if( targetPlayer->getZoneId() != player.getZoneId() ) targetPlayer->setZone( player.getZoneId() ); targetPlayer->changePosition( player.getPos().x, player.getPos().y, player.getPos().z, diff --git a/src/servers/sapphire_zone/Zone/Zone.cpp b/src/servers/sapphire_zone/Zone/Zone.cpp index eee90859..30d7e399 100644 --- a/src/servers/sapphire_zone/Zone/Zone.cpp +++ b/src/servers/sapphire_zone/Zone/Zone.cpp @@ -44,15 +44,15 @@ extern Core::TerritoryMgr g_territoryMgr; Core::Zone::Zone() : m_territoryId( 0 ), m_guId( 0 ), - m_currentWeather( static_cast< uint8_t >( Common::Weather::FairSkies ) ), - m_weatherOverride( 0 ), + m_currentWeather( Common::Weather::FairSkies ), + m_weatherOverride( Common::Weather::None ), m_lastMobUpdate( 0 ), m_currentFestivalId( 0 ) { } Core::Zone::Zone( uint16_t territoryId, uint32_t guId, const std::string& internalName, const std::string& placeName ) : - m_currentWeather( static_cast< uint8_t >( Common::Weather::FairSkies ) ) + m_currentWeather( Common::Weather::FairSkies ) { m_guId = guId; @@ -61,9 +61,22 @@ Core::Zone::Zone( uint16_t territoryId, uint32_t guId, const std::string& intern m_placeName = placeName; m_lastMobUpdate = 0; - m_weatherOverride = 0; + m_weatherOverride = Common::Weather::None; m_territoryTypeInfo = g_exdDataGen.get< Core::Data::TerritoryType >( territoryId ); + loadWeatherRates(); + + m_currentWeather = getNextWeather(); +} + +void Core::Zone::loadWeatherRates() +{ + if( !m_territoryTypeInfo ) + { + g_log.error( std::string( __FUNCTION__ ) + " TerritoryTypeInfo not loaded!" ); + return; + } + uint8_t weatherRateId = m_territoryTypeInfo->weatherRate > g_exdDataGen.getWeatherRateIdList().size() ? uint8_t{ 0 } : m_territoryTypeInfo->weatherRate; @@ -80,8 +93,6 @@ Core::Zone::Zone( uint16_t territoryId, uint32_t guId, const std::string& intern m_weatherRateMap[sumPc] = weatherId; i += 2; } - - m_currentWeather = getNextWeather(); } Core::Zone::~Zone() @@ -102,12 +113,12 @@ bool Core::Zone::init() return true; } -void Core::Zone::setWeatherOverride( uint8_t weather ) +void Core::Zone::setWeatherOverride( Common::Weather weather ) { m_weatherOverride = weather; } -uint8_t Core::Zone::getCurrentWeather() const +Core::Common::Weather Core::Zone::getCurrentWeather() const { return m_currentWeather; } @@ -227,7 +238,7 @@ void Core::Zone::loadCellCache() } -uint8_t Core::Zone::getNextWeather() +Core::Common::Weather Core::Zone::getNextWeather() { uint32_t unixTime = static_cast< uint32_t >( Util::getTimeSeconds() ); // Get Eorzea hour for weather start @@ -248,13 +259,13 @@ uint8_t Core::Zone::getNextWeather() for( auto entry : m_weatherRateMap ) { uint8_t sRate = entry.first; - auto weatherId = static_cast< uint8_t >( entry.second ); + auto weatherId = static_cast< Common::Weather >( entry.second ); if( rate <= sRate ) return weatherId; } - return 1; + return Common::Weather::FairSkies; } void Core::Zone::pushActor( Entity::ActorPtr pActor ) @@ -407,22 +418,24 @@ std::size_t Core::Zone::getPopCount() const bool Core::Zone::checkWeather() { - if ( m_weatherOverride != 0 ) + if( m_weatherOverride != Common::Weather::None ) { - if ( m_weatherOverride != m_currentWeather ) + if( m_weatherOverride != m_currentWeather ) { m_currentWeather = m_weatherOverride; - g_log.debug( "[Zone:" + m_internalName + "] overriding weather to : " + std::to_string( m_weatherOverride ) ); + g_log.debug( "[Zone:" + m_internalName + "] overriding weather to : " + + std::to_string( static_cast< uint8_t >( m_weatherOverride ) ) ); return true; } } else { auto nextWeather = getNextWeather(); - if ( nextWeather != m_currentWeather ) + if( nextWeather != m_currentWeather ) { m_currentWeather = nextWeather; - g_log.debug( "[Zone:" + m_internalName + "] changing weather to : " + std::to_string( nextWeather ) ); + g_log.debug( "[Zone:" + m_internalName + "] changing weather to : " + + std::to_string( static_cast< uint8_t >( nextWeather ) ) ); return true; } } @@ -522,7 +535,7 @@ void Core::Zone::updateSessions( bool changedWeather ) { Core::Network::Packets::ZoneChannelPacket< Core::Network::Packets::Server::FFXIVIpcWeatherChange > weatherChangePacket( pSession->getPlayer()->getId() ); - weatherChangePacket.data().weatherId = m_currentWeather; + weatherChangePacket.data().weatherId = static_cast< uint8_t >( m_currentWeather ); weatherChangePacket.data().delay = 5.0f; pSession->getPlayer()->queuePacket( weatherChangePacket ); } diff --git a/src/servers/sapphire_zone/Zone/Zone.h b/src/servers/sapphire_zone/Zone/Zone.h index a9b09ecc..3a84eaee 100644 --- a/src/servers/sapphire_zone/Zone/Zone.h +++ b/src/servers/sapphire_zone/Zone/Zone.h @@ -44,8 +44,8 @@ protected: CellCache** m_pCellCache[_sizeX]; - uint8_t m_currentWeather; - uint8_t m_weatherOverride; + Common::Weather m_currentWeather; + Common::Weather m_weatherOverride; uint64_t m_lastMobUpdate; @@ -65,9 +65,9 @@ public: bool init(); /*! overrides the zone's weather, set to 0 to unlock */ - void setWeatherOverride( uint8_t weather ); + void setWeatherOverride( Common::Weather weather ); - uint8_t getCurrentWeather() const; + Common::Weather getCurrentWeather() const; uint16_t getCurrentFestival() const; void setCurrentFestival( uint16_t festivalId ); @@ -84,7 +84,7 @@ public: virtual void onLeaveTerritory( Entity::Player& player ); virtual void onUpdate( uint32_t currTime ); - uint8_t getNextWeather(); + Common::Weather getNextWeather(); void pushActor( Entity::ActorPtr pActor ); @@ -106,6 +106,7 @@ public: const std::string& getInternalName() const; std::size_t getPopCount() const; + void loadWeatherRates(); bool checkWeather(); void updateBnpcs( int64_t tickCount ); From cb441475647251b7e140f437fabd6c26baa10166 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 15 Feb 2018 19:27:44 +1100 Subject: [PATCH 03/69] fix compile warning --- src/servers/sapphire_zone/Actor/PlayerSql.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/servers/sapphire_zone/Actor/PlayerSql.cpp b/src/servers/sapphire_zone/Actor/PlayerSql.cpp index b3b63f1f..8e72f3cd 100644 --- a/src/servers/sapphire_zone/Actor/PlayerSql.cpp +++ b/src/servers/sapphire_zone/Actor/PlayerSql.cpp @@ -313,7 +313,8 @@ bool Core::Entity::Player::loadSearchInfo() m_searchSelectClass = res->getUInt8( 1 ); m_searchSelectRegion = res->getUInt8( 2 ); - sprintf( m_searchMessage, res->getString( 3 ).c_str() ); + auto searchMessage = res->getString( 3 ); + std::copy( searchMessage.begin(), searchMessage.end(), m_searchMessage ); return true; } From 48a1fd502a05a6f2eb60b952987bbd647679d4c6 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 15 Feb 2018 19:44:54 +1100 Subject: [PATCH 04/69] add todo note --- src/servers/sapphire_zone/Actor/PlayerSql.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/servers/sapphire_zone/Actor/PlayerSql.cpp b/src/servers/sapphire_zone/Actor/PlayerSql.cpp index 8e72f3cd..b1522720 100644 --- a/src/servers/sapphire_zone/Actor/PlayerSql.cpp +++ b/src/servers/sapphire_zone/Actor/PlayerSql.cpp @@ -313,6 +313,8 @@ bool Core::Entity::Player::loadSearchInfo() m_searchSelectClass = res->getUInt8( 1 ); m_searchSelectRegion = res->getUInt8( 2 ); + + // todo: internally use an std::string instead of a char[] auto searchMessage = res->getString( 3 ); std::copy( searchMessage.begin(), searchMessage.end(), m_searchMessage ); From b8cbdf3fa5fc476d021940450a95644a507a6fe7 Mon Sep 17 00:00:00 2001 From: Mordred Date: Thu, 15 Feb 2018 23:50:28 +0100 Subject: [PATCH 05/69] removed all unused state flags, mapped more client actions --- src/common/Common.h | 70 +++---------------- .../Network/PacketDef/Zone/ServerZoneDef.h | 6 +- .../sapphire_zone/Action/ActionCast.cpp | 2 +- .../sapphire_zone/Action/ActionMount.cpp | 2 +- .../sapphire_zone/Action/EventAction.cpp | 8 +-- src/servers/sapphire_zone/Actor/Player.cpp | 2 +- src/servers/sapphire_zone/Actor/Player.h | 2 +- .../sapphire_zone/Actor/PlayerEvent.cpp | 5 +- .../Network/Handlers/ActionHandler.cpp | 25 ++++++- .../Network/Handlers/PacketHandlers.cpp | 6 +- .../PacketWrappers/PlayerStateFlagsPacket.h | 6 +- 11 files changed, 48 insertions(+), 86 deletions(-) diff --git a/src/common/Common.h b/src/common/Common.h index 15fb9800..2a62c6ef 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -380,73 +380,21 @@ namespace Common { InvincibilityStayAlive, }; - enum struct PlayerStateFlag : uint8_t + enum PlayerStateFlag : uint8_t { - NoCombat, - Combat, - Casting, - StatusAffliction, - StatusAffliction1, - Occupied, - Occupied1, - Occupied2, - Occupied3, + HideUILockChar = 0, // as the name suggests, hides the ui and logs the char... + InCombat = 1, // in Combat, locks gearchange/return/teleport + Casting = 2, + InNpcEvent = 7, // when talking to an npc, locks ui giving "occupied" message - BoundByDuty, - Occupied4, - DuelingArea, - TradeOpen, - Occupied5, - HandlingItems, - Crafting, - PreparingToCraft, - Gathering, - Fishing, + InNpcEvent1 = 10, // Sent together with InNpcEvent, when waiting for input? just a guess... - BeingRaised, - BetweenAreas, - Stealthed, - InnRoom, - Jumping, - AutoRun, - Occupied6, - BetweenAreas1, - SystemError, - LoggingOut, + BoundByDuty = 11, - InvalidLocation, - WaitingForDuty, - BoundByDuty1, - Mounting, - WatchingCutscene, - WaitingForDutyFinder, - CreatingCharacter, - Jumping1, - PvpDisplay, - StatusAfflication2, + BetweenAreas = 24, - Mounting1, - CarryingItem, - UsingPartyFinder, - HousingFunctions, - Transformed, - FreeTrail, - BeingMoved, - Mounting2, - StatusAffliction3, - StatusAffliction4, + WatchingCutscene = 50, // this is actually just a dummy, this id is different - RegisteringRaceOrMatch, - WaitingForRaceOrMatch, - WaitingForTripleTriadMatch, - InFlight, - WatchingCutscene1, - DeepDungeon, - Swimming, - Diving, - RegisteringTripleTriad, - WaitingTripleTriad, - InCrossWorldParty }; diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index aba88ad3..d63dc394 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -826,10 +826,8 @@ struct FFXIVIpcActorOwner : FFXIVIpcBasePacket */ struct FFXIVIpcPlayerStateFlags : FFXIVIpcBasePacket { - uint8_t flags[7]; - uint8_t padding1[3]; - uint32_t padding2; - uint16_t padding; + uint8_t flags[12]; + uint32_t padding; }; /** diff --git a/src/servers/sapphire_zone/Action/ActionCast.cpp b/src/servers/sapphire_zone/Action/ActionCast.cpp index ee75c48b..00e0e966 100644 --- a/src/servers/sapphire_zone/Action/ActionCast.cpp +++ b/src/servers/sapphire_zone/Action/ActionCast.cpp @@ -83,7 +83,7 @@ void Core::Action::ActionCast::onInterrupt() if( !m_pSource ) return; - m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Occupied1 ); + //m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Occupied1 ); m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Casting ); auto control = ActorControlPacket142( m_pSource->getId(), ActorControlType::CastInterrupt, diff --git a/src/servers/sapphire_zone/Action/ActionMount.cpp b/src/servers/sapphire_zone/Action/ActionMount.cpp index 13dcc05d..9ec4588e 100644 --- a/src/servers/sapphire_zone/Action/ActionMount.cpp +++ b/src/servers/sapphire_zone/Action/ActionMount.cpp @@ -94,7 +94,7 @@ void Core::Action::ActionMount::onInterrupt() if( !m_pSource ) return; - m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Occupied1 ); + //m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Occupied1 ); m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Casting ); auto control = ActorControlPacket142( m_pSource->getId(), ActorControlType::CastInterrupt, diff --git a/src/servers/sapphire_zone/Action/EventAction.cpp b/src/servers/sapphire_zone/Action/EventAction.cpp index 9c08f3a7..47b9895f 100644 --- a/src/servers/sapphire_zone/Action/EventAction.cpp +++ b/src/servers/sapphire_zone/Action/EventAction.cpp @@ -53,7 +53,7 @@ void Core::Action::EventAction::onStart() if( m_pSource->isPlayer() ) { m_pSource->sendToInRangeSet( control, true ); - m_pSource->getAsPlayer()->setStateFlag( PlayerStateFlag::Occupied2 ); + //m_pSource->getAsPlayer()->setStateFlag( PlayerStateFlag::Occupied2 ); } else m_pSource->sendToInRangeSet( control ); @@ -82,7 +82,7 @@ void Core::Action::EventAction::onFinish() if( m_pSource->isPlayer() ) { - m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Occupied2 ); + //m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Occupied2 ); m_pSource->sendToInRangeSet( control, true ); } else @@ -110,8 +110,8 @@ void Core::Action::EventAction::onInterrupt() { auto control1 = ActorControlPacket143( m_pSource->getId(), ActorControlType::FreeEventPos, m_eventId ); - m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::NoCombat ); - m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Occupied1 ); + //m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::NoCombat ); + //m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Occupied1 ); m_pSource->sendToInRangeSet( control ); m_pSource->sendToInRangeSet( control1 ); diff --git a/src/servers/sapphire_zone/Actor/Player.cpp b/src/servers/sapphire_zone/Actor/Player.cpp index 3b0afa41..2cbcfe09 100644 --- a/src/servers/sapphire_zone/Actor/Player.cpp +++ b/src/servers/sapphire_zone/Actor/Player.cpp @@ -177,7 +177,7 @@ Core::Common::OnlineStatus Core::Entity::Player::getOnlineStatus() if( m_onlineStatus & rpMask ) status = OnlineStatus::Roleplaying; - if( hasStateFlag( PlayerStateFlag::WatchingCutscene ) || hasStateFlag( PlayerStateFlag::WatchingCutscene1 ) ) + if( hasStateFlag( PlayerStateFlag::WatchingCutscene ) ) status = OnlineStatus::ViewingCutscene; // TODO: add all the logic for returning the proper online status, there probably is a better way for this alltogether diff --git a/src/servers/sapphire_zone/Actor/Player.h b/src/servers/sapphire_zone/Actor/Player.h index 712aa1c2..22a474fa 100644 --- a/src/servers/sapphire_zone/Actor/Player.h +++ b/src/servers/sapphire_zone/Actor/Player.h @@ -637,7 +637,7 @@ private: boost::shared_ptr< Common::QuestActive > m_activeQuests[30]; int16_t m_questTracking[5]; - uint8_t m_stateFlags[7]; + uint8_t m_stateFlags[12]; uint8_t m_gmRank; uint16_t zoneId; diff --git a/src/servers/sapphire_zone/Actor/PlayerEvent.cpp b/src/servers/sapphire_zone/Actor/PlayerEvent.cpp index 7189b106..aeeb5ad9 100644 --- a/src/servers/sapphire_zone/Actor/PlayerEvent.cpp +++ b/src/servers/sapphire_zone/Actor/PlayerEvent.cpp @@ -84,7 +84,7 @@ void Core::Entity::Player::eventStart( uint64_t actorId, uint32_t eventId, addEvent( newEvent ); - setStateFlag( PlayerStateFlag::Occupied2 ); + setStateFlag( PlayerStateFlag::InNpcEvent ); EventStartPacket eventStart( getId(), actorId, eventId, eventType, eventParam1, eventParam2 ); @@ -218,7 +218,7 @@ void Core::Entity::Player::eventFinish( uint32_t eventId, uint32_t freePlayer ) removeEvent( pEvent->getId() ); if( freePlayer == 1 ) - unsetStateFlag( PlayerStateFlag::Occupied2 ); + unsetStateFlag( PlayerStateFlag::InNpcEvent ); } void Core::Entity::Player::eventActionStart( uint32_t eventId, @@ -290,7 +290,6 @@ void Core::Entity::Player::onDeath() } - // TODO: slightly ugly here and way too static. Needs too be done properly void Core::Entity::Player::onTick() { diff --git a/src/servers/sapphire_zone/Network/Handlers/ActionHandler.cpp b/src/servers/sapphire_zone/Network/Handlers/ActionHandler.cpp index d79c8001..d709f552 100644 --- a/src/servers/sapphire_zone/Network/Handlers/ActionHandler.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/ActionHandler.cpp @@ -117,6 +117,10 @@ void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& in player.getCurrentAction()->setInterrupted(); break; } + case 0x12D: // Mark player + { + break; + } case 0x12E: // Set player title { player.setTitle( static_cast< uint16_t >( param1 ) ); @@ -132,7 +136,7 @@ void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& in } case 0x133: // Update howtos seen { - uint32_t howToId = static_cast< uint32_t >( param1 ); + uint32_t howToId = param11; player.updateHowtosSeen( howToId ); break; } @@ -144,7 +148,23 @@ void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& in player.sendToInRangeSet( ActorControlPacket144( player.getId(), Emote, emoteId, 0, 0, 0, targetId ) ); break; } - case 0xC8: // return dead + case 0x1F7: // cancel persistant emote + { + break; + } + case 0x1F9: // change pose + { + break; + } + case 0x1FA: // reapply pose + { + break; + } + case 0x1FB: // cancel pose + { + break; + } + case 0xC8: // return dead / accept raise { switch ( static_cast < ResurrectType >( param1 ) ) { @@ -193,7 +213,6 @@ void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& in player.setZoningType( Common::ZoneingType::None ); player.unsetStateFlag( PlayerStateFlag::BetweenAreas ); - player.unsetStateFlag( PlayerStateFlag::BetweenAreas1 ); break; } diff --git a/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp b/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp index 8e5d27d5..c6232a22 100644 --- a/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp @@ -564,16 +564,14 @@ void Core::Network::GameConnection::tellHandler( const Packets::GamePacket& inPa auto pTargetPlayer = pSession->getPlayer(); - if( pTargetPlayer->hasStateFlag( PlayerStateFlag::BetweenAreas ) || - pTargetPlayer->hasStateFlag( PlayerStateFlag::BetweenAreas1 ) ) + if( pTargetPlayer->hasStateFlag( PlayerStateFlag::BetweenAreas ) ) { // send error for player between areas // TODO: implement me return; } - if( pTargetPlayer->hasStateFlag( PlayerStateFlag::BoundByDuty ) || - pTargetPlayer->hasStateFlag( PlayerStateFlag::BoundByDuty1 ) ) + if( pTargetPlayer->hasStateFlag( PlayerStateFlag::BoundByDuty ) ) { // send error for player bound by duty // TODO: implement me diff --git a/src/servers/sapphire_zone/Network/PacketWrappers/PlayerStateFlagsPacket.h b/src/servers/sapphire_zone/Network/PacketWrappers/PlayerStateFlagsPacket.h index 920a4a80..ac1bf5a5 100644 --- a/src/servers/sapphire_zone/Network/PacketWrappers/PlayerStateFlagsPacket.h +++ b/src/servers/sapphire_zone/Network/PacketWrappers/PlayerStateFlagsPacket.h @@ -26,8 +26,8 @@ public: PlayerStateFlagsPacket( Entity::Player& player, std::vector< Common::PlayerStateFlag > flags ) : ZoneChannelPacket< FFXIVIpcPlayerStateFlags >( player.getId(), player.getId() ) { - uint8_t newFlags[7]; - memset( newFlags, 0, 7 ); + uint8_t newFlags[12]; + memset( newFlags, 0, 12 ); for( auto& flag : flags ) { @@ -46,7 +46,7 @@ public: private: void initialize( const uint8_t* flags ) { - memcpy( m_data.flags, flags, 7 ); + memcpy( m_data.flags, flags, 12 ); }; }; From 1f37416202d7361e6b9d66087ec6e38a45777cd9 Mon Sep 17 00:00:00 2001 From: Mordred Date: Sat, 17 Feb 2018 01:20:40 +0100 Subject: [PATCH 06/69] Actionhandler cleaned up a bit --- src/servers/sapphire_zone/Actor/Player.cpp | 23 ++++- src/servers/sapphire_zone/Actor/Player.h | 3 + .../Network/Handlers/ActionHandler.cpp | 96 ++++++++++++++----- 3 files changed, 92 insertions(+), 30 deletions(-) diff --git a/src/servers/sapphire_zone/Actor/Player.cpp b/src/servers/sapphire_zone/Actor/Player.cpp index 2cbcfe09..18cec2d1 100644 --- a/src/servers/sapphire_zone/Actor/Player.cpp +++ b/src/servers/sapphire_zone/Actor/Player.cpp @@ -1357,6 +1357,11 @@ uint8_t* Core::Entity::Player::getTitleList() return m_titleList; } +const uint8_t* Core::Entity::Player::getTitleList() const +{ + return m_titleList; +} + uint16_t Core::Entity::Player::getTitle() const { return m_activeTitle; @@ -1541,17 +1546,17 @@ void Core::Entity::Player::setEorzeaTimeOffset( uint64_t timestamp ) queuePacket( packet ); } -void Player::setTerritoryId( uint32_t territoryId ) +void Core::Entity::Player::setTerritoryId( uint32_t territoryId ) { m_zoneId = territoryId; } -uint32_t Player::getTerritoryId() const +uint32_t Core::Entity::Player::getTerritoryId() const { return m_zoneId; } -void Player::sendZonePackets() +void Core::Entity::Player::sendZonePackets() { ZoneChannelPacket< FFXIVIpcInit > initPacket( getId() ); initPacket.data().charId = getId(); @@ -1623,12 +1628,20 @@ void Player::sendZonePackets() m_bMarkedForZoning = false; } -void Player::setDirectorInitialized( bool isInitialized ) +void Core::Entity::Player::setDirectorInitialized( bool isInitialized ) { m_directorInitialized = isInitialized; } -bool Player::isDirectorInitialized() const +bool Core::Entity::Player::isDirectorInitialized() const { return m_directorInitialized; } + +void Core::Entity::Player::sendTitleList() +{ + ZoneChannelPacket< FFXIVIpcPlayerTitleList > titleListPacket( getId() ); + memcpy( titleListPacket.data().titleList, getTitleList(), sizeof( titleListPacket.data().titleList ) ); + + queuePacket( titleListPacket ); +} diff --git a/src/servers/sapphire_zone/Actor/Player.h b/src/servers/sapphire_zone/Actor/Player.h index 22a474fa..65f7638e 100644 --- a/src/servers/sapphire_zone/Actor/Player.h +++ b/src/servers/sapphire_zone/Actor/Player.h @@ -347,12 +347,15 @@ public: void prepareZoning( uint16_t targetZone, bool fadeOut, uint8_t fadoutTime = 0, uint16_t animation = 0 ); /*! get player's title list (available titles) */ uint8_t* getTitleList(); + const uint8_t* getTitleList() const; /*! get player's active title */ uint16_t getTitle() const; /*! add title to player title list */ void addTitle( uint16_t titleId ); /*! change player's active title */ void setTitle( uint16_t titleId ); + /*! send the players title list */ + void sendTitleList(); /*! change gear param state */ void setEquipDisplayFlags( uint8_t state ); /*! get gear param state */ diff --git a/src/servers/sapphire_zone/Network/Handlers/ActionHandler.cpp b/src/servers/sapphire_zone/Network/Handlers/ActionHandler.cpp index d709f552..e20a9784 100644 --- a/src/servers/sapphire_zone/Network/Handlers/ActionHandler.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/ActionHandler.cpp @@ -43,6 +43,55 @@ using namespace Core::Common; using namespace Core::Network::Packets; using namespace Core::Network::Packets::Server; +enum ClientTrigger +{ + ToggleSeathe = 0x01, + ToggleAutoAttack = 0x02, + ChangeTarget = 0x03, + + Dismount = 0x65, + + RemoveStatusEffect = 0x68, + CastCancel = 0x69, + + Return = 0xC8, // return dead / accept raise + FinishZoning = 0xC9, + Teleport = 0xCA, + + MarkPlayer = 0x12D, // Mark player, visible to party only + SetTitle = 0x12E, + TitleList = 0x12F, + + UpdatedSeenHowTos = 0x133, + AllotAttribute = 0x135, + + HuntingLogDetails = 0x194, + + EstateTimers = 0x1AB, + + DyeItem = 0x1B5, + + Emote = 0x1F4, + PersistantEmoteCancel = 0x1F7, + PoseChange = 0x1F9, + PoseReapply = 0x1FA, + PoseCancel = 0x1FB, + + AchievementCrit = 0x202, + AchievementComp = 0x203, + AchievementCatChat = 0x206, + + AchievementCritReq = 0x3E8, + AchievementList = 0x3E9, + + DirectorInitFinish = 0x321, + + CompanionAction = 0x6A4, + CompanionSetBarding = 0x6A5, + CompanionActionUnlock = 0x6A6, + +}; + void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& inPacket, Entity::Player& player ) { @@ -65,7 +114,7 @@ void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& in switch( commandId ) { - case 0x01: // Toggle sheathe + case ClientTrigger::ToggleSeathe: // Toggle sheathe { if ( param11 == 1 ) player.setStance( Entity::Actor::Stance::Active ); @@ -79,7 +128,7 @@ void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& in break; } - case 0x02: // Toggle auto-attack + case ClientTrigger::ToggleAutoAttack: // Toggle auto-attack { if ( param11 == 1 ) { @@ -93,78 +142,75 @@ void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& in break; } - case 0x03: // Change target + case ClientTrigger::ChangeTarget: // Change target { uint64_t targetId = inPacket.getValAt< uint64_t >( 0x24 ); player.changeTarget( targetId ); break; } - case 0x65: + case ClientTrigger::Dismount: { player.dismount(); break; } - case 0x68: // Remove status (clicking it off) + case ClientTrigger::RemoveStatusEffect: // Remove status (clicking it off) { // todo: check if status can be removed by client from exd player.removeSingleStatusEffectById( static_cast< uint32_t >( param1 ) ); break; } - case 0x69: // Cancel cast + case ClientTrigger::CastCancel: // Cancel cast { if( player.getCurrentAction() ) player.getCurrentAction()->setInterrupted(); break; } - case 0x12D: // Mark player + case ClientTrigger::MarkPlayer: // Mark player { break; } - case 0x12E: // Set player title + case ClientTrigger::SetTitle: // Set player title { player.setTitle( static_cast< uint16_t >( param1 ) ); break; } - case 0x12F: // Get title list + case ClientTrigger::TitleList: // Get title list { - ZoneChannelPacket< FFXIVIpcPlayerTitleList > titleListPacket( player.getId() ); - memcpy( titleListPacket.data().titleList, player.getTitleList(), sizeof( titleListPacket.data().titleList ) ); - - player.queuePacket( titleListPacket ); + player.sendTitleList(); break; } - case 0x133: // Update howtos seen + case ClientTrigger::UpdatedSeenHowTos: // Update howtos seen { uint32_t howToId = param11; player.updateHowtosSeen( howToId ); break; } - case 0x1F4: // emote + case ClientTrigger::Emote: // emote { uint64_t targetId = player.getTargetId(); uint32_t emoteId = inPacket.getValAt< uint32_t >( 0x24 ); - player.sendToInRangeSet( ActorControlPacket144( player.getId(), Emote, emoteId, 0, 0, 0, targetId ) ); + player.sendToInRangeSet( ActorControlPacket144( player.getId(), ActorControlType::Emote, emoteId, 0, 0, 0, targetId ) ); break; } - case 0x1F7: // cancel persistant emote + case ClientTrigger::PersistantEmoteCancel: // cancel persistant emote { break; } - case 0x1F9: // change pose + case ClientTrigger::PoseChange: // change pose { break; } - case 0x1FA: // reapply pose + case ClientTrigger::PoseReapply: // reapply pose { break; } - case 0x1FB: // cancel pose + case ClientTrigger::PoseCancel: // cancel pose { break; } - case 0xC8: // return dead / accept raise + case ClientTrigger::Return: // return dead / accept raise { switch ( static_cast < ResurrectType >( param1 ) ) { @@ -180,7 +226,7 @@ void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& in } } - case 0xC9: // Finish zoning + case ClientTrigger::FinishZoning: // Finish zoning { switch( player.getZoningType() ) { @@ -216,7 +262,7 @@ void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& in break; } - case 0xCA: // Teleport + case ClientTrigger::Teleport: // Teleport { // TODO: only register this action if enough gil is in possession auto targetAetheryte = g_exdDataGen.get< Core::Data::Aetheryte >( param11 ); @@ -244,11 +290,11 @@ void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& in } break; } - case 0x1B5: // Dye item + case ClientTrigger::DyeItem: // Dye item { break; } - case 0x321: // Director init finish + case ClientTrigger::DirectorInitFinish: // Director init finish { player.getCurrentZone()->onInitDirector( player ); break; From 883916aa489151205bb7a9ff7dee0896e56169b3 Mon Sep 17 00:00:00 2001 From: Mordred Date: Sun, 18 Feb 2018 01:50:20 +0100 Subject: [PATCH 07/69] More cleanup of actionhandler --- src/servers/sapphire_zone/Actor/Player.cpp | 85 +++++++++++++++++-- src/servers/sapphire_zone/Actor/Player.h | 6 ++ .../Network/Handlers/ActionHandler.cpp | 59 +------------ 3 files changed, 89 insertions(+), 61 deletions(-) diff --git a/src/servers/sapphire_zone/Actor/Player.cpp b/src/servers/sapphire_zone/Actor/Player.cpp index 18cec2d1..4c7c3df8 100644 --- a/src/servers/sapphire_zone/Actor/Player.cpp +++ b/src/servers/sapphire_zone/Actor/Player.cpp @@ -19,6 +19,7 @@ #include "Network/GameConnection.h" #include "Network/PacketWrappers/ActorControlPacket142.h" #include "Network/PacketWrappers/ActorControlPacket143.h" +#include "Network/PacketWrappers/ActorControlPacket144.h" #include "Network/PacketWrappers/InitUIPacket.h" #include "Network/PacketWrappers/ServerNoticePacket.h" #include "Network/PacketWrappers/ChatPacket.h" @@ -36,6 +37,7 @@ #include "Action/Action.h" #include "Action/EventAction.h" #include "Action/EventItemAction.h" +#include "Action/ActionTeleport.h" #include "Zone/ZonePosition.h" #include "Math/CalcStats.h" #include "Math/CalcBattle.h" @@ -299,7 +301,7 @@ void Core::Entity::Player::teleport( uint16_t aetheryteId, uint8_t type ) setStateFlag( PlayerStateFlag::BetweenAreas ); - auto z_pos = g_territoryMgr.getTerritoryPosition( data->territory ); + auto targetPos = g_territoryMgr.getTerritoryPosition( data->territory ); Common::FFXIVARR_POSITION3 pos; pos.x = 0; @@ -307,10 +309,10 @@ void Core::Entity::Player::teleport( uint16_t aetheryteId, uint8_t type ) pos.z = 0; float rot = 0; - if( z_pos != nullptr ) + if( targetPos != nullptr ) { - pos = z_pos->getTargetPosition(); - rot = z_pos->getTargetRotation(); + pos = targetPos->getTargetPosition(); + rot = targetPos->getTargetRotation(); } sendDebug( "Teleport: " + g_exdDataGen.get< Core::Data::PlaceName >( data->placeName )->name + " " + @@ -1638,10 +1640,83 @@ bool Core::Entity::Player::isDirectorInitialized() const return m_directorInitialized; } -void Core::Entity::Player::sendTitleList() +void Core::Entity::Player::sendTitleList() { ZoneChannelPacket< FFXIVIpcPlayerTitleList > titleListPacket( getId() ); memcpy( titleListPacket.data().titleList, getTitleList(), sizeof( titleListPacket.data().titleList ) ); queuePacket( titleListPacket ); } + +void Core::Entity::Player::finishZoning() +{ + switch( getZoningType() ) + { + case ZoneingType::None: + sendToInRangeSet( ActorControlPacket143( getId(), ZoneIn, 0x01 ), true ); + break; + + case ZoneingType::Teleport: + sendToInRangeSet( ActorControlPacket143( getId(), ZoneIn, 0x01, 0, 0, 110 ), true ); + break; + + case ZoneingType::Return: + case ZoneingType::ReturnDead: + { + if( getStatus() == Entity::Actor::ActorStatus::Dead ) + { + resetHp(); + resetMp(); + setStatus( Entity::Actor::ActorStatus::Idle ); + + sendToInRangeSet( ActorControlPacket143( getId(), ZoneIn, 0x01, 0x01, 0, 111 ), true ); + sendToInRangeSet( ActorControlPacket142( getId(), SetStatus, + static_cast< uint8_t >( Entity::Actor::ActorStatus::Idle ) ), true ); + } + else + sendToInRangeSet( ActorControlPacket143( getId(), ZoneIn, 0x01, 0x00, 0, 111 ), true ); + } + break; + + case ZoneingType::FadeIn: + break; + } + + setZoningType( Common::ZoneingType::None ); + unsetStateFlag( PlayerStateFlag::BetweenAreas ); +} + +void Player::emote( uint32_t emoteId, uint64_t targetId ) +{ + sendToInRangeSet( ActorControlPacket144( getId(), ActorControlType::Emote, emoteId, 0, 0, 0, targetId ) ); +} + +void Player::teleportQuery( uint16_t aetheryteId ) +{ + // TODO: only register this action if enough gil is in possession + auto targetAetheryte = g_exdDataGen.get< Core::Data::Aetheryte >( aetheryteId ); + + if( targetAetheryte ) + { + auto fromAetheryte = g_exdDataGen.get< Core::Data::Aetheryte >( + g_exdDataGen.get< Core::Data::TerritoryType >( getZoneId() )->aetheryte ); + + // calculate cost - does not apply for favorite points or homepoints neither checks for aether tickets + auto cost = static_cast< uint16_t > ( ( sqrt( pow( fromAetheryte->aetherstreamX - targetAetheryte->aetherstreamX, 2 ) + + pow( fromAetheryte->aetherstreamY - targetAetheryte->aetherstreamY, 2 ) ) / 2 ) + 100 ); + + // cap at 999 gil + cost = cost > uint16_t{999} ? uint16_t{999} : cost; + + bool insufficientGil = getCurrency( Inventory::CurrencyType::Gil ) < cost; + // TODO: figure out what param1 really does + queuePacket( ActorControlPacket143( getId(), TeleportStart, insufficientGil ? 2 : 0, aetheryteId ) ); + + if( !insufficientGil ) + { + Action::ActionPtr pActionTeleport; + pActionTeleport = Action::make_ActionTeleport( getAsPlayer(), aetheryteId, cost ); + setCurrentAction( pActionTeleport ); + } + } +} diff --git a/src/servers/sapphire_zone/Actor/Player.h b/src/servers/sapphire_zone/Actor/Player.h index 65f7638e..7fb80e58 100644 --- a/src/servers/sapphire_zone/Actor/Player.h +++ b/src/servers/sapphire_zone/Actor/Player.h @@ -343,6 +343,8 @@ public: uint64_t getOnlineStatusMask() const; /*! perform a teleport of a specified type ( teleport,return,aethernet ) */ void teleport( uint16_t aetheryteId, uint8_t type = 1 ); + /*! query teleport of a specified type */ + void teleportQuery( uint16_t aetheryteId ); /*! prepares zoning / fades out the screen */ void prepareZoning( uint16_t targetZone, bool fadeOut, uint8_t fadoutTime = 0, uint16_t animation = 0 ); /*! get player's title list (available titles) */ @@ -488,6 +490,10 @@ public: /*! return true if the player is marked for zoning */ bool isMarkedForZoning() const; + void emote( uint32_t emoteId, uint64_t targetId ); + + void finishZoning(); + void sendZonePackets(); Common::ZoneingType getZoningType() const; diff --git a/src/servers/sapphire_zone/Network/Handlers/ActionHandler.cpp b/src/servers/sapphire_zone/Network/Handlers/ActionHandler.cpp index e20a9784..b04e9074 100644 --- a/src/servers/sapphire_zone/Network/Handlers/ActionHandler.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/ActionHandler.cpp @@ -191,7 +191,7 @@ void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& in uint64_t targetId = player.getTargetId(); uint32_t emoteId = inPacket.getValAt< uint32_t >( 0x24 ); - player.sendToInRangeSet( ActorControlPacket144( player.getId(), ActorControlType::Emote, emoteId, 0, 0, 0, targetId ) ); + player.emote( emoteId, targetId ); break; } case ClientTrigger::PersistantEmoteCancel: // cancel persistant emote @@ -228,66 +228,13 @@ void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& in } case ClientTrigger::FinishZoning: // Finish zoning { - switch( player.getZoningType() ) - { - case ZoneingType::None: - player.sendToInRangeSet( ActorControlPacket143( player.getId(), ZoneIn, 0x01 ), true ); - break; - case ZoneingType::Teleport: - player.sendToInRangeSet( ActorControlPacket143( player.getId(), ZoneIn, 0x01, 0, 0, 110 ), true ); - break; - case ZoneingType::Return: - case ZoneingType::ReturnDead: - { - if( player.getStatus() == Entity::Actor::ActorStatus::Dead ) - { - player.resetHp(); - player.resetMp(); - player.setStatus( Entity::Actor::ActorStatus::Idle ); - - player.sendToInRangeSet( ActorControlPacket143( player.getId(), ZoneIn, 0x01, 0x01, 0, 111 ), true ); - player.sendToInRangeSet( ActorControlPacket142( player.getId(), SetStatus, static_cast< uint8_t >( Entity::Actor::ActorStatus::Idle ) ), true ); - } - else - player.sendToInRangeSet( ActorControlPacket143( player.getId(), ZoneIn, 0x01, 0x00, 0, 111 ), true ); - } - break; - case ZoneingType::FadeIn: - break; - } - - player.setZoningType( Common::ZoneingType::None ); - - player.unsetStateFlag( PlayerStateFlag::BetweenAreas ); + player.finishZoning(); break; } case ClientTrigger::Teleport: // Teleport { - // TODO: only register this action if enough gil is in possession - auto targetAetheryte = g_exdDataGen.get< Core::Data::Aetheryte >( param11 ); - - if( targetAetheryte ) - { - auto fromAetheryte = g_exdDataGen.get< Core::Data::Aetheryte >( g_exdDataGen.get< Core::Data::TerritoryType >( player.getZoneId() )->aetheryte ); - - // calculate cost - does not apply for favorite points or homepoints neither checks for aether tickets - auto cost = static_cast< uint16_t > ( ( sqrt( pow( fromAetheryte->aetherstreamX - targetAetheryte->aetherstreamX, 2 ) + - pow( fromAetheryte->aetherstreamY - targetAetheryte->aetherstreamY, 2 ) ) / 2 ) + 100 ); - - // cap at 999 gil - cost = cost > uint16_t{999} ? uint16_t{999} : cost; - - bool insufficientGil = player.getCurrency( Inventory::CurrencyType::Gil ) < cost; - // todo: figure out what param1 really does - player.queuePacket( ActorControlPacket143( player.getId(), TeleportStart, insufficientGil ? 2 : 0, param11 ) ); - - if( !insufficientGil ) - { - auto pActionTeleport = Action::make_ActionTeleport( player.getAsPlayer(), param11, cost ); - player.setCurrentAction( pActionTeleport ); - } - } + player.teleportQuery( param11 ); break; } case ClientTrigger::DyeItem: // Dye item From 237d3cc7a6f5615c9c69a7adb36d099bc7b3421a Mon Sep 17 00:00:00 2001 From: Mordred Date: Sun, 18 Feb 2018 02:05:25 +0100 Subject: [PATCH 08/69] Added Waymarks trigger to enum, fixed initial array sizes for new chars --- src/servers/sapphire_api/PlayerMinimal.cpp | 10 +++++----- .../sapphire_zone/Network/Handlers/ActionHandler.cpp | 4 +++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/servers/sapphire_api/PlayerMinimal.cpp b/src/servers/sapphire_api/PlayerMinimal.cpp index ba95c96f..1fa2604d 100644 --- a/src/servers/sapphire_api/PlayerMinimal.cpp +++ b/src/servers/sapphire_api/PlayerMinimal.cpp @@ -148,13 +148,13 @@ namespace Core { { std::vector< uint8_t > customize( 26 ); - std::vector< uint8_t > howTo( 32 ); - std::vector< uint8_t > aetherytes( 12 ); - std::vector< uint8_t > discovery( 411 ); + std::vector< uint8_t > howTo( 33 ); + std::vector< uint8_t > aetherytes( 16 ); + std::vector< uint8_t > discovery( 421 ); std::vector< uint8_t > questComplete( 396 ); std::vector< uint8_t > unlocks( 64 ); - std::vector< uint8_t > mountGuide( 13 ); - std::vector< uint8_t > orchestrion( 38 ); + std::vector< uint8_t > mountGuide( 15 ); + std::vector< uint8_t > orchestrion( 40 ); std::vector< uint8_t > modelEquip( 40 ); std::vector< uint8_t > questTracking8( 10 ); std::vector< int16_t > questTracking = { -1, -1, -1, -1, -1 }; diff --git a/src/servers/sapphire_zone/Network/Handlers/ActionHandler.cpp b/src/servers/sapphire_zone/Network/Handlers/ActionHandler.cpp index b04e9074..70ce5885 100644 --- a/src/servers/sapphire_zone/Network/Handlers/ActionHandler.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/ActionHandler.cpp @@ -65,9 +65,11 @@ enum ClientTrigger UpdatedSeenHowTos = 0x133, AllotAttribute = 0x135, + ClearWaymarks = 0x13A, + HuntingLogDetails = 0x194, - EstateTimers = 0x1AB, + Timers = 0x1AB, DyeItem = 0x1B5, From 62f69040b470e26c11ffb5c91053d10d7f9116b4 Mon Sep 17 00:00:00 2001 From: Mordred Date: Sun, 18 Feb 2018 02:12:15 +0100 Subject: [PATCH 09/69] Added comment to spawn packet indicating field meaning of type --- src/common/Network/PacketDef/Zone/ServerZoneDef.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index d63dc394..572b08fb 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -382,7 +382,7 @@ struct FFXIVIpcPlayerSpawn : FFXIVIpcBasePacket uint8_t spawnIndex; uint8_t state; uint8_t persistantEmote; - uint8_t type; + uint8_t type; // modelType -> eventSystemDefine uint8_t subtype; uint8_t voice; uint16_t u25c; From c4206ee9bc7a3c60c4d7be4b562d10feb5e459d5 Mon Sep 17 00:00:00 2001 From: Mordred Date: Sun, 18 Feb 2018 22:53:12 +0100 Subject: [PATCH 10/69] Simplified in range logic --- src/servers/sapphire_zone/Actor/Actor.cpp | 32 ----------------------- src/servers/sapphire_zone/Actor/Actor.h | 2 -- src/servers/sapphire_zone/Zone/Zone.cpp | 24 +++++++++++------ 3 files changed, 16 insertions(+), 42 deletions(-) diff --git a/src/servers/sapphire_zone/Actor/Actor.cpp b/src/servers/sapphire_zone/Actor/Actor.cpp index a874b71c..45b076a6 100644 --- a/src/servers/sapphire_zone/Actor/Actor.cpp +++ b/src/servers/sapphire_zone/Actor/Actor.cpp @@ -538,38 +538,6 @@ void Core::Entity::Actor::removeFromInRange() } -void Core::Entity::Actor::checkInRangeActors() -{ - if( hasInRangeActor() ) - { - Entity::ActorPtr pCurAct; - - float fRange = 70.0f; - for( auto iter = m_inRangeActors.begin(); iter != m_inRangeActors.end();) - { - pCurAct = *iter; - auto iter2 = iter++; - - float distance = Math::Util::distance( pCurAct->getPos().x, pCurAct->getPos().y, pCurAct->getPos().z, - getPos().x, getPos().y, getPos().z ); - - if( fRange > 0.0f && distance > fRange ) - { - pCurAct->removeInRangeActor( *this ); - - if( getCurrentZone() != pCurAct->getCurrentZone() ) - return; - - removeInRangeActor( **iter2 ); - - // @TODO FIXME! - // this break is more or less a hack, iteration will break otherwise after removing - break; - } - } - } -} - /*! Clear the whole in range set, this does no cleanup */ void Core::Entity::Actor::clearInRangeSet() { diff --git a/src/servers/sapphire_zone/Actor/Actor.h b/src/servers/sapphire_zone/Actor/Actor.h index e65d1b0a..cb2142af 100644 --- a/src/servers/sapphire_zone/Actor/Actor.h +++ b/src/servers/sapphire_zone/Actor/Actor.h @@ -271,8 +271,6 @@ public: // return true if there is at least one actor in the in range set bool hasInRangeActor() const; - void checkInRangeActors(); - void removeFromInRange(); // clear the whole in range set, this does no cleanup diff --git a/src/servers/sapphire_zone/Zone/Zone.cpp b/src/servers/sapphire_zone/Zone/Zone.cpp index 30d7e399..c930f3da 100644 --- a/src/servers/sapphire_zone/Zone/Zone.cpp +++ b/src/servers/sapphire_zone/Zone/Zone.cpp @@ -631,7 +631,7 @@ void Core::Zone::updateActorPosition( Entity::Actor &actor ) if( actor.getCurrentZone() != shared_from_this() ) return; - actor.checkInRangeActors(); + //actor.checkInRangeActors(); uint32_t cellX = getPosX( actor.getPos().x ); uint32_t cellY = getPosY( actor.getPos().z ); @@ -712,19 +712,18 @@ void Core::Zone::updateInRangeSet( Entity::ActorPtr pActor, Cell* pCell ) pCurAct = *iter; ++iter; - if( !pCurAct ) + if( !pCurAct || pCurAct == pActor ) continue; float distance = Math::Util::distance( pCurAct->getPos().x, pCurAct->getPos().y, pCurAct->getPos().z, pActor->getPos().x, pActor->getPos().y, pActor->getPos().z ); - // Add if we are not ourself and range == 0 or distance is withing range. - if( pCurAct != pActor && ( fRange == 0.0f || distance <= fRange ) ) - { + bool isInRange = ( fRange == 0.0f || distance <= fRange ); + bool isInRangeSet = pActor->isInRangeSet( pCurAct ); - if( pActor->isInRangeSet( pCurAct ) ) - // Actor already in range set, skip - continue; + // Add if we are not ourself and range == 0 or distance is withing range. + if( isInRange && !isInRangeSet ) + { if( pActor->isPlayer() ) { @@ -769,6 +768,15 @@ void Core::Zone::updateInRangeSet( Entity::ActorPtr pActor, Cell* pCell ) pCurAct->addInRangeActor( pActor ); } } + else if( !isInRange && isInRangeSet ) + { + pCurAct->removeInRangeActor( *pActor ); + + if( pActor->getCurrentZone() != pCurAct->getCurrentZone() ) + continue; + + pActor->removeInRangeActor( *pCurAct ); + } } } From 7d916f7d86684303306952338f867ca122b818fb Mon Sep 17 00:00:00 2001 From: Mordred Date: Sun, 18 Feb 2018 23:48:51 +0100 Subject: [PATCH 11/69] Changeing base access type of actors to gameobject --- .../sapphire_zone/Action/ActionCollision.cpp | 23 +-- .../sapphire_zone/Action/ActionCollision.h | 2 +- src/servers/sapphire_zone/Actor/Actor.cpp | 131 +----------------- src/servers/sapphire_zone/Actor/Actor.h | 26 ---- src/servers/sapphire_zone/Actor/BattleNpc.cpp | 8 +- .../sapphire_zone/Actor/GameObject.cpp | 128 +++++++++++++++++ src/servers/sapphire_zone/Actor/GameObject.h | 26 ++++ src/servers/sapphire_zone/Actor/Player.cpp | 15 +- .../Network/Handlers/GMCommandHandlers.cpp | 12 +- .../Network/Handlers/PacketHandlers.cpp | 2 +- src/servers/sapphire_zone/Zone/Zone.cpp | 16 +-- 11 files changed, 199 insertions(+), 190 deletions(-) diff --git a/src/servers/sapphire_zone/Action/ActionCollision.cpp b/src/servers/sapphire_zone/Action/ActionCollision.cpp index a66d234c..60948fcf 100644 --- a/src/servers/sapphire_zone/Action/ActionCollision.cpp +++ b/src/servers/sapphire_zone/Action/ActionCollision.cpp @@ -2,6 +2,7 @@ #include #include "ActionCollision.h" +#include "Actor/GameObject.h" #include "Actor/Actor.h" #include "Actor/Player.h" @@ -51,7 +52,7 @@ bool ActionCollision::isActorApplicable( Actor& actor, TargetFilter targetFilter } std::set< Core::Entity::ActorPtr > ActionCollision::getActorsHitFromAction( FFXIVARR_POSITION3 aoePosition, - std::set< ActorPtr > actorsInRange, + std::set< GameObjectPtr > gameObjectsInRange, boost::shared_ptr< Core::Data::Action > actionInfo, TargetFilter targetFilter ) { @@ -64,52 +65,52 @@ std::set< Core::Entity::ActorPtr > ActionCollision::getActorsHitFromAction( FFXI { // This is actually needed. There is "splash damage" in actions marked as single target. // Notice how we're using aoe_width. How collision works for SingleTarget is unknown as of now. - for( auto pActor : actorsInRange ) + for( auto pActor : gameObjectsInRange ) { // Make sure actor exists. If it doesn't we done goofed. assert( pActor ); // Don't bother wasting on collision if actor doesn't apply for it - if ( !isActorApplicable( *pActor, targetFilter ) ) + if ( !isActorApplicable( *pActor->getAsActor(), targetFilter ) ) continue; // Test our collision from actor with the area generated by the action from the AoE data if ( radiusCollision( pActor->getPos(), aoePosition, actionInfo->effectRange ) ) { // Add it to the actors collided with the area - actorsCollided.insert( pActor ); + //actorsCollided.insert( pActor ); } } break; } case ActionCollisionType::Circle: { - for( auto pActor : actorsInRange ) + for( auto pActor : gameObjectsInRange ) { assert( pActor ); - if ( !isActorApplicable( *pActor, targetFilter ) ) + if ( !isActorApplicable( *pActor->getAsActor(), targetFilter ) ) continue; - if ( radiusCollision( pActor->getPos(), aoePosition, actionInfo->effectRange ) ) - actorsCollided.insert( pActor ); + //if ( radiusCollision( pActor->getPos(), aoePosition, actionInfo->effectRange ) ) + //actorsCollided.insert( pActor ); } break; } case ActionCollisionType::Box: { - for( auto pActor : actorsInRange ) + for( auto pActor : gameObjectsInRange ) { assert( pActor ); - if ( !isActorApplicable( *pActor, targetFilter ) ) + if ( !isActorApplicable( *pActor->getAsActor(), targetFilter ) ) continue; if ( boxCollision( pActor->getPos(), aoePosition, actionInfo->xAxisModifier, actionInfo->effectRange ) ) { // todo: does this actually work? - actorsCollided.insert( pActor ); + //actorsCollided.insert( pActor ); } } break; diff --git a/src/servers/sapphire_zone/Action/ActionCollision.h b/src/servers/sapphire_zone/Action/ActionCollision.h index 0c0da597..47684448 100644 --- a/src/servers/sapphire_zone/Action/ActionCollision.h +++ b/src/servers/sapphire_zone/Action/ActionCollision.h @@ -25,7 +25,7 @@ namespace Entity { static bool isActorApplicable( Actor& actor, TargetFilter targetFilter ); static std::set< ActorPtr > getActorsHitFromAction( Common::FFXIVARR_POSITION3 aoePosition, - std::set< ActorPtr > actorsInRange, + std::set< GameObjectPtr > gameObjectsInRange, boost::shared_ptr< Data::Action > actionInfo, TargetFilter targetFilter ); diff --git a/src/servers/sapphire_zone/Actor/Actor.cpp b/src/servers/sapphire_zone/Actor/Actor.cpp index 45b076a6..8b7f02ea 100644 --- a/src/servers/sapphire_zone/Actor/Actor.cpp +++ b/src/servers/sapphire_zone/Actor/Actor.cpp @@ -52,17 +52,6 @@ std::string Core::Entity::Actor::getName() const return std::string( m_name ); } -/*! \return list of actors currently in range */ -std::set< Core::Entity::ActorPtr > Core::Entity::Actor::getInRangeActors( bool includeSelf ) -{ - auto tempInRange = m_inRangeActors; - - if( includeSelf ) - tempInRange.insert( getAsActor() ); - - return tempInRange; - } - /*! \return current stance of the actors */ Core::Entity::Actor::Stance Core::Entity::Actor::getStance() const { @@ -396,48 +385,6 @@ void Core::Entity::Actor::setCurrentAction( Core::Action::ActionPtr pAction ) m_pCurrentAction = pAction; } -/*! -check if a given actor is in the actors in range set - -\param ActorPtr to be checked for -\return true if the actor was found -*/ -bool Core::Entity::Actor::isInRangeSet( ActorPtr pActor ) const -{ - return !( m_inRangeActors.find( pActor ) == m_inRangeActors.end() ); -} - -/*! \return ActorPtr of the closest actor in range, if none, nullptr */ -Core::Entity::ActorPtr Core::Entity::Actor::getClosestActor() -{ - if( m_inRangeActors.empty() ) - // no actors in range, don't bother - return nullptr; - - ActorPtr tmpActor = nullptr; - - // arbitrary high number - float minDistance = 10000; - - for( const auto& pCurAct : m_inRangeActors ) - { - float distance = Math::Util::distance( getPos().x, - getPos().y, - getPos().z, - pCurAct->getPos().x, - pCurAct->getPos().y, - pCurAct->getPos().z ); - - if( distance < minDistance ) - { - minDistance = distance; - tmpActor = pCurAct; - } - } - - return tmpActor; -} - /*! Send a packet to all players in range, potentially to self if set and is player @@ -471,80 +418,6 @@ void Core::Entity::Actor::sendToInRangeSet( Network::Packets::GamePacketPtr pPac } } -/*! -Add a given actor to the fitting in range set according to type -but also to the global actor map - -\param ActorPtr to add -*/ -void Core::Entity::Actor::addInRangeActor( ActorPtr pActor ) -{ - - // if this is null, something went wrong - assert( pActor ); - - // add actor to in range set - m_inRangeActors.insert( pActor ); - - if( pActor->isPlayer() ) - { - auto pPlayer = pActor->getAsPlayer(); - - // if actor is a player, add it to the in range player set - m_inRangePlayers.insert( pPlayer ); - } -} - -/*! -Remove a given actor from the matching in range set according to type -but also to the global actor map - -\param ActorPtr to remove -*/ -void Core::Entity::Actor::removeInRangeActor( Actor& actor ) -{ - // call virtual event - onRemoveInRangeActor( actor ); - - // remove actor from in range actor set - m_inRangeActors.erase( actor.getAsActor() ); - - // if actor is a player, despawn ourself for him - // TODO: move to virtual onRemove? - if( isPlayer() ) - actor.despawn( getAsPlayer() ); - - if( actor.isPlayer() ) - m_inRangePlayers.erase( actor.getAsPlayer() ); -} - -/*! \return true if there is at least one actor in the in range set */ -bool Core::Entity::Actor::hasInRangeActor() const -{ - return ( m_inRangeActors.size() > 0 ); -} - -void Core::Entity::Actor::removeFromInRange() -{ - if( !hasInRangeActor() ) - return; - - Entity::ActorPtr pCurAct; - - for( auto& pCurAct : m_inRangeActors ) - { - pCurAct->removeInRangeActor( *this ); - } - -} - -/*! Clear the whole in range set, this does no cleanup */ -void Core::Entity::Actor::clearInRangeSet() -{ - m_inRangeActors.clear(); - m_inRangePlayers.clear(); -} - /*! \return ZonePtr to the current zone, nullptr if not set */ Core::ZonePtr Core::Entity::Actor::getCurrentZone() const { @@ -682,7 +555,7 @@ void Core::Entity::Actor::handleScriptSkill( uint32_t type, uint16_t actionId, u else { - auto actorsCollided = ActionCollision::getActorsHitFromAction( target.getPos(), getInRangeActors( true ), + auto actorsCollided = ActionCollision::getActorsHitFromAction( target.getPos(), getInRangeGameObjects( true ), actionInfoPtr, TargetFilter::Enemies ); for( const auto& pHitActor : actorsCollided ) @@ -734,7 +607,7 @@ void Core::Entity::Actor::handleScriptSkill( uint32_t type, uint16_t actionId, u // todo: get proper packets: the following was just kind of thrown together from what we know. // atm buggy (packets look "delayed" from client) - auto actorsCollided = ActionCollision::getActorsHitFromAction( target.getPos(), getInRangeActors( true ), + auto actorsCollided = ActionCollision::getActorsHitFromAction( target.getPos(), getInRangeGameObjects( true ), actionInfoPtr, TargetFilter::Allies ); for( auto pHitActor : actorsCollided ) diff --git a/src/servers/sapphire_zone/Actor/Actor.h b/src/servers/sapphire_zone/Actor/Actor.h index cb2142af..3948b547 100644 --- a/src/servers/sapphire_zone/Actor/Actor.h +++ b/src/servers/sapphire_zone/Actor/Actor.h @@ -139,9 +139,6 @@ protected: std::vector< std::pair< uint8_t, uint32_t> > m_statusEffectList; std::map< uint8_t, StatusEffect::StatusEffectPtr > m_statusEffectMap; - std::set< ActorPtr > m_inRangeActors; - std::set< PlayerPtr > m_inRangePlayers; - public: Actor( ObjKind type ); @@ -182,8 +179,6 @@ public: std::string getName() const; - std::set< ActorPtr > getInRangeActors( bool includeSelf = false ); - bool face( const Common::FFXIVARR_POSITION3& p ); Stance getStance() const; @@ -233,8 +228,6 @@ public: virtual void autoAttack( ActorPtr pTarget ); - virtual void onRemoveInRangeActor( Actor& pActor ) {} - virtual void onDeath() {}; virtual void onDamageTaken( Actor& pSource ) {}; virtual void onActionHostile( Actor& source ) {}; @@ -255,27 +248,8 @@ public: ///// IN RANGE LOGIC ///// - // check if another actor is in the actors in range set - bool isInRangeSet( ActorPtr pActor ) const; - - ActorPtr getClosestActor(); - void sendToInRangeSet( Network::Packets::GamePacketPtr pPacket, bool bToSelf = false ); - // add an actor to in range set - void addInRangeActor( ActorPtr pActor ); - - // remove an actor from the in range set - void removeInRangeActor( Actor& pActor ); - - // return true if there is at least one actor in the in range set - bool hasInRangeActor() const; - - void removeFromInRange(); - - // clear the whole in range set, this does no cleanup - virtual void clearInRangeSet(); - ZonePtr getCurrentZone() const; void setCurrentZone( ZonePtr currZone ); diff --git a/src/servers/sapphire_zone/Actor/BattleNpc.cpp b/src/servers/sapphire_zone/Actor/BattleNpc.cpp index 5b43728b..29cdf7b3 100644 --- a/src/servers/sapphire_zone/Actor/BattleNpc.cpp +++ b/src/servers/sapphire_zone/Actor/BattleNpc.cpp @@ -501,9 +501,13 @@ void Core::Entity::BattleNpc::update( int64_t currTime ) case MODE_IDLE: { - ActorPtr pClosestActor = getClosestActor(); + // this is bad, it should be getClosesPlayer + GameObjectPtr pClosestActor = getClosestGameObject(); - if( pClosestActor && pClosestActor->isAlive() ) + if( !pClosestActor->isPlayer() ) + break; + + if( pClosestActor && pClosestActor->getAsPlayer()->isAlive() ) { distance = Math::Util::distance( getPos().x, getPos().y, getPos().z, pClosestActor->getPos().x, diff --git a/src/servers/sapphire_zone/Actor/GameObject.cpp b/src/servers/sapphire_zone/Actor/GameObject.cpp index 16c042ab..475abb37 100644 --- a/src/servers/sapphire_zone/Actor/GameObject.cpp +++ b/src/servers/sapphire_zone/Actor/GameObject.cpp @@ -1,5 +1,8 @@ #include "GameObject.h" +#include +#include + #include "Player.h" #include "Actor.h" #include "BattleNpc.h" @@ -63,6 +66,131 @@ bool Core::Entity::GameObject::isEventNpc() const return m_objKind == ObjKind::EventNpc; } +/*! +Add a given actor to the fitting in range set according to type +but also to the global actor map + +\param ActorPtr to add +*/ +void Core::Entity::GameObject::addInRangeGameObject( GameObjectPtr pGameObject ) +{ + + // if this is null, something went wrong + assert( pGameObject ); + + // add actor to in range set + m_inRangeGameObjects.insert( { pGameObject } ); + + if( pGameObject->isPlayer() ) + { + auto pPlayer = pGameObject->getAsPlayer(); + + // if actor is a player, add it to the in range player set + m_inRangePlayers.insert( pGameObject->getAsPlayer() ); + } +} + +/*! +Remove a given actor from the matching in range set according to type +but also to the global actor map + +\param ActorPtr to remove +*/ +void Core::Entity::GameObject::removeInRangeGameObject( GameObject& gameObject ) +{ + // call virtual event + onRemoveInRangeGameObject( gameObject ); + + // remove actor from in range actor set + m_inRangeGameObjects.erase( gameObject.shared_from_this() ); + + // if actor is a player, despawn ourself for him + // TODO: move to virtual onRemove? + if( isPlayer() ) + gameObject.despawn( getAsPlayer() ); + + if( gameObject.isPlayer() ) + m_inRangePlayers.erase( gameObject.getAsPlayer() ); +} + +/*! \return true if there is at least one actor in the in range set */ +bool Core::Entity::GameObject::hasInRangeGameObject() const +{ + return ( m_inRangeGameObjects.size() > 0 ); +} + +void Core::Entity::GameObject::removeFromInRange() +{ + if( !hasInRangeGameObject() ) + return; + + for( auto& pCurAct : m_inRangeGameObjects ) + { + pCurAct->removeInRangeGameObject( *this ); + } + +} + +/*! Clear the whole in range set, this does no cleanup */ +void Core::Entity::GameObject::clearInRangeSet() +{ + m_inRangeGameObjects.clear(); + m_inRangePlayers.clear(); +} + +/*! \return list of actors currently in range */ +std::set< Core::Entity::GameObjectPtr > Core::Entity::GameObject::getInRangeGameObjects( bool includeSelf ) +{ + auto tempInRange = m_inRangeGameObjects; + + if( includeSelf ) + tempInRange.insert( { shared_from_this() } ); + + return tempInRange; +} + +/*! +check if a given actor is in the actors in range set + +\param ActorPtr to be checked for +\return true if the actor was found +*/ +bool Core::Entity::GameObject::isInRangeSet( GameObjectPtr pGameObject ) const +{ + return !( m_inRangeGameObjects.find( pGameObject ) == m_inRangeGameObjects.end() ); +} + +/*! \return ActorPtr of the closest actor in range, if none, nullptr */ +Core::Entity::GameObjectPtr Core::Entity::GameObject::getClosestGameObject() +{ + if( m_inRangeGameObjects.empty() ) + // no actors in range, don't bother + return nullptr; + + GameObjectPtr tmpActor = nullptr; + + // arbitrary high number + float minDistance = 10000; + + for( const auto& pCurAct : m_inRangeGameObjects ) + { + float distance = Math::Util::distance( getPos().x, + getPos().y, + getPos().z, + pCurAct->getPos().x, + pCurAct->getPos().y, + pCurAct->getPos().z ); + + if( distance < minDistance ) + { + minDistance = distance; + tmpActor = pCurAct; + } + } + + return tmpActor; +} + /*! \return pointer to this instance as ActorPtr */ Core::Entity::ActorPtr Core::Entity::GameObject::getAsActor() { diff --git a/src/servers/sapphire_zone/Actor/GameObject.h b/src/servers/sapphire_zone/Actor/GameObject.h index d1f70b3b..cc4e7eb2 100644 --- a/src/servers/sapphire_zone/Actor/GameObject.h +++ b/src/servers/sapphire_zone/Actor/GameObject.h @@ -49,6 +49,9 @@ namespace Entity { /*! Type of the actor */ ObjKind m_objKind; + std::set< GameObjectPtr > m_inRangeGameObjects; + std::set< PlayerPtr > m_inRangePlayers; + public: explicit GameObject( ObjKind type ); virtual ~GameObject() {}; @@ -56,6 +59,29 @@ namespace Entity { virtual void spawn( PlayerPtr pTarget ) {} virtual void despawn( PlayerPtr pTarget ) {} + virtual void onRemoveInRangeGameObject( GameObject &pGameObject ) {} + + // add an actor to in range set + void addInRangeGameObject( GameObjectPtr pGameObject ); + + // remove an actor from the in range set + void removeInRangeGameObject( GameObject& pGameObject ); + + // return true if there is at least one actor in the in range set + bool hasInRangeGameObject() const; + + void removeFromInRange(); + + // clear the whole in range set, this does no cleanup + virtual void clearInRangeSet(); + + std::set< GameObjectPtr > getInRangeGameObjects( bool includeSelf = false ); + + // check if another actor is in the actors in range set + bool isInRangeSet( GameObjectPtr pGameObject ) const; + + GameObjectPtr getClosestGameObject(); + uint32_t getId() const; ObjKind getObjKind() const; diff --git a/src/servers/sapphire_zone/Actor/Player.cpp b/src/servers/sapphire_zone/Actor/Player.cpp index 4c7c3df8..8b6762d3 100644 --- a/src/servers/sapphire_zone/Actor/Player.cpp +++ b/src/servers/sapphire_zone/Actor/Player.cpp @@ -831,14 +831,14 @@ void Core::Entity::Player::despawn( Entity::PlayerPtr pTarget ) Core::Entity::ActorPtr Core::Entity::Player::lookupTargetById( uint64_t targetId ) { - ActorPtr targetActor; - auto inRange = getInRangeActors( true ); + GameObjectPtr targetActor; + auto inRange = getInRangeGameObjects(true); for( auto actor : inRange ) { if( actor->getId() == targetId ) targetActor = actor; } - return targetActor; + return targetActor->getAsActor(); } void Core::Entity::Player::setLastPing( uint32_t ping ) @@ -1005,9 +1005,12 @@ void Core::Entity::Player::update( int64_t currTime ) auto mainWeap = m_pInventory->getItemAt( Inventory::GearSet0, Inventory::EquipSlot::MainHand ); // @TODO i dislike this, iterating over all in range actors when you already know the id of the actor you need... - for( auto actor : m_inRangeActors ) + for( auto actor : m_inRangeGameObjects ) { - if( actor->getId() == m_targetId && actor->isAlive() && mainWeap ) + if( actor->getId() != m_targetId || !actor->isBattleNpc() ) + continue; + + if( actor->getAsBattleNpc()->isAlive() && mainWeap ) { // default autoattack range // TODO make this dependant on bnpc size @@ -1027,7 +1030,7 @@ void Core::Entity::Player::update( int64_t currTime ) if( ( currTime - m_lastAttack ) > mainWeap->getDelay() ) { m_lastAttack = currTime; - autoAttack( actor ); + autoAttack( actor->getAsBattleNpc() ); } } diff --git a/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp b/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp index 865ffdc1..74d9e453 100644 --- a/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp @@ -113,11 +113,11 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac } else { - auto inRange = player.getInRangeActors(); + auto inRange = player.getInRangeGameObjects(); for( auto actor : inRange ) { if( actor->getId() == param3 ) - targetActor = actor; + targetActor = actor->getAsActor(); } } @@ -138,7 +138,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac targetPlayer->setLookAt( CharaLook::Race, param1 ); player.sendNotice( "Race for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) ); targetPlayer->spawn( targetPlayer ); - auto inRange = targetPlayer->getInRangeActors(); + auto inRange = targetPlayer->getInRangeGameObjects(); for( auto actor : inRange ) { targetPlayer->despawn( actor->getAsPlayer() ); @@ -151,7 +151,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac targetPlayer->setLookAt( CharaLook::Tribe, param1 ); player.sendNotice( "Tribe for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) ); targetPlayer->spawn( targetPlayer ); - auto inRange = targetPlayer->getInRangeActors(); + auto inRange = targetPlayer->getInRangeGameObjects(); for( auto actor : inRange ) { targetPlayer->despawn( actor->getAsPlayer() ); @@ -164,7 +164,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac targetPlayer->setLookAt( CharaLook::Gender, param1 ); player.sendNotice( "Sex for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) ); targetPlayer->spawn( targetPlayer ); - auto inRange = targetActor->getInRangeActors(); + auto inRange = targetActor->getInRangeGameObjects(); for( auto actor : inRange ) { targetPlayer->despawn( actor->getAsPlayer() ); @@ -439,7 +439,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac case GmCommand::Jump: { - auto inRange = player.getInRangeActors(); + auto inRange = player.getInRangeGameObjects(); player.changePosition( targetActor->getPos().x, targetActor->getPos().y, targetActor->getPos().z, targetActor->getRotation() ); diff --git a/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp b/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp index c6232a22..55488fa5 100644 --- a/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp @@ -190,7 +190,7 @@ void Core::Network::GameConnection::updatePositionHandler( const Packets::GamePa player.getCurrentAction()->setInterrupted(); // if no one is in range, don't bother trying to send a position update - if( !player.hasInRangeActor() ) + if( !player.hasInRangeGameObject() ) return; uint8_t unk = inPacket.getValAt< uint8_t >( 0x29 ); diff --git a/src/servers/sapphire_zone/Zone/Zone.cpp b/src/servers/sapphire_zone/Zone/Zone.cpp index c930f3da..e0ecad27 100644 --- a/src/servers/sapphire_zone/Zone/Zone.cpp +++ b/src/servers/sapphire_zone/Zone/Zone.cpp @@ -737,8 +737,8 @@ void Core::Zone::updateInRangeSet( Entity::ActorPtr pActor, Cell* pCell ) if( count > 12 ) break; - pActor->addInRangeActor( pCurAct ); - pCurAct->addInRangeActor( pActor ); + pActor->addInRangeGameObject( pCurAct ); + pCurAct->addInRangeGameObject( pActor ); // spawn the actor for the player pCurAct->spawn( pOwnPlayer ); @@ -758,24 +758,24 @@ void Core::Zone::updateInRangeSet( Entity::ActorPtr pActor, Cell* pCell ) if( pPlayer->isLoadingComplete() ) { pActor->spawn( pPlayer ); - pCurAct->addInRangeActor( pActor ); - pActor->addInRangeActor( pCurAct ); + pCurAct->addInRangeGameObject( pActor ); + pActor->addInRangeGameObject( pCurAct ); } } else { - pActor->addInRangeActor( pCurAct ); - pCurAct->addInRangeActor( pActor ); + pActor->addInRangeGameObject( pCurAct ); + pCurAct->addInRangeGameObject( pActor ); } } else if( !isInRange && isInRangeSet ) { - pCurAct->removeInRangeActor( *pActor ); + pCurAct->removeInRangeGameObject( *pActor ); if( pActor->getCurrentZone() != pCurAct->getCurrentZone() ) continue; - pActor->removeInRangeActor( *pCurAct ); + pActor->removeInRangeGameObject( *pCurAct ); } } } From ba511a23e22c0963263f1053612f23380acf8b4d Mon Sep 17 00:00:00 2001 From: Mordred Date: Mon, 19 Feb 2018 22:00:32 +0100 Subject: [PATCH 12/69] Revert "Changeing base access type of actors to gameobject" This reverts commit 7d916f7 --- .../sapphire_zone/Action/ActionCollision.cpp | 23 ++- .../sapphire_zone/Action/ActionCollision.h | 2 +- src/servers/sapphire_zone/Actor/Actor.cpp | 131 +++++++++++++++++- src/servers/sapphire_zone/Actor/Actor.h | 26 ++++ src/servers/sapphire_zone/Actor/BattleNpc.cpp | 8 +- .../sapphire_zone/Actor/GameObject.cpp | 128 ----------------- src/servers/sapphire_zone/Actor/GameObject.h | 26 ---- src/servers/sapphire_zone/Actor/Player.cpp | 15 +- .../Network/Handlers/GMCommandHandlers.cpp | 12 +- .../Network/Handlers/PacketHandlers.cpp | 2 +- src/servers/sapphire_zone/Zone/Zone.cpp | 16 +-- 11 files changed, 190 insertions(+), 199 deletions(-) diff --git a/src/servers/sapphire_zone/Action/ActionCollision.cpp b/src/servers/sapphire_zone/Action/ActionCollision.cpp index 60948fcf..a66d234c 100644 --- a/src/servers/sapphire_zone/Action/ActionCollision.cpp +++ b/src/servers/sapphire_zone/Action/ActionCollision.cpp @@ -2,7 +2,6 @@ #include #include "ActionCollision.h" -#include "Actor/GameObject.h" #include "Actor/Actor.h" #include "Actor/Player.h" @@ -52,7 +51,7 @@ bool ActionCollision::isActorApplicable( Actor& actor, TargetFilter targetFilter } std::set< Core::Entity::ActorPtr > ActionCollision::getActorsHitFromAction( FFXIVARR_POSITION3 aoePosition, - std::set< GameObjectPtr > gameObjectsInRange, + std::set< ActorPtr > actorsInRange, boost::shared_ptr< Core::Data::Action > actionInfo, TargetFilter targetFilter ) { @@ -65,52 +64,52 @@ std::set< Core::Entity::ActorPtr > ActionCollision::getActorsHitFromAction( FFXI { // This is actually needed. There is "splash damage" in actions marked as single target. // Notice how we're using aoe_width. How collision works for SingleTarget is unknown as of now. - for( auto pActor : gameObjectsInRange ) + for( auto pActor : actorsInRange ) { // Make sure actor exists. If it doesn't we done goofed. assert( pActor ); // Don't bother wasting on collision if actor doesn't apply for it - if ( !isActorApplicable( *pActor->getAsActor(), targetFilter ) ) + if ( !isActorApplicable( *pActor, targetFilter ) ) continue; // Test our collision from actor with the area generated by the action from the AoE data if ( radiusCollision( pActor->getPos(), aoePosition, actionInfo->effectRange ) ) { // Add it to the actors collided with the area - //actorsCollided.insert( pActor ); + actorsCollided.insert( pActor ); } } break; } case ActionCollisionType::Circle: { - for( auto pActor : gameObjectsInRange ) + for( auto pActor : actorsInRange ) { assert( pActor ); - if ( !isActorApplicable( *pActor->getAsActor(), targetFilter ) ) + if ( !isActorApplicable( *pActor, targetFilter ) ) continue; - //if ( radiusCollision( pActor->getPos(), aoePosition, actionInfo->effectRange ) ) - //actorsCollided.insert( pActor ); + if ( radiusCollision( pActor->getPos(), aoePosition, actionInfo->effectRange ) ) + actorsCollided.insert( pActor ); } break; } case ActionCollisionType::Box: { - for( auto pActor : gameObjectsInRange ) + for( auto pActor : actorsInRange ) { assert( pActor ); - if ( !isActorApplicable( *pActor->getAsActor(), targetFilter ) ) + if ( !isActorApplicable( *pActor, targetFilter ) ) continue; if ( boxCollision( pActor->getPos(), aoePosition, actionInfo->xAxisModifier, actionInfo->effectRange ) ) { // todo: does this actually work? - //actorsCollided.insert( pActor ); + actorsCollided.insert( pActor ); } } break; diff --git a/src/servers/sapphire_zone/Action/ActionCollision.h b/src/servers/sapphire_zone/Action/ActionCollision.h index 47684448..0c0da597 100644 --- a/src/servers/sapphire_zone/Action/ActionCollision.h +++ b/src/servers/sapphire_zone/Action/ActionCollision.h @@ -25,7 +25,7 @@ namespace Entity { static bool isActorApplicable( Actor& actor, TargetFilter targetFilter ); static std::set< ActorPtr > getActorsHitFromAction( Common::FFXIVARR_POSITION3 aoePosition, - std::set< GameObjectPtr > gameObjectsInRange, + std::set< ActorPtr > actorsInRange, boost::shared_ptr< Data::Action > actionInfo, TargetFilter targetFilter ); diff --git a/src/servers/sapphire_zone/Actor/Actor.cpp b/src/servers/sapphire_zone/Actor/Actor.cpp index 8b7f02ea..45b076a6 100644 --- a/src/servers/sapphire_zone/Actor/Actor.cpp +++ b/src/servers/sapphire_zone/Actor/Actor.cpp @@ -52,6 +52,17 @@ std::string Core::Entity::Actor::getName() const return std::string( m_name ); } +/*! \return list of actors currently in range */ +std::set< Core::Entity::ActorPtr > Core::Entity::Actor::getInRangeActors( bool includeSelf ) +{ + auto tempInRange = m_inRangeActors; + + if( includeSelf ) + tempInRange.insert( getAsActor() ); + + return tempInRange; + } + /*! \return current stance of the actors */ Core::Entity::Actor::Stance Core::Entity::Actor::getStance() const { @@ -385,6 +396,48 @@ void Core::Entity::Actor::setCurrentAction( Core::Action::ActionPtr pAction ) m_pCurrentAction = pAction; } +/*! +check if a given actor is in the actors in range set + +\param ActorPtr to be checked for +\return true if the actor was found +*/ +bool Core::Entity::Actor::isInRangeSet( ActorPtr pActor ) const +{ + return !( m_inRangeActors.find( pActor ) == m_inRangeActors.end() ); +} + +/*! \return ActorPtr of the closest actor in range, if none, nullptr */ +Core::Entity::ActorPtr Core::Entity::Actor::getClosestActor() +{ + if( m_inRangeActors.empty() ) + // no actors in range, don't bother + return nullptr; + + ActorPtr tmpActor = nullptr; + + // arbitrary high number + float minDistance = 10000; + + for( const auto& pCurAct : m_inRangeActors ) + { + float distance = Math::Util::distance( getPos().x, + getPos().y, + getPos().z, + pCurAct->getPos().x, + pCurAct->getPos().y, + pCurAct->getPos().z ); + + if( distance < minDistance ) + { + minDistance = distance; + tmpActor = pCurAct; + } + } + + return tmpActor; +} + /*! Send a packet to all players in range, potentially to self if set and is player @@ -418,6 +471,80 @@ void Core::Entity::Actor::sendToInRangeSet( Network::Packets::GamePacketPtr pPac } } +/*! +Add a given actor to the fitting in range set according to type +but also to the global actor map + +\param ActorPtr to add +*/ +void Core::Entity::Actor::addInRangeActor( ActorPtr pActor ) +{ + + // if this is null, something went wrong + assert( pActor ); + + // add actor to in range set + m_inRangeActors.insert( pActor ); + + if( pActor->isPlayer() ) + { + auto pPlayer = pActor->getAsPlayer(); + + // if actor is a player, add it to the in range player set + m_inRangePlayers.insert( pPlayer ); + } +} + +/*! +Remove a given actor from the matching in range set according to type +but also to the global actor map + +\param ActorPtr to remove +*/ +void Core::Entity::Actor::removeInRangeActor( Actor& actor ) +{ + // call virtual event + onRemoveInRangeActor( actor ); + + // remove actor from in range actor set + m_inRangeActors.erase( actor.getAsActor() ); + + // if actor is a player, despawn ourself for him + // TODO: move to virtual onRemove? + if( isPlayer() ) + actor.despawn( getAsPlayer() ); + + if( actor.isPlayer() ) + m_inRangePlayers.erase( actor.getAsPlayer() ); +} + +/*! \return true if there is at least one actor in the in range set */ +bool Core::Entity::Actor::hasInRangeActor() const +{ + return ( m_inRangeActors.size() > 0 ); +} + +void Core::Entity::Actor::removeFromInRange() +{ + if( !hasInRangeActor() ) + return; + + Entity::ActorPtr pCurAct; + + for( auto& pCurAct : m_inRangeActors ) + { + pCurAct->removeInRangeActor( *this ); + } + +} + +/*! Clear the whole in range set, this does no cleanup */ +void Core::Entity::Actor::clearInRangeSet() +{ + m_inRangeActors.clear(); + m_inRangePlayers.clear(); +} + /*! \return ZonePtr to the current zone, nullptr if not set */ Core::ZonePtr Core::Entity::Actor::getCurrentZone() const { @@ -555,7 +682,7 @@ void Core::Entity::Actor::handleScriptSkill( uint32_t type, uint16_t actionId, u else { - auto actorsCollided = ActionCollision::getActorsHitFromAction( target.getPos(), getInRangeGameObjects( true ), + auto actorsCollided = ActionCollision::getActorsHitFromAction( target.getPos(), getInRangeActors( true ), actionInfoPtr, TargetFilter::Enemies ); for( const auto& pHitActor : actorsCollided ) @@ -607,7 +734,7 @@ void Core::Entity::Actor::handleScriptSkill( uint32_t type, uint16_t actionId, u // todo: get proper packets: the following was just kind of thrown together from what we know. // atm buggy (packets look "delayed" from client) - auto actorsCollided = ActionCollision::getActorsHitFromAction( target.getPos(), getInRangeGameObjects( true ), + auto actorsCollided = ActionCollision::getActorsHitFromAction( target.getPos(), getInRangeActors( true ), actionInfoPtr, TargetFilter::Allies ); for( auto pHitActor : actorsCollided ) diff --git a/src/servers/sapphire_zone/Actor/Actor.h b/src/servers/sapphire_zone/Actor/Actor.h index 3948b547..cb2142af 100644 --- a/src/servers/sapphire_zone/Actor/Actor.h +++ b/src/servers/sapphire_zone/Actor/Actor.h @@ -139,6 +139,9 @@ protected: std::vector< std::pair< uint8_t, uint32_t> > m_statusEffectList; std::map< uint8_t, StatusEffect::StatusEffectPtr > m_statusEffectMap; + std::set< ActorPtr > m_inRangeActors; + std::set< PlayerPtr > m_inRangePlayers; + public: Actor( ObjKind type ); @@ -179,6 +182,8 @@ public: std::string getName() const; + std::set< ActorPtr > getInRangeActors( bool includeSelf = false ); + bool face( const Common::FFXIVARR_POSITION3& p ); Stance getStance() const; @@ -228,6 +233,8 @@ public: virtual void autoAttack( ActorPtr pTarget ); + virtual void onRemoveInRangeActor( Actor& pActor ) {} + virtual void onDeath() {}; virtual void onDamageTaken( Actor& pSource ) {}; virtual void onActionHostile( Actor& source ) {}; @@ -248,8 +255,27 @@ public: ///// IN RANGE LOGIC ///// + // check if another actor is in the actors in range set + bool isInRangeSet( ActorPtr pActor ) const; + + ActorPtr getClosestActor(); + void sendToInRangeSet( Network::Packets::GamePacketPtr pPacket, bool bToSelf = false ); + // add an actor to in range set + void addInRangeActor( ActorPtr pActor ); + + // remove an actor from the in range set + void removeInRangeActor( Actor& pActor ); + + // return true if there is at least one actor in the in range set + bool hasInRangeActor() const; + + void removeFromInRange(); + + // clear the whole in range set, this does no cleanup + virtual void clearInRangeSet(); + ZonePtr getCurrentZone() const; void setCurrentZone( ZonePtr currZone ); diff --git a/src/servers/sapphire_zone/Actor/BattleNpc.cpp b/src/servers/sapphire_zone/Actor/BattleNpc.cpp index 29cdf7b3..5b43728b 100644 --- a/src/servers/sapphire_zone/Actor/BattleNpc.cpp +++ b/src/servers/sapphire_zone/Actor/BattleNpc.cpp @@ -501,13 +501,9 @@ void Core::Entity::BattleNpc::update( int64_t currTime ) case MODE_IDLE: { - // this is bad, it should be getClosesPlayer - GameObjectPtr pClosestActor = getClosestGameObject(); + ActorPtr pClosestActor = getClosestActor(); - if( !pClosestActor->isPlayer() ) - break; - - if( pClosestActor && pClosestActor->getAsPlayer()->isAlive() ) + if( pClosestActor && pClosestActor->isAlive() ) { distance = Math::Util::distance( getPos().x, getPos().y, getPos().z, pClosestActor->getPos().x, diff --git a/src/servers/sapphire_zone/Actor/GameObject.cpp b/src/servers/sapphire_zone/Actor/GameObject.cpp index 475abb37..16c042ab 100644 --- a/src/servers/sapphire_zone/Actor/GameObject.cpp +++ b/src/servers/sapphire_zone/Actor/GameObject.cpp @@ -1,8 +1,5 @@ #include "GameObject.h" -#include -#include - #include "Player.h" #include "Actor.h" #include "BattleNpc.h" @@ -66,131 +63,6 @@ bool Core::Entity::GameObject::isEventNpc() const return m_objKind == ObjKind::EventNpc; } -/*! -Add a given actor to the fitting in range set according to type -but also to the global actor map - -\param ActorPtr to add -*/ -void Core::Entity::GameObject::addInRangeGameObject( GameObjectPtr pGameObject ) -{ - - // if this is null, something went wrong - assert( pGameObject ); - - // add actor to in range set - m_inRangeGameObjects.insert( { pGameObject } ); - - if( pGameObject->isPlayer() ) - { - auto pPlayer = pGameObject->getAsPlayer(); - - // if actor is a player, add it to the in range player set - m_inRangePlayers.insert( pGameObject->getAsPlayer() ); - } -} - -/*! -Remove a given actor from the matching in range set according to type -but also to the global actor map - -\param ActorPtr to remove -*/ -void Core::Entity::GameObject::removeInRangeGameObject( GameObject& gameObject ) -{ - // call virtual event - onRemoveInRangeGameObject( gameObject ); - - // remove actor from in range actor set - m_inRangeGameObjects.erase( gameObject.shared_from_this() ); - - // if actor is a player, despawn ourself for him - // TODO: move to virtual onRemove? - if( isPlayer() ) - gameObject.despawn( getAsPlayer() ); - - if( gameObject.isPlayer() ) - m_inRangePlayers.erase( gameObject.getAsPlayer() ); -} - -/*! \return true if there is at least one actor in the in range set */ -bool Core::Entity::GameObject::hasInRangeGameObject() const -{ - return ( m_inRangeGameObjects.size() > 0 ); -} - -void Core::Entity::GameObject::removeFromInRange() -{ - if( !hasInRangeGameObject() ) - return; - - for( auto& pCurAct : m_inRangeGameObjects ) - { - pCurAct->removeInRangeGameObject( *this ); - } - -} - -/*! Clear the whole in range set, this does no cleanup */ -void Core::Entity::GameObject::clearInRangeSet() -{ - m_inRangeGameObjects.clear(); - m_inRangePlayers.clear(); -} - -/*! \return list of actors currently in range */ -std::set< Core::Entity::GameObjectPtr > Core::Entity::GameObject::getInRangeGameObjects( bool includeSelf ) -{ - auto tempInRange = m_inRangeGameObjects; - - if( includeSelf ) - tempInRange.insert( { shared_from_this() } ); - - return tempInRange; -} - -/*! -check if a given actor is in the actors in range set - -\param ActorPtr to be checked for -\return true if the actor was found -*/ -bool Core::Entity::GameObject::isInRangeSet( GameObjectPtr pGameObject ) const -{ - return !( m_inRangeGameObjects.find( pGameObject ) == m_inRangeGameObjects.end() ); -} - -/*! \return ActorPtr of the closest actor in range, if none, nullptr */ -Core::Entity::GameObjectPtr Core::Entity::GameObject::getClosestGameObject() -{ - if( m_inRangeGameObjects.empty() ) - // no actors in range, don't bother - return nullptr; - - GameObjectPtr tmpActor = nullptr; - - // arbitrary high number - float minDistance = 10000; - - for( const auto& pCurAct : m_inRangeGameObjects ) - { - float distance = Math::Util::distance( getPos().x, - getPos().y, - getPos().z, - pCurAct->getPos().x, - pCurAct->getPos().y, - pCurAct->getPos().z ); - - if( distance < minDistance ) - { - minDistance = distance; - tmpActor = pCurAct; - } - } - - return tmpActor; -} - /*! \return pointer to this instance as ActorPtr */ Core::Entity::ActorPtr Core::Entity::GameObject::getAsActor() { diff --git a/src/servers/sapphire_zone/Actor/GameObject.h b/src/servers/sapphire_zone/Actor/GameObject.h index cc4e7eb2..d1f70b3b 100644 --- a/src/servers/sapphire_zone/Actor/GameObject.h +++ b/src/servers/sapphire_zone/Actor/GameObject.h @@ -49,9 +49,6 @@ namespace Entity { /*! Type of the actor */ ObjKind m_objKind; - std::set< GameObjectPtr > m_inRangeGameObjects; - std::set< PlayerPtr > m_inRangePlayers; - public: explicit GameObject( ObjKind type ); virtual ~GameObject() {}; @@ -59,29 +56,6 @@ namespace Entity { virtual void spawn( PlayerPtr pTarget ) {} virtual void despawn( PlayerPtr pTarget ) {} - virtual void onRemoveInRangeGameObject( GameObject &pGameObject ) {} - - // add an actor to in range set - void addInRangeGameObject( GameObjectPtr pGameObject ); - - // remove an actor from the in range set - void removeInRangeGameObject( GameObject& pGameObject ); - - // return true if there is at least one actor in the in range set - bool hasInRangeGameObject() const; - - void removeFromInRange(); - - // clear the whole in range set, this does no cleanup - virtual void clearInRangeSet(); - - std::set< GameObjectPtr > getInRangeGameObjects( bool includeSelf = false ); - - // check if another actor is in the actors in range set - bool isInRangeSet( GameObjectPtr pGameObject ) const; - - GameObjectPtr getClosestGameObject(); - uint32_t getId() const; ObjKind getObjKind() const; diff --git a/src/servers/sapphire_zone/Actor/Player.cpp b/src/servers/sapphire_zone/Actor/Player.cpp index 8b6762d3..4c7c3df8 100644 --- a/src/servers/sapphire_zone/Actor/Player.cpp +++ b/src/servers/sapphire_zone/Actor/Player.cpp @@ -831,14 +831,14 @@ void Core::Entity::Player::despawn( Entity::PlayerPtr pTarget ) Core::Entity::ActorPtr Core::Entity::Player::lookupTargetById( uint64_t targetId ) { - GameObjectPtr targetActor; - auto inRange = getInRangeGameObjects(true); + ActorPtr targetActor; + auto inRange = getInRangeActors( true ); for( auto actor : inRange ) { if( actor->getId() == targetId ) targetActor = actor; } - return targetActor->getAsActor(); + return targetActor; } void Core::Entity::Player::setLastPing( uint32_t ping ) @@ -1005,12 +1005,9 @@ void Core::Entity::Player::update( int64_t currTime ) auto mainWeap = m_pInventory->getItemAt( Inventory::GearSet0, Inventory::EquipSlot::MainHand ); // @TODO i dislike this, iterating over all in range actors when you already know the id of the actor you need... - for( auto actor : m_inRangeGameObjects ) + for( auto actor : m_inRangeActors ) { - if( actor->getId() != m_targetId || !actor->isBattleNpc() ) - continue; - - if( actor->getAsBattleNpc()->isAlive() && mainWeap ) + if( actor->getId() == m_targetId && actor->isAlive() && mainWeap ) { // default autoattack range // TODO make this dependant on bnpc size @@ -1030,7 +1027,7 @@ void Core::Entity::Player::update( int64_t currTime ) if( ( currTime - m_lastAttack ) > mainWeap->getDelay() ) { m_lastAttack = currTime; - autoAttack( actor->getAsBattleNpc() ); + autoAttack( actor ); } } diff --git a/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp b/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp index 74d9e453..865ffdc1 100644 --- a/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp @@ -113,11 +113,11 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac } else { - auto inRange = player.getInRangeGameObjects(); + auto inRange = player.getInRangeActors(); for( auto actor : inRange ) { if( actor->getId() == param3 ) - targetActor = actor->getAsActor(); + targetActor = actor; } } @@ -138,7 +138,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac targetPlayer->setLookAt( CharaLook::Race, param1 ); player.sendNotice( "Race for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) ); targetPlayer->spawn( targetPlayer ); - auto inRange = targetPlayer->getInRangeGameObjects(); + auto inRange = targetPlayer->getInRangeActors(); for( auto actor : inRange ) { targetPlayer->despawn( actor->getAsPlayer() ); @@ -151,7 +151,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac targetPlayer->setLookAt( CharaLook::Tribe, param1 ); player.sendNotice( "Tribe for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) ); targetPlayer->spawn( targetPlayer ); - auto inRange = targetPlayer->getInRangeGameObjects(); + auto inRange = targetPlayer->getInRangeActors(); for( auto actor : inRange ) { targetPlayer->despawn( actor->getAsPlayer() ); @@ -164,7 +164,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac targetPlayer->setLookAt( CharaLook::Gender, param1 ); player.sendNotice( "Sex for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) ); targetPlayer->spawn( targetPlayer ); - auto inRange = targetActor->getInRangeGameObjects(); + auto inRange = targetActor->getInRangeActors(); for( auto actor : inRange ) { targetPlayer->despawn( actor->getAsPlayer() ); @@ -439,7 +439,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac case GmCommand::Jump: { - auto inRange = player.getInRangeGameObjects(); + auto inRange = player.getInRangeActors(); player.changePosition( targetActor->getPos().x, targetActor->getPos().y, targetActor->getPos().z, targetActor->getRotation() ); diff --git a/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp b/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp index 55488fa5..c6232a22 100644 --- a/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp @@ -190,7 +190,7 @@ void Core::Network::GameConnection::updatePositionHandler( const Packets::GamePa player.getCurrentAction()->setInterrupted(); // if no one is in range, don't bother trying to send a position update - if( !player.hasInRangeGameObject() ) + if( !player.hasInRangeActor() ) return; uint8_t unk = inPacket.getValAt< uint8_t >( 0x29 ); diff --git a/src/servers/sapphire_zone/Zone/Zone.cpp b/src/servers/sapphire_zone/Zone/Zone.cpp index e0ecad27..c930f3da 100644 --- a/src/servers/sapphire_zone/Zone/Zone.cpp +++ b/src/servers/sapphire_zone/Zone/Zone.cpp @@ -737,8 +737,8 @@ void Core::Zone::updateInRangeSet( Entity::ActorPtr pActor, Cell* pCell ) if( count > 12 ) break; - pActor->addInRangeGameObject( pCurAct ); - pCurAct->addInRangeGameObject( pActor ); + pActor->addInRangeActor( pCurAct ); + pCurAct->addInRangeActor( pActor ); // spawn the actor for the player pCurAct->spawn( pOwnPlayer ); @@ -758,24 +758,24 @@ void Core::Zone::updateInRangeSet( Entity::ActorPtr pActor, Cell* pCell ) if( pPlayer->isLoadingComplete() ) { pActor->spawn( pPlayer ); - pCurAct->addInRangeGameObject( pActor ); - pActor->addInRangeGameObject( pCurAct ); + pCurAct->addInRangeActor( pActor ); + pActor->addInRangeActor( pCurAct ); } } else { - pActor->addInRangeGameObject( pCurAct ); - pCurAct->addInRangeGameObject( pActor ); + pActor->addInRangeActor( pCurAct ); + pCurAct->addInRangeActor( pActor ); } } else if( !isInRange && isInRangeSet ) { - pCurAct->removeInRangeGameObject( *pActor ); + pCurAct->removeInRangeActor( *pActor ); if( pActor->getCurrentZone() != pCurAct->getCurrentZone() ) continue; - pActor->removeInRangeGameObject( *pCurAct ); + pActor->removeInRangeActor( *pCurAct ); } } } From 9a4e7533c630bb9196f7cc17d52ea1d55441e610 Mon Sep 17 00:00:00 2001 From: Mordred Date: Tue, 20 Feb 2018 22:46:44 +0100 Subject: [PATCH 13/69] Renaming classes in preperation of actor rework --- CONTRIBUTING.md | 4 +- src/servers/sapphire_api/Forwards.h | 4 +- src/servers/sapphire_zone/Action/Action.cpp | 4 +- src/servers/sapphire_zone/Action/Action.h | 8 +- .../sapphire_zone/Action/ActionCast.cpp | 2 +- src/servers/sapphire_zone/Action/ActionCast.h | 2 +- .../sapphire_zone/Action/ActionCollision.cpp | 20 +- .../sapphire_zone/Action/ActionCollision.h | 8 +- .../sapphire_zone/Action/ActionMount.cpp | 2 +- .../sapphire_zone/Action/ActionMount.h | 2 +- .../sapphire_zone/Action/ActionTeleport.cpp | 2 +- .../sapphire_zone/Action/ActionTeleport.h | 2 +- .../sapphire_zone/Action/EventAction.cpp | 2 +- .../sapphire_zone/Action/EventAction.h | 2 +- .../sapphire_zone/Action/EventItemAction.cpp | 2 +- .../sapphire_zone/Action/EventItemAction.h | 2 +- src/servers/sapphire_zone/Actor/Actor.cpp | 966 +---------------- src/servers/sapphire_zone/Actor/Actor.h | 335 ++---- src/servers/sapphire_zone/Actor/BattleNpc.cpp | 80 +- src/servers/sapphire_zone/Actor/BattleNpc.h | 28 +- src/servers/sapphire_zone/Actor/Chara.cpp | 974 ++++++++++++++++++ src/servers/sapphire_zone/Actor/Chara.h | 295 ++++++ src/servers/sapphire_zone/Actor/EventNpc.cpp | 4 +- src/servers/sapphire_zone/Actor/EventNpc.h | 6 +- .../sapphire_zone/Actor/GameObject.cpp | 94 -- src/servers/sapphire_zone/Actor/GameObject.h | 82 -- .../sapphire_zone/Actor/InstanceObject.cpp | 2 +- .../sapphire_zone/Actor/InstanceObject.h | 4 +- src/servers/sapphire_zone/Actor/Player.cpp | 26 +- src/servers/sapphire_zone/Actor/Player.h | 8 +- .../sapphire_zone/Actor/PlayerEvent.cpp | 4 +- src/servers/sapphire_zone/Forwards.h | 2 +- src/servers/sapphire_zone/Math/CalcBattle.cpp | 2 +- src/servers/sapphire_zone/Math/CalcBattle.h | 2 +- src/servers/sapphire_zone/Math/CalcStats.cpp | 2 +- src/servers/sapphire_zone/Math/CalcStats.h | 2 +- .../Network/Handlers/ActionHandler.cpp | 6 +- .../Network/Handlers/EventHandlers.cpp | 4 +- .../Network/Handlers/GMCommandHandlers.cpp | 18 +- .../Network/Handlers/SkillHandler.cpp | 2 +- .../Network/PacketWrappers/MoveActorPacket.h | 4 +- .../PacketWrappers/PlayerSpawnPacket.h | 8 +- .../PacketWrappers/UpdateHpMpTpPacket.h | 6 +- .../sapphire_zone/Script/NativeScriptApi.h | 24 +- .../sapphire_zone/Script/ScriptManager.cpp | 20 +- .../sapphire_zone/Script/ScriptManager.h | 8 +- .../Script/Scripts/ScriptObject.h | 2 +- .../Script/Scripts/action/ActionSprint3.cpp | 2 +- .../StatusEffect/StatusEffect.cpp | 4 +- .../sapphire_zone/StatusEffect/StatusEffect.h | 6 +- src/servers/sapphire_zone/Zone/Cell.cpp | 269 +++-- src/servers/sapphire_zone/Zone/Cell.h | 32 +- src/servers/sapphire_zone/Zone/Zone.cpp | 114 +- src/servers/sapphire_zone/Zone/Zone.h | 8 +- 54 files changed, 1749 insertions(+), 1774 deletions(-) create mode 100644 src/servers/sapphire_zone/Actor/Chara.cpp create mode 100644 src/servers/sapphire_zone/Actor/Chara.h delete mode 100644 src/servers/sapphire_zone/Actor/GameObject.cpp delete mode 100644 src/servers/sapphire_zone/Actor/GameObject.h diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9f3f22ab..da0c7441 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -33,10 +33,10 @@ switch( commandId ) case 0x01: // Toggle sheathe { if ( param11 == 1 ) - pPlayer->setStance( Entity::Actor::Stance::Active ); + pPlayer->setStance( Entity::Chara::Stance::Active ); else { - pPlayer->setStance( Entity::Actor::Stance::Passive ); + pPlayer->setStance( Entity::Chara::Stance::Passive ); pPlayer->setAutoattack( false ); } diff --git a/src/servers/sapphire_api/Forwards.h b/src/servers/sapphire_api/Forwards.h index bdffff9f..cbc8d820 100644 --- a/src/servers/sapphire_api/Forwards.h +++ b/src/servers/sapphire_api/Forwards.h @@ -34,11 +34,11 @@ namespace Core namespace Entity { - class Actor; + class Chara; class Player; class BattleNpc; - typedef boost::shared_ptr ActorPtr; + typedef boost::shared_ptr ActorPtr; typedef boost::shared_ptr PlayerPtr; typedef boost::shared_ptr BattleNpcPtr; } diff --git a/src/servers/sapphire_zone/Action/Action.cpp b/src/servers/sapphire_zone/Action/Action.cpp index 56512f09..ed3c3e36 100644 --- a/src/servers/sapphire_zone/Action/Action.cpp +++ b/src/servers/sapphire_zone/Action/Action.cpp @@ -22,7 +22,7 @@ Core::Common::HandleActionType Core::Action::Action::getHandleActionType() const return m_handleActionType; } -Core::Entity::ActorPtr Core::Action::Action::getTargetActor() const +Core::Entity::CharaPtr Core::Action::Action::getTargetChara() const { return m_pTarget; } @@ -57,7 +57,7 @@ void Core::Action::Action::setCastTime( uint32_t castTime ) m_castTime = castTime; } -Core::Entity::ActorPtr Core::Action::Action::getActionSource() const +Core::Entity::CharaPtr Core::Action::Action::getActionSource() const { return m_pSource; } diff --git a/src/servers/sapphire_zone/Action/Action.h b/src/servers/sapphire_zone/Action/Action.h index 8cd4c3cc..995835dd 100644 --- a/src/servers/sapphire_zone/Action/Action.h +++ b/src/servers/sapphire_zone/Action/Action.h @@ -18,7 +18,7 @@ namespace Action { Common::HandleActionType getHandleActionType() const; - Entity::ActorPtr getTargetActor() const; + Entity::CharaPtr getTargetChara() const; bool isInterrupted() const; @@ -32,7 +32,7 @@ namespace Action { void setCastTime( uint32_t castTime ); - Entity::ActorPtr getActionSource() const; + Entity::CharaPtr getActionSource() const; virtual void onStart() {}; virtual void onFinish() {}; @@ -48,8 +48,8 @@ namespace Action { uint64_t m_startTime; uint32_t m_castTime; - Entity::ActorPtr m_pSource; - Entity::ActorPtr m_pTarget; + Entity::CharaPtr m_pSource; + Entity::CharaPtr m_pTarget; bool m_bInterrupt; diff --git a/src/servers/sapphire_zone/Action/ActionCast.cpp b/src/servers/sapphire_zone/Action/ActionCast.cpp index 00e0e966..fbdd780e 100644 --- a/src/servers/sapphire_zone/Action/ActionCast.cpp +++ b/src/servers/sapphire_zone/Action/ActionCast.cpp @@ -26,7 +26,7 @@ Core::Action::ActionCast::ActionCast() m_handleActionType = Common::HandleActionType::Event; } -Core::Action::ActionCast::ActionCast( Entity::ActorPtr pActor, Entity::ActorPtr pTarget, uint16_t actionId ) +Core::Action::ActionCast::ActionCast( Entity::CharaPtr pActor, Entity::CharaPtr pTarget, uint16_t actionId ) { m_startTime = 0; m_id = actionId; diff --git a/src/servers/sapphire_zone/Action/ActionCast.h b/src/servers/sapphire_zone/Action/ActionCast.h index b656b391..c1dac482 100644 --- a/src/servers/sapphire_zone/Action/ActionCast.h +++ b/src/servers/sapphire_zone/Action/ActionCast.h @@ -15,7 +15,7 @@ namespace Action { ActionCast(); ~ActionCast(); - ActionCast( Entity::ActorPtr pActor, Entity::ActorPtr pTarget, uint16_t actionId ); + ActionCast( Entity::CharaPtr pActor, Entity::CharaPtr pTarget, uint16_t actionId ); void onStart() override; void onFinish() override; diff --git a/src/servers/sapphire_zone/Action/ActionCollision.cpp b/src/servers/sapphire_zone/Action/ActionCollision.cpp index a66d234c..c13a3e29 100644 --- a/src/servers/sapphire_zone/Action/ActionCollision.cpp +++ b/src/servers/sapphire_zone/Action/ActionCollision.cpp @@ -2,7 +2,7 @@ #include #include "ActionCollision.h" -#include "Actor/Actor.h" +#include "Actor/Chara.h" #include "Actor/Player.h" #include @@ -13,7 +13,7 @@ using namespace Core::Common; // todo: add AoE actor limits (16, 32) -bool ActionCollision::isActorApplicable( Actor& actor, TargetFilter targetFilter ) +bool ActionCollision::isActorApplicable( Chara& chara, TargetFilter targetFilter ) { bool actorApplicable = false; switch( targetFilter ) @@ -25,37 +25,37 @@ bool ActionCollision::isActorApplicable( Actor& actor, TargetFilter targetFilter } case TargetFilter::Players: { - actorApplicable = actor.isPlayer(); + actorApplicable = chara.isPlayer(); break; } case TargetFilter::Allies: { // todo: implement ally NPCs - actorApplicable = !actor.isBattleNpc(); + actorApplicable = !chara.isBattleNpc(); break; } case TargetFilter::Party: { // todo: implement party - actorApplicable = actor.isPlayer(); + actorApplicable = chara.isPlayer(); break; } case TargetFilter::Enemies: { - actorApplicable = actor.isBattleNpc(); + actorApplicable = chara.isBattleNpc(); break; } } - return ( actorApplicable && actor.isAlive() ); + return ( actorApplicable && chara.isAlive() ); } -std::set< Core::Entity::ActorPtr > ActionCollision::getActorsHitFromAction( FFXIVARR_POSITION3 aoePosition, - std::set< ActorPtr > actorsInRange, +std::set< Core::Entity::CharaPtr > ActionCollision::getActorsHitFromAction( FFXIVARR_POSITION3 aoePosition, + std::set< CharaPtr > actorsInRange, boost::shared_ptr< Core::Data::Action > actionInfo, TargetFilter targetFilter ) { - std::set< ActorPtr > actorsCollided; + std::set< CharaPtr > actorsCollided; switch( static_cast< ActionCollisionType >( actionInfo->castType ) ) { diff --git a/src/servers/sapphire_zone/Action/ActionCollision.h b/src/servers/sapphire_zone/Action/ActionCollision.h index 0c0da597..470a31f2 100644 --- a/src/servers/sapphire_zone/Action/ActionCollision.h +++ b/src/servers/sapphire_zone/Action/ActionCollision.h @@ -4,7 +4,7 @@ #include #include -#include "Actor/Actor.h" +#include "Actor/Chara.h" #include "Action.h" namespace Core { @@ -23,9 +23,9 @@ namespace Entity { { public: - static bool isActorApplicable( Actor& actor, TargetFilter targetFilter ); - static std::set< ActorPtr > getActorsHitFromAction( Common::FFXIVARR_POSITION3 aoePosition, - std::set< ActorPtr > actorsInRange, + static bool isActorApplicable( Chara& actor, TargetFilter targetFilter ); + static std::set< CharaPtr > getActorsHitFromAction( Common::FFXIVARR_POSITION3 aoePosition, + std::set< CharaPtr > actorsInRange, boost::shared_ptr< Data::Action > actionInfo, TargetFilter targetFilter ); diff --git a/src/servers/sapphire_zone/Action/ActionMount.cpp b/src/servers/sapphire_zone/Action/ActionMount.cpp index 9ec4588e..53d72eca 100644 --- a/src/servers/sapphire_zone/Action/ActionMount.cpp +++ b/src/servers/sapphire_zone/Action/ActionMount.cpp @@ -24,7 +24,7 @@ Core::Action::ActionMount::ActionMount() m_handleActionType = HandleActionType::Event; } -Core::Action::ActionMount::ActionMount( Entity::ActorPtr pActor, uint16_t mountId ) +Core::Action::ActionMount::ActionMount( Entity::CharaPtr pActor, uint16_t mountId ) { m_startTime = 0; m_id = mountId; diff --git a/src/servers/sapphire_zone/Action/ActionMount.h b/src/servers/sapphire_zone/Action/ActionMount.h index ba32817d..3450a2b2 100644 --- a/src/servers/sapphire_zone/Action/ActionMount.h +++ b/src/servers/sapphire_zone/Action/ActionMount.h @@ -15,7 +15,7 @@ namespace Action { ActionMount(); ~ActionMount(); - ActionMount( Entity::ActorPtr pActor, uint16_t mountId ); + ActionMount( Entity::CharaPtr pActor, uint16_t mountId ); void onStart() override; void onFinish() override; diff --git a/src/servers/sapphire_zone/Action/ActionTeleport.cpp b/src/servers/sapphire_zone/Action/ActionTeleport.cpp index 6151b2cd..18c41dee 100644 --- a/src/servers/sapphire_zone/Action/ActionTeleport.cpp +++ b/src/servers/sapphire_zone/Action/ActionTeleport.cpp @@ -21,7 +21,7 @@ Core::Action::ActionTeleport::ActionTeleport() m_handleActionType = HandleActionType::Event; } -Core::Action::ActionTeleport::ActionTeleport( Entity::ActorPtr pActor, uint16_t targetZone, uint16_t cost ) +Core::Action::ActionTeleport::ActionTeleport( Entity::CharaPtr pActor, uint16_t targetZone, uint16_t cost ) { m_startTime = 0; m_id = 5; diff --git a/src/servers/sapphire_zone/Action/ActionTeleport.h b/src/servers/sapphire_zone/Action/ActionTeleport.h index 480090eb..fab98d06 100644 --- a/src/servers/sapphire_zone/Action/ActionTeleport.h +++ b/src/servers/sapphire_zone/Action/ActionTeleport.h @@ -17,7 +17,7 @@ namespace Action { ActionTeleport(); ~ActionTeleport(); - ActionTeleport( Entity::ActorPtr pActor, uint16_t action, uint16_t cost ); + ActionTeleport( Entity::CharaPtr pActor, uint16_t action, uint16_t cost ); void onStart() override; void onFinish() override; diff --git a/src/servers/sapphire_zone/Action/EventAction.cpp b/src/servers/sapphire_zone/Action/EventAction.cpp index 47b9895f..5bdef79c 100644 --- a/src/servers/sapphire_zone/Action/EventAction.cpp +++ b/src/servers/sapphire_zone/Action/EventAction.cpp @@ -21,7 +21,7 @@ Core::Action::EventAction::EventAction() m_handleActionType = HandleActionType::Event; } -Core::Action::EventAction::EventAction( Entity::ActorPtr pActor, uint32_t eventId, uint16_t action, +Core::Action::EventAction::EventAction( Entity::CharaPtr pActor, uint32_t eventId, uint16_t action, ActionCallback finishRef, ActionCallback interruptRef, uint64_t additional ) { m_additional = additional; diff --git a/src/servers/sapphire_zone/Action/EventAction.h b/src/servers/sapphire_zone/Action/EventAction.h index f0857d34..a92831ef 100644 --- a/src/servers/sapphire_zone/Action/EventAction.h +++ b/src/servers/sapphire_zone/Action/EventAction.h @@ -16,7 +16,7 @@ namespace Action { EventAction(); ~EventAction(); - EventAction( Entity::ActorPtr pActor, uint32_t eventId, uint16_t action, + EventAction( Entity::CharaPtr pActor, uint32_t eventId, uint16_t action, ActionCallback finishRef, ActionCallback interruptRef, uint64_t additional ); void onStart() override; diff --git a/src/servers/sapphire_zone/Action/EventItemAction.cpp b/src/servers/sapphire_zone/Action/EventItemAction.cpp index 28ddd8fb..742a40ae 100644 --- a/src/servers/sapphire_zone/Action/EventItemAction.cpp +++ b/src/servers/sapphire_zone/Action/EventItemAction.cpp @@ -22,7 +22,7 @@ Core::Action::EventItemAction::EventItemAction() m_handleActionType = HandleActionType::Event; } -Core::Action::EventItemAction::EventItemAction( Entity::ActorPtr pActor, uint32_t eventId, uint16_t action, +Core::Action::EventItemAction::EventItemAction( Entity::CharaPtr pActor, uint32_t eventId, uint16_t action, ActionCallback finishRef, ActionCallback interruptRef, uint64_t additional ) { m_additional = additional; diff --git a/src/servers/sapphire_zone/Action/EventItemAction.h b/src/servers/sapphire_zone/Action/EventItemAction.h index bd9eee9d..6c69e1aa 100644 --- a/src/servers/sapphire_zone/Action/EventItemAction.h +++ b/src/servers/sapphire_zone/Action/EventItemAction.h @@ -14,7 +14,7 @@ namespace Action { EventItemAction(); ~EventItemAction(); - EventItemAction( Entity::ActorPtr pActor, uint32_t eventId, uint16_t action, + EventItemAction( Entity::CharaPtr pActor, uint32_t eventId, uint16_t action, ActionCallback finishRef, ActionCallback interruptRef, uint64_t additional ); void onStart() override; diff --git a/src/servers/sapphire_zone/Actor/Actor.cpp b/src/servers/sapphire_zone/Actor/Actor.cpp index 45b076a6..5fa1cc69 100644 --- a/src/servers/sapphire_zone/Actor/Actor.cpp +++ b/src/servers/sapphire_zone/Actor/Actor.cpp @@ -1,974 +1,94 @@ -#include -#include -#include -#include -#include - -#include "Forwards.h" -#include "Action/Action.h" - -#include "Zone/Zone.h" - -#include "Network/GameConnection.h" -#include "Network/PacketWrappers/ActorControlPacket142.h" -#include "Network/PacketWrappers/ActorControlPacket143.h" -#include "Network/PacketWrappers/ActorControlPacket144.h" -#include "Network/PacketWrappers/UpdateHpMpTpPacket.h" - -#include "StatusEffect/StatusEffect.h" -#include "Action/ActionCollision.h" -#include "ServerZone.h" -#include "Session.h" -#include "Math/CalcBattle.h" #include "Actor.h" + #include "Player.h" -#include "Zone/TerritoryMgr.h" - -extern Core::ServerZone g_serverZone; -extern Core::Data::ExdDataGenerated g_exdDataGen; -extern Core::TerritoryMgr g_territoryMgr; - -using namespace Core::Common; -using namespace Core::Network::Packets; -using namespace Core::Network::Packets::Server; +#include "Chara.h" +#include "BattleNpc.h" +#include "EventNpc.h" Core::Entity::Actor::Actor( ObjKind type ) : - GameObject( type ) + m_objKind( type ) { - // initialize the free slot queue - for( uint8_t i = 0; i < MAX_STATUS_EFFECTS; i++ ) - { - m_statusEffectFreeSlotQueue.push( i ); - } -} - -Core::Entity::Actor::~Actor() -{ -} - -/*! \return the actors name */ -std::string Core::Entity::Actor::getName() const -{ - return std::string( m_name ); -} - -/*! \return list of actors currently in range */ -std::set< Core::Entity::ActorPtr > Core::Entity::Actor::getInRangeActors( bool includeSelf ) -{ - auto tempInRange = m_inRangeActors; - - if( includeSelf ) - tempInRange.insert( getAsActor() ); - - return tempInRange; - } - -/*! \return current stance of the actors */ -Core::Entity::Actor::Stance Core::Entity::Actor::getStance() const -{ - return m_currentStance; -} - -/*! \return actor stats */ -Core::Entity::Actor::ActorStats Core::Entity::Actor::getStats() const -{ - return m_baseStats; -} - -/*! \return current HP */ -uint32_t Core::Entity::Actor::getHp() const -{ - return m_hp; -} - -/*! \return current MP */ -uint32_t Core::Entity::Actor::getMp() const -{ - return m_mp; -} - -/*! \return current TP */ -uint16_t Core::Entity::Actor::getTp() const -{ - return m_tp; -} - -/*! \return current GP */ -uint16_t Core::Entity::Actor::getGp() const -{ - return m_gp; -} - -/*! \return current invincibility type */ -InvincibilityType Core::Entity::Actor::getInvincibilityType() const -{ - return m_invincibilityType; -} - -/*! \return current class or job */ -Core::Common::ClassJob Core::Entity::Actor::getClass() const -{ - return m_class; -} - -/*! \return current class or job as int32_t ( this feels pointless ) */ -uint8_t Core::Entity::Actor::getClassAsInt() const -{ - return static_cast< uint8_t >( m_class ); -} - -/*! \param ClassJob to set */ -void Core::Entity::Actor::setClass( Common::ClassJob classJob ) -{ - m_class = classJob; -} - -/*! \param Id of the target to set */ -void Core::Entity::Actor::setTargetId( uint64_t targetId ) -{ - m_targetId = targetId; -} - -/*! \return Id of the current target */ -uint64_t Core::Entity::Actor::getTargetId() const -{ - return m_targetId; -} - -/*! \return True if the actor is alive */ -bool Core::Entity::Actor::isAlive() const -{ - return ( m_hp > 0 ); -} - -/*! \return max hp for the actor */ -uint32_t Core::Entity::Actor::getMaxHp() const -{ - return m_baseStats.max_hp; -} - -/*! \return max mp for the actor */ -uint32_t Core::Entity::Actor::getMaxMp() const -{ - return m_baseStats.max_mp; -} - -/*! \return reset hp to current max hp */ -void Core::Entity::Actor::resetHp() -{ - m_hp = getMaxHp(); - sendStatusUpdate( true ); -} - -/*! \return reset mp to current max mp */ -void Core::Entity::Actor::resetMp() -{ - m_mp = getMaxMp(); - sendStatusUpdate( true ); -} - -/*! \param hp amount to set ( caps to maxHp ) */ -void Core::Entity::Actor::setHp( uint32_t hp ) -{ - m_hp = hp < getMaxHp() ? hp : getMaxHp(); - sendStatusUpdate( true ); -} - -/*! \param mp amount to set ( caps to maxMp ) */ -void Core::Entity::Actor::setMp( uint32_t mp ) -{ - m_mp = mp < getMaxMp() ? mp : getMaxMp(); - sendStatusUpdate( true ); -} - -/*! \param gp amount to set*/ -void Core::Entity::Actor::setGp( uint32_t gp ) -{ - m_gp = gp; - sendStatusUpdate( true ); -} - -/*! \param type invincibility type to set */ -void Core::Entity::Actor::setInvincibilityType( Common::InvincibilityType type ) -{ - m_invincibilityType = type; -} - -/*! \return current status of the actor */ -Core::Entity::Actor::ActorStatus Core::Entity::Actor::getStatus() const -{ - return m_status; -} - -/*! \param status to set */ -void Core::Entity::Actor::setStatus( ActorStatus status ) -{ - m_status = status; -} - -/*! -Performs necessary steps to mark an actor dead. -Sets hp/mp/tp, sets status, plays animation and fires onDeath event -*/ -void Core::Entity::Actor::die() -{ - m_status = ActorStatus::Dead; - m_hp = 0; - m_mp = 0; - m_tp = 0; - - // fire onDeath event - onDeath(); - - // if the actor is a player, the update needs to be send to himself too - bool selfNeedsUpdate = isPlayer(); - - sendToInRangeSet( ActorControlPacket142( m_id, SetStatus, static_cast< uint8_t >( ActorStatus::Dead ) ), selfNeedsUpdate ); - - // TODO: not all actor show the death animation when they die, some quest npcs might just despawn - // although that might be handled by setting the HP to 1 and doing some script magic - sendToInRangeSet( ActorControlPacket142( m_id, DeathAnimation, 0, 0, 0, 0x20 ), selfNeedsUpdate ); } -/*! -Calculates and sets the rotation to look towards a specified -position - -\param Position to look towards -*/ -bool Core::Entity::Actor::face( const Common::FFXIVARR_POSITION3& p ) +uint32_t Core::Entity::Actor::getId() const { - float oldRot = getRotation(); - float rot = Math::Util::calcAngFrom( getPos().x, getPos().z, p.x, p.z ); - float newRot = PI - rot + ( PI / 2 ); - - m_pCell = nullptr; - - setRotation( newRot ); - - return oldRot != newRot ? true : false; + return m_id; } -/*! -Sets the actors position and notifies the zone to propagate the change - -\param Position to set -*/ -void Core::Entity::Actor::setPosition( const Common::FFXIVARR_POSITION3& pos ) +Core::Entity::Actor::ObjKind Core::Entity::Actor::getObjKind() const { - m_pos = pos; - m_pCurrentZone->updateActorPosition( *this ); + return m_objKind; } -void Core::Entity::Actor::setPosition( float x, float y, float z ) +Core::Common::FFXIVARR_POSITION3& Core::Entity::Actor::getPos() +{ + return m_pos; +} + +void Core::Entity::Actor::setPos( float x, float y, float z ) { m_pos.x = x; m_pos.y = y; m_pos.z = z; - m_pCurrentZone->updateActorPosition( *this ); } -/*! -Set and propagate the actor stance to in range players -( not the actor himself ) - -\param stance to set -*/ -void Core::Entity::Actor::setStance( Stance stance ) +void Core::Entity::Actor::setPos( const Core::Common::FFXIVARR_POSITION3& pos ) { - m_currentStance = stance; - - sendToInRangeSet( ActorControlPacket142( m_id, ToggleAggro, stance, 1 ) ); + m_pos = pos; } -/*! -Check if an action is queued for execution, if so update it -and if fully performed, clean up again. - -\return true if a queued action has been updated -*/ -bool Core::Entity::Actor::checkAction() -{ - - if( m_pCurrentAction == nullptr ) - return false; - - if( m_pCurrentAction->update() ) - m_pCurrentAction.reset(); - - return true; - -} - -/*! -Change the current target and propagate to in range players - -\param target actor id -*/ -void Core::Entity::Actor::changeTarget( uint64_t targetId ) -{ - setTargetId( targetId ); - sendToInRangeSet( ActorControlPacket144( m_id, SetTarget, 0, 0, 0, 0, targetId ) ); -} - -/*! -Dummy function \return 0 -*/ -uint8_t Core::Entity::Actor::getLevel() const -{ - return 0; -} - -/*! -Let an actor take damage and perform necessary steps -according to resulting hp, propagates new hp value to players -in range -TODO: eventually this needs to distinguish between physical and -magical dmg and take status effects into account - -\param amount of damage to be taken -*/ -void Core::Entity::Actor::takeDamage( uint32_t damage ) -{ - if( damage >= m_hp ) - { - switch( m_invincibilityType ) { - case InvincibilityNone: - setHp( 0 ); - die(); - break; - case InvincibilityRefill: - resetHp(); - break; - case InvincibilityStayAlive: - setHp( 0 ); - break; - } - } - else - m_hp -= damage; - - sendStatusUpdate( false ); -} - -/*! -Let an actor get healed and perform necessary steps -according to resulting hp, propagates new hp value to players -in range - -\param amount of hp to be healed -*/ -void Core::Entity::Actor::heal( uint32_t amount ) -{ - if( ( m_hp + amount ) > getMaxHp() ) - { - m_hp = getMaxHp(); - } - else - m_hp += amount; - - sendStatusUpdate( false ); -} - -/*! -Send an HpMpTp update to players in range ( and potentially to self ) -TODO: poor naming, should be changed. Status is not HP. Also should be virtual -so players can have their own version and we can abolish the param. - -\param true if the update should also be sent to the actor ( player ) himself -*/ -void Core::Entity::Actor::sendStatusUpdate( bool toSelf ) -{ - UpdateHpMpTpPacket updateHpPacket( *this ); - sendToInRangeSet( updateHpPacket ); -} - -/*! \return ActionPtr of the currently registered action, or nullptr */ -Core::Action::ActionPtr Core::Entity::Actor::getCurrentAction() const -{ - return m_pCurrentAction; -} - -/*! \param ActionPtr of the action to be registered */ -void Core::Entity::Actor::setCurrentAction( Core::Action::ActionPtr pAction ) -{ - m_pCurrentAction = pAction; -} - -/*! -check if a given actor is in the actors in range set - -\param ActorPtr to be checked for -\return true if the actor was found -*/ -bool Core::Entity::Actor::isInRangeSet( ActorPtr pActor ) const -{ - return !( m_inRangeActors.find( pActor ) == m_inRangeActors.end() ); -} - -/*! \return ActorPtr of the closest actor in range, if none, nullptr */ -Core::Entity::ActorPtr Core::Entity::Actor::getClosestActor() -{ - if( m_inRangeActors.empty() ) - // no actors in range, don't bother - return nullptr; - - ActorPtr tmpActor = nullptr; - - // arbitrary high number - float minDistance = 10000; - - for( const auto& pCurAct : m_inRangeActors ) - { - float distance = Math::Util::distance( getPos().x, - getPos().y, - getPos().z, - pCurAct->getPos().x, - pCurAct->getPos().y, - pCurAct->getPos().z ); - - if( distance < minDistance ) - { - minDistance = distance; - tmpActor = pCurAct; - } - } - - return tmpActor; -} - -/*! -Send a packet to all players in range, potentially to self if set and is player - -\param GamePacketPtr to send -\param bool should be send to self? -*/ -void Core::Entity::Actor::sendToInRangeSet( Network::Packets::GamePacketPtr pPacket, bool bToSelf ) -{ - - if( bToSelf && isPlayer() ) - { - auto pPlayer = getAsPlayer(); - - auto pSession = g_serverZone.getSession( pPlayer->getId() ); - - // it might be that the player DC'd in which case the session would be invalid - if( pSession ) - pSession->getZoneConnection()->queueOutPacket( pPacket ); - } - - if( m_inRangePlayers.empty() ) - return; - - for( const auto &pCurAct : m_inRangePlayers ) - { - assert( pCurAct ); - pPacket->setValAt< uint32_t >( 0x04, m_id ); - pPacket->setValAt< uint32_t >( 0x08, pCurAct->m_id ); - // it might be that the player DC'd in which case the session would be invalid - pCurAct->queuePacket( pPacket ); - } -} - -/*! -Add a given actor to the fitting in range set according to type -but also to the global actor map - -\param ActorPtr to add -*/ -void Core::Entity::Actor::addInRangeActor( ActorPtr pActor ) -{ - - // if this is null, something went wrong - assert( pActor ); - - // add actor to in range set - m_inRangeActors.insert( pActor ); - - if( pActor->isPlayer() ) - { - auto pPlayer = pActor->getAsPlayer(); - - // if actor is a player, add it to the in range player set - m_inRangePlayers.insert( pPlayer ); - } -} - -/*! -Remove a given actor from the matching in range set according to type -but also to the global actor map - -\param ActorPtr to remove -*/ -void Core::Entity::Actor::removeInRangeActor( Actor& actor ) -{ - // call virtual event - onRemoveInRangeActor( actor ); - - // remove actor from in range actor set - m_inRangeActors.erase( actor.getAsActor() ); - - // if actor is a player, despawn ourself for him - // TODO: move to virtual onRemove? - if( isPlayer() ) - actor.despawn( getAsPlayer() ); - - if( actor.isPlayer() ) - m_inRangePlayers.erase( actor.getAsPlayer() ); -} - -/*! \return true if there is at least one actor in the in range set */ -bool Core::Entity::Actor::hasInRangeActor() const -{ - return ( m_inRangeActors.size() > 0 ); -} - -void Core::Entity::Actor::removeFromInRange() -{ - if( !hasInRangeActor() ) - return; - - Entity::ActorPtr pCurAct; - - for( auto& pCurAct : m_inRangeActors ) - { - pCurAct->removeInRangeActor( *this ); - } - -} - -/*! Clear the whole in range set, this does no cleanup */ -void Core::Entity::Actor::clearInRangeSet() -{ - m_inRangeActors.clear(); - m_inRangePlayers.clear(); -} - -/*! \return ZonePtr to the current zone, nullptr if not set */ -Core::ZonePtr Core::Entity::Actor::getCurrentZone() const -{ - return m_pCurrentZone; -} - -/*! \param ZonePtr to the zone to be set as current */ -void Core::Entity::Actor::setCurrentZone( ZonePtr currZone ) -{ - m_pCurrentZone = currZone; -} - -/*! -Get the current cell of a region the actor is in - -\return Cell* -*/ -Core::Cell * Core::Entity::Actor::getCell() const -{ - return m_pCell; -} - -/*! -Set the current cell the actor is in - -\param Cell* for the cell to be set -*/ -void Core::Entity::Actor::setCell( Cell * pCell ) -{ - m_pCell = pCell; -} - -/*! -Autoattack prototype implementation -TODO: move the check if the autoAttack can be performed to the callee -also rename autoAttack to autoAttack as that is more elaborate -On top of that, this only solves attacks from melee classes. -Will have to be extended for ranged attacks. - -\param ActorPtr the autoAttack is performed on -*/ -void Core::Entity::Actor::autoAttack( ActorPtr pTarget ) -{ - - uint64_t tick = Util::getTimeMs(); - - if( ( tick - m_lastAttack ) > 2500 ) - { - pTarget->onActionHostile( *this ); - m_lastAttack = tick; - srand( static_cast< uint32_t >( tick ) ); - - uint16_t damage = static_cast< uint16_t >( 10 + rand() % 12 ); - uint32_t variation = static_cast< uint32_t >( 0 + rand() % 4 ); - - ZoneChannelPacket< FFXIVIpcEffect > effectPacket( getId() ); - effectPacket.data().targetId = pTarget->getId(); - effectPacket.data().actionAnimationId = 0x366; - effectPacket.data().unknown_2 = variation; -// effectPacket.data().unknown_3 = 1; - effectPacket.data().actionTextId = 0x366; - effectPacket.data().numEffects = 1; - effectPacket.data().rotation = Math::Util::floatToUInt16Rot( getRotation() ); - effectPacket.data().effectTarget = pTarget->getId(); - effectPacket.data().effects[0].value = damage; - effectPacket.data().effects[0].effectType = ActionEffectType::Damage; - effectPacket.data().effects[0].hitSeverity = static_cast< ActionHitSeverityType >( variation ); - effectPacket.data().effects[0].unknown_3 = 7; - - sendToInRangeSet( effectPacket ); - - if( this->isPlayer() ) - this->getAsPlayer()->queuePacket( effectPacket ); - - pTarget->takeDamage( damage ); - } -} - -/*! -ChaiScript Skill Handler. - -\param GamePacketPtr to send -\param bool should be send to self? -*/ -void Core::Entity::Actor::handleScriptSkill( uint32_t type, uint16_t actionId, uint64_t param1, - uint64_t param2, Entity::Actor& target ) -{ - - if( isPlayer() ) - { - getAsPlayer()->sendDebug( std::to_string( target.getId() ) ); - getAsPlayer()->sendDebug( "Handle script skill type: " + std::to_string( type ) ); - } - - auto actionInfoPtr = g_exdDataGen.get< Core::Data::Action >( actionId ); - - // Todo: Effect packet generator. 90% of this is basically setting params and it's basically unreadable. - // Prepare packet. This is seemingly common for all packets in the action handler. - - ZoneChannelPacket< FFXIVIpcEffect > effectPacket( getId() ); - effectPacket.data().targetId = target.getId(); - effectPacket.data().actionAnimationId = actionId; - effectPacket.data().unknown_62 = 1; // Affects displaying action name next to number in floating text - effectPacket.data().unknown_2 = 1; // This seems to have an effect on the "double-cast finish" animation - effectPacket.data().actionTextId = actionId; - effectPacket.data().numEffects = 1; - effectPacket.data().rotation = Math::Util::floatToUInt16Rot( getRotation() ); - effectPacket.data().effectTarget = target.getId(); - - // Todo: for each actor, calculate how much damage the calculated value should deal to them - 2-step damage calc. we only have 1-step - switch( type ) - { - - case ActionEffectType::Damage: - { - effectPacket.data().effects[0].value = static_cast< uint16_t >( param1 ); - effectPacket.data().effects[0].effectType = ActionEffectType::Damage; - effectPacket.data().effects[0].hitSeverity = ActionHitSeverityType::NormalDamage; - effectPacket.data().effects[0].unknown_3 = 7; - - if( actionInfoPtr->castType == 1 && actionInfoPtr->effectRange != 0 || actionInfoPtr->castType != 1 ) - { - // If action on this specific target is valid... - if ( isPlayer() && !ActionCollision::isActorApplicable( target, TargetFilter::Enemies ) ) - break; - - sendToInRangeSet( effectPacket, true ); - - if ( target.isAlive() ) - target.onActionHostile( *this ); - - target.takeDamage( static_cast< uint32_t >( param1 ) ); - - } - else - { - - auto actorsCollided = ActionCollision::getActorsHitFromAction( target.getPos(), getInRangeActors( true ), - actionInfoPtr, TargetFilter::Enemies ); - - for( const auto& pHitActor : actorsCollided ) - { - effectPacket.data().targetId = pHitActor->getId(); - effectPacket.data().effectTarget = pHitActor->getId(); - - // todo: send to range of what? ourselves? when mob script hits this is going to be lacking - sendToInRangeSet( effectPacket, true ); - - - if( pHitActor->isAlive() ) - pHitActor->onActionHostile( *this ); - - pHitActor->takeDamage( static_cast< uint32_t >( param1 ) ); - - // Debug - if ( isPlayer() ) - { - if ( pHitActor->isPlayer() ) - getAsPlayer()->sendDebug( "AoE hit actor " + std::to_string( pHitActor->getId() ) + " (" + pHitActor->getName() + ")" ); - else - getAsPlayer()->sendDebug( "AoE hit actor " + std::to_string( pHitActor->getId() ) ); - } - } - } - - break; - } - - case ActionEffectType::Heal: - { - uint32_t calculatedHeal = Math::CalcBattle::calculateHealValue( getAsPlayer(), static_cast< uint32_t >( param1 ) ); - - effectPacket.data().effects[0].value = calculatedHeal; - effectPacket.data().effects[0].effectType = ActionEffectType::Heal; - effectPacket.data().effects[0].hitSeverity = ActionHitSeverityType::NormalHeal; - - if( actionInfoPtr->castType == 1 && actionInfoPtr->effectRange != 0 || actionInfoPtr->castType != 1 ) - { - if( isPlayer() && !ActionCollision::isActorApplicable( target, TargetFilter::Allies ) ) - break; - - sendToInRangeSet( effectPacket, true ); - target.heal( calculatedHeal ); - } - else - { - // todo: get proper packets: the following was just kind of thrown together from what we know. - // atm buggy (packets look "delayed" from client) - - auto actorsCollided = ActionCollision::getActorsHitFromAction( target.getPos(), getInRangeActors( true ), - actionInfoPtr, TargetFilter::Allies ); - - for( auto pHitActor : actorsCollided ) - { - effectPacket.data().targetId = target.getId(); - effectPacket.data().effectTarget = pHitActor->getId(); - - sendToInRangeSet( effectPacket, true ); - pHitActor->heal( calculatedHeal ); - - // Debug - if( isPlayer() ) - { - if( pHitActor->isPlayer() ) - getAsPlayer()->sendDebug( "AoE hit actor " + std::to_string( pHitActor->getId() ) + " (" + pHitActor->getName() + ")" ); - else - getAsPlayer()->sendDebug( "AoE hit actor " + std::to_string( pHitActor->getId() ) ); - } - } - } - break; - } - - default: - break; - } -} - -/*! \param StatusEffectPtr to be applied to the actor */ -void Core::Entity::Actor::addStatusEffect( StatusEffect::StatusEffectPtr pEffect ) -{ - int8_t nextSlot = getStatusEffectFreeSlot(); - // if there is no slot left, do not add the effect - if( nextSlot == -1 ) - return; - - pEffect->applyStatus(); - m_statusEffectMap[nextSlot] = pEffect; - - ZoneChannelPacket< Server::FFXIVIpcAddStatusEffect > statusEffectAdd( getId() ); - statusEffectAdd.data().actor_id = pEffect->getTargetActorId(); - statusEffectAdd.data().actor_id1 = pEffect->getSrcActorId(); - statusEffectAdd.data().current_hp = getHp(); - statusEffectAdd.data().current_mp = getMp(); - statusEffectAdd.data().current_tp = getTp(); - statusEffectAdd.data().duration = static_cast< float >( pEffect->getDuration() ) / 1000; - statusEffectAdd.data().effect_id = pEffect->getId(); - statusEffectAdd.data().effect_index = nextSlot; - statusEffectAdd.data().max_hp = getMaxHp(); - statusEffectAdd.data().max_mp = getMaxMp(); - statusEffectAdd.data().max_something = 1; - //statusEffectAdd.data().unknown2 = 28; - statusEffectAdd.data().param = pEffect->getParam(); - - sendToInRangeSet( statusEffectAdd, isPlayer() ); -} - -/*! \param StatusEffectPtr to be applied to the actor */ -void Core::Entity::Actor::addStatusEffectById( uint32_t id, int32_t duration, Entity::Actor& source, uint16_t param ) -{ - auto effect = StatusEffect::make_StatusEffect( id, source.getAsActor(), getAsActor(), duration, 3000 ); - effect->setParam( param ); - addStatusEffect( effect ); -} - -/*! \param StatusEffectPtr to be applied to the actor */ -void Core::Entity::Actor::addStatusEffectByIdIfNotExist( uint32_t id, int32_t duration, Entity::Actor& source, uint16_t param ) -{ - if( hasStatusEffect( id ) ) - return; - - auto effect = StatusEffect::make_StatusEffect( id, source.getAsActor(), getAsActor(), duration, 3000 ); - effect->setParam( param ); - addStatusEffect( effect ); - -} - -float Core::Entity::Actor::getRotation() const +float Core::Entity::Actor::getRot() const { return m_rot; } -void Core::Entity::Actor::setRotation( float rot ) +void Core::Entity::Actor::setRot( float rot ) { m_rot = rot; } -int8_t Core::Entity::Actor::getStatusEffectFreeSlot() +bool Core::Entity::Actor::isPlayer() const { - int8_t freeEffectSlot = -1; - - if( m_statusEffectFreeSlotQueue.empty() ) - return freeEffectSlot; - - freeEffectSlot = m_statusEffectFreeSlotQueue.front(); - m_statusEffectFreeSlotQueue.pop(); - - return freeEffectSlot; + return m_objKind == ObjKind::Player; } -void Core::Entity::Actor::statusEffectFreeSlot( uint8_t slotId ) +bool Core::Entity::Actor::isBattleNpc() const { - m_statusEffectFreeSlotQueue.push( slotId ); + return m_objKind == ObjKind::BattleNpc; } -void Core::Entity::Actor::removeSingleStatusEffectById( uint32_t id ) +bool Core::Entity::Actor::isEventNpc() const { - for( auto effectIt : m_statusEffectMap ) - { - if( effectIt.second->getId() == id ) - { - removeStatusEffect( effectIt.first ); - break; - } - } + return m_objKind == ObjKind::EventNpc; } -void Core::Entity::Actor::removeStatusEffect( uint8_t effectSlotId ) +/*! \return pointer to this instance as ActorPtr */ +Core::Entity::CharaPtr Core::Entity::Actor::getAsChara() { - auto pEffectIt = m_statusEffectMap.find( effectSlotId ); - if( pEffectIt == m_statusEffectMap.end() ) - return; - - statusEffectFreeSlot( effectSlotId ); - - auto pEffect = pEffectIt->second; - pEffect->removeStatus(); - - sendToInRangeSet( ActorControlPacket142( getId(), StatusEffectLose, pEffect->getId() ), isPlayer() ); - - m_statusEffectMap.erase( effectSlotId ); - - sendStatusEffectUpdate(); + return boost::dynamic_pointer_cast< Entity::Chara, Entity::Actor >( shared_from_this() ); } -std::map< uint8_t, Core::StatusEffect::StatusEffectPtr > Core::Entity::Actor::getStatusEffectMap() const +/*! \return pointer to this instance as PlayerPtr */ +Core::Entity::PlayerPtr Core::Entity::Actor::getAsPlayer() { - return m_statusEffectMap; + if( !isPlayer() ) + return nullptr; + return boost::dynamic_pointer_cast< Entity::Player, Entity::Actor >( shared_from_this() ); } -void Core::Entity::Actor::sendStatusEffectUpdate() +/*! \return pointer to this instance as BattleNpcPtr */ +Core::Entity::BattleNpcPtr Core::Entity::Actor::getAsBattleNpc() { - uint64_t currentTimeMs = Util::getTimeMs(); - - ZoneChannelPacket< Server::FFXIVIpcStatusEffectList > statusEffectList( getId() ); - - statusEffectList.data().current_hp = getHp(); - statusEffectList.data().current_mp = getMp(); - statusEffectList.data().currentTp = getTp(); - statusEffectList.data().max_hp = getMaxHp(); - statusEffectList.data().max_mp = getMaxMp(); - uint8_t slot = 0; - for( auto effectIt : m_statusEffectMap ) - { - float timeLeft = static_cast< float >( effectIt.second->getDuration() - - ( currentTimeMs - effectIt.second->getStartTimeMs() ) ) / 1000; - statusEffectList.data().effect[slot].duration = timeLeft; - statusEffectList.data().effect[slot].effect_id = effectIt.second->getId(); - statusEffectList.data().effect[slot].sourceActorId = effectIt.second->getSrcActorId(); - slot++; - } - - sendToInRangeSet( statusEffectList, isPlayer() ); - + if( !isBattleNpc() ) + return nullptr; + return boost::dynamic_pointer_cast< Entity::BattleNpc, Entity::Actor >( shared_from_this() ); } -void Core::Entity::Actor::updateStatusEffects() +/*! \return pointer to this instance as EventNpcPtr */ +Core::Entity::EventNpcPtr Core::Entity::Actor::getAsEventNpc() { - uint64_t currentTimeMs = Util::getTimeMs(); - - uint32_t thisTickDmg = 0; - uint32_t thisTickHeal = 0; - - for( auto effectIt : m_statusEffectMap ) - { - uint8_t effectIndex = effectIt.first; - auto effect = effectIt.second; - - uint64_t lastTick = effect->getLastTickMs(); - uint64_t startTime = effect->getStartTimeMs(); - uint32_t duration = effect->getDuration(); - uint32_t tickRate = effect->getTickRate(); - - if( ( currentTimeMs - startTime ) > duration ) - { - // remove status effect - removeStatusEffect( effectIndex ); - // break because removing invalidates iterators - break; - } - - if( ( currentTimeMs - lastTick ) > tickRate ) - { - effect->setLastTick( currentTimeMs ); - effect->onTick(); - - auto thisEffect = effect->getTickEffect(); - - switch( thisEffect.first ) - { - - case 1: - { - thisTickDmg += thisEffect.second; - break; - } - - case 2: - { - thisTickHeal += thisEffect.second; - break; - } - - } - } - - } - - if( thisTickDmg != 0 ) - { - takeDamage( thisTickDmg ); - sendToInRangeSet( ActorControlPacket142( getId(), HPFloatingText, 0, static_cast< uint8_t >( ActionEffectType::Damage ), thisTickDmg ) ); - } - - if( thisTickHeal != 0 ) - { - heal( thisTickDmg ); - sendToInRangeSet( ActorControlPacket142( getId(), HPFloatingText, 0, static_cast< uint8_t >( ActionEffectType::Heal ), thisTickHeal ) ); - } -} - -bool Core::Entity::Actor::hasStatusEffect( uint32_t id ) -{ - if( m_statusEffectMap.find( id ) != m_statusEffectMap.end() ) - return true; - return false; + if( !isEventNpc() ) + return nullptr; + return boost::dynamic_pointer_cast< Entity::EventNpc, Entity::Actor >( shared_from_this() ); } diff --git a/src/servers/sapphire_zone/Actor/Actor.h b/src/servers/sapphire_zone/Actor/Actor.h index cb2142af..ccd5996c 100644 --- a/src/servers/sapphire_zone/Actor/Actor.h +++ b/src/servers/sapphire_zone/Actor/Actor.h @@ -1,11 +1,10 @@ -#ifndef _ACTOR_H_ -#define _ACTOR_H_ +#ifndef _GAME_OBJECT_H_ +#define _GAME_OBJECT_H_ #include #include #include "Forwards.h" -#include "GameObject.h" #include #include #include @@ -14,282 +13,70 @@ namespace Core { namespace Entity { /*! -\class Actor -\brief Base class for all actors +\class GameObject +\brief Base class for all actor/objects */ -class Actor : public GameObject -{ -public: - enum Stance : uint8_t + class Actor : public boost::enable_shared_from_this< Actor > { - Passive = 0, - Active = 1, + public: + enum ObjKind : uint8_t + { + None = 0x00, + Player = 0x01, + BattleNpc = 0x02, + EventNpc = 0x03, + Treasure = 0x04, + Aetheryte = 0x05, + GatheringPoint = 0x06, + EventObj = 0x07, + Mount = 0x08, + Companion = 0x09, + Retainer = 0x0A, + Area = 0x0B, + Housing = 0x0C, + Cutscene = 0x0D, + CardStand = 0x0E, + }; + + protected: + /*! Position of the object */ + Common::FFXIVARR_POSITION3 m_pos; + /*! Rotation of the object */ + float m_rot; + /*! Id of the actor */ + uint32_t m_id; + /*! Type of the actor */ + ObjKind m_objKind; + + public: + explicit Actor( ObjKind type ); + virtual ~Actor() {}; + + virtual void spawn( PlayerPtr pTarget ) {} + virtual void despawn( PlayerPtr pTarget ) {} + + uint32_t getId() const; + + ObjKind getObjKind() const; + + Common::FFXIVARR_POSITION3& getPos(); + void setPos( const Common::FFXIVARR_POSITION3& pos ); + void setPos( float x, float y, float z ); + + float getRot() const; + void setRot( float rot ); + + bool isPlayer() const; + bool isBattleNpc() const; + bool isEventNpc() const; + + CharaPtr getAsChara(); + PlayerPtr getAsPlayer(); + BattleNpcPtr getAsBattleNpc(); + EventNpcPtr getAsEventNpc(); }; - enum DisplayFlags : uint16_t - { - ActiveStance = 0x001, - Invisible = 0x020, - HideHead = 0x040, - HideWeapon = 0x080, - Faded = 0x100, - Visor = 0x800, - }; - - enum struct ActorStatus : uint8_t - { - Idle = 0x01, - Dead = 0x02, - Sitting = 0x03, - Mounted = 0x04, - Crafting = 0x05, - Gathering = 0x06, - Melding = 0x07, - SMachine = 0x08 - }; - - struct ActorStats - { - uint32_t max_mp = 0; - uint32_t max_hp = 0; - - uint32_t str = 0; - uint32_t dex = 0; - uint32_t vit = 0; - uint32_t inte = 0; - uint32_t mnd = 0; - uint32_t pie = 0; - - uint32_t tenacity = 0; - uint32_t attack = 0; - uint32_t defense = 0; - uint32_t accuracy = 0; - uint32_t spellSpeed = 0; - uint32_t magicDefense = 0; - uint32_t critHitRate = 0; - uint32_t resistSlash = 0; - uint32_t resistPierce = 0; - uint32_t resistBlunt = 0; - uint32_t attackPotMagic = 0; - uint32_t healingPotMagic = 0; - uint32_t determination = 0; - uint32_t skillSpeed = 0; - - uint32_t resistSlow = 0; - uint32_t resistSilence = 0; - uint32_t resistBlind = 0; - uint32_t resistPoison = 0; - uint32_t resistStun = 0; - uint32_t resistSleep = 0; - uint32_t resistBind = 0; - uint32_t resistHeavy = 0; - - uint32_t resistFire = 0; - uint32_t resistIce = 0; - uint32_t resistWind = 0; - uint32_t resistEarth = 0; - uint32_t resistLightning = 0; - uint32_t resistWater = 0; - - } m_baseStats; - -protected: - char m_name[34]; - /*! Id of the zone the actor currently is in */ - uint32_t m_zoneId; - /*! Ptr to the ZoneObj the actor belongs to */ - ZonePtr m_pCurrentZone; - /*! Last tick time for the actor ( in ms ) */ - uint64_t m_lastTickTime; - /*! Last time the actor performed an autoAttack ( in ms ) */ - uint64_t m_lastAttack; - /*! Last time the actor was updated ( in ms ) */ - uint64_t m_lastUpdate; - /*! Current stance of the actor */ - Stance m_currentStance; - /*! Current staus of the actor */ - ActorStatus m_status; - /*! Max HP of the actor ( based on job / class ) */ - uint32_t m_maxHp; - /*! Max MP of the actor ( based on job / class ) */ - uint32_t m_maxMp; - /*! Current HP of the actor */ - uint32_t m_hp; - /*! Current MP of the actor */ - uint32_t m_mp; - /*! Current TP of the actor */ - uint16_t m_tp; - /*! Current GP of the actor */ - uint16_t m_gp; - /*! Additional look info of the actor */ - uint8_t m_customize[26]; - /*! Current class of the actor */ - Common::ClassJob m_class; - /*! Id of the currently selected target actor */ - uint64_t m_targetId; - /*! Ptr to a queued action */ - Action::ActionPtr m_pCurrentAction; - /*! Invincibility type */ - Common::InvincibilityType m_invincibilityType; - - /*! Status effects */ - const uint8_t MAX_STATUS_EFFECTS = 30; - std::queue< uint8_t > m_statusEffectFreeSlotQueue; - std::vector< std::pair< uint8_t, uint32_t> > m_statusEffectList; - std::map< uint8_t, StatusEffect::StatusEffectPtr > m_statusEffectMap; - - std::set< ActorPtr > m_inRangeActors; - std::set< PlayerPtr > m_inRangePlayers; - -public: - Actor( ObjKind type ); - - virtual ~Actor() override; - - virtual void calculateStats() {}; - - /// Status effect functions - void addStatusEffect( StatusEffect::StatusEffectPtr pEffect ); - void removeStatusEffect( uint8_t effectSlotId ); - void removeSingleStatusEffectById( uint32_t id ); - void updateStatusEffects(); - - bool hasStatusEffect( uint32_t id ); - - int8_t getStatusEffectFreeSlot(); - void statusEffectFreeSlot( uint8_t slotId ); - - std::map< uint8_t, Core::StatusEffect::StatusEffectPtr > getStatusEffectMap() const; - - void sendStatusEffectUpdate(); - // add a status effect by id - void addStatusEffectById( uint32_t id, int32_t duration, Entity::Actor& pSource, uint16_t param = 0 ); - - // add a status effect by id if it doesn't exist - void addStatusEffectByIdIfNotExist( uint32_t id, int32_t duration, Entity::Actor& pSource, uint16_t param = 0 ); - - // remove a status effect by id - void removeSingleStatusEffectFromId( uint32_t id ); - /// End Status Effect Functions - - void setPosition( const Common::FFXIVARR_POSITION3& pos ); - void setPosition( float x, float y, float z ); - - void setRotation( float rot ); - - float getRotation() const; - - std::string getName() const; - - std::set< ActorPtr > getInRangeActors( bool includeSelf = false ); - - bool face( const Common::FFXIVARR_POSITION3& p ); - - Stance getStance() const; - - void setStance( Stance stance ); - - ActorStats getStats() const; - - uint32_t getHp() const; - uint32_t getMp() const; - uint16_t getTp() const; - uint16_t getGp() const; - - Common::InvincibilityType getInvincibilityType() const; - - Common::ClassJob getClass() const; - - uint8_t getClassAsInt() const; - - void setClass( Common::ClassJob classJob ); - - void setTargetId( uint64_t targetId ); - - uint64_t getTargetId() const; - - bool isAlive() const; - - virtual uint32_t getMaxHp() const; - virtual uint32_t getMaxMp() const; - - void resetHp(); - void resetMp(); - - void setHp( uint32_t hp ); - void setMp( uint32_t mp ); - void setGp( uint32_t gp ); - - void setInvincibilityType( Common::InvincibilityType type ); - - void die(); - - ActorStatus getStatus() const; - - void setStatus( ActorStatus status ); - - void handleScriptSkill( uint32_t type, uint16_t actionId, uint64_t param1, uint64_t param2, Entity::Actor& target ); - - virtual void autoAttack( ActorPtr pTarget ); - - virtual void onRemoveInRangeActor( Actor& pActor ) {} - - virtual void onDeath() {}; - virtual void onDamageTaken( Actor& pSource ) {}; - virtual void onActionHostile( Actor& source ) {}; - virtual void onActionFriendly( Actor& pSource ) {}; - virtual void onTick() {}; - - virtual void changeTarget( uint64_t targetId ); - virtual uint8_t getLevel() const; - virtual void sendStatusUpdate( bool toSelf = true ); - virtual void takeDamage( uint32_t damage ); - virtual void heal( uint32_t amount ); - virtual bool checkAction(); - virtual void update( int64_t currTime ) {}; - - Action::ActionPtr getCurrentAction() const; - - void setCurrentAction( Action::ActionPtr pAction ); - - ///// IN RANGE LOGIC ///// - - // check if another actor is in the actors in range set - bool isInRangeSet( ActorPtr pActor ) const; - - ActorPtr getClosestActor(); - - void sendToInRangeSet( Network::Packets::GamePacketPtr pPacket, bool bToSelf = false ); - - // add an actor to in range set - void addInRangeActor( ActorPtr pActor ); - - // remove an actor from the in range set - void removeInRangeActor( Actor& pActor ); - - // return true if there is at least one actor in the in range set - bool hasInRangeActor() const; - - void removeFromInRange(); - - // clear the whole in range set, this does no cleanup - virtual void clearInRangeSet(); - - ZonePtr getCurrentZone() const; - - void setCurrentZone( ZonePtr currZone ); - - // get the current cell of a region the actor is in - Cell* getCell() const; - - // set the current cell - void setCell( Cell* pCell ); - - Core::Cell* m_pCell; - -}; - } } #endif diff --git a/src/servers/sapphire_zone/Actor/BattleNpc.cpp b/src/servers/sapphire_zone/Actor/BattleNpc.cpp index 5b43728b..26d76f4a 100644 --- a/src/servers/sapphire_zone/Actor/BattleNpc.cpp +++ b/src/servers/sapphire_zone/Actor/BattleNpc.cpp @@ -26,7 +26,7 @@ extern Core::Data::ExdDataGenerated g_exdDataGen; uint32_t Core::Entity::BattleNpc::m_nextID = 1149241694; Core::Entity::BattleNpc::BattleNpc() : - Actor( ObjKind::BattleNpc ) + Chara( ObjKind::BattleNpc ) { m_id = 0; m_status = ActorStatus::Idle; @@ -40,7 +40,7 @@ Core::Entity::BattleNpc::~BattleNpc() Core::Entity::BattleNpc::BattleNpc( uint16_t modelId, uint16_t nameid, const Common::FFXIVARR_POSITION3& spawnPos, uint16_t bnpcBaseId, uint32_t type, uint8_t level, uint8_t behaviour, uint32_t mobType ) : - Actor( ObjKind::BattleNpc ) + Chara( ObjKind::BattleNpc ) { BattleNpc::m_nextID++; m_id = BattleNpc::m_nextID; @@ -177,16 +177,16 @@ uint8_t Core::Entity::BattleNpc::getbehavior() const return m_behavior; } -void Core::Entity::BattleNpc::hateListAdd( Actor& actor, int32_t hateAmount ) +void Core::Entity::BattleNpc::hateListAdd( Chara& actor, int32_t hateAmount ) { auto hateEntry = new HateListEntry(); hateEntry->m_hateAmount = hateAmount; - hateEntry->m_pActor = actor.getAsActor(); + hateEntry->m_pChara = actor.getAsChara(); m_hateList.insert( hateEntry ); } -Core::Entity::ActorPtr Core::Entity::BattleNpc::hateListGetHighest() +Core::Entity::CharaPtr Core::Entity::BattleNpc::hateListGetHighest() { auto it = m_hateList.begin(); @@ -202,7 +202,7 @@ Core::Entity::ActorPtr Core::Entity::BattleNpc::hateListGetHighest() } if( entry && maxHate != 0 ) - return entry->m_pActor; + return entry->m_pChara; return nullptr; } @@ -274,7 +274,7 @@ bool Core::Entity::BattleNpc::moveTo( Common::FFXIVARR_POSITION3& pos ) } -void Core::Entity::BattleNpc::aggro( Actor& actor ) +void Core::Entity::BattleNpc::aggro( Chara& actor ) { m_lastAttack = Util::getTimeMs(); @@ -292,7 +292,7 @@ void Core::Entity::BattleNpc::aggro( Actor& actor ) } } -void Core::Entity::BattleNpc::deaggro( Actor& actor ) +void Core::Entity::BattleNpc::deaggro( Chara& actor ) { if( !hateListHasActor( actor ) ) hateListRemove( actor ); @@ -309,8 +309,8 @@ void Core::Entity::BattleNpc::hateListClear() auto it = m_hateList.begin(); for( ; it != m_hateList.end(); ++it ) { - if( isInRangeSet( ( *it )->m_pActor ) ) - deaggro( *( *it )->m_pActor ); + if( isInRangeSet( ( *it )->m_pChara ) ) + deaggro( *( *it )->m_pChara ); HateListEntry* tmpListEntry = ( *it ); delete tmpListEntry; } @@ -318,12 +318,12 @@ void Core::Entity::BattleNpc::hateListClear() } -void Core::Entity::BattleNpc::hateListRemove( Actor& actor ) +void Core::Entity::BattleNpc::hateListRemove( Chara& actor ) { auto it = m_hateList.begin(); for( ; it != m_hateList.end(); ++it ) { - if( ( *it )->m_pActor->getId() == actor.getId() ) + if( ( *it )->m_pChara->getId() == actor.getId() ) { HateListEntry* pEntry = *it; m_hateList.erase( it ); @@ -338,12 +338,12 @@ void Core::Entity::BattleNpc::hateListRemove( Actor& actor ) } } -bool Core::Entity::BattleNpc::hateListHasActor( Actor& actor ) +bool Core::Entity::BattleNpc::hateListHasActor( Chara& actor ) { auto it = m_hateList.begin(); for( ; it != m_hateList.end(); ++it ) { - if( ( *it )->m_pActor->getId() == actor.getId() ) + if( ( *it )->m_pChara->getId() == actor.getId() ) return true; } return false; @@ -359,13 +359,13 @@ uint32_t Core::Entity::BattleNpc::getNameId() const return m_nameId; } -void Core::Entity::BattleNpc::hateListUpdate( Actor& actor, int32_t hateAmount ) +void Core::Entity::BattleNpc::hateListUpdate( Chara& actor, int32_t hateAmount ) { auto it = m_hateList.begin(); for( ; it != m_hateList.end(); ++it ) { - if( ( *it )->m_pActor->getId() == actor.getId() ) + if( ( *it )->m_pChara->getId() == actor.getId() ) { ( *it )->m_hateAmount += hateAmount; return; @@ -374,7 +374,7 @@ void Core::Entity::BattleNpc::hateListUpdate( Actor& actor, int32_t hateAmount ) auto hateEntry = new HateListEntry(); hateEntry->m_hateAmount = hateAmount; - hateEntry->m_pActor = actor.getAsActor(); + hateEntry->m_pChara = actor.getAsChara(); m_hateList.insert( hateEntry ); } @@ -396,7 +396,7 @@ void Core::Entity::BattleNpc::onDeath() uint32_t totalHate = 0; for( auto& pHateEntry : m_hateList ) { - if( pHateEntry->m_pActor->isPlayer() ) + if( pHateEntry->m_pChara->isPlayer() ) { if( pHateEntry->m_hateAmount < minHate ) minHate = pHateEntry->m_hateAmount; @@ -412,9 +412,9 @@ void Core::Entity::BattleNpc::onDeath() { // todo: this is pure retarded // todo: check for companion - if( pHateEntry->m_pActor->isPlayer() ) // && pHateEntry->m_hateAmount >= plsBeHatedThisMuchAtLeast ) + if( pHateEntry->m_pChara->isPlayer() ) // && pHateEntry->m_hateAmount >= plsBeHatedThisMuchAtLeast ) { - uint8_t level = pHateEntry->m_pActor->getLevel(); + uint8_t level = pHateEntry->m_pChara->getLevel(); auto levelDiff = static_cast< int32_t >( this->m_level ) - level; auto cappedLevelDiff = Math::Util::clamp( levelDiff, 1, 6 ); @@ -439,7 +439,7 @@ void Core::Entity::BattleNpc::onDeath() // todo: this is actually retarded, we need real rand() srand( static_cast< uint32_t > ( time( nullptr ) ) ); - auto pPlayer = pHateEntry->m_pActor->getAsPlayer(); + auto pPlayer = pHateEntry->m_pChara->getAsPlayer(); pPlayer->gainExp( exp ); pPlayer->onMobKill( m_nameId ); } @@ -448,7 +448,7 @@ void Core::Entity::BattleNpc::onDeath() hateListClear(); } -void Core::Entity::BattleNpc::onActionHostile( Actor& source ) +void Core::Entity::BattleNpc::onActionHostile( Chara& source ) { if( hateListGetHighest() == nullptr ) @@ -458,7 +458,7 @@ void Core::Entity::BattleNpc::onActionHostile( Actor& source ) setOwner( source.getAsPlayer() ); } -Core::Entity::ActorPtr Core::Entity::BattleNpc::getClaimer() const +Core::Entity::CharaPtr Core::Entity::BattleNpc::getClaimer() const { return m_pOwner; } @@ -501,46 +501,46 @@ void Core::Entity::BattleNpc::update( int64_t currTime ) case MODE_IDLE: { - ActorPtr pClosestActor = getClosestActor(); + CharaPtr pClosestChara = getClosestChara(); - if( pClosestActor && pClosestActor->isAlive() ) + if( pClosestChara && pClosestChara->isAlive() ) { distance = Math::Util::distance( getPos().x, getPos().y, getPos().z, - pClosestActor->getPos().x, - pClosestActor->getPos().y, - pClosestActor->getPos().z ); + pClosestChara->getPos().x, + pClosestChara->getPos().y, + pClosestChara->getPos().z ); //if( distance < 8 && getbehavior() == 2 ) - // aggro( pClosestActor ); + // aggro( pClosestChara ); } } break; case MODE_COMBAT: { - ActorPtr pClosestActor = hateListGetHighest(); + CharaPtr pClosestChara = hateListGetHighest(); - if( pClosestActor != nullptr && !pClosestActor->isAlive() ) + if( pClosestChara != nullptr && !pClosestChara->isAlive() ) { - hateListRemove( *pClosestActor ); - pClosestActor = hateListGetHighest(); + hateListRemove( *pClosestChara ); + pClosestChara = hateListGetHighest(); } - if( pClosestActor != nullptr ) + if( pClosestChara != nullptr ) { distance = Math::Util::distance( getPos().x, getPos().y, getPos().z, - pClosestActor->getPos().x, - pClosestActor->getPos().y, - pClosestActor->getPos().z ); + pClosestChara->getPos().x, + pClosestChara->getPos().y, + pClosestChara->getPos().z ); if( distance > 4 ) - moveTo( pClosestActor->getPos() ); + moveTo( pClosestChara->getPos() ); else { - if( face( pClosestActor->getPos() ) ) + if( face( pClosestChara->getPos() ) ) sendPositionUpdate(); // in combat range. ATTACK! - autoAttack( pClosestActor ); + autoAttack( pClosestChara ); } } else diff --git a/src/servers/sapphire_zone/Actor/BattleNpc.h b/src/servers/sapphire_zone/Actor/BattleNpc.h index b80e6340..a072bca1 100644 --- a/src/servers/sapphire_zone/Actor/BattleNpc.h +++ b/src/servers/sapphire_zone/Actor/BattleNpc.h @@ -1,7 +1,7 @@ #ifndef _BATTLENPC_H #define _BATTLENPC_H -#include "Actor.h" +#include "Chara.h" namespace Core { namespace Entity { @@ -16,11 +16,11 @@ enum StateMode typedef struct { uint32_t m_hateAmount; - ActorPtr m_pActor; + CharaPtr m_pChara; } HateListEntry; -// class for Mobs inheriting from Actor -class BattleNpc : public Actor +// class for Mobs inheriting from Chara +class BattleNpc : public Chara { public: BattleNpc(); @@ -52,12 +52,12 @@ public: uint8_t getbehavior() const; - void hateListAdd( Actor& actor, int32_t hateAmount ); + void hateListAdd( Chara& actor, int32_t hateAmount ); - void hateListUpdate( Actor& actor, int32_t hateAmount ); - void hateListRemove( Actor& actor ); + void hateListUpdate( Chara& actor, int32_t hateAmount ); + void hateListRemove( Chara& actor ); - bool hateListHasActor( Actor& actor ); + bool hateListHasActor( Chara& actor ); void resetPos(); @@ -65,19 +65,19 @@ public: void hateListClear(); - ActorPtr hateListGetHighest(); + CharaPtr hateListGetHighest(); - void aggro( Actor& actor ); + void aggro( Chara& actor ); - void deaggro( Actor& actor ); + void deaggro( Chara& actor ); void setOwner( PlayerPtr pPlayer ); void onDeath() override; - void onActionHostile( Actor& source ) override; + void onActionHostile( Chara& source ) override; - ActorPtr getClaimer() const; + CharaPtr getClaimer() const; void sendPositionUpdate(); @@ -103,7 +103,7 @@ private: uint32_t m_unk1; uint32_t m_unk2; std::set< HateListEntry* > m_hateList; - ActorPtr m_pOwner; + CharaPtr m_pOwner; uint32_t m_timeOfDeath; uint32_t m_mobType; diff --git a/src/servers/sapphire_zone/Actor/Chara.cpp b/src/servers/sapphire_zone/Actor/Chara.cpp new file mode 100644 index 00000000..a7162f4e --- /dev/null +++ b/src/servers/sapphire_zone/Actor/Chara.cpp @@ -0,0 +1,974 @@ +#include +#include +#include +#include +#include + +#include "Forwards.h" +#include "Action/Action.h" + +#include "Zone/Zone.h" + +#include "Network/GameConnection.h" +#include "Network/PacketWrappers/ActorControlPacket142.h" +#include "Network/PacketWrappers/ActorControlPacket143.h" +#include "Network/PacketWrappers/ActorControlPacket144.h" +#include "Network/PacketWrappers/UpdateHpMpTpPacket.h" + +#include "StatusEffect/StatusEffect.h" +#include "Action/ActionCollision.h" +#include "ServerZone.h" +#include "Session.h" +#include "Math/CalcBattle.h" +#include "Chara.h" +#include "Player.h" +#include "Zone/TerritoryMgr.h" + +extern Core::ServerZone g_serverZone; +extern Core::Data::ExdDataGenerated g_exdDataGen; +extern Core::TerritoryMgr g_territoryMgr; + +using namespace Core::Common; +using namespace Core::Network::Packets; +using namespace Core::Network::Packets::Server; + +Core::Entity::Chara::Chara( ObjKind type ) : + Actor( type ) +{ + // initialize the free slot queue + for( uint8_t i = 0; i < MAX_STATUS_EFFECTS; i++ ) + { + m_statusEffectFreeSlotQueue.push( i ); + } +} + +Core::Entity::Chara::~Chara() +{ +} + +/*! \return the actors name */ +std::string Core::Entity::Chara::getName() const +{ + return std::string( m_name ); +} + +/*! \return list of actors currently in range */ +std::set< Core::Entity::CharaPtr > Core::Entity::Chara::getInRangeCharas( bool includeSelf ) +{ + auto tempInRange = m_inRangeCharas; + + if( includeSelf ) + tempInRange.insert( getAsChara() ); + + return tempInRange; + } + +/*! \return current stance of the actors */ +Core::Entity::Chara::Stance Core::Entity::Chara::getStance() const +{ + return m_currentStance; +} + +/*! \return actor stats */ +Core::Entity::Chara::ActorStats Core::Entity::Chara::getStats() const +{ + return m_baseStats; +} + +/*! \return current HP */ +uint32_t Core::Entity::Chara::getHp() const +{ + return m_hp; +} + +/*! \return current MP */ +uint32_t Core::Entity::Chara::getMp() const +{ + return m_mp; +} + +/*! \return current TP */ +uint16_t Core::Entity::Chara::getTp() const +{ + return m_tp; +} + +/*! \return current GP */ +uint16_t Core::Entity::Chara::getGp() const +{ + return m_gp; +} + +/*! \return current invincibility type */ +InvincibilityType Core::Entity::Chara::getInvincibilityType() const +{ + return m_invincibilityType; +} + +/*! \return current class or job */ +Core::Common::ClassJob Core::Entity::Chara::getClass() const +{ + return m_class; +} + +/*! \return current class or job as int32_t ( this feels pointless ) */ +uint8_t Core::Entity::Chara::getClassAsInt() const +{ + return static_cast< uint8_t >( m_class ); +} + +/*! \param ClassJob to set */ +void Core::Entity::Chara::setClass( Common::ClassJob classJob ) +{ + m_class = classJob; +} + +/*! \param Id of the target to set */ +void Core::Entity::Chara::setTargetId( uint64_t targetId ) +{ + m_targetId = targetId; +} + +/*! \return Id of the current target */ +uint64_t Core::Entity::Chara::getTargetId() const +{ + return m_targetId; +} + +/*! \return True if the actor is alive */ +bool Core::Entity::Chara::isAlive() const +{ + return ( m_hp > 0 ); +} + +/*! \return max hp for the actor */ +uint32_t Core::Entity::Chara::getMaxHp() const +{ + return m_baseStats.max_hp; +} + +/*! \return max mp for the actor */ +uint32_t Core::Entity::Chara::getMaxMp() const +{ + return m_baseStats.max_mp; +} + +/*! \return reset hp to current max hp */ +void Core::Entity::Chara::resetHp() +{ + m_hp = getMaxHp(); + sendStatusUpdate( true ); +} + +/*! \return reset mp to current max mp */ +void Core::Entity::Chara::resetMp() +{ + m_mp = getMaxMp(); + sendStatusUpdate( true ); +} + +/*! \param hp amount to set ( caps to maxHp ) */ +void Core::Entity::Chara::setHp( uint32_t hp ) +{ + m_hp = hp < getMaxHp() ? hp : getMaxHp(); + sendStatusUpdate( true ); +} + +/*! \param mp amount to set ( caps to maxMp ) */ +void Core::Entity::Chara::setMp( uint32_t mp ) +{ + m_mp = mp < getMaxMp() ? mp : getMaxMp(); + sendStatusUpdate( true ); +} + +/*! \param gp amount to set*/ +void Core::Entity::Chara::setGp( uint32_t gp ) +{ + m_gp = gp; + sendStatusUpdate( true ); +} + +/*! \param type invincibility type to set */ +void Core::Entity::Chara::setInvincibilityType( Common::InvincibilityType type ) +{ + m_invincibilityType = type; +} + +/*! \return current status of the actor */ +Core::Entity::Chara::ActorStatus Core::Entity::Chara::getStatus() const +{ + return m_status; +} + +/*! \param status to set */ +void Core::Entity::Chara::setStatus( ActorStatus status ) +{ + m_status = status; +} + +/*! +Performs necessary steps to mark an actor dead. +Sets hp/mp/tp, sets status, plays animation and fires onDeath event +*/ +void Core::Entity::Chara::die() +{ + m_status = ActorStatus::Dead; + m_hp = 0; + m_mp = 0; + m_tp = 0; + + // fire onDeath event + onDeath(); + + // if the actor is a player, the update needs to be send to himself too + bool selfNeedsUpdate = isPlayer(); + + sendToInRangeSet( ActorControlPacket142( m_id, SetStatus, static_cast< uint8_t >( ActorStatus::Dead ) ), selfNeedsUpdate ); + + // TODO: not all actor show the death animation when they die, some quest npcs might just despawn + // although that might be handled by setting the HP to 1 and doing some script magic + sendToInRangeSet( ActorControlPacket142( m_id, DeathAnimation, 0, 0, 0, 0x20 ), selfNeedsUpdate ); + +} + +/*! +Calculates and sets the rotation to look towards a specified +position + +\param Position to look towards +*/ +bool Core::Entity::Chara::face( const Common::FFXIVARR_POSITION3& p ) +{ + float oldRot = getRotation(); + float rot = Math::Util::calcAngFrom( getPos().x, getPos().z, p.x, p.z ); + float newRot = PI - rot + ( PI / 2 ); + + m_pCell = nullptr; + + setRotation( newRot ); + + return oldRot != newRot ? true : false; +} + +/*! +Sets the actors position and notifies the zone to propagate the change + +\param Position to set +*/ +void Core::Entity::Chara::setPosition( const Common::FFXIVARR_POSITION3& pos ) +{ + m_pos = pos; + m_pCurrentZone->updateActorPosition( *this ); +} + +void Core::Entity::Chara::setPosition( float x, float y, float z ) +{ + m_pos.x = x; + m_pos.y = y; + m_pos.z = z; + m_pCurrentZone->updateActorPosition( *this ); +} + +/*! +Set and propagate the actor stance to in range players +( not the actor himself ) + +\param stance to set +*/ +void Core::Entity::Chara::setStance( Stance stance ) +{ + m_currentStance = stance; + + sendToInRangeSet( ActorControlPacket142( m_id, ToggleAggro, stance, 1 ) ); +} + +/*! +Check if an action is queued for execution, if so update it +and if fully performed, clean up again. + +\return true if a queued action has been updated +*/ +bool Core::Entity::Chara::checkAction() +{ + + if( m_pCurrentAction == nullptr ) + return false; + + if( m_pCurrentAction->update() ) + m_pCurrentAction.reset(); + + return true; + +} + +/*! +Change the current target and propagate to in range players + +\param target actor id +*/ +void Core::Entity::Chara::changeTarget( uint64_t targetId ) +{ + setTargetId( targetId ); + sendToInRangeSet( ActorControlPacket144( m_id, SetTarget, 0, 0, 0, 0, targetId ) ); +} + +/*! +Dummy function \return 0 +*/ +uint8_t Core::Entity::Chara::getLevel() const +{ + return 0; +} + +/*! +Let an actor take damage and perform necessary steps +according to resulting hp, propagates new hp value to players +in range +TODO: eventually this needs to distinguish between physical and +magical dmg and take status effects into account + +\param amount of damage to be taken +*/ +void Core::Entity::Chara::takeDamage( uint32_t damage ) +{ + if( damage >= m_hp ) + { + switch( m_invincibilityType ) { + case InvincibilityNone: + setHp( 0 ); + die(); + break; + case InvincibilityRefill: + resetHp(); + break; + case InvincibilityStayAlive: + setHp( 0 ); + break; + } + } + else + m_hp -= damage; + + sendStatusUpdate( false ); +} + +/*! +Let an actor get healed and perform necessary steps +according to resulting hp, propagates new hp value to players +in range + +\param amount of hp to be healed +*/ +void Core::Entity::Chara::heal( uint32_t amount ) +{ + if( ( m_hp + amount ) > getMaxHp() ) + { + m_hp = getMaxHp(); + } + else + m_hp += amount; + + sendStatusUpdate( false ); +} + +/*! +Send an HpMpTp update to players in range ( and potentially to self ) +TODO: poor naming, should be changed. Status is not HP. Also should be virtual +so players can have their own version and we can abolish the param. + +\param true if the update should also be sent to the actor ( player ) himself +*/ +void Core::Entity::Chara::sendStatusUpdate( bool toSelf ) +{ + UpdateHpMpTpPacket updateHpPacket( *this ); + sendToInRangeSet( updateHpPacket ); +} + +/*! \return ActionPtr of the currently registered action, or nullptr */ +Core::Action::ActionPtr Core::Entity::Chara::getCurrentAction() const +{ + return m_pCurrentAction; +} + +/*! \param ActionPtr of the action to be registered */ +void Core::Entity::Chara::setCurrentAction( Core::Action::ActionPtr pAction ) +{ + m_pCurrentAction = pAction; +} + +/*! +check if a given actor is in the actors in range set + +\param ActorPtr to be checked for +\return true if the actor was found +*/ +bool Core::Entity::Chara::isInRangeSet( CharaPtr pChara ) const +{ + return !( m_inRangeCharas.find( pChara ) == m_inRangeCharas.end() ); +} + +/*! \return ActorPtr of the closest actor in range, if none, nullptr */ +Core::Entity::CharaPtr Core::Entity::Chara::getClosestChara() +{ + if( m_inRangeCharas.empty() ) + // no actors in range, don't bother + return nullptr; + + CharaPtr tmpActor = nullptr; + + // arbitrary high number + float minDistance = 10000; + + for( const auto& pCurAct : m_inRangeCharas ) + { + float distance = Math::Util::distance( getPos().x, + getPos().y, + getPos().z, + pCurAct->getPos().x, + pCurAct->getPos().y, + pCurAct->getPos().z ); + + if( distance < minDistance ) + { + minDistance = distance; + tmpActor = pCurAct; + } + } + + return tmpActor; +} + +/*! +Send a packet to all players in range, potentially to self if set and is player + +\param GamePacketPtr to send +\param bool should be send to self? +*/ +void Core::Entity::Chara::sendToInRangeSet( Network::Packets::GamePacketPtr pPacket, bool bToSelf ) +{ + + if( bToSelf && isPlayer() ) + { + auto pPlayer = getAsPlayer(); + + auto pSession = g_serverZone.getSession( pPlayer->getId() ); + + // it might be that the player DC'd in which case the session would be invalid + if( pSession ) + pSession->getZoneConnection()->queueOutPacket( pPacket ); + } + + if( m_inRangePlayers.empty() ) + return; + + for( const auto &pCurAct : m_inRangePlayers ) + { + assert( pCurAct ); + pPacket->setValAt< uint32_t >( 0x04, m_id ); + pPacket->setValAt< uint32_t >( 0x08, pCurAct->m_id ); + // it might be that the player DC'd in which case the session would be invalid + pCurAct->queuePacket( pPacket ); + } +} + +/*! +Add a given actor to the fitting in range set according to type +but also to the global actor map + +\param ActorPtr to add +*/ +void Core::Entity::Chara::addInRangeChara( CharaPtr pChara ) +{ + + // if this is null, something went wrong + assert( pChara ); + + // add actor to in range set + m_inRangeCharas.insert( pChara ); + + if( pChara->isPlayer() ) + { + auto pPlayer = pChara->getAsPlayer(); + + // if actor is a player, add it to the in range player set + m_inRangePlayers.insert( pPlayer ); + } +} + +/*! +Remove a given actor from the matching in range set according to type +but also to the global actor map + +\param ActorPtr to remove +*/ +void Core::Entity::Chara::removeInRangeChara( Chara& chara ) +{ + // call virtual event + onRemoveInRangeChara( chara ); + + // remove actor from in range actor set + m_inRangeCharas.erase( chara.getAsChara() ); + + // if actor is a player, despawn ourself for him + // TODO: move to virtual onRemove? + if( isPlayer() ) + chara.despawn( getAsPlayer() ); + + if( chara.isPlayer() ) + m_inRangePlayers.erase( chara.getAsPlayer() ); +} + +/*! \return true if there is at least one actor in the in range set */ +bool Core::Entity::Chara::hasInRangeActor() const +{ + return ( m_inRangeCharas.size() > 0 ); +} + +void Core::Entity::Chara::removeFromInRange() +{ + if( !hasInRangeActor() ) + return; + + Entity::ActorPtr pCurAct; + + for( auto& pCurAct : m_inRangeCharas ) + { + pCurAct->removeInRangeChara( *this ); + } + +} + +/*! Clear the whole in range set, this does no cleanup */ +void Core::Entity::Chara::clearInRangeSet() +{ + m_inRangeCharas.clear(); + m_inRangePlayers.clear(); +} + +/*! \return ZonePtr to the current zone, nullptr if not set */ +Core::ZonePtr Core::Entity::Chara::getCurrentZone() const +{ + return m_pCurrentZone; +} + +/*! \param ZonePtr to the zone to be set as current */ +void Core::Entity::Chara::setCurrentZone( ZonePtr currZone ) +{ + m_pCurrentZone = currZone; +} + +/*! +Get the current cell of a region the actor is in + +\return Cell* +*/ +Core::Cell * Core::Entity::Chara::getCell() const +{ + return m_pCell; +} + +/*! +Set the current cell the actor is in + +\param Cell* for the cell to be set +*/ +void Core::Entity::Chara::setCell( Cell * pCell ) +{ + m_pCell = pCell; +} + +/*! +Autoattack prototype implementation +TODO: move the check if the autoAttack can be performed to the callee +also rename autoAttack to autoAttack as that is more elaborate +On top of that, this only solves attacks from melee classes. +Will have to be extended for ranged attacks. + +\param ActorPtr the autoAttack is performed on +*/ +void Core::Entity::Chara::autoAttack( CharaPtr pTarget ) +{ + + uint64_t tick = Util::getTimeMs(); + + if( ( tick - m_lastAttack ) > 2500 ) + { + pTarget->onActionHostile( *this ); + m_lastAttack = tick; + srand( static_cast< uint32_t >( tick ) ); + + uint16_t damage = static_cast< uint16_t >( 10 + rand() % 12 ); + uint32_t variation = static_cast< uint32_t >( 0 + rand() % 4 ); + + ZoneChannelPacket< FFXIVIpcEffect > effectPacket( getId() ); + effectPacket.data().targetId = pTarget->getId(); + effectPacket.data().actionAnimationId = 0x366; + effectPacket.data().unknown_2 = variation; +// effectPacket.data().unknown_3 = 1; + effectPacket.data().actionTextId = 0x366; + effectPacket.data().numEffects = 1; + effectPacket.data().rotation = Math::Util::floatToUInt16Rot( getRotation() ); + effectPacket.data().effectTarget = pTarget->getId(); + effectPacket.data().effects[0].value = damage; + effectPacket.data().effects[0].effectType = ActionEffectType::Damage; + effectPacket.data().effects[0].hitSeverity = static_cast< ActionHitSeverityType >( variation ); + effectPacket.data().effects[0].unknown_3 = 7; + + sendToInRangeSet( effectPacket ); + + if( isPlayer() ) + getAsPlayer()->queuePacket( effectPacket ); + + pTarget->takeDamage( damage ); + } +} + +/*! +ChaiScript Skill Handler. + +\param GamePacketPtr to send +\param bool should be send to self? +*/ +void Core::Entity::Chara::handleScriptSkill( uint32_t type, uint16_t actionId, uint64_t param1, + uint64_t param2, Entity::Chara& target ) +{ + + if( isPlayer() ) + { + getAsPlayer()->sendDebug( std::to_string( target.getId() ) ); + getAsPlayer()->sendDebug( "Handle script skill type: " + std::to_string( type ) ); + } + + auto actionInfoPtr = g_exdDataGen.get< Core::Data::Action >( actionId ); + + // Todo: Effect packet generator. 90% of this is basically setting params and it's basically unreadable. + // Prepare packet. This is seemingly common for all packets in the action handler. + + ZoneChannelPacket< FFXIVIpcEffect > effectPacket( getId() ); + effectPacket.data().targetId = target.getId(); + effectPacket.data().actionAnimationId = actionId; + effectPacket.data().unknown_62 = 1; // Affects displaying action name next to number in floating text + effectPacket.data().unknown_2 = 1; // This seems to have an effect on the "double-cast finish" animation + effectPacket.data().actionTextId = actionId; + effectPacket.data().numEffects = 1; + effectPacket.data().rotation = Math::Util::floatToUInt16Rot( getRotation() ); + effectPacket.data().effectTarget = target.getId(); + + // Todo: for each actor, calculate how much damage the calculated value should deal to them - 2-step damage calc. we only have 1-step + switch( type ) + { + + case ActionEffectType::Damage: + { + effectPacket.data().effects[0].value = static_cast< uint16_t >( param1 ); + effectPacket.data().effects[0].effectType = ActionEffectType::Damage; + effectPacket.data().effects[0].hitSeverity = ActionHitSeverityType::NormalDamage; + effectPacket.data().effects[0].unknown_3 = 7; + + if( actionInfoPtr->castType == 1 && actionInfoPtr->effectRange != 0 || actionInfoPtr->castType != 1 ) + { + // If action on this specific target is valid... + if ( isPlayer() && !ActionCollision::isActorApplicable( target, TargetFilter::Enemies ) ) + break; + + sendToInRangeSet( effectPacket, true ); + + if ( target.isAlive() ) + target.onActionHostile( *this ); + + target.takeDamage( static_cast< uint32_t >( param1 ) ); + + } + else + { + + auto actorsCollided = ActionCollision::getActorsHitFromAction( target.getPos(), getInRangeCharas(true), + actionInfoPtr, TargetFilter::Enemies ); + + for( const auto& pHitActor : actorsCollided ) + { + effectPacket.data().targetId = pHitActor->getId(); + effectPacket.data().effectTarget = pHitActor->getId(); + + // todo: send to range of what? ourselves? when mob script hits this is going to be lacking + sendToInRangeSet( effectPacket, true ); + + + if( pHitActor->isAlive() ) + pHitActor->onActionHostile( *this ); + + pHitActor->takeDamage( static_cast< uint32_t >( param1 ) ); + + // Debug + if ( isPlayer() ) + { + if ( pHitActor->isPlayer() ) + getAsPlayer()->sendDebug( "AoE hit actor " + std::to_string( pHitActor->getId() ) + " (" + pHitActor->getName() + ")" ); + else + getAsPlayer()->sendDebug( "AoE hit actor " + std::to_string( pHitActor->getId() ) ); + } + } + } + + break; + } + + case ActionEffectType::Heal: + { + uint32_t calculatedHeal = Math::CalcBattle::calculateHealValue( getAsPlayer(), static_cast< uint32_t >( param1 ) ); + + effectPacket.data().effects[0].value = calculatedHeal; + effectPacket.data().effects[0].effectType = ActionEffectType::Heal; + effectPacket.data().effects[0].hitSeverity = ActionHitSeverityType::NormalHeal; + + if( actionInfoPtr->castType == 1 && actionInfoPtr->effectRange != 0 || actionInfoPtr->castType != 1 ) + { + if( isPlayer() && !ActionCollision::isActorApplicable( target, TargetFilter::Allies ) ) + break; + + sendToInRangeSet( effectPacket, true ); + target.heal( calculatedHeal ); + } + else + { + // todo: get proper packets: the following was just kind of thrown together from what we know. + // atm buggy (packets look "delayed" from client) + + auto actorsCollided = ActionCollision::getActorsHitFromAction( target.getPos(), getInRangeCharas(true), + actionInfoPtr, TargetFilter::Allies ); + + for( auto pHitActor : actorsCollided ) + { + effectPacket.data().targetId = target.getId(); + effectPacket.data().effectTarget = pHitActor->getId(); + + sendToInRangeSet( effectPacket, true ); + pHitActor->heal( calculatedHeal ); + + // Debug + if( isPlayer() ) + { + if( pHitActor->isPlayer() ) + getAsPlayer()->sendDebug( "AoE hit actor " + std::to_string( pHitActor->getId() ) + " (" + pHitActor->getName() + ")" ); + else + getAsPlayer()->sendDebug( "AoE hit actor " + std::to_string( pHitActor->getId() ) ); + } + } + } + break; + } + + default: + break; + } +} + +/*! \param StatusEffectPtr to be applied to the actor */ +void Core::Entity::Chara::addStatusEffect( StatusEffect::StatusEffectPtr pEffect ) +{ + int8_t nextSlot = getStatusEffectFreeSlot(); + // if there is no slot left, do not add the effect + if( nextSlot == -1 ) + return; + + pEffect->applyStatus(); + m_statusEffectMap[nextSlot] = pEffect; + + ZoneChannelPacket< Server::FFXIVIpcAddStatusEffect > statusEffectAdd( getId() ); + statusEffectAdd.data().actor_id = pEffect->getTargetActorId(); + statusEffectAdd.data().actor_id1 = pEffect->getSrcActorId(); + statusEffectAdd.data().current_hp = getHp(); + statusEffectAdd.data().current_mp = getMp(); + statusEffectAdd.data().current_tp = getTp(); + statusEffectAdd.data().duration = static_cast< float >( pEffect->getDuration() ) / 1000; + statusEffectAdd.data().effect_id = pEffect->getId(); + statusEffectAdd.data().effect_index = nextSlot; + statusEffectAdd.data().max_hp = getMaxHp(); + statusEffectAdd.data().max_mp = getMaxMp(); + statusEffectAdd.data().max_something = 1; + //statusEffectAdd.data().unknown2 = 28; + statusEffectAdd.data().param = pEffect->getParam(); + + sendToInRangeSet( statusEffectAdd, isPlayer() ); +} + +/*! \param StatusEffectPtr to be applied to the actor */ +void Core::Entity::Chara::addStatusEffectById( uint32_t id, int32_t duration, Entity::Chara& source, uint16_t param ) +{ + auto effect = StatusEffect::make_StatusEffect( id, source.getAsChara(), getAsChara(), duration, 3000 ); + effect->setParam( param ); + addStatusEffect( effect ); +} + +/*! \param StatusEffectPtr to be applied to the actor */ +void Core::Entity::Chara::addStatusEffectByIdIfNotExist( uint32_t id, int32_t duration, Entity::Chara& source, uint16_t param ) +{ + if( hasStatusEffect( id ) ) + return; + + auto effect = StatusEffect::make_StatusEffect( id, source.getAsChara(), getAsChara(), duration, 3000 ); + effect->setParam( param ); + addStatusEffect( effect ); + +} + +float Core::Entity::Chara::getRotation() const +{ + return m_rot; +} + +void Core::Entity::Chara::setRotation( float rot ) +{ + m_rot = rot; +} + +int8_t Core::Entity::Chara::getStatusEffectFreeSlot() +{ + int8_t freeEffectSlot = -1; + + if( m_statusEffectFreeSlotQueue.empty() ) + return freeEffectSlot; + + freeEffectSlot = m_statusEffectFreeSlotQueue.front(); + m_statusEffectFreeSlotQueue.pop(); + + return freeEffectSlot; +} + +void Core::Entity::Chara::statusEffectFreeSlot( uint8_t slotId ) +{ + m_statusEffectFreeSlotQueue.push( slotId ); +} + +void Core::Entity::Chara::removeSingleStatusEffectById( uint32_t id ) +{ + for( auto effectIt : m_statusEffectMap ) + { + if( effectIt.second->getId() == id ) + { + removeStatusEffect( effectIt.first ); + break; + } + } +} + +void Core::Entity::Chara::removeStatusEffect( uint8_t effectSlotId ) +{ + auto pEffectIt = m_statusEffectMap.find( effectSlotId ); + if( pEffectIt == m_statusEffectMap.end() ) + return; + + statusEffectFreeSlot( effectSlotId ); + + auto pEffect = pEffectIt->second; + pEffect->removeStatus(); + + sendToInRangeSet( ActorControlPacket142( getId(), StatusEffectLose, pEffect->getId() ), isPlayer() ); + + m_statusEffectMap.erase( effectSlotId ); + + sendStatusEffectUpdate(); +} + +std::map< uint8_t, Core::StatusEffect::StatusEffectPtr > Core::Entity::Chara::getStatusEffectMap() const +{ + return m_statusEffectMap; +} + +void Core::Entity::Chara::sendStatusEffectUpdate() +{ + uint64_t currentTimeMs = Util::getTimeMs(); + + ZoneChannelPacket< Server::FFXIVIpcStatusEffectList > statusEffectList( getId() ); + + statusEffectList.data().current_hp = getHp(); + statusEffectList.data().current_mp = getMp(); + statusEffectList.data().currentTp = getTp(); + statusEffectList.data().max_hp = getMaxHp(); + statusEffectList.data().max_mp = getMaxMp(); + uint8_t slot = 0; + for( auto effectIt : m_statusEffectMap ) + { + float timeLeft = static_cast< float >( effectIt.second->getDuration() - + ( currentTimeMs - effectIt.second->getStartTimeMs() ) ) / 1000; + statusEffectList.data().effect[slot].duration = timeLeft; + statusEffectList.data().effect[slot].effect_id = effectIt.second->getId(); + statusEffectList.data().effect[slot].sourceActorId = effectIt.second->getSrcActorId(); + slot++; + } + + sendToInRangeSet( statusEffectList, isPlayer() ); + +} + +void Core::Entity::Chara::updateStatusEffects() +{ + uint64_t currentTimeMs = Util::getTimeMs(); + + uint32_t thisTickDmg = 0; + uint32_t thisTickHeal = 0; + + for( auto effectIt : m_statusEffectMap ) + { + uint8_t effectIndex = effectIt.first; + auto effect = effectIt.second; + + uint64_t lastTick = effect->getLastTickMs(); + uint64_t startTime = effect->getStartTimeMs(); + uint32_t duration = effect->getDuration(); + uint32_t tickRate = effect->getTickRate(); + + if( ( currentTimeMs - startTime ) > duration ) + { + // remove status effect + removeStatusEffect( effectIndex ); + // break because removing invalidates iterators + break; + } + + if( ( currentTimeMs - lastTick ) > tickRate ) + { + effect->setLastTick( currentTimeMs ); + effect->onTick(); + + auto thisEffect = effect->getTickEffect(); + + switch( thisEffect.first ) + { + + case 1: + { + thisTickDmg += thisEffect.second; + break; + } + + case 2: + { + thisTickHeal += thisEffect.second; + break; + } + + } + } + + } + + if( thisTickDmg != 0 ) + { + takeDamage( thisTickDmg ); + sendToInRangeSet( ActorControlPacket142( getId(), HPFloatingText, 0, static_cast< uint8_t >( ActionEffectType::Damage ), thisTickDmg ) ); + } + + if( thisTickHeal != 0 ) + { + heal( thisTickDmg ); + sendToInRangeSet( ActorControlPacket142( getId(), HPFloatingText, 0, static_cast< uint8_t >( ActionEffectType::Heal ), thisTickHeal ) ); + } +} + +bool Core::Entity::Chara::hasStatusEffect( uint32_t id ) +{ + if( m_statusEffectMap.find( id ) != m_statusEffectMap.end() ) + return true; + return false; +} diff --git a/src/servers/sapphire_zone/Actor/Chara.h b/src/servers/sapphire_zone/Actor/Chara.h new file mode 100644 index 00000000..116288f5 --- /dev/null +++ b/src/servers/sapphire_zone/Actor/Chara.h @@ -0,0 +1,295 @@ +#ifndef _ACTOR_H_ +#define _ACTOR_H_ + +#include +#include + +#include "Forwards.h" +#include "Actor.h" +#include +#include +#include + +namespace Core { +namespace Entity { + +/*! +\class Chara +\brief Base class for all animate actors + +*/ +class Chara : public Actor +{ +public: + enum Stance : uint8_t + { + Passive = 0, + Active = 1, + }; + + enum DisplayFlags : uint16_t + { + ActiveStance = 0x001, + Invisible = 0x020, + HideHead = 0x040, + HideWeapon = 0x080, + Faded = 0x100, + Visor = 0x800, + }; + + enum struct ActorStatus : uint8_t + { + Idle = 0x01, + Dead = 0x02, + Sitting = 0x03, + Mounted = 0x04, + Crafting = 0x05, + Gathering = 0x06, + Melding = 0x07, + SMachine = 0x08 + }; + + struct ActorStats + { + uint32_t max_mp = 0; + uint32_t max_hp = 0; + + uint32_t str = 0; + uint32_t dex = 0; + uint32_t vit = 0; + uint32_t inte = 0; + uint32_t mnd = 0; + uint32_t pie = 0; + + uint32_t tenacity = 0; + uint32_t attack = 0; + uint32_t defense = 0; + uint32_t accuracy = 0; + uint32_t spellSpeed = 0; + uint32_t magicDefense = 0; + uint32_t critHitRate = 0; + uint32_t resistSlash = 0; + uint32_t resistPierce = 0; + uint32_t resistBlunt = 0; + uint32_t attackPotMagic = 0; + uint32_t healingPotMagic = 0; + uint32_t determination = 0; + uint32_t skillSpeed = 0; + + uint32_t resistSlow = 0; + uint32_t resistSilence = 0; + uint32_t resistBlind = 0; + uint32_t resistPoison = 0; + uint32_t resistStun = 0; + uint32_t resistSleep = 0; + uint32_t resistBind = 0; + uint32_t resistHeavy = 0; + + uint32_t resistFire = 0; + uint32_t resistIce = 0; + uint32_t resistWind = 0; + uint32_t resistEarth = 0; + uint32_t resistLightning = 0; + uint32_t resistWater = 0; + + } m_baseStats; + +protected: + char m_name[34]; + /*! Id of the zone the actor currently is in */ + uint32_t m_zoneId; + /*! Ptr to the ZoneObj the actor belongs to */ + ZonePtr m_pCurrentZone; + /*! Last tick time for the actor ( in ms ) */ + uint64_t m_lastTickTime; + /*! Last time the actor performed an autoAttack ( in ms ) */ + uint64_t m_lastAttack; + /*! Last time the actor was updated ( in ms ) */ + uint64_t m_lastUpdate; + /*! Current stance of the actor */ + Stance m_currentStance; + /*! Current staus of the actor */ + ActorStatus m_status; + /*! Max HP of the actor ( based on job / class ) */ + uint32_t m_maxHp; + /*! Max MP of the actor ( based on job / class ) */ + uint32_t m_maxMp; + /*! Current HP of the actor */ + uint32_t m_hp; + /*! Current MP of the actor */ + uint32_t m_mp; + /*! Current TP of the actor */ + uint16_t m_tp; + /*! Current GP of the actor */ + uint16_t m_gp; + /*! Additional look info of the actor */ + uint8_t m_customize[26]; + /*! Current class of the actor */ + Common::ClassJob m_class; + /*! Id of the currently selected target actor */ + uint64_t m_targetId; + /*! Ptr to a queued action */ + Action::ActionPtr m_pCurrentAction; + /*! Invincibility type */ + Common::InvincibilityType m_invincibilityType; + + /*! Status effects */ + const uint8_t MAX_STATUS_EFFECTS = 30; + std::queue< uint8_t > m_statusEffectFreeSlotQueue; + std::vector< std::pair< uint8_t, uint32_t> > m_statusEffectList; + std::map< uint8_t, StatusEffect::StatusEffectPtr > m_statusEffectMap; + + std::set< CharaPtr > m_inRangeCharas; + std::set< PlayerPtr > m_inRangePlayers; + +public: + Chara( ObjKind type ); + + virtual ~Chara() override; + + virtual void calculateStats() {}; + + /// Status effect functions + void addStatusEffect( StatusEffect::StatusEffectPtr pEffect ); + void removeStatusEffect( uint8_t effectSlotId ); + void removeSingleStatusEffectById( uint32_t id ); + void updateStatusEffects(); + + bool hasStatusEffect( uint32_t id ); + + int8_t getStatusEffectFreeSlot(); + void statusEffectFreeSlot( uint8_t slotId ); + + std::map< uint8_t, Core::StatusEffect::StatusEffectPtr > getStatusEffectMap() const; + + void sendStatusEffectUpdate(); + // add a status effect by id + void addStatusEffectById( uint32_t id, int32_t duration, Entity::Chara& source, uint16_t param = 0 ); + + // add a status effect by id if it doesn't exist + void addStatusEffectByIdIfNotExist( uint32_t id, int32_t duration, Entity::Chara& source, uint16_t param = 0 ); + + // remove a status effect by id + void removeSingleStatusEffectFromId( uint32_t id ); + /// End Status Effect Functions + + void setPosition( const Common::FFXIVARR_POSITION3& pos ); + void setPosition( float x, float y, float z ); + + void setRotation( float rot ); + + float getRotation() const; + + std::string getName() const; + + std::set< CharaPtr > getInRangeCharas( bool includeSelf = false ); + + bool face( const Common::FFXIVARR_POSITION3& p ); + + Stance getStance() const; + + void setStance( Stance stance ); + + ActorStats getStats() const; + + uint32_t getHp() const; + uint32_t getMp() const; + uint16_t getTp() const; + uint16_t getGp() const; + + Common::InvincibilityType getInvincibilityType() const; + + Common::ClassJob getClass() const; + + uint8_t getClassAsInt() const; + + void setClass( Common::ClassJob classJob ); + + void setTargetId( uint64_t targetId ); + + uint64_t getTargetId() const; + + bool isAlive() const; + + virtual uint32_t getMaxHp() const; + virtual uint32_t getMaxMp() const; + + void resetHp(); + void resetMp(); + + void setHp( uint32_t hp ); + void setMp( uint32_t mp ); + void setGp( uint32_t gp ); + + void setInvincibilityType( Common::InvincibilityType type ); + + void die(); + + ActorStatus getStatus() const; + + void setStatus( ActorStatus status ); + + void handleScriptSkill( uint32_t type, uint16_t actionId, uint64_t param1, uint64_t param2, Entity::Chara& target ); + + virtual void autoAttack( CharaPtr pTarget ); + + virtual void onRemoveInRangeChara( Chara& pActor ) {} + + virtual void onDeath() {}; + virtual void onDamageTaken( Chara& pSource ) {}; + virtual void onActionHostile( Chara& source ) {}; + virtual void onActionFriendly( Chara& pSource ) {}; + virtual void onTick() {}; + + virtual void changeTarget( uint64_t targetId ); + virtual uint8_t getLevel() const; + virtual void sendStatusUpdate( bool toSelf = true ); + virtual void takeDamage( uint32_t damage ); + virtual void heal( uint32_t amount ); + virtual bool checkAction(); + virtual void update( int64_t currTime ) {}; + + Action::ActionPtr getCurrentAction() const; + + void setCurrentAction( Action::ActionPtr pAction ); + + ///// IN RANGE LOGIC ///// + + // check if another actor is in the actors in range set + bool isInRangeSet( CharaPtr pChara ) const; + + CharaPtr getClosestChara(); + + void sendToInRangeSet( Network::Packets::GamePacketPtr pPacket, bool bToSelf = false ); + + // add an actor to in range set + void addInRangeChara( CharaPtr pChara ); + + // remove an actor from the in range set + void removeInRangeChara( Chara& chara ); + + // return true if there is at least one actor in the in range set + bool hasInRangeActor() const; + + void removeFromInRange(); + + // clear the whole in range set, this does no cleanup + virtual void clearInRangeSet(); + + ZonePtr getCurrentZone() const; + + void setCurrentZone( ZonePtr currZone ); + + // get the current cell of a region the actor is in + Cell* getCell() const; + + // set the current cell + void setCell( Cell* pCell ); + + Core::Cell* m_pCell; + +}; + +} +} +#endif diff --git a/src/servers/sapphire_zone/Actor/EventNpc.cpp b/src/servers/sapphire_zone/Actor/EventNpc.cpp index af3eb0a3..47555f8b 100644 --- a/src/servers/sapphire_zone/Actor/EventNpc.cpp +++ b/src/servers/sapphire_zone/Actor/EventNpc.cpp @@ -24,7 +24,7 @@ extern Core::Logger g_log; uint32_t Core::Entity::EventNpc::m_nextID = 1249241694; Core::Entity::EventNpc::EventNpc() : - Actor( ObjKind::EventNpc ) + Chara( ObjKind::EventNpc ) { m_id = 0; m_status = ActorStatus::Idle; @@ -36,7 +36,7 @@ Core::Entity::EventNpc::~EventNpc() } Core::Entity::EventNpc::EventNpc( uint32_t enpcId, const Common::FFXIVARR_POSITION3& spawnPos, float rotation ) : - Actor( ObjKind::EventNpc ) + Chara( ObjKind::EventNpc ) { EventNpc::m_nextID++; m_id = EventNpc::m_nextID; diff --git a/src/servers/sapphire_zone/Actor/EventNpc.h b/src/servers/sapphire_zone/Actor/EventNpc.h index 726eae94..854e4453 100644 --- a/src/servers/sapphire_zone/Actor/EventNpc.h +++ b/src/servers/sapphire_zone/Actor/EventNpc.h @@ -1,13 +1,13 @@ #ifndef _EVENTNPC_H #define _EVENTNPC_H -#include "Actor.h" +#include "Chara.h" namespace Core { namespace Entity { -// class for Mobs inheriting from Actor -class EventNpc : public Actor +// class for Mobs inheriting from Chara +class EventNpc : public Chara { public: EventNpc(); diff --git a/src/servers/sapphire_zone/Actor/GameObject.cpp b/src/servers/sapphire_zone/Actor/GameObject.cpp deleted file mode 100644 index 16c042ab..00000000 --- a/src/servers/sapphire_zone/Actor/GameObject.cpp +++ /dev/null @@ -1,94 +0,0 @@ -#include "GameObject.h" - -#include "Player.h" -#include "Actor.h" -#include "BattleNpc.h" -#include "EventNpc.h" - -Core::Entity::GameObject::GameObject( ObjKind type ) : - m_objKind( type ) -{ - -} - -uint32_t Core::Entity::GameObject::getId() const -{ - return m_id; -} - -Core::Entity::GameObject::ObjKind Core::Entity::GameObject::getObjKind() const -{ - return m_objKind; -} - -Core::Common::FFXIVARR_POSITION3& Core::Entity::GameObject::getPos() -{ - return m_pos; -} - -void Core::Entity::GameObject::setPos( float x, float y, float z ) -{ - m_pos.x = x; - m_pos.y = y; - m_pos.z = z; -} - -void Core::Entity::GameObject::setPos( const Core::Common::FFXIVARR_POSITION3& pos ) -{ - m_pos = pos; -} - -float Core::Entity::GameObject::getRot() const -{ - return m_rot; -} - -void Core::Entity::GameObject::setRot( float rot ) -{ - m_rot = rot; -} - -bool Core::Entity::GameObject::isPlayer() const -{ - return m_objKind == ObjKind::Player; -} - -bool Core::Entity::GameObject::isBattleNpc() const -{ - return m_objKind == ObjKind::BattleNpc; -} - -bool Core::Entity::GameObject::isEventNpc() const -{ - return m_objKind == ObjKind::EventNpc; -} - -/*! \return pointer to this instance as ActorPtr */ -Core::Entity::ActorPtr Core::Entity::GameObject::getAsActor() -{ - return boost::dynamic_pointer_cast< Entity::Actor, Entity::GameObject >( shared_from_this() ); -} - -/*! \return pointer to this instance as PlayerPtr */ -Core::Entity::PlayerPtr Core::Entity::GameObject::getAsPlayer() -{ - if( !isPlayer() ) - return nullptr; - return boost::dynamic_pointer_cast< Entity::Player, Entity::GameObject >( shared_from_this() ); -} - -/*! \return pointer to this instance as BattleNpcPtr */ -Core::Entity::BattleNpcPtr Core::Entity::GameObject::getAsBattleNpc() -{ - if( !isBattleNpc() ) - return nullptr; - return boost::dynamic_pointer_cast< Entity::BattleNpc, Entity::GameObject >( shared_from_this() ); -} - -/*! \return pointer to this instance as EventNpcPtr */ -Core::Entity::EventNpcPtr Core::Entity::GameObject::getAsEventNpc() -{ - if( !isEventNpc() ) - return nullptr; - return boost::dynamic_pointer_cast< Entity::EventNpc, Entity::GameObject >( shared_from_this() ); -} diff --git a/src/servers/sapphire_zone/Actor/GameObject.h b/src/servers/sapphire_zone/Actor/GameObject.h deleted file mode 100644 index d1f70b3b..00000000 --- a/src/servers/sapphire_zone/Actor/GameObject.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef _GAME_OBJECT_H_ -#define _GAME_OBJECT_H_ - -#include -#include - -#include "Forwards.h" -#include -#include -#include - -namespace Core { -namespace Entity { - -/*! -\class GameObject -\brief Base class for all actor/objects - -*/ - class GameObject : public boost::enable_shared_from_this< GameObject > - { - public: - enum ObjKind : uint8_t - { - None = 0x00, - Player = 0x01, - BattleNpc = 0x02, - EventNpc = 0x03, - Treasure = 0x04, - Aetheryte = 0x05, - GatheringPoint = 0x06, - EventObj = 0x07, - Mount = 0x08, - Companion = 0x09, - Retainer = 0x0A, - Area = 0x0B, - Housing = 0x0C, - Cutscene = 0x0D, - CardStand = 0x0E, - }; - - protected: - /*! Position of the object */ - Common::FFXIVARR_POSITION3 m_pos; - /*! Rotation of the object */ - float m_rot; - /*! Id of the actor */ - uint32_t m_id; - /*! Type of the actor */ - ObjKind m_objKind; - - public: - explicit GameObject( ObjKind type ); - virtual ~GameObject() {}; - - virtual void spawn( PlayerPtr pTarget ) {} - virtual void despawn( PlayerPtr pTarget ) {} - - uint32_t getId() const; - - ObjKind getObjKind() const; - - Common::FFXIVARR_POSITION3& getPos(); - void setPos( const Common::FFXIVARR_POSITION3& pos ); - void setPos( float x, float y, float z ); - - float getRot() const; - void setRot( float rot ); - - bool isPlayer() const; - bool isBattleNpc() const; - bool isEventNpc() const; - - ActorPtr getAsActor(); - PlayerPtr getAsPlayer(); - BattleNpcPtr getAsBattleNpc(); - EventNpcPtr getAsEventNpc(); - }; - -} -} -#endif diff --git a/src/servers/sapphire_zone/Actor/InstanceObject.cpp b/src/servers/sapphire_zone/Actor/InstanceObject.cpp index a182b66b..17b75497 100644 --- a/src/servers/sapphire_zone/Actor/InstanceObject.cpp +++ b/src/servers/sapphire_zone/Actor/InstanceObject.cpp @@ -2,7 +2,7 @@ #include "Zone/InstanceContent.h" Core::Entity::InstanceObject::InstanceObject( uint32_t objectId, uint32_t mapLinkId ) : - Core::Entity::GameObject( ObjKind::EventObj ), + Core::Entity::Actor( ObjKind::EventObj ), m_mapLinkId( mapLinkId ), m_state( 0 ) { diff --git a/src/servers/sapphire_zone/Actor/InstanceObject.h b/src/servers/sapphire_zone/Actor/InstanceObject.h index 6bd61e0f..ed7d4d1a 100644 --- a/src/servers/sapphire_zone/Actor/InstanceObject.h +++ b/src/servers/sapphire_zone/Actor/InstanceObject.h @@ -1,13 +1,13 @@ #ifndef SAPPHIRE_INSTANCEOBJECT_H #define SAPPHIRE_INSTANCEOBJECT_H -#include "GameObject.h" +#include "Actor.h" namespace Core { namespace Entity { - class InstanceObject : public GameObject + class InstanceObject : public Actor { public: InstanceObject( uint32_t objectId, uint32_t mapLinkId ); diff --git a/src/servers/sapphire_zone/Actor/Player.cpp b/src/servers/sapphire_zone/Actor/Player.cpp index 4c7c3df8..e3cf4b3c 100644 --- a/src/servers/sapphire_zone/Actor/Player.cpp +++ b/src/servers/sapphire_zone/Actor/Player.cpp @@ -55,7 +55,7 @@ using namespace Core::Network::Packets::Server; // player constructor Core::Entity::Player::Player() : - Actor( ObjKind::Player ), + Chara( ObjKind::Player ), m_lastWrite( 0 ), m_lastPing( 0 ), m_bIsLogin( false ), @@ -250,7 +250,7 @@ void Core::Entity::Player::calculateStats() } -void Core::Entity::Player::setAutoattack(bool mode) +void Core::Entity::Player::setAutoattack( bool mode ) { m_bAutoattack = mode; m_lastAttack = Util::getTimeMs(); @@ -829,10 +829,10 @@ void Core::Entity::Player::despawn( Entity::PlayerPtr pTarget ) pPlayer->queuePacket( ActorControlPacket143( getId(), DespawnZoneScreenMsg, 0x04, getId(), 0x01 ) ); } -Core::Entity::ActorPtr Core::Entity::Player::lookupTargetById( uint64_t targetId ) +Core::Entity::CharaPtr Core::Entity::Player::lookupTargetById( uint64_t targetId ) { - ActorPtr targetActor; - auto inRange = getInRangeActors( true ); + CharaPtr targetActor; + auto inRange = getInRangeCharas(true); for( auto actor : inRange ) { if( actor->getId() == targetId ) @@ -1000,12 +1000,12 @@ void Core::Entity::Player::update( int64_t currTime ) if( !checkAction() ) { - if( m_targetId && m_currentStance == Entity::Actor::Stance::Active && isAutoattackOn() ) + if( m_targetId && m_currentStance == Entity::Chara::Stance::Active && isAutoattackOn() ) { auto mainWeap = m_pInventory->getItemAt( Inventory::GearSet0, Inventory::EquipSlot::MainHand ); // @TODO i dislike this, iterating over all in range actors when you already know the id of the actor you need... - for( auto actor : m_inRangeActors ) + for( auto actor : m_inRangeCharas ) { if( actor->getId() == m_targetId && actor->isAlive() && mainWeap ) { @@ -1408,7 +1408,7 @@ uint8_t Core::Entity::Player::getEquipDisplayFlags() const void Core::Entity::Player::mount( uint32_t id ) { m_mount = id; - sendToInRangeSet( ActorControlPacket142( getId(), ActorControlType::SetStatus, static_cast< uint8_t >( Entity::Actor::ActorStatus::Mounted )), true ); + sendToInRangeSet( ActorControlPacket142( getId(), ActorControlType::SetStatus, static_cast< uint8_t >( Entity::Chara::ActorStatus::Mounted )), true ); sendToInRangeSet( ActorControlPacket143( getId(), 0x39e, 12 ), true ); //? ZoneChannelPacket< FFXIVIpcMount > mountPacket( getId() ); @@ -1419,7 +1419,7 @@ void Core::Entity::Player::mount( uint32_t id ) void Core::Entity::Player::dismount() { sendToInRangeSet( ActorControlPacket142( getId(), ActorControlType::SetStatus, - static_cast< uint8_t >( Entity::Actor::ActorStatus::Idle )), true ); + static_cast< uint8_t >( Entity::Chara::ActorStatus::Idle )), true ); sendToInRangeSet( ActorControlPacket143( getId(), ActorControlType::Dismount, 1 ), true ); m_mount = 0; } @@ -1429,7 +1429,7 @@ uint8_t Core::Entity::Player::getCurrentMount() const return m_mount; } -void Core::Entity::Player::autoAttack( ActorPtr pTarget ) +void Core::Entity::Player::autoAttack( CharaPtr pTarget ) { auto mainWeap = m_pInventory->getItemAt( Inventory::GearSet0, @@ -1663,15 +1663,15 @@ void Core::Entity::Player::finishZoning() case ZoneingType::Return: case ZoneingType::ReturnDead: { - if( getStatus() == Entity::Actor::ActorStatus::Dead ) + if( getStatus() == Entity::Chara::ActorStatus::Dead ) { resetHp(); resetMp(); - setStatus( Entity::Actor::ActorStatus::Idle ); + setStatus( Entity::Chara::ActorStatus::Idle ); sendToInRangeSet( ActorControlPacket143( getId(), ZoneIn, 0x01, 0x01, 0, 111 ), true ); sendToInRangeSet( ActorControlPacket142( getId(), SetStatus, - static_cast< uint8_t >( Entity::Actor::ActorStatus::Idle ) ), true ); + static_cast< uint8_t >( Entity::Chara::ActorStatus::Idle ) ), true ); } else sendToInRangeSet( ActorControlPacket143( getId(), ZoneIn, 0x01, 0x00, 0, 111 ), true ); diff --git a/src/servers/sapphire_zone/Actor/Player.h b/src/servers/sapphire_zone/Actor/Player.h index 7fb80e58..291091c0 100644 --- a/src/servers/sapphire_zone/Actor/Player.h +++ b/src/servers/sapphire_zone/Actor/Player.h @@ -5,7 +5,7 @@ #include -#include "Actor.h" +#include "Chara.h" #include "Inventory/Inventory.h" #include "Event/EventHandler.h" #include @@ -33,7 +33,7 @@ struct QueuedZoning * Inheriting from Actor * */ -class Player : public Actor +class Player : public Chara { public: /*! Contructor */ @@ -42,7 +42,7 @@ public: /*! Destructor */ ~Player(); - void autoAttack( ActorPtr pTarget ) override; + void autoAttack( CharaPtr pTarget ) override; // EventHandlers ////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -526,7 +526,7 @@ public: bool actionHasCastTime( uint32_t actionId ); - Core::Entity::ActorPtr lookupTargetById( uint64_t targetId ); + Core::Entity::CharaPtr lookupTargetById( uint64_t targetId ); bool isLogin() const; void setIsLogin( bool bIsLogin ); diff --git a/src/servers/sapphire_zone/Actor/PlayerEvent.cpp b/src/servers/sapphire_zone/Actor/PlayerEvent.cpp index aeeb5ad9..b0ba4679 100644 --- a/src/servers/sapphire_zone/Actor/PlayerEvent.cpp +++ b/src/servers/sapphire_zone/Actor/PlayerEvent.cpp @@ -227,7 +227,7 @@ void Core::Entity::Player::eventActionStart( uint32_t eventId, ActionCallback interruptCallback, uint64_t additional ) { - auto pEventAction = Action::make_EventAction( getAsActor(), eventId, action, + auto pEventAction = Action::make_EventAction( getAsChara(), eventId, action, finishCallback, interruptCallback, additional ); setCurrentAction( pEventAction ); @@ -257,7 +257,7 @@ void Core::Entity::Player::eventItemActionStart( uint32_t eventId, ActionCallback interruptCallback, uint64_t additional ) { - Action::ActionPtr pEventItemAction = Action::make_EventItemAction( getAsActor(), eventId, action, + Action::ActionPtr pEventItemAction = Action::make_EventItemAction( getAsChara(), eventId, action, finishCallback, interruptCallback, additional ); setCurrentAction( pEventItemAction ); diff --git a/src/servers/sapphire_zone/Forwards.h b/src/servers/sapphire_zone/Forwards.h index fa387adb..85e07eef 100644 --- a/src/servers/sapphire_zone/Forwards.h +++ b/src/servers/sapphire_zone/Forwards.h @@ -34,8 +34,8 @@ namespace Core namespace Entity { - TYPE_FORWARD( GameObject ); TYPE_FORWARD( Actor ); + TYPE_FORWARD( Chara ); TYPE_FORWARD( Player ); TYPE_FORWARD( BattleNpc ); TYPE_FORWARD( EventNpc ); diff --git a/src/servers/sapphire_zone/Math/CalcBattle.cpp b/src/servers/sapphire_zone/Math/CalcBattle.cpp index fb95cddc..9b1bc1a4 100644 --- a/src/servers/sapphire_zone/Math/CalcBattle.cpp +++ b/src/servers/sapphire_zone/Math/CalcBattle.cpp @@ -2,7 +2,7 @@ #include #include -#include "Actor/Actor.h" +#include "Actor/Chara.h" #include "Actor/Player.h" #include "CalcBattle.h" diff --git a/src/servers/sapphire_zone/Math/CalcBattle.h b/src/servers/sapphire_zone/Math/CalcBattle.h index 8c43107f..72a160c0 100644 --- a/src/servers/sapphire_zone/Math/CalcBattle.h +++ b/src/servers/sapphire_zone/Math/CalcBattle.h @@ -2,7 +2,7 @@ #define _CALCBATTLE_H #include -#include "Actor/Actor.h" +#include "Actor/Chara.h" using namespace Core::Entity; diff --git a/src/servers/sapphire_zone/Math/CalcStats.cpp b/src/servers/sapphire_zone/Math/CalcStats.cpp index d15814dd..52213552 100644 --- a/src/servers/sapphire_zone/Math/CalcStats.cpp +++ b/src/servers/sapphire_zone/Math/CalcStats.cpp @@ -2,7 +2,7 @@ #include #include -#include "Actor/Actor.h" +#include "Actor/Chara.h" #include "Actor/Player.h" #include "CalcStats.h" diff --git a/src/servers/sapphire_zone/Math/CalcStats.h b/src/servers/sapphire_zone/Math/CalcStats.h index 2bf17da5..868d86f4 100644 --- a/src/servers/sapphire_zone/Math/CalcStats.h +++ b/src/servers/sapphire_zone/Math/CalcStats.h @@ -2,7 +2,7 @@ #define _CALCSTATS_H #include -#include "Actor/Actor.h" +#include "Actor/Chara.h" using namespace Core::Entity; diff --git a/src/servers/sapphire_zone/Network/Handlers/ActionHandler.cpp b/src/servers/sapphire_zone/Network/Handlers/ActionHandler.cpp index 70ce5885..9739756a 100644 --- a/src/servers/sapphire_zone/Network/Handlers/ActionHandler.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/ActionHandler.cpp @@ -119,10 +119,10 @@ void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& in case ClientTrigger::ToggleSeathe: // Toggle sheathe { if ( param11 == 1 ) - player.setStance( Entity::Actor::Stance::Active ); + player.setStance( Entity::Chara::Stance::Active ); else { - player.setStance( Entity::Actor::Stance::Passive ); + player.setStance( Entity::Chara::Stance::Passive ); player.setAutoattack( false ); } @@ -135,7 +135,7 @@ void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& in if ( param11 == 1 ) { player.setAutoattack( true ); - player.setStance( Entity::Actor::Stance::Active ); + player.setStance( Entity::Chara::Stance::Active ); } else player.setAutoattack( false ); diff --git a/src/servers/sapphire_zone/Network/Handlers/EventHandlers.cpp b/src/servers/sapphire_zone/Network/Handlers/EventHandlers.cpp index 399fdf9b..692fc1a5 100644 --- a/src/servers/sapphire_zone/Network/Handlers/EventHandlers.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/EventHandlers.cpp @@ -37,7 +37,7 @@ void Core::Network::GameConnection::eventHandlerTalk( const Packets::GamePacket& std::string eventName = "onTalk"; std::string objName = Event::getEventName( eventId ); - player.sendDebug( "Actor: " + + player.sendDebug( "Chara: " + std::to_string( actorId ) + " -> " + std::to_string( Event::mapEventActorToRealActor( static_cast< uint32_t >( actorId ) ) ) + " \neventId: " + @@ -72,7 +72,7 @@ void Core::Network::GameConnection::eventHandlerEmote( const Packets::GamePacket std::string eventName = "onEmote"; std::string objName = Event::getEventName( eventId ); - player.sendDebug( "Actor: " + + player.sendDebug( "Chara: " + std::to_string( actorId ) + " -> " + std::to_string( Event::mapEventActorToRealActor( static_cast< uint32_t >( actorId ) ) ) + " \neventId: " + diff --git a/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp b/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp index 865ffdc1..63c19006 100644 --- a/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp @@ -104,7 +104,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac ", params: " + std::to_string( param1 ) + ", " + std::to_string( param2 ) + ", " + std::to_string( param3 ) ); - Core::Entity::ActorPtr targetActor; + Core::Entity::CharaPtr targetActor; if( player.getId() == param3 ) @@ -113,7 +113,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac } else { - auto inRange = player.getInRangeActors(); + auto inRange = player.getInRangeCharas(); for( auto actor : inRange ) { if( actor->getId() == param3 ) @@ -138,7 +138,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac targetPlayer->setLookAt( CharaLook::Race, param1 ); player.sendNotice( "Race for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) ); targetPlayer->spawn( targetPlayer ); - auto inRange = targetPlayer->getInRangeActors(); + auto inRange = targetPlayer->getInRangeCharas(); for( auto actor : inRange ) { targetPlayer->despawn( actor->getAsPlayer() ); @@ -151,7 +151,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac targetPlayer->setLookAt( CharaLook::Tribe, param1 ); player.sendNotice( "Tribe for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) ); targetPlayer->spawn( targetPlayer ); - auto inRange = targetPlayer->getInRangeActors(); + auto inRange = targetPlayer->getInRangeCharas(); for( auto actor : inRange ) { targetPlayer->despawn( actor->getAsPlayer() ); @@ -164,7 +164,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac targetPlayer->setLookAt( CharaLook::Gender, param1 ); player.sendNotice( "Sex for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) ); targetPlayer->spawn( targetPlayer ); - auto inRange = targetActor->getInRangeActors(); + auto inRange = targetActor->getInRangeCharas(); for( auto actor : inRange ) { targetPlayer->despawn( actor->getAsPlayer() ); @@ -439,7 +439,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac case GmCommand::Jump: { - auto inRange = player.getInRangeActors(); + auto inRange = player.getInRangeCharas(); player.changePosition( targetActor->getPos().x, targetActor->getPos().y, targetActor->getPos().z, targetActor->getRotation() ); @@ -466,7 +466,7 @@ void Core::Network::GameConnection::gm2Handler( const Packets::GamePacket& inPac g_log.debug( player.getName() + " used GM2 commandId: " + std::to_string( commandId ) + ", params: " + param1 ); auto targetSession = g_serverZone.getSession( param1 ); - Core::Entity::ActorPtr targetActor; + Core::Entity::CharaPtr targetActor; if( targetSession != nullptr ) { @@ -496,11 +496,11 @@ void Core::Network::GameConnection::gm2Handler( const Packets::GamePacket& inPac { targetPlayer->resetHp(); targetPlayer->resetMp(); - targetPlayer->setStatus( Entity::Actor::ActorStatus::Idle ); + targetPlayer->setStatus( Entity::Chara::ActorStatus::Idle ); targetPlayer->sendToInRangeSet( ActorControlPacket143( player.getId(), ZoneIn, 0x01, 0x01, 0, 113 ), true ); targetPlayer->sendToInRangeSet( ActorControlPacket142( player.getId(), SetStatus, - static_cast< uint8_t >( Entity::Actor::ActorStatus::Idle ) ), true ); + static_cast< uint8_t >( Entity::Chara::ActorStatus::Idle ) ), true ); player.sendNotice( "Raised " + targetPlayer->getName() ); break; } diff --git a/src/servers/sapphire_zone/Network/Handlers/SkillHandler.cpp b/src/servers/sapphire_zone/Network/Handlers/SkillHandler.cpp index a47a4988..ac964471 100644 --- a/src/servers/sapphire_zone/Network/Handlers/SkillHandler.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/SkillHandler.cpp @@ -75,7 +75,7 @@ void Core::Network::GameConnection::skillHandler( const Packets::GamePacket& inP } else { - Core::Entity::ActorPtr targetActor = player.getAsPlayer(); + Core::Entity::CharaPtr targetActor = player.getAsPlayer(); if( targetId != player.getId() ) { targetActor = player.lookupTargetById( targetId ); diff --git a/src/servers/sapphire_zone/Network/PacketWrappers/MoveActorPacket.h b/src/servers/sapphire_zone/Network/PacketWrappers/MoveActorPacket.h index 1771d801..ee671e85 100644 --- a/src/servers/sapphire_zone/Network/PacketWrappers/MoveActorPacket.h +++ b/src/servers/sapphire_zone/Network/PacketWrappers/MoveActorPacket.h @@ -21,14 +21,14 @@ class MoveActorPacket : public ZoneChannelPacket< FFXIVIpcActorMove > { public: - MoveActorPacket( Entity::Actor& actor, uint8_t unk1, uint8_t unk2, uint8_t unk3, uint16_t unk4 ) : + MoveActorPacket( Entity::Chara& actor, uint8_t unk1, uint8_t unk2, uint8_t unk3, uint16_t unk4 ) : ZoneChannelPacket< FFXIVIpcActorMove >( actor.getId(), actor.getId() ) { initialize( actor, unk1, unk2, unk3, unk4 ); }; private: - void initialize( Entity::Actor& actor, uint8_t unk1, uint8_t unk2, uint8_t unk3, uint16_t unk4 ) + void initialize( Entity::Chara& actor, uint8_t unk1, uint8_t unk2, uint8_t unk3, uint16_t unk4 ) { m_data.rotation = Math::Util::floatToUInt8Rot( actor.getRotation() ); diff --git a/src/servers/sapphire_zone/Network/PacketWrappers/PlayerSpawnPacket.h b/src/servers/sapphire_zone/Network/PacketWrappers/PlayerSpawnPacket.h index 9c367aa9..e940e53a 100644 --- a/src/servers/sapphire_zone/Network/PacketWrappers/PlayerSpawnPacket.h +++ b/src/servers/sapphire_zone/Network/PacketWrappers/PlayerSpawnPacket.h @@ -90,22 +90,22 @@ namespace Server { if( player.getZoningType() != Common::ZoneingType::None ) { - m_data.displayFlags |= Entity::Actor::DisplayFlags::Invisible; + m_data.displayFlags |= Entity::Chara::DisplayFlags::Invisible; } if( player.getEquipDisplayFlags() & Core::Common::EquipDisplayFlags::HideHead ) { - m_data.displayFlags |= Entity::Actor::DisplayFlags::HideHead; + m_data.displayFlags |= Entity::Chara::DisplayFlags::HideHead; } if( player.getEquipDisplayFlags() & Core::Common::EquipDisplayFlags::HideWeapon ) { - m_data.displayFlags |= Entity::Actor::DisplayFlags::HideWeapon; + m_data.displayFlags |= Entity::Chara::DisplayFlags::HideWeapon; } if( player.getEquipDisplayFlags() & Core::Common::EquipDisplayFlags::Visor ) { - m_data.displayFlags |= Entity::Actor::DisplayFlags::Visor; + m_data.displayFlags |= Entity::Chara::DisplayFlags::Visor; } m_data.currentMount = player.getCurrentMount(); diff --git a/src/servers/sapphire_zone/Network/PacketWrappers/UpdateHpMpTpPacket.h b/src/servers/sapphire_zone/Network/PacketWrappers/UpdateHpMpTpPacket.h index e880a4da..64952593 100644 --- a/src/servers/sapphire_zone/Network/PacketWrappers/UpdateHpMpTpPacket.h +++ b/src/servers/sapphire_zone/Network/PacketWrappers/UpdateHpMpTpPacket.h @@ -2,7 +2,7 @@ #define _UPDATEHPMPTP_H #include -#include +#include #include "Forwards.h" namespace Core { @@ -17,14 +17,14 @@ class UpdateHpMpTpPacket : public ZoneChannelPacket< FFXIVIpcUpdateHpMpTp > { public: - UpdateHpMpTpPacket( Entity::Actor& actor ) : + UpdateHpMpTpPacket( Entity::Chara& actor ) : ZoneChannelPacket< FFXIVIpcUpdateHpMpTp >( actor.getId(), actor.getId() ) { initialize( actor ); }; private: - void initialize( Entity::Actor& actor ) + void initialize( Entity::Chara& actor ) { m_data.hp = actor.getHp(); m_data.mp = actor.getMp(); diff --git a/src/servers/sapphire_zone/Script/NativeScriptApi.h b/src/servers/sapphire_zone/Script/NativeScriptApi.h index 893dc6cd..1d5e5b22 100644 --- a/src/servers/sapphire_zone/Script/NativeScriptApi.h +++ b/src/servers/sapphire_zone/Script/NativeScriptApi.h @@ -5,7 +5,7 @@ #include #include -#include +#include #include #include #include @@ -53,14 +53,14 @@ public: ScriptObject( effectId, typeid( StatusEffectScript ).hash_code() ) { } - virtual void onTick( Entity::Actor& actor ) { } - virtual void onApply( Entity::Actor& actor ) { } - virtual void onRemove( Entity::Actor& actor ) { } - virtual void onExpire( Entity::Actor& actor ) { } - virtual void onPlayerCollision( Entity::Actor& actor, Entity::Actor& actorHit ) { } - virtual void onPlayerFinishCast( Entity::Actor& actor ) { } - virtual void onPlayerDamaged( Entity::Actor& actor ) { } - virtual void onPlayerDeath( Entity::Actor& actor ) { } + virtual void onTick( Entity::Chara& actor ) { } + virtual void onApply( Entity::Chara& actor ) { } + virtual void onRemove( Entity::Chara& actor ) { } + virtual void onExpire( Entity::Chara& actor ) { } + virtual void onPlayerCollision( Entity::Chara& actor, Entity::Chara& actorHit ) { } + virtual void onPlayerFinishCast( Entity::Chara& actor ) { } + virtual void onPlayerDamaged( Entity::Chara& actor ) { } + virtual void onPlayerDeath( Entity::Chara& actor ) { } }; @@ -71,9 +71,9 @@ public: ScriptObject( abilityId, typeid( ActionScript ).hash_code() ) { } - virtual void onStart( Entity::Actor& sourceActor, Entity::Actor& targetActor ) { } - virtual void onCastFinish( Entity::Player& player, Entity::Actor& targetActor ) { } - virtual void onInterrupt( Entity::Actor& sourceActor/*, Core::Entity::Actor targetActor*/ ) { } + virtual void onStart( Entity::Chara& sourceActor, Entity::Chara& targetActor ) { } + virtual void onCastFinish( Entity::Player& player, Entity::Chara& targetActor ) { } + virtual void onInterrupt( Entity::Chara& sourceActor/*, Core::Entity::Chara targetActor*/ ) { } }; diff --git a/src/servers/sapphire_zone/Script/ScriptManager.cpp b/src/servers/sapphire_zone/Script/ScriptManager.cpp index 1e569918..07f0b18f 100644 --- a/src/servers/sapphire_zone/Script/ScriptManager.cpp +++ b/src/servers/sapphire_zone/Script/ScriptManager.cpp @@ -275,7 +275,7 @@ bool Core::Scripting::ScriptManager::onMobKill( Entity::Player& player, uint16_t return true; } -bool Core::Scripting::ScriptManager::onCastFinish( Entity::Player& player, Entity::ActorPtr pTarget, uint32_t actionId ) +bool Core::Scripting::ScriptManager::onCastFinish( Entity::Player& player, Entity::CharaPtr pTarget, uint32_t actionId ) { auto script = m_nativeScriptManager->getScript< ActionScript >( actionId ); @@ -284,7 +284,7 @@ bool Core::Scripting::ScriptManager::onCastFinish( Entity::Player& player, Entit return true; } -bool Core::Scripting::ScriptManager::onStatusReceive( Entity::ActorPtr pActor, uint32_t effectId ) +bool Core::Scripting::ScriptManager::onStatusReceive( Entity::CharaPtr pActor, uint32_t effectId ) { auto script = m_nativeScriptManager->getScript< StatusEffectScript >( effectId ); @@ -300,30 +300,30 @@ bool Core::Scripting::ScriptManager::onStatusReceive( Entity::ActorPtr pActor, u return false; } -bool Core::Scripting::ScriptManager::onStatusTick( Entity::ActorPtr pActor, Core::StatusEffect::StatusEffect& effect ) +bool Core::Scripting::ScriptManager::onStatusTick( Entity::CharaPtr pChara, Core::StatusEffect::StatusEffect& effect ) { auto script = m_nativeScriptManager->getScript< StatusEffectScript >( effect.getId() ); if( script ) { - if( pActor->isPlayer() ) - pActor->getAsPlayer()->sendDebug( "Calling status tick for statusid: " + std::to_string( effect.getId() ) ); + if( pChara->isPlayer() ) + pChara->getAsPlayer()->sendDebug( "Calling status tick for statusid: " + std::to_string( effect.getId() ) ); - script->onTick( *pActor ); + script->onTick( *pChara ); return true; } return false; } -bool Core::Scripting::ScriptManager::onStatusTimeOut( Entity::ActorPtr pActor, uint32_t effectId ) +bool Core::Scripting::ScriptManager::onStatusTimeOut( Entity::CharaPtr pChara, uint32_t effectId ) { auto script = m_nativeScriptManager->getScript< StatusEffectScript >( effectId ); if( script ) { - if( pActor->isPlayer() ) - pActor->getAsPlayer()->sendDebug( "Calling status timeout for statusid: " + std::to_string( effectId ) ); + if( pChara->isPlayer() ) + pChara->getAsPlayer()->sendDebug( "Calling status timeout for statusid: " + std::to_string( effectId ) ); - script->onExpire( *pActor ); + script->onExpire( *pChara ); return true; } diff --git a/src/servers/sapphire_zone/Script/ScriptManager.h b/src/servers/sapphire_zone/Script/ScriptManager.h index 634afefb..ac423b39 100644 --- a/src/servers/sapphire_zone/Script/ScriptManager.h +++ b/src/servers/sapphire_zone/Script/ScriptManager.h @@ -48,11 +48,11 @@ namespace Core bool onMobKill( Entity::Player& player, uint16_t nameId ); - bool onCastFinish( Entity::Player& pPlayer, Entity::ActorPtr pTarget, uint32_t actionId ); + bool onCastFinish( Entity::Player& pPlayer, Entity::CharaPtr pTarget, uint32_t actionId ); - bool onStatusReceive( Entity::ActorPtr pActor, uint32_t effectId ); - bool onStatusTick( Entity::ActorPtr pActor, Core::StatusEffect::StatusEffect& effect ); - bool onStatusTimeOut( Entity::ActorPtr pActor, uint32_t effectId ); + bool onStatusReceive( Entity::CharaPtr pActor, uint32_t effectId ); + bool onStatusTick( Entity::CharaPtr pActor, Core::StatusEffect::StatusEffect& effect ); + bool onStatusTimeOut( Entity::CharaPtr pActor, uint32_t effectId ); bool onZoneInit( ZonePtr pZone ); diff --git a/src/servers/sapphire_zone/Script/Scripts/ScriptObject.h b/src/servers/sapphire_zone/Script/Scripts/ScriptObject.h index 17da1520..3848b55c 100644 --- a/src/servers/sapphire_zone/Script/Scripts/ScriptObject.h +++ b/src/servers/sapphire_zone/Script/Scripts/ScriptObject.h @@ -3,7 +3,7 @@ #include