1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-29 07:37:45 +00:00
This commit is contained in:
Alice Ogeda 2023-03-05 20:46:58 -03:00
commit 78766f9700
21 changed files with 326 additions and 361 deletions

View file

@ -3,12 +3,10 @@
#include <Action/Action.h> #include <Action/Action.h>
#include <Inventory/Item.h> #include <Inventory/Item.h>
class ActionDye2472 : class ActionDye2472 : public Sapphire::ScriptAPI::ActionScript
public Sapphire::ScriptAPI::ActionScript
{ {
public: public:
ActionDye2472() : ActionDye2472() : Sapphire::ScriptAPI::ActionScript( 2472 )
Sapphire::ScriptAPI::ActionScript( 2472 )
{ {
} }

View file

@ -3,12 +3,10 @@
#include <Action/Action.h> #include <Action/Action.h>
#include <Inventory/Item.h> #include <Inventory/Item.h>
class ActionGlamour2471 : class ActionGlamour2471 : public Sapphire::ScriptAPI::ActionScript
public Sapphire::ScriptAPI::ActionScript
{ {
public: public:
ActionGlamour2471() : ActionGlamour2471() : Sapphire::ScriptAPI::ActionScript( 2471 )
Sapphire::ScriptAPI::ActionScript( 2471 )
{ {
} }

View file

@ -5,12 +5,10 @@
#include <Manager/PlayerMgr.h> #include <Manager/PlayerMgr.h>
#include <Service.h> #include <Service.h>
class ActionReturn6 : class ActionReturn6 : public Sapphire::ScriptAPI::ActionScript
public Sapphire::ScriptAPI::ActionScript
{ {
public: public:
ActionReturn6() : ActionReturn6() : Sapphire::ScriptAPI::ActionScript( 6 )
Sapphire::ScriptAPI::ActionScript( 6 )
{ {
} }

View file

@ -5,8 +5,7 @@
class ActionSprint3 : public Sapphire::ScriptAPI::ActionScript class ActionSprint3 : public Sapphire::ScriptAPI::ActionScript
{ {
public: public:
ActionSprint3() : ActionSprint3() : Sapphire::ScriptAPI::ActionScript( 3 )
Sapphire::ScriptAPI::ActionScript( 3 )
{ {
} }

View file

@ -5,12 +5,10 @@
using namespace Sapphire; using namespace Sapphire;
class ActionTeleport5 : class ActionTeleport5 : public Sapphire::ScriptAPI::ActionScript
public Sapphire::ScriptAPI::ActionScript
{ {
public: public:
ActionTeleport5() : ActionTeleport5() : Sapphire::ScriptAPI::ActionScript( 5 )
Sapphire::ScriptAPI::ActionScript( 5 )
{ {
} }

View file

@ -101,8 +101,7 @@ private:
void Scene00001Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) void Scene00001Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result )
{ {
playerMgr().setGrandCompany( player, OrderOfTwinAdder ); player.setGrandCompany( OrderOfTwinAdder );
playerMgr().setGrandCompanyRank( player, OrderOfTwinAdder, 1 );
Scene00002( quest, player ); Scene00002( quest, player );
} }

View file

@ -23,6 +23,7 @@
#include "Network/PacketWrappers/ActorControlPacket.h" #include "Network/PacketWrappers/ActorControlPacket.h"
#include "Network/PacketWrappers/ActorControlSelfPacket.h" #include "Network/PacketWrappers/ActorControlSelfPacket.h"
#include "Network/PacketWrappers/ActorControlTargetPacket.h" #include "Network/PacketWrappers/ActorControlTargetPacket.h"
#include "Network/Util/PlayerUtil.h"
#include <Logging/Logger.h> #include <Logging/Logger.h>
@ -517,7 +518,8 @@ void Action::Action::buildEffects()
return; return;
} }
playerMgr().onHudParamChanged( *m_pSource->getAsPlayer() );
Network::Util::Player::sendHudParam( *m_pSource->getAsPlayer() );
if( !hasLutEntry || m_hitActors.empty() ) if( !hasLutEntry || m_hitActors.empty() )
{ {

View file

@ -34,6 +34,8 @@
#include "Network/PacketWrappers/EffectPacket1.h" #include "Network/PacketWrappers/EffectPacket1.h"
#include "Network/PacketWrappers/InitZonePacket.h" #include "Network/PacketWrappers/InitZonePacket.h"
#include "Network/Util/PlayerUtil.h"
#include "Action/Action.h" #include "Action/Action.h"
#include "Math/CalcStats.h" #include "Math/CalcStats.h"
@ -261,7 +263,7 @@ void Player::addOnlineStatus( OnlineStatus status )
setOnlineStatusMask( newFlags ); setOnlineStatusMask( newFlags );
Service< World::Manager::PlayerMgr >::ref().onOnlineStatusChanged( *this, false ); Network::Util::Player::sendOnlineStatus( *this );
} }
void Player::addOnlineStatus( const std::vector< Common::OnlineStatus >& status ) void Player::addOnlineStatus( const std::vector< Common::OnlineStatus >& status )
@ -275,7 +277,7 @@ void Player::addOnlineStatus( const std::vector< Common::OnlineStatus >& status
setOnlineStatusMask( newFlags ); setOnlineStatusMask( newFlags );
Service< World::Manager::PlayerMgr >::ref().onOnlineStatusChanged( *this, false ); Network::Util::Player::sendOnlineStatus( *this );
} }
void Player::removeOnlineStatus( OnlineStatus status ) void Player::removeOnlineStatus( OnlineStatus status )
@ -289,7 +291,7 @@ void Player::removeOnlineStatus( OnlineStatus status )
setOnlineStatusMask( newFlags ); setOnlineStatusMask( newFlags );
setOnlineStatusCustomMask( newFlagsCustom ); setOnlineStatusCustomMask( newFlagsCustom );
Service< World::Manager::PlayerMgr >::ref().onOnlineStatusChanged( *this, false ); Network::Util::Player::sendOnlineStatus( *this );
} }
void Player::removeOnlineStatus( const std::vector< Common::OnlineStatus >& status ) void Player::removeOnlineStatus( const std::vector< Common::OnlineStatus >& status )
@ -306,7 +308,7 @@ void Player::removeOnlineStatus( const std::vector< Common::OnlineStatus >& stat
setOnlineStatusMask( newFlags ); setOnlineStatusMask( newFlags );
setOnlineStatusCustomMask( newFlagsCustom ); setOnlineStatusCustomMask( newFlagsCustom );
Service< World::Manager::PlayerMgr >::ref().onOnlineStatusChanged( *this, false ); Network::Util::Player::sendOnlineStatus( *this );
} }
void Player::calculateStats() void Player::calculateStats()
@ -394,11 +396,6 @@ bool Player::isAutoattackOn() const
return m_bAutoattack; return m_bAutoattack;
} }
void Player::sendStats()
{
Service< World::Manager::PlayerMgr >::ref().onStatsChanged( *this );
}
bool Player::exitInstance() bool Player::exitInstance()
{ {
auto& warpMgr = Common::Service< WarpMgr >::ref(); auto& warpMgr = Common::Service< WarpMgr >::ref();
@ -459,7 +456,7 @@ void Player::registerAetheryte( uint8_t aetheryteId )
Util::valueToFlagByteIndexValue( aetheryteId, value, index ); Util::valueToFlagByteIndexValue( aetheryteId, value, index );
m_aetheryte[ index ] |= value; m_aetheryte[ index ] |= value;
server().queueForPlayer( getCharacterId(), makeActorControlSelf( getId(), LearnTeleport, aetheryteId, 1 ) ); Network::Util::Player::sendActorControlSelf( *this, LearnTeleport, aetheryteId, 1 );
} }
bool Player::isAetheryteRegistered( uint8_t aetheryteId ) const bool Player::isAetheryteRegistered( uint8_t aetheryteId ) const
@ -476,48 +473,43 @@ Player::Discovery& Player::getDiscoveryBitmask()
return m_discovery; return m_discovery;
} }
void Player::discover( int16_t map_id, int16_t sub_id ) void Player::discover( int16_t mapId, int16_t subId )
{ {
// map.exd field 12 -> index in one of the two discovery sections, if field 15 is false, need to use 2nd section
// section 1 starts at 0 - 2 bytes each
// section to starts at 320 - 4 bytes long
auto& exdData = Common::Service< Data::ExdData >::ref(); auto& exdData = Common::Service< Data::ExdData >::ref();
int32_t offset; int32_t offset;
auto info = exdData.getRow< Excel::Map >( map_id ); auto info = exdData.getRow< Excel::Map >( mapId );
if( !info ) if( !info )
{ {
PlayerMgr::sendDebug( *this, "discover(): Could not obtain map data for map_id == {0}", map_id ); PlayerMgr::sendDebug( *this, "discover(): Could not obtain map data for map_id == {0}", mapId );
return; return;
} }
if( info->data().IsUint16Discovery ) const auto& mapData = info->data();
offset = 2 * info->data().DiscoveryIndex;
if( mapData.IsUint16Discovery )
offset = 2 * mapData.DiscoveryIndex;
else else
offset = 320 + 4 * info->data().DiscoveryIndex; offset = 320 + 4 * mapData.DiscoveryIndex;
int32_t index = offset + sub_id / 8; uint16_t index;
uint8_t bitIndex = sub_id % 8; uint8_t value;
Util::valueToFlagByteIndexValue( subId, value, index );
uint8_t value = 1 << bitIndex; m_discovery[ offset + index ] |= value;
m_discovery[ index ] |= value;
uint16_t level = getLevel(); uint16_t level = getLevel();
uint32_t exp = ( exdData.getRow< Excel::ParamGrow >( level )->data().NextExp * 5 / 100 ); uint32_t exp = ( exdData.getRow< Excel::ParamGrow >( level )->data().NextExp * 5 / 100 );
gainExp( exp ); gainExp( exp );
// gain 10x additional EXP if entire map is completed // gain 10x additional EXP if entire map is completed
uint32_t mask = info->data().DiscoveryFlag; uint32_t mask = mapData.DiscoveryFlag;
uint32_t discoveredAreas; uint32_t discoveredAreas;
if( info->data().IsUint16Discovery ) if( info->data().IsUint16Discovery )
{ {
discoveredAreas = ( m_discovery[ offset + 1 ] << 8 ) | discoveredAreas = ( m_discovery[ offset + 1 ] << 8 ) | m_discovery[ offset ];
m_discovery[ offset ];
} }
else else
{ {
@ -567,7 +559,7 @@ void Player::setRewardFlag( Common::UnlockEntry unlockId )
m_unlocks[ index ] |= value; m_unlocks[ index ] |= value;
server().queueForPlayer( getCharacterId(), makeActorControlSelf( getId(), SetRewardFlag, unlock, 1 ) ); Network::Util::Player::sendActorControlSelf( *this, SetRewardFlag, unlock, 1 );
} }
void Player::learnSong( uint8_t songId, uint32_t itemId ) void Player::learnSong( uint8_t songId, uint32_t itemId )
@ -629,18 +621,19 @@ void Player::gainExp( uint32_t amount )
amount = ( currentExp + amount - neededExpToLevel ) > neededExpToLevelPlus1 ? amount = ( currentExp + amount - neededExpToLevel ) > neededExpToLevelPlus1 ?
neededExpToLevelPlus1 - 1 : neededExpToLevelPlus1 - 1 :
( currentExp + amount - neededExpToLevel ); ( currentExp + amount - neededExpToLevel );
if( level + 1 >= Common::MAX_PLAYER_LEVEL ) if( level + 1 >= Common::MAX_PLAYER_LEVEL )
amount = 0; amount = 0;
setExp( amount ); setExp( amount );
Service< World::Manager::PlayerMgr >::ref().onGainExp( *this, amount );
levelUp(); levelUp();
} }
else else
{ {
setExp( currentExp + amount ); setExp( currentExp + amount );
Service< World::Manager::PlayerMgr >::ref().onGainExp( *this, amount );
} }
Service< World::Manager::PlayerMgr >::ref().onGainExp( *this, amount );
} }
void Player::levelUp() void Player::levelUp()
@ -654,12 +647,6 @@ void Player::levelUp()
Service< World::Manager::MapMgr >::ref().updateQuests( *this ); Service< World::Manager::MapMgr >::ref().updateQuests( *this );
} }
void Player::sendHudParam()
{
// todo: overrides are funky
Service< World::Manager::PlayerMgr >::ref().onHudParamChanged( *this );
}
uint8_t Player::getLevel() const uint8_t Player::getLevel() const
{ {
auto& exdData = Common::Service< Data::ExdData >::ref(); auto& exdData = Common::Service< Data::ExdData >::ref();
@ -673,10 +660,10 @@ uint8_t Player::getLevelSync() const
return getLevel(); return getLevel();
} }
uint8_t Player::getLevelForClass( Common::ClassJob pClass ) const uint8_t Player::getLevelForClass( Common::ClassJob classJobId ) const
{ {
auto& exdData = Common::Service< Data::ExdData >::ref(); auto& exdData = Common::Service< Data::ExdData >::ref();
uint8_t classJobIndex = exdData.getRow< Excel::ClassJob >( static_cast< uint8_t >( pClass ) )->data().WorkIndex; uint8_t classJobIndex = exdData.getRow< Excel::ClassJob >( static_cast< uint8_t >( classJobId ) )->data().WorkIndex;
return static_cast< uint8_t >( m_classArray[ classJobIndex ] ); return static_cast< uint8_t >( m_classArray[ classJobIndex ] );
} }
@ -728,8 +715,9 @@ void Player::setClassJob( Common::ClassJob classJob )
m_tp = 0; m_tp = 0;
Service< World::Manager::PlayerMgr >::ref().sendStatusUpdate( *this ); Network::Util::Player::sendStatusUpdate( *this );
Service< World::Manager::PlayerMgr >::ref().onClassChanged( *this ); server().queueForPlayers( getInRangePlayerIds( true ), makeActorControl( getId(), ClassJobChange, 0x04 ) );
Network::Util::Player::sendHudParam( *this );
Service< World::Manager::MapMgr >::ref().updateQuests( *this ); Service< World::Manager::MapMgr >::ref().updateQuests( *this );
} }
@ -825,7 +813,7 @@ void Player::despawn( Entity::PlayerPtr pTarget )
Logger::debug( "Despawning {0} for {1}", getName(), pTarget->getName() ); Logger::debug( "Despawning {0} for {1}", getName(), pTarget->getName() );
pPlayer->freePlayerSpawnId( getId() ); pPlayer->freePlayerSpawnId( getId() );
server().queueForPlayer( pTarget->getCharacterId(), makeActorControlSelf( getId(), WarpStart, 0x04, getId(), 0x01 ) ); Network::Util::Player::sendActorControlSelf( *this, WarpStart, 4, getId(), 1 );
} }
GameObjectPtr Player::lookupTargetById( uint64_t targetId ) GameObjectPtr Player::lookupTargetById( uint64_t targetId )
@ -850,14 +838,18 @@ void Player::setVoiceId( uint8_t voiceId )
m_voice = voiceId; m_voice = voiceId;
} }
void Player::setGc( uint8_t gc ) void Player::setGrandCompany( uint8_t gc )
{ {
m_gc = gc; m_gc = gc;
if( m_gcRank[ gc ] == 0 )
m_gcRank[ gc ] = 1;
Network::Util::Player::sendGrandCompany( *this );
} }
void Player::setGcRankAt( uint8_t index, uint8_t rank ) void Player::setGrandCompanyRankAt( uint8_t index, uint8_t rank )
{ {
m_gcRank[ index ] = rank; m_gcRank[ index ] = rank;
Network::Util::Player::sendGrandCompany( *this );
} }
const Player::Condition& Player::getConditions() const const Player::Condition& Player::getConditions() const
@ -942,7 +934,7 @@ Player::AetheryteList& Player::getAetheryteArray()
void Player::setHomepoint( uint8_t aetheryteId ) void Player::setHomepoint( uint8_t aetheryteId )
{ {
m_homePoint = aetheryteId; m_homePoint = aetheryteId;
server().queueForPlayer( getCharacterId(), makeActorControlSelf( getId(), SetHomepoint, aetheryteId ) ); Network::Util::Player::sendActorControlSelf( *this, SetHomepoint, aetheryteId );
} }
/*! get homepoint */ /*! get homepoint */
@ -991,7 +983,7 @@ void Player::unlockMount( uint32_t mountId )
m_mountGuide[ mount->data().MountOrder / 8 ] |= ( 1 << ( mount->data().MountOrder % 8 ) ); m_mountGuide[ mount->data().MountOrder / 8 ] |= ( 1 << ( mount->data().MountOrder % 8 ) );
server().queueForPlayer( getCharacterId(), makeActorControlSelf( getId(), Network::ActorControl::SetMountBitmask, mount->data().MountOrder, 1 ) ); Network::Util::Player::sendActorControlSelf( *this, SetMountBitmask, mount->data().MountOrder, 1 );
} }
void Player::unlockCompanion( uint32_t companionId ) void Player::unlockCompanion( uint32_t companionId )
@ -1008,7 +1000,7 @@ void Player::unlockCompanion( uint32_t companionId )
m_minionGuide[ index ] |= value; m_minionGuide[ index ] |= value;
server().queueForPlayer( getCharacterId(), makeActorControlSelf( getId(), Network::ActorControl::LearnCompanion, companionId, 1 ) ); Network::Util::Player::sendActorControlSelf( *this, LearnCompanion, companionId, 1 );
} }
Player::MinionList& Player::getMinionGuideBitmask() Player::MinionList& Player::getMinionGuideBitmask()
@ -1199,8 +1191,7 @@ void Player::setAchievementData( const Player::AchievementData& achievementData
void Player::setMaxGearSets( uint8_t amount ) void Player::setMaxGearSets( uint8_t amount )
{ {
m_equippedMannequin = amount; m_equippedMannequin = amount;
Network::Util::Player::sendActorControlSelf( *this, SetMaxGearSets, m_equippedMannequin );
server().queueForPlayer( getCharacterId(), makeActorControlSelf( getId(), SetMaxGearSets, m_equippedMannequin ) );
} }
void Player::addGearSet() void Player::addGearSet()
@ -1222,14 +1213,15 @@ uint8_t Player::getMaxGearSets() const
return m_equippedMannequin; return m_equippedMannequin;
} }
void Player::setEquipDisplayFlags( uint16_t state ) void Player::setConfigFlags( uint16_t state )
{ {
m_equipDisplayFlags = static_cast< uint8_t >( state ); m_configFlags = static_cast< uint8_t >( state );
Network::Util::Player::sendConfigFlags( *this );
} }
uint8_t Player::getEquipDisplayFlags() const uint8_t Player::getConfigFlags() const
{ {
return m_equipDisplayFlags; return m_configFlags;
} }
void Player::setMount( uint32_t mountId ) void Player::setMount( uint32_t mountId )
@ -1379,24 +1371,16 @@ bool Player::isDirectorInitialized() const
return m_directorInitialized; return m_directorInitialized;
} }
void Player::sendTitleList()
{
auto titleListPacket = makeZonePacket< FFXIVIpcTitleList >( getId() );
memcpy( titleListPacket->data().TitleFlagsArray, getTitleList().data(), sizeof( titleListPacket->data().TitleFlagsArray ) );
server().queueForPlayer( getCharacterId(), titleListPacket );
}
void Player::teleportQuery( uint16_t aetheryteId ) void Player::teleportQuery( uint16_t aetheryteId )
{ {
auto& exdData = Common::Service< Data::ExdData >::ref(); auto& exdData = Common::Service< Data::ExdData >::ref();
// TODO: only register this action if enough gil is in possession // TODO: only register this action if enough gil is in possession
auto targetAetheryte = exdData.getRow< Excel::Aetheryte >( aetheryteId ); auto targetAetheryte = exdData.getRow< Excel::Aetheryte >( aetheryteId );
if( targetAetheryte ) if( !targetAetheryte )
{ return;
auto fromAetheryte = exdData.getRow< Excel::Aetheryte >(
exdData.getRow< Excel::TerritoryType >( getTerritoryTypeId() )->data().Aetheryte ); auto fromAetheryte = exdData.getRow< Excel::Aetheryte >( exdData.getRow< Excel::TerritoryType >( getTerritoryTypeId() )->data().Aetheryte );
// calculate cost - does not apply for favorite points or homepoints neither checks for aether tickets // calculate cost - does not apply for favorite points or homepoints neither checks for aether tickets
auto cost = static_cast< uint16_t > ( auto cost = static_cast< uint16_t > (
@ -1407,7 +1391,7 @@ void Player::teleportQuery( uint16_t aetheryteId )
cost = std::min< uint16_t >( 999, cost ); cost = std::min< uint16_t >( 999, cost );
bool insufficientGil = getCurrency( Common::CurrencyType::Gil ) < cost; bool insufficientGil = getCurrency( Common::CurrencyType::Gil ) < cost;
server().queueForPlayer( getCharacterId(), makeActorControlSelf( getId(), OnExecuteTelepo, insufficientGil ? 2 : 0, aetheryteId ) ); Network::Util::Player::sendActorControlSelf( *this, OnExecuteTelepo, insufficientGil ? 2 : 0, aetheryteId );
if( !insufficientGil ) if( !insufficientGil )
{ {
@ -1418,7 +1402,7 @@ void Player::teleportQuery( uint16_t aetheryteId )
{ {
clearTeleportQuery(); clearTeleportQuery();
} }
}
} }
Sapphire::Common::PlayerTeleportQuery Player::getTeleportQuery() const Sapphire::Common::PlayerTeleportQuery Player::getTeleportQuery() const
@ -1483,8 +1467,7 @@ void Player::dyeItemFromDyeingInfo()
insertInventoryItem( static_cast< Sapphire::Common::InventoryType >( itemToDyeContainer ), static_cast< uint16_t >( itemToDyeSlot ), itemToDye ); insertInventoryItem( static_cast< Sapphire::Common::InventoryType >( itemToDyeContainer ), static_cast< uint16_t >( itemToDyeSlot ), itemToDye );
writeItem( itemToDye ); writeItem( itemToDye );
auto dyePkt = makeActorControlSelf( getId(), DyeMsg, itemToDye->getId(), shouldDye, invalidateGearSet ); Network::Util::Player::sendActorControlSelf( *this, DyeMsg, itemToDye->getId(), shouldDye, invalidateGearSet );
server().queueForPlayer( getCharacterId(), dyePkt );
} }
void Player::setGlamouringInfo( uint32_t itemToGlamourContainer, uint32_t itemToGlamourSlot, uint32_t glamourBagContainer, uint32_t glamourBagSlot, bool shouldGlamour ) void Player::setGlamouringInfo( uint32_t itemToGlamourContainer, uint32_t itemToGlamourSlot, uint32_t glamourBagContainer, uint32_t glamourBagSlot, bool shouldGlamour )
@ -1538,15 +1521,9 @@ void Player::glamourItemFromGlamouringInfo()
writeItem( itemToGlamour ); writeItem( itemToGlamour );
if( shouldGlamour ) if( shouldGlamour )
{ Network::Util::Player::sendActorControlSelf( *this, GlamourCastMsg, itemToGlamour->getId(), glamourToUse->getId(), invalidateGearSet );
auto castGlamPkt = makeActorControlSelf( getId(), GlamourCastMsg, itemToGlamour->getId(), glamourToUse->getId(), invalidateGearSet );
server().queueForPlayer( getCharacterId(), castGlamPkt );
}
else else
{ Network::Util::Player::sendActorControlSelf( *this, GlamourRemoveMsg, itemToGlamour->getId(), invalidateGearSet );
auto dispelGlamPkt = makeActorControlSelf( getId(), GlamourRemoveMsg, itemToGlamour->getId(), invalidateGearSet );
server().queueForPlayer( getCharacterId(), dispelGlamPkt );
}
} }
void Player::resetObjSpawnIndex() void Player::resetObjSpawnIndex()
@ -1597,50 +1574,6 @@ Sapphire::Common::HuntingLogEntry& Player::getHuntingLogEntry( uint8_t index )
return m_huntingLogEntries[ index ]; return m_huntingLogEntries[ index ];
} }
void Player::sendHuntingLog()
{
auto& exdData = Common::Service< Data::ExdData >::ref();
uint8_t count = 0;
for( const auto& entry : m_huntingLogEntries )
{
uint64_t completionFlag = 0;
auto huntPacket = makeZonePacket< FFXIVIpcMonsterNoteCategory >( getId() );
huntPacket->data().contextId = -1;
huntPacket->data().currentRank = entry.rank;
huntPacket->data().categoryIndex = count;
for( int i = 1; i <= 10; ++i )
{
auto index0 = i - 1;
bool allComplete = true;
auto monsterNoteId = ( count + 1 ) * 10000 + entry.rank * 10 + i;
auto monsterNote = exdData.getRow< Excel::MonsterNote >( monsterNoteId );
if( !monsterNote )
continue;
const auto huntEntry = entry.entries[ index0 ];
for( int x = 0; x < 3; ++x )
{
if( ( huntEntry[ x ] == monsterNote->data().NeededKills[ x ] ) && monsterNote->data().NeededKills[ x ] != 0 )
completionFlag |= ( 1ull << ( index0 * 5 + x ) );
else if( monsterNote->data().NeededKills[ x ] != 0 )
allComplete = false;
}
if( allComplete )
completionFlag |= ( 1ull << ( index0 * 5 + 4 ) );
}
memcpy( huntPacket->data().killCount, entry.entries, sizeof( entry.entries ) );
huntPacket->data().completeFlags = completionFlag;
++count;
server().queueForPlayer( getCharacterId(), huntPacket );
}
}
void Player::updateHuntingLog( uint16_t id ) void Player::updateHuntingLog( uint16_t id )
{ {
std::vector< uint32_t > rankRewards{ 2500, 10000, 20000, 30000, 40000 }; std::vector< uint32_t > rankRewards{ 2500, 10000, 20000, 30000, 40000 };
@ -1677,7 +1610,7 @@ void Player::updateHuntingLog( uint16_t id )
if( note1->data().Monster == id && logEntry.entries[ i - 1 ][ x ] < note->data().NeededKills[ x ] ) if( note1->data().Monster == id && logEntry.entries[ i - 1 ][ x ] < note->data().NeededKills[ x ] )
{ {
logEntry.entries[ i - 1 ][ x ]++; logEntry.entries[ i - 1 ][ x ]++;
server().queueForPlayer( getCharacterId(), makeActorControlSelf( getId(), HuntingLogEntryUpdate, monsterNoteId, x, logEntry.entries[ i - 1 ][ x ] ) ); Network::Util::Player::sendActorControlSelf( *this, HuntingLogEntryUpdate, monsterNoteId, x, logEntry.entries[ i - 1 ][ x ] );
logChanged = true; logChanged = true;
sectionChanged = true; sectionChanged = true;
} }
@ -1686,7 +1619,7 @@ void Player::updateHuntingLog( uint16_t id )
} }
if( logChanged && sectionComplete && sectionChanged ) if( logChanged && sectionComplete && sectionChanged )
{ {
server().queueForPlayer( getCharacterId(), makeActorControlSelf( getId(), HuntingLogSectionFinish, monsterNoteId, i, 0 ) ); Network::Util::Player::sendActorControlSelf( *this, HuntingLogSectionFinish, monsterNoteId, i, 0 );
gainExp( note->data().RewardExp ); gainExp( note->data().RewardExp );
} }
if( !sectionComplete ) if( !sectionComplete )
@ -1696,18 +1629,18 @@ void Player::updateHuntingLog( uint16_t id )
} }
if( logChanged && allSectionsComplete ) if( logChanged && allSectionsComplete )
{ {
server().queueForPlayer( getCharacterId(), makeActorControlSelf( getId(), HuntingLogRankFinish, 4, 0, 0 ) ); Network::Util::Player::sendActorControlSelf( *this, HuntingLogRankFinish, 4 );
gainExp( rankRewards[ logEntry.rank ] ); gainExp( rankRewards[ logEntry.rank ] );
if( logEntry.rank < 4 ) if( logEntry.rank < 4 )
{ {
logEntry.rank++; logEntry.rank++;
memset( logEntry.entries, 0, 40 ); memset( logEntry.entries, 0, 40 );
server().queueForPlayer( getCharacterId(), makeActorControlSelf( getId(), HuntingLogRankUnlock, currentClassId, logEntry.rank + 1, 0 ) ); Network::Util::Player::sendActorControlSelf( *this, HuntingLogRankUnlock, currentClassId, logEntry.rank + 1, 0 );
} }
} }
if( logChanged ) if( logChanged )
sendHuntingLog(); Network::Util::Player::sendHuntingLog( *this );
} }
void Player::setActiveLand( uint8_t land, uint8_t ward ) void Player::setActiveLand( uint8_t land, uint8_t ward )
@ -1779,19 +1712,14 @@ bool Player::checkAction()
if( m_pCurrentAction->update() ) if( m_pCurrentAction->update() )
{ {
if( m_pCurrentAction->isInterrupted() && m_pCurrentAction->getInterruptType() != Common::ActionInterruptType::DamageInterrupt ) if( m_pCurrentAction->isInterrupted() && m_pCurrentAction->getInterruptType() != Common::ActionInterruptType::DamageInterrupt )
{
// we moved (or whatever not damage interrupt) so we don't want to execute queued cast
m_pQueuedAction = nullptr; m_pQueuedAction = nullptr;
}
m_pCurrentAction = nullptr; m_pCurrentAction = nullptr;
if( hasQueuedAction() ) if( hasQueuedAction() )
{ {
PlayerMgr::sendDebug( *this, "Queued skill start: {0}", m_pQueuedAction->getId() ); PlayerMgr::sendDebug( *this, "Queued skill start: {0}", m_pQueuedAction->getId() );
if( m_pQueuedAction->hasCastTime() ) if( m_pQueuedAction->hasCastTime() )
{
setCurrentAction( m_pQueuedAction ); setCurrentAction( m_pQueuedAction );
}
m_pQueuedAction->start(); m_pQueuedAction->start();
m_pQueuedAction = nullptr; m_pQueuedAction = nullptr;
} }

View file

@ -214,7 +214,7 @@ namespace Sapphire::Entity
uint8_t getLevelSync() const; uint8_t getLevelSync() const;
/*! returns the level of the provided class / job */ /*! returns the level of the provided class / job */
uint8_t getLevelForClass( Common::ClassJob pClass ) const; uint8_t getLevelForClass( Common::ClassJob classJobId ) const;
/*! \return the first class of the player */ /*! \return the first class of the player */
Common::ClassJob getFirstClass() const; Common::ClassJob getFirstClass() const;
@ -288,10 +288,10 @@ namespace Sapphire::Entity
void setVoiceId( uint8_t voiceId ); void setVoiceId( uint8_t voiceId );
/*! set the grand company */ /*! set the grand company */
void setGc( uint8_t gc ); void setGrandCompany( uint8_t gc );
/*! set the grand company rank */ /*! set the grand company rank */
void setGcRankAt( uint8_t index, uint8_t rank ); void setGrandCompanyRankAt( uint8_t index, uint8_t rank );
/*! returns true if the player is currently in combat */ /*! returns true if the player is currently in combat */
bool isInCombat() const; bool isInCombat() const;
@ -372,9 +372,6 @@ namespace Sapphire::Entity
/*! change player's active title */ /*! change player's active title */
void setTitle( uint16_t titleId ); void setTitle( uint16_t titleId );
/*! send the players title list */
void sendTitleList();
/*! get player's achievement data */ /*! get player's achievement data */
const AchievementData& getAchievementData() const; const AchievementData& getAchievementData() const;
@ -391,10 +388,10 @@ namespace Sapphire::Entity
uint8_t getMaxGearSets() const; uint8_t getMaxGearSets() const;
/*! change gear param state */ /*! change gear param state */
void setEquipDisplayFlags( uint16_t state ); void setConfigFlags( uint16_t state );
/*! get gear param state */ /*! get gear param state */
uint8_t getEquipDisplayFlags() const; uint8_t getConfigFlags() const;
/*! mount the specified setMount and send the packets */ /*! mount the specified setMount and send the packets */
void setMount( uint32_t mountId ); void setMount( uint32_t mountId );
@ -414,9 +411,6 @@ namespace Sapphire::Entity
void calculateStats() override; void calculateStats() override;
void sendStats();
// Aetheryte / Action / Attribute bitmasks // Aetheryte / Action / Attribute bitmasks
////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////
/*! register aetheryte aetheryteId and send update */ /*! register aetheryte aetheryteId and send update */
@ -438,7 +432,7 @@ namespace Sapphire::Entity
uint8_t getHomepoint() const; uint8_t getHomepoint() const;
/*! discover subarea subid fo map map_id, also send udpate packet */ /*! discover subarea subid fo map map_id, also send udpate packet */
void discover( int16_t map_id, int16_t sub_id ); void discover( int16_t mapId, int16_t subId );
/*! return a reference to the discovery bitmask array */ /*! return a reference to the discovery bitmask array */
Discovery& getDiscoveryBitmask(); Discovery& getDiscoveryBitmask();
@ -583,9 +577,6 @@ namespace Sapphire::Entity
/*! send current models ( equipment ) */ /*! send current models ( equipment ) */
void sendModel(); void sendModel();
/*! send status update */
void sendHudParam() override;
/*! send the entire inventory sequence */ /*! send the entire inventory sequence */
void sendInventory(); void sendInventory();
@ -735,22 +726,13 @@ namespace Sapphire::Entity
InvSlotPair getFreeContainerSlot( uint32_t containerId ); InvSlotPair getFreeContainerSlot( uint32_t containerId );
ItemPtr addItem( uint32_t catalogId, uint32_t quantity = 1, bool isHq = false, bool slient = false, bool canMerge = true ); ItemPtr addItem( uint32_t catalogId, uint32_t quantity = 1, bool isHq = false, bool slient = false, bool canMerge = true );
bool removeItem( uint32_t catalogId, uint32_t quantity = 1, bool isHq = false ); bool removeItem( uint32_t catalogId, uint32_t quantity = 1, bool isHq = false );
void moveItem( uint16_t fromInventoryId, uint16_t fromSlotId, uint16_t toInventoryId, uint16_t toSlot ); void moveItem( uint16_t fromInventoryId, uint16_t fromSlotId, uint16_t toInventoryId, uint16_t toSlot );
void swapItem( uint16_t fromInventoryId, uint16_t fromSlotId, uint16_t toInventoryId, uint16_t toSlot ); void swapItem( uint16_t fromInventoryId, uint16_t fromSlotId, uint16_t toInventoryId, uint16_t toSlot );
void discardItem( uint16_t fromInventoryId, uint16_t fromSlotId ); void discardItem( uint16_t fromInventoryId, uint16_t fromSlotId );
void splitItem( uint16_t fromInventoryId, uint16_t fromSlotId, uint16_t toInventoryId, uint16_t toSlot, uint16_t splitCount );
void splitItem( uint16_t fromInventoryId, uint16_t fromSlotId, uint16_t toInventoryId, uint16_t toSlot,
uint16_t splitCount );
void mergeItem( uint16_t fromInventoryId, uint16_t fromSlotId, uint16_t toInventoryId, uint16_t toSlot ); void mergeItem( uint16_t fromInventoryId, uint16_t fromSlotId, uint16_t toInventoryId, uint16_t toSlot );
ItemPtr getItemAt( uint16_t containerId, uint16_t slotId ); ItemPtr getItemAt( uint16_t containerId, uint16_t slotId );
bool updateContainer( uint16_t storageId, uint16_t slotId, ItemPtr pItem ); bool updateContainer( uint16_t storageId, uint16_t slotId, ItemPtr pItem );
/*! calculate and return player ilvl based off equipped gear */ /*! calculate and return player ilvl based off equipped gear */
@ -803,8 +785,6 @@ namespace Sapphire::Entity
Common::HuntingLogEntry& getHuntingLogEntry( uint8_t index ); Common::HuntingLogEntry& getHuntingLogEntry( uint8_t index );
void sendHuntingLog();
void updateHuntingLog( uint16_t id ); void updateHuntingLog( uint16_t id );
uint64_t getPartyId() const; uint64_t getPartyId() const;
@ -930,7 +910,7 @@ namespace Sapphire::Entity
uint8_t m_gmRank{}; uint8_t m_gmRank{};
bool m_gmInvis{false}; bool m_gmInvis{false};
uint8_t m_equipDisplayFlags{}; uint8_t m_configFlags{};
bool m_bInCombat; bool m_bInCombat;
bool m_bLoadingComplete; bool m_bLoadingComplete;

View file

@ -18,6 +18,7 @@
#include "Network/PacketWrappers/ActorControlSelfPacket.h" #include "Network/PacketWrappers/ActorControlSelfPacket.h"
#include "Network/PacketWrappers/UpdateInventorySlotPacket.h" #include "Network/PacketWrappers/UpdateInventorySlotPacket.h"
#include <Network/PacketDef/Zone/ServerZoneDef.h> #include <Network/PacketDef/Zone/ServerZoneDef.h>
#include <Network/Util/PlayerUtil.h>
#include "Manager/InventoryMgr.h" #include "Manager/InventoryMgr.h"
#include "Manager/ItemMgr.h" #include "Manager/ItemMgr.h"
@ -231,8 +232,8 @@ void Sapphire::Entity::Player::equipItem( Common::GearSetSlot equipSlotId, Item&
{ {
sendModel(); sendModel();
sendItemLevel(); sendItemLevel();
sendStats(); Network::Util::Player::sendBaseParams( *this );
sendHudParam(); Network::Util::Player::sendHudParam( *this );
} }
} }
@ -253,8 +254,8 @@ void Sapphire::Entity::Player::unequipItem( Common::GearSetSlot equipSlotId, Ite
{ {
sendModel(); sendModel();
sendItemLevel(); sendItemLevel();
sendStats(); Network::Util::Player::sendBaseParams( *this );
sendHudParam(); Network::Util::Player::sendHudParam( *this );
} }
} }
@ -635,7 +636,7 @@ Sapphire::ItemPtr Sapphire::Entity::Player::addItem( uint32_t catalogId, uint32_
// add the related armoury bag to the applicable bags and try and fill a free slot there before falling back to regular inventory // add the related armoury bag to the applicable bags and try and fill a free slot there before falling back to regular inventory
// EXD TODO: wtf... // EXD TODO: wtf...
if( itemInfo->data().Slot > 0 && getEquipDisplayFlags() & StoreNewItemsInArmouryChest ) if( itemInfo->data().Slot > 0 && getConfigFlags() & StoreNewItemsInArmouryChest )
{ {
auto bag = World::Manager::ItemMgr::getCharaEquipSlotCategoryToArmoryId( itemInfo->data().Slot ); auto bag = World::Manager::ItemMgr::getCharaEquipSlotCategoryToArmoryId( itemInfo->data().Slot );

View file

@ -103,7 +103,7 @@ bool Sapphire::Entity::Player::loadFromDb( uint64_t characterId )
m_equippedMannequin = res->getUInt8( "EquippedMannequin" ); m_equippedMannequin = res->getUInt8( "EquippedMannequin" );
m_equipDisplayFlags = res->getUInt8( "EquipDisplayFlags" ); m_configFlags = res->getUInt8( "EquipDisplayFlags" );
m_pose = res->getUInt8( "Pose" ); m_pose = res->getUInt8( "Pose" );
@ -467,7 +467,7 @@ void Sapphire::Entity::Player::updateDbChara() const
stmt->setInt( 51, m_gmRank ); stmt->setInt( 51, m_gmRank );
stmt->setInt( 52, m_equipDisplayFlags ); stmt->setInt( 52, m_configFlags );
std::vector< uint8_t > unlockVec( m_unlocks.size() ); std::vector< uint8_t > unlockVec( m_unlocks.size() );
memcpy( unlockVec.data(), m_unlocks.data(), m_unlocks.size() ); memcpy( unlockVec.data(), m_unlocks.data(), m_unlocks.size() );

View file

@ -16,6 +16,7 @@ file( GLOB SERVER_SOURCE_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
Manager/*.cpp Manager/*.cpp
Math/*.cpp Math/*.cpp
Network/*.cpp Network/*.cpp
Network/Util/*.cpp
Network/Handlers/*.cpp Network/Handlers/*.cpp
Network/PacketWrappers/*.cpp Network/PacketWrappers/*.cpp
Script/*.cpp Script/*.cpp

View file

@ -32,6 +32,7 @@
#include <Network/PacketWrappers/ServerNoticePacket.h> #include <Network/PacketWrappers/ServerNoticePacket.h>
#include <Network/PacketWrappers/ChatPacket.h> #include <Network/PacketWrappers/ChatPacket.h>
#include <Network/PacketWrappers/HudParamPacket.h> #include <Network/PacketWrappers/HudParamPacket.h>
#include <Network/Util/PlayerUtil.h>
#include <Actor/Player.h> #include <Actor/Player.h>
#include <Actor/BNpc.h> #include <Actor/BNpc.h>
@ -214,34 +215,6 @@ Sapphire::Entity::PlayerPtr PlayerMgr::syncPlayer( uint64_t characterId )
return pPlayer; return pPlayer;
} }
void PlayerMgr::onOnlineStatusChanged( Entity::Player& player, bool updateProfile )
{
auto statusPacket = makeZonePacket< FFXIVIpcSetOnlineStatus >( player.getId() );
statusPacket->data().onlineStatusFlags = player.getFullOnlineStatusMask();
server().queueForPlayer( player.getCharacterId(), statusPacket );
if( updateProfile )
{
auto searchInfoPacket = makeZonePacket< FFXIVIpcSetProfileResult >( player.getId());
searchInfoPacket->data().OnlineStatus = player.getFullOnlineStatusMask();
searchInfoPacket->data().Region = player.getSearchSelectRegion();
strcpy( searchInfoPacket->data().SearchComment, player.getSearchMessage());
server().queueForPlayer( player.getCharacterId(), searchInfoPacket );
}
server().queueForPlayers( player.getInRangePlayerIds( true ),
makeActorControl( player.getId(), SetStatusIcon, static_cast< uint8_t >( player.getOnlineStatus() ) ) );
}
void PlayerMgr::onEquipDisplayFlagsChanged( Entity::Player& player )
{
auto paramPacket = makeZonePacket< FFXIVIpcConfig >( player.getId() );
paramPacket->data().flag = player.getEquipDisplayFlags();
server().queueForPlayers( player.getInRangePlayerIds( true ), paramPacket );
}
void PlayerMgr::onConditionChanged( Entity::Player& player, bool updateInRange ) void PlayerMgr::onConditionChanged( Entity::Player& player, bool updateInRange )
{ {
@ -282,55 +255,6 @@ void PlayerMgr::onUnlockAchievement( Entity::Player& player, uint32_t achievemen
server().queueForPlayer( player.getCharacterId(), makeActorControl( player.getId(), AchievementObtainMsg, achievementId ) ); server().queueForPlayer( player.getCharacterId(), makeActorControl( player.getId(), AchievementObtainMsg, achievementId ) );
} }
void PlayerMgr::onStatsChanged( Entity::Player& player )
{
std::array< uint32_t, 50 > statParams{};
std::fill( std::begin( statParams ), std::end( statParams ), 0 );
auto& exd = Common::Service< Data::ExdData >::ref();
// todo: this is no doubt slow as shit...
auto idList = exd.getIdList< Excel::BaseParam >();
for( const auto id : idList )
{
auto row = exd.getRow< Excel::BaseParam >( id );
if( !row )
{
continue;
}
if( row->data().PacketIndex < 0 )
{
continue;
}
statParams[ row->data().PacketIndex ] = player.getStatValue( static_cast< Common::BaseParam >( id ) );
}
auto statPacket = makeZonePacket< FFXIVIpcBaseParam >( player.getId() );
memcpy( statPacket->data().Param, statParams.data(), sizeof( uint32_t ) * statParams.size() );
server().queueForPlayer( player.getCharacterId(), statPacket );
}
void PlayerMgr::sendStatusUpdate( Entity::Player& player )
{
auto playerStatusUpdate = makeZonePacket< FFXIVIpcPlayerStatusUpdate >( player.getId() );
playerStatusUpdate->data().ClassJob = static_cast< uint8_t >( player.getClass() );
playerStatusUpdate->data().Lv = player.getLevel();
playerStatusUpdate->data().Lv1 = player.getLevel();
playerStatusUpdate->data().LvSync = 0; //player.getLevelSync();
playerStatusUpdate->data().Exp = player.getExp();
server().queueForPlayer( player.getCharacterId(), playerStatusUpdate );
}
void PlayerMgr::onHudParamChanged( Entity::Player& player )
{
auto hudParamPacket = makeHudParam( player );
server().queueForPlayer( player.getCharacterId(), hudParamPacket );
}
void PlayerMgr::onRestingTick( Entity::Player& player ) void PlayerMgr::onRestingTick( Entity::Player& player )
{ {
server().queueForPlayers( player.getInRangePlayerIds( true ), std::make_shared< RestingPacket >( player ) ); server().queueForPlayers( player.getInRangePlayerIds( true ), std::make_shared< RestingPacket >( player ) );
@ -344,8 +268,8 @@ void PlayerMgr::sendItemLevel( Entity::Player& player )
void PlayerMgr::onLevelUp( Entity::Player& player ) void PlayerMgr::onLevelUp( Entity::Player& player )
{ {
player.calculateStats(); player.calculateStats();
player.sendStats(); Network::Util::Player::sendBaseParams( player );
player.sendHudParam(); Network::Util::Player::sendHudParam( player );
auto inRangePlayerIds = player.getInRangePlayerIds( true ); auto inRangePlayerIds = player.getInRangePlayerIds( true );
@ -353,7 +277,7 @@ void PlayerMgr::onLevelUp( Entity::Player& player )
server().queueForPlayers( inRangePlayerIds, makeActorControl( player.getId(), LevelUpEffect, static_cast< uint8_t >( player.getClass() ), server().queueForPlayers( inRangePlayerIds, makeActorControl( player.getId(), LevelUpEffect, static_cast< uint8_t >( player.getClass() ),
player.getLevel(), player.getLevel() - 1 ) ); player.getLevel(), player.getLevel() - 1 ) );
sendStatusUpdate( player ); Network::Util::Player::sendStatusUpdate( player );
auto& achvMgr = Common::Service< World::Manager::AchievementMgr >::ref(); auto& achvMgr = Common::Service< World::Manager::AchievementMgr >::ref();
achvMgr.progressAchievementByType< Common::Achievement::Type::Classjob >( player, static_cast< uint32_t >( player.getClass() ) ); achvMgr.progressAchievementByType< Common::Achievement::Type::Classjob >( player, static_cast< uint32_t >( player.getClass() ) );
@ -393,29 +317,6 @@ void PlayerMgr::onGearChanged( Entity::Player& player )
server().queueForPlayers( player.getInRangePlayerIds( true ), std::make_shared< ModelEquipPacket >( player ) ); server().queueForPlayers( player.getInRangePlayerIds( true ), std::make_shared< ModelEquipPacket >( player ) );
} }
void PlayerMgr::sendGrandCompany( Entity::Player& player )
{
auto gcAffPacket = makeZonePacket< FFXIVIpcGrandCompany >( player.getId() );
gcAffPacket->data().ActiveCompanyId = player.getGc();
gcAffPacket->data().MaelstromRank = player.getGcRankArray()[ 0 ];
gcAffPacket->data().TwinAdderRank = player.getGcRankArray()[ 1 ];
gcAffPacket->data().ImmortalFlamesRank = player.getGcRankArray()[ 2 ];
server().queueForPlayer( player.getCharacterId(), gcAffPacket );
}
void PlayerMgr::setGrandCompany( Entity::Player& player, uint8_t gc )
{
player.setGc( gc );
sendGrandCompany( player );
}
void PlayerMgr::setGrandCompanyRank( Entity::Player& player, uint8_t gc, uint8_t rank )
{
player.setGcRankAt( gc, rank );
sendGrandCompany( player );
}
void PlayerMgr::onCompanionUpdate( Entity::Player& player, uint8_t companionId ) void PlayerMgr::onCompanionUpdate( Entity::Player& player, uint8_t companionId )
{ {
auto& exdData = Common::Service< Data::ExdData >::ref(); auto& exdData = Common::Service< Data::ExdData >::ref();
@ -425,7 +326,7 @@ void PlayerMgr::onCompanionUpdate( Entity::Player& player, uint8_t companionId )
return; return;
player.setCompanion( companionId ); player.setCompanion( companionId );
server().queueForPlayers( player.getInRangePlayerIds( true ), makeActorControl( player.getId(), ActorControlType::ToggleCompanion, companionId ) ); Network::Util::Player::sendActorControl( player.getInRangePlayerIds( true ), player, ToggleCompanion, companionId );
} }
void PlayerMgr::onMountUpdate( Entity::Player& player, uint32_t mountId ) void PlayerMgr::onMountUpdate( Entity::Player& player, uint32_t mountId )
@ -434,15 +335,13 @@ void PlayerMgr::onMountUpdate( Entity::Player& player, uint32_t mountId )
auto inRangePlayerIds = player.getInRangePlayerIds( true ); auto inRangePlayerIds = player.getInRangePlayerIds( true );
if( mountId != 0 ) if( mountId != 0 )
{ {
server().queueForPlayers( inRangePlayerIds, Network::Util::Player::sendActorControl( inRangePlayerIds, player, SetStatus, static_cast< uint8_t >( Common::ActorStatus::Mounted ) );
makeActorControl( player.getId(), ActorControlType::SetStatus, static_cast< uint8_t >( Common::ActorStatus::Mounted ) ) ); Network::Util::Player::sendActorControlSelf( inRangePlayerIds, player, 0x39e, 12 );
server().queueForPlayers( inRangePlayerIds, makeActorControlSelf( player.getId(), 0x39e, 12 ) );
} }
else else
{ {
server().queueForPlayers( inRangePlayerIds, Network::Util::Player::sendActorControl( inRangePlayerIds, player, SetStatus, static_cast< uint8_t >( Common::ActorStatus::Idle ) );
makeActorControl( player.getId(), ActorControlType::SetStatus, static_cast< uint8_t >( Common::ActorStatus::Idle ) ) ); Network::Util::Player::sendActorControlSelf( inRangePlayerIds, player, Dismount, 1 );
server().queueForPlayers( inRangePlayerIds, makeActorControlSelf( player.getId(), ActorControlType::Dismount, 1 ) );
} }
auto mountPacket = makeZonePacket< FFXIVIpcMount >( player.getId() ); auto mountPacket = makeZonePacket< FFXIVIpcMount >( player.getId() );
@ -501,12 +400,6 @@ void PlayerMgr::onHateListChanged( Entity::Player& player )
server().queueForPlayer( player.getCharacterId(), { hateListPacket, hateRankPacket } ); server().queueForPlayer( player.getCharacterId(), { hateListPacket, hateRankPacket } );
} }
void PlayerMgr::onClassChanged( Entity::Player& player )
{
server().queueForPlayers( player.getInRangePlayerIds( true ), makeActorControl( player.getId(), ClassJobChange, 0x04 ) );
onHudParamChanged( player );
}
void PlayerMgr::sendLoginMessage( Entity::Player& player ) void PlayerMgr::sendLoginMessage( Entity::Player& player )
{ {
auto motd = server().getConfig().motd; auto motd = server().getConfig().motd;
@ -556,7 +449,7 @@ void PlayerMgr::onMoveZone( Sapphire::Entity::Player& player )
if( player.isLogin() ) if( player.isLogin() )
{ {
server().queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), SetConfigFlags, player.getEquipDisplayFlags(), 1 ) ); server().queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), SetConfigFlags, player.getConfigFlags(), 1 ) );
server().queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), SetMaxGearSets, player.getMaxGearSets() ) ); server().queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), SetMaxGearSets, player.getMaxGearSets() ) );
} }
@ -564,13 +457,13 @@ void PlayerMgr::onMoveZone( Sapphire::Entity::Player& player )
//setStateFlag( PlayerStateFlag::BetweenAreas ); //setStateFlag( PlayerStateFlag::BetweenAreas );
//setStateFlag( PlayerStateFlag::BetweenAreas1 ); //setStateFlag( PlayerStateFlag::BetweenAreas1 );
player.sendHuntingLog(); Network::Util::Player::sendHuntingLog( player );
if( player.isLogin() ) if( player.isLogin() )
server().queueForPlayer( player.getCharacterId(), makePlayerSetup( player ) ); server().queueForPlayer( player.getCharacterId(), makePlayerSetup( player ) );
player.sendRecastGroups(); player.sendRecastGroups();
player.sendStats(); Network::Util::Player::sendBaseParams( player );
sendItemLevel( player ); sendItemLevel( player );
if( player.isLogin() ) if( player.isLogin() )
{ {
@ -621,7 +514,7 @@ void PlayerMgr::onMoveZone( Sapphire::Entity::Player& player )
auto &questMgr = Common::Service< World::Manager::QuestMgr >::ref(); auto &questMgr = Common::Service< World::Manager::QuestMgr >::ref();
questMgr.sendQuestsInfo( player ); questMgr.sendQuestsInfo( player );
sendGrandCompany( player ); Network::Util::Player::sendGrandCompany( player );
} }
} }

View file

@ -23,16 +23,8 @@ namespace Sapphire::World::Manager
bool loadPlayers(); bool loadPlayers();
Entity::PlayerPtr syncPlayer( uint64_t characterId ); Entity::PlayerPtr syncPlayer( uint64_t characterId );
void onOnlineStatusChanged( Sapphire::Entity::Player& player, bool updateProfile = true );
void onEquipDisplayFlagsChanged( Sapphire::Entity::Player& player );
void sendStatusUpdate( Sapphire::Entity::Player& player );
void onUnlockAchievement( Sapphire::Entity::Player& player, uint32_t achievementId ); void onUnlockAchievement( Sapphire::Entity::Player& player, uint32_t achievementId );
void onHudParamChanged( Sapphire::Entity::Player& player );
void onRestingTick( Sapphire::Entity::Player& player ); void onRestingTick( Sapphire::Entity::Player& player );
void sendItemLevel( Sapphire::Entity::Player& player ); void sendItemLevel( Sapphire::Entity::Player& player );
@ -63,17 +55,12 @@ namespace Sapphire::World::Manager
void onUpdate( Sapphire::Entity::Player& player, uint64_t tickCount ); void onUpdate( Sapphire::Entity::Player& player, uint64_t tickCount );
void onConditionChanged( Sapphire::Entity::Player& player, bool updateInRange ); void onConditionChanged( Sapphire::Entity::Player& player, bool updateInRange );
void onStatsChanged( Sapphire::Entity::Player& player );
void onAchievementListChanged( Sapphire::Entity::Player& player ); void onAchievementListChanged( Sapphire::Entity::Player& player );
void onAchievementProgressChanged( Sapphire::Entity::Player& player, uint32_t achievementId ); void onAchievementProgressChanged( Sapphire::Entity::Player& player, uint32_t achievementId );
void onGearChanged( Sapphire::Entity::Player& player ); void onGearChanged( Sapphire::Entity::Player& player );
void sendGrandCompany( Sapphire::Entity::Player& player );
void onClassChanged( Sapphire::Entity::Player& player );
void setCondition( Sapphire::Entity::Player& player, Common::PlayerCondition flag ); void setCondition( Sapphire::Entity::Player& player, Common::PlayerCondition flag );
void removeCondition( Sapphire::Entity::Player& player, Common::PlayerCondition flag ); void removeCondition( Sapphire::Entity::Player& player, Common::PlayerCondition flag );
void setGrandCompany( Sapphire::Entity::Player& player, uint8_t gc );
void setGrandCompanyRank( Sapphire::Entity::Player& player, uint8_t gc, uint8_t rank );
//////////// Helpers //////////// Helpers

View file

@ -422,18 +422,7 @@ void Sapphire::Network::GameConnection::gmCommandHandler( const Packets::FFXIVAR
return; return;
} }
Service< World::Manager::PlayerMgr >::ref().setGrandCompany( player, static_cast< uint8_t >( param1 ) ); player.setGrandCompany( static_cast< uint8_t >( param1 ) );
// if we're changing them to a GC, check if they have a rank and if not, set it to the lowest rank
if( param1 > 0 )
{
auto gcRankIdx = static_cast< uint8_t >( param1 ) - 1;
if( targetPlayer->getGcRankArray()[ gcRankIdx ] == 0 )
{
player.setGcRankAt( static_cast< uint8_t >( gcRankIdx ), 1 );
}
}
PlayerMgr::sendServerNotice( player, "GC for {0} was set to {1}", targetPlayer->getName(), targetPlayer->getGc()); PlayerMgr::sendServerNotice( player, "GC for {0} was set to {1}", targetPlayer->getName(), targetPlayer->getGc());
break; break;
} }
@ -447,7 +436,7 @@ void Sapphire::Network::GameConnection::gmCommandHandler( const Packets::FFXIVAR
return; return;
} }
Service< World::Manager::PlayerMgr >::ref().setGrandCompanyRank( player, static_cast< uint8_t >( gcId ), static_cast< uint8_t >( param1 ) ); player.setGrandCompanyRankAt( static_cast< uint8_t >( gcId ), static_cast< uint8_t >( param1 ) );
PlayerMgr::sendServerNotice( player, "GC Rank for {0} for GC {1} was set to {2}", targetPlayer->getName(), targetPlayer->getGc(), PlayerMgr::sendServerNotice( player, "GC Rank for {0} for GC {1} was set to {2}", targetPlayer->getName(), targetPlayer->getGc(),
targetPlayer->getGcRankArray()[ targetPlayer->getGc() - 1 ] ); targetPlayer->getGcRankArray()[ targetPlayer->getGc() - 1 ] );
break; break;

View file

@ -16,6 +16,7 @@
#include "Network/PacketWrappers/ActorControlPacket.h" #include "Network/PacketWrappers/ActorControlPacket.h"
#include "Network/PacketWrappers/ActorControlTargetPacket.h" #include "Network/PacketWrappers/ActorControlTargetPacket.h"
#include "Network/PacketWrappers/MoveActorPacket.h" #include "Network/PacketWrappers/MoveActorPacket.h"
#include "Network/Util/PlayerUtil.h"
#include "Action/Action.h" #include "Action/Action.h"
@ -492,7 +493,7 @@ void Sapphire::Network::GameConnection::commandHandler( const Packets::FFXIVARR_
} }
case PacketCommand::TITLE_LIST: // Get title list case PacketCommand::TITLE_LIST: // Get title list
{ {
player.sendTitleList(); Network::Util::Player::sendTitleList( player );
break; break;
} }
case PacketCommand::SET_HOWTO: // Update howtos seen case PacketCommand::SET_HOWTO: // Update howtos seen

View file

@ -254,8 +254,8 @@ void Sapphire::Network::GameConnection::configHandler( const Packets::FFXIVARR_P
{ {
const auto packet = ZoneChannelPacket< Client::FFXIVIpcConfig >( inPacket ); const auto packet = ZoneChannelPacket< Client::FFXIVIpcConfig >( inPacket );
player.setEquipDisplayFlags( packet.data().flag ); player.setConfigFlags( packet.data().flag );
PlayerMgr().onEquipDisplayFlagsChanged( player );
} }
void Sapphire::Network::GameConnection::zoneJumpHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player ) void Sapphire::Network::GameConnection::zoneJumpHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )

View file

@ -27,8 +27,7 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
}; };
private: private:
void initialize( uint16_t category, uint32_t param1, uint32_t param2, uint32_t param3, uint32_t param4, void initialize( uint16_t category, uint32_t param1, uint32_t param2, uint32_t param3, uint32_t param4, uint32_t param5 )
uint32_t param5 )
{ {
m_data.padding = 0; m_data.padding = 0;
m_data.category = category; m_data.category = category;

View file

@ -115,22 +115,22 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
m_data.Flag |= static_cast< uint16_t >( Common::DisplayFlags::Invisible ); m_data.Flag |= static_cast< uint16_t >( Common::DisplayFlags::Invisible );
} }
if( player.getEquipDisplayFlags() & Sapphire::Common::EquipDisplayFlags::HideHead ) if( player.getConfigFlags() & Sapphire::Common::EquipDisplayFlags::HideHead )
{ {
m_data.Flag |= static_cast< uint16_t >( Common::DisplayFlags::HideHead ); m_data.Flag |= static_cast< uint16_t >( Common::DisplayFlags::HideHead );
} }
if( player.getEquipDisplayFlags() & Sapphire::Common::EquipDisplayFlags::HideWeapon ) if( player.getConfigFlags() & Sapphire::Common::EquipDisplayFlags::HideWeapon )
{ {
m_data.Flag |= static_cast< uint16_t >( Common::DisplayFlags::HideWeapon ); m_data.Flag |= static_cast< uint16_t >( Common::DisplayFlags::HideWeapon );
} }
if( player.getEquipDisplayFlags() & Sapphire::Common::EquipDisplayFlags::Visor ) if( player.getConfigFlags() & Sapphire::Common::EquipDisplayFlags::Visor )
{ {
m_data.Flag |= static_cast< uint16_t >( Common::DisplayFlags::Visor ); m_data.Flag |= static_cast< uint16_t >( Common::DisplayFlags::Visor );
} }
if( !( player.getEquipDisplayFlags() & Sapphire::Common::EquipDisplayFlags::HideLegacyMark ) ) if( !( player.getConfigFlags() & Sapphire::Common::EquipDisplayFlags::HideLegacyMark ) )
{ {
m_data.Customize[ 0xC ] = m_data.Customize[ 0xC ] | 1 << 7; m_data.Customize[ 0xC ] = m_data.Customize[ 0xC ] | 1 << 7;
} }

View file

@ -0,0 +1,162 @@
#include "PlayerUtil.h"
#include <Exd/ExdData.h>
#include <Manager/MgrUtil.h>
#include <Network/CommonActorControl.h>
#include <Network/PacketDef/Zone/ServerZoneDef.h>
#include <Network/PacketWrappers/ActorControlPacket.h>
#include <Network/PacketWrappers/ActorControlSelfPacket.h>
#include <Network/PacketWrappers/ActorControlTargetPacket.h>
#include <Network/PacketWrappers/HudParamPacket.h>
using namespace Sapphire;
using namespace Sapphire::World::Manager;
using namespace Sapphire::Network;
using namespace Sapphire::Network::Util::Player;
using namespace Sapphire::Network::Packets;
using namespace Sapphire::Network::Packets::WorldPackets::Server;
using namespace Sapphire::Network::ActorControl;
void Util::Player::sendConfigFlags( Entity::Player& player )
{
auto paramPacket = makeZonePacket< FFXIVIpcConfig >( player.getId() );
paramPacket->data().flag = player.getConfigFlags();
server().queueForPlayers( player.getInRangePlayerIds( true ), paramPacket );
}
void Util::Player::sendOnlineStatus( Entity::Player& player )
{
auto statusPacket = makeZonePacket< FFXIVIpcSetOnlineStatus >( player.getId() );
statusPacket->data().onlineStatusFlags = player.getFullOnlineStatusMask();
server().queueForPlayer( player.getCharacterId(), statusPacket );
server().queueForPlayers( player.getInRangePlayerIds( true ),
makeActorControl( player.getId(), SetStatusIcon, static_cast< uint8_t >( player.getOnlineStatus() ) ) );
}
void Util::Player::sendBaseParams( Entity::Player& player )
{
std::array< uint32_t, 50 > statParams{};
std::fill( std::begin( statParams ), std::end( statParams ), 0 );
auto& exd = Common::Service< Data::ExdData >::ref();
auto idList = exd.getIdList< Excel::BaseParam >();
for( const auto id : idList )
{
auto row = exd.getRow< Excel::BaseParam >( id );
if( !row )
continue;
if( row->data().PacketIndex < 0 )
continue;
statParams[ row->data().PacketIndex ] = player.getStatValue( static_cast< Common::BaseParam >( id ) );
}
auto statPacket = makeZonePacket< FFXIVIpcBaseParam >( player.getId() );
memcpy( statPacket->data().Param, statParams.data(), sizeof( uint32_t ) * statParams.size() );
server().queueForPlayer( player.getCharacterId(), statPacket );
}
void Util::Player::sendHudParam( Entity::Player& player )
{
auto hudParamPacket = makeHudParam( player );
server().queueForPlayer( player.getCharacterId(), hudParamPacket );
}
void Util::Player::sendStatusUpdate( Entity::Player& player )
{
auto playerStatusUpdate = makeZonePacket< FFXIVIpcPlayerStatusUpdate >( player.getId() );
playerStatusUpdate->data().ClassJob = static_cast< uint8_t >( player.getClass() );
playerStatusUpdate->data().Lv = player.getLevel();
playerStatusUpdate->data().Lv1 = player.getLevel();
playerStatusUpdate->data().LvSync = 0; //player.getLevelSync();
playerStatusUpdate->data().Exp = player.getExp();
server().queueForPlayer( player.getCharacterId(), playerStatusUpdate );
}
void Util::Player::sendHuntingLog( Entity::Player& player )
{
auto& exdData = Common::Service< Data::ExdData >::ref();
for( auto entryCount = 0; entryCount < Common::ARRSIZE_MONSTERNOTE; ++entryCount )
{
auto& entry = player.getHuntingLogEntry( entryCount );
uint64_t completionFlag = 0;
auto huntPacket = makeZonePacket< FFXIVIpcMonsterNoteCategory >( player.getId() );
huntPacket->data().contextId = -1;
huntPacket->data().currentRank = entry.rank;
huntPacket->data().categoryIndex = entryCount;
for( int i = 1; i <= 10; ++i )
{
auto index0 = i - 1;
bool allComplete = true;
auto monsterNoteId = ( entryCount + 1 ) * 10000 + entry.rank * 10 + i;
auto monsterNote = exdData.getRow< Excel::MonsterNote >( monsterNoteId );
if( !monsterNote )
continue;
const auto huntEntry = entry.entries[ index0 ];
for( int x = 0; x < 3; ++x )
{
if( ( huntEntry[ x ] == monsterNote->data().NeededKills[ x ] ) && monsterNote->data().NeededKills[ x ] != 0 )
completionFlag |= ( 1ull << ( index0 * 5 + x ) );
else if( monsterNote->data().NeededKills[ x ] != 0 )
allComplete = false;
}
if( allComplete )
completionFlag |= ( 1ull << ( index0 * 5 + 4 ) );
}
memcpy( huntPacket->data().killCount, entry.entries, sizeof( entry.entries ) );
huntPacket->data().completeFlags = completionFlag;
server().queueForPlayer( player.getCharacterId(), huntPacket );
}
}
void Util::Player::sendActorControlSelf( Entity::Player& player, uint16_t category, uint32_t param1, uint32_t param2, uint32_t param3,
uint32_t param4, uint32_t param5 )
{
server().queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), category, param1, param2, param3, param4, param5 ) );
}
void Util::Player::sendActorControlSelf( const std::set< uint64_t >& characterIds, Entity::Player& player, uint16_t category, uint32_t param1,
uint32_t param2, uint32_t param3, uint32_t param4, uint32_t param5 )
{
server().queueForPlayers( characterIds, makeActorControlSelf( player.getId(), category, param1, param2, param3, param4, param5 ) );
}
void Util::Player::sendActorControl( Entity::Player& player, uint16_t category, uint32_t param1, uint32_t param2, uint32_t param3, uint32_t param4 )
{
server().queueForPlayer( player.getCharacterId(), makeActorControl( player.getId(), category, param1, param2, param3, param4 ) );
}
void Util::Player::sendActorControl( const std::set< uint64_t >& characterIds, Entity::Player& player, uint16_t category, uint32_t param1,
uint32_t param2, uint32_t param3, uint32_t param4 )
{
server().queueForPlayers( characterIds, makeActorControl( player.getId(), category, param1, param2, param3, param4 ) );
}
void Util::Player::sendTitleList( Entity::Player& player )
{
auto titleListPacket = makeZonePacket< FFXIVIpcTitleList >( player.getId() );
memcpy( titleListPacket->data().TitleFlagsArray, player.getTitleList().data(), sizeof( titleListPacket->data().TitleFlagsArray ) );
server().queueForPlayer( player.getCharacterId(), titleListPacket );
}
void Util::Player::sendGrandCompany( Entity::Player& player )
{
auto gcAffPacket = makeZonePacket< FFXIVIpcGrandCompany >( player.getId() );
gcAffPacket->data().ActiveCompanyId = player.getGc();
gcAffPacket->data().MaelstromRank = player.getGcRankArray()[ 0 ];
gcAffPacket->data().TwinAdderRank = player.getGcRankArray()[ 1 ];
gcAffPacket->data().ImmortalFlamesRank = player.getGcRankArray()[ 2 ];
server().queueForPlayer( player.getCharacterId(), gcAffPacket );
}

View file

@ -0,0 +1,32 @@
#pragma once
#include <Network/GamePacket.h>
#include <Network/PacketDef/Zone/ServerZoneDef.h>
#include <Actor/Player.h>
#include "Forwards.h"
namespace Sapphire::Network::Util::Player
{
void sendConfigFlags( Entity::Player& player );
void sendOnlineStatus( Entity::Player& player );
void sendBaseParams( Entity::Player& player );
void sendHudParam( Entity::Player& player );
void sendStatusUpdate( Entity::Player& player );
void sendHuntingLog( Entity::Player& player );
void sendTitleList( Entity::Player& player );
void sendGrandCompany( Entity::Player& player );
void sendActorControlSelf( Entity::Player& player, uint16_t category, uint32_t param1 = 0, uint32_t param2 = 0, uint32_t param3 = 0,
uint32_t param4 = 0, uint32_t param5 = 0 );
void sendActorControlSelf( const std::set< uint64_t >& characterIds, Entity::Player& player, uint16_t category, uint32_t param1 = 0,
uint32_t param2 = 0, uint32_t param3 = 0, uint32_t param4 = 0, uint32_t param5 = 0 );
void sendActorControl( Entity::Player& player, uint16_t category, uint32_t param1 = 0, uint32_t param2 = 0, uint32_t param3 = 0, uint32_t param4 = 0 );
void sendActorControl( const std::set< uint64_t >& characterIds, Entity::Player& player, uint16_t category, uint32_t param1 = 0, uint32_t param2 = 0,
uint32_t param3 = 0, uint32_t param4 = 0 );
}