1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-28 07:07:45 +00:00

Merge branch 'master' of https://github.com/SapphireServer/Sapphire into actions-war

This commit is contained in:
Lucy 2023-03-12 20:04:12 +01:00
commit fb65f728a7
68 changed files with 1684 additions and 1605 deletions

View file

@ -1,7 +1,7 @@
{ {
"7": { "7": {
"name": "Attack", "name": "Attack",
"potency": 0, "potency": 110,
"comboPotency": 0, "comboPotency": 0,
"flankPotency": 0, "flankPotency": 0,
"frontPotency": 0, "frontPotency": 0,
@ -16,7 +16,7 @@
}, },
"8": { "8": {
"name": "Shot", "name": "Shot",
"potency": 0, "potency": 100,
"comboPotency": 0, "comboPotency": 0,
"flankPotency": 0, "flankPotency": 0,
"frontPotency": 0, "frontPotency": 0,

View file

@ -1053,7 +1053,7 @@ namespace Sapphire::Common
CritDirectHitDamage = 3 CritDirectHitDamage = 3
}; };
enum class ActionEffectResultFlag : uint8_t enum class ActionResultFlag : uint8_t
{ {
None = 0, None = 0,
Absorbed = 0x04, Absorbed = 0x04,

View file

@ -17,10 +17,7 @@ public:
return; return;
uint32_t duration = ( sourceChara->getAsPlayer()->getTp() / 50 ) * 1000; uint32_t duration = ( sourceChara->getAsPlayer()->getTp() / 50 ) * 1000;
action.getActionResultBuilder()->applyStatusEffect( sourceChara, 50, duration, 30, false );
action.getEffectbuilder()->applyStatusEffect( sourceChara, 50, 30 );
sourceChara->getAsPlayer()->addStatusEffectByIdIfNotExist( 50, duration, *sourceChara, 30 );
sourceChara->getAsPlayer()->setTp( 0 ); sourceChara->getAsPlayer()->setTp( 0 );
} }
}; };

View file

@ -30,13 +30,11 @@ public:
status->setModifier( Common::ParamModifier::DamageDealtPercent, 0 ); status->setModifier( Common::ParamModifier::DamageDealtPercent, 0 );
auto dmg = action.calcDamage( Potency ); auto dmg = action.calcDamage( Potency );
action.getEffectbuilder()->damage( pSource, pTarget, dmg.first, dmg.second ); action.getActionResultBuilder()->damage( pSource, pTarget, dmg.first, dmg.second );
action.getEffectbuilder()->heal( pTarget, pSource, dmg.first, Common::ActionHitSeverityType::NormalHeal, action.getActionResultBuilder()->heal( pTarget, pSource, dmg.first, Common::ActionHitSeverityType::NormalHeal,
Common::ActionEffectResultFlag::EffectOnSource ); Common::ActionResultFlag::EffectOnSource );
action.applyStatusEffectSelf( InnerBeast ); action.applyStatusEffectSelf( InnerBeast, 15000, false, { StatusModifier{ Common::ParamModifier::DamageTakenPercent, -20 } } );
pPlayer->addStatusEffectByIdIfNotExist( InnerBeast, 15000, *pSource,
{ StatusModifier{ Common::ParamModifier::DamageTakenPercent, -20 } } );
if( !pPlayer->hasStatusEffect( Unchained ) ) if( !pPlayer->hasStatusEffect( Unchained ) )
{ {

View file

@ -25,8 +25,7 @@ public:
if( auto status = pPlayer->getStatusEffectById( Defiance ); status ) if( auto status = pPlayer->getStatusEffectById( Defiance ); status )
status->setModifier( Common::ParamModifier::DamageDealtPercent, 0 ); status->setModifier( Common::ParamModifier::DamageDealtPercent, 0 );
action.applyStatusEffectSelf( Unchained ); action.applyStatusEffectSelf( Unchained, 20000, false );
pPlayer->addStatusEffectByIdIfNotExist( Unchained, 20000, *pPlayer->getAsChara() );
} }
}; };

View file

@ -1,7 +1,7 @@
{ {
"7": { "7": {
"name": "Attack", "name": "Attack",
"potency": 0, "potency": 110,
"comboPotency": 0, "comboPotency": 0,
"flankPotency": 0, "flankPotency": 0,
"frontPotency": 0, "frontPotency": 0,
@ -16,7 +16,7 @@
}, },
"8": { "8": {
"name": "Shot", "name": "Shot",
"potency": 0, "potency": 100,
"comboPotency": 0, "comboPotency": 0,
"flankPotency": 0, "flankPotency": 0,
"frontPotency": 0, "frontPotency": 0,

View file

@ -0,0 +1,52 @@
#include <cstdint>
#include <ForwardsZone.h>
#include "GambitTargetCondition.h"
#include "GambitRule.h"
using namespace Sapphire;
using namespace Sapphire::World;
AI::GambitRule::GambitRule( const GambitTargetConditionPtr targetCondition, Action::ActionPtr action, uint32_t coolDown ) :
m_targetCondition( targetCondition ),
m_pAction( std::move( action ) ),
m_lastExecutionMs( 0 ),
m_coolDownMs( coolDown ),
m_isEnabled( true )
{
}
void AI::GambitRule::toggleEnabled()
{
m_isEnabled = !m_isEnabled;
}
bool AI::GambitRule::isEnabled() const
{
return m_isEnabled;
}
uint64_t AI::GambitRule::getLastExecutionMs() const
{
return m_lastExecutionMs;
}
void AI::GambitRule::setLastExecutionMs( uint64_t lastExecution )
{
m_lastExecutionMs = lastExecution;
}
uint32_t AI::GambitRule::getCoolDown() const
{
return m_coolDownMs;
}
AI::GambitTargetConditionPtr AI::GambitRule::getGambitTargetCondition()
{
return m_targetCondition;
}
Action::ActionPtr AI::GambitRule::getActionPtr()
{
return m_pAction;
}

33
src/world/AI/GambitRule.h Normal file
View file

@ -0,0 +1,33 @@
#include <cstdint>
#include <ForwardsZone.h>
#include "GambitTargetCondition.h"
#pragma once
namespace Sapphire::World::AI
{
class GambitRule
{
public:
GambitRule( GambitTargetConditionPtr targetCondition, Action::ActionPtr action, uint32_t coolDown );
~GambitRule() = default;
bool isEnabled() const;
void toggleEnabled();
uint64_t getLastExecutionMs() const;
void setLastExecutionMs( uint64_t lastExecution );
uint32_t getCoolDown() const;
GambitTargetConditionPtr getGambitTargetCondition();
Action::ActionPtr getActionPtr();
private:
GambitTargetConditionPtr m_targetCondition;
Action::ActionPtr m_pAction;
uint32_t m_coolDownMs;
uint64_t m_lastExecutionMs;
bool m_isEnabled;
};
}

View file

@ -0,0 +1,66 @@
#include <cstdint>
#include <ForwardsZone.h>
#include <Actor/BNpc.h>
#pragma once
namespace Sapphire::World::AI
{
enum GambitTargetType : uint8_t
{
Self,
Player,
PlayerAndAlly,
Ally,
BNpc
};
class GambitTargetCondition
{
public:
GambitTargetCondition( GambitTargetType targetType ) : m_targetType( targetType ) {};
virtual ~GambitTargetCondition() = default;
virtual bool isConditionMet( Sapphire::Entity::BNpc& src ) { return false; };
Sapphire::Entity::CharaPtr getTarget() const { return m_pTarget; };
protected:
GambitTargetType m_targetType;
Sapphire::Entity::CharaPtr m_pTarget;
};
class TopHateTargetCondition : public GambitTargetCondition
{
public:
TopHateTargetCondition() : GambitTargetCondition( PlayerAndAlly ) {};
bool isConditionMet( Sapphire::Entity::BNpc& src ) override
{
auto foundChara = src.hateListGetHighest();
if( foundChara )
{
m_pTarget = foundChara;
return true;
}
return false;
};
};
class HPSelfPctLessThan : public GambitTargetCondition
{
public:
HPSelfPctLessThan( uint8_t pct ) : GambitTargetCondition( Self ), m_HpPct( pct ) {};
virtual bool isConditionMet( Sapphire::Entity::BNpc& src )
{
if( src.getHpPercent() < m_HpPct )
{
m_pTarget = src.getAsBNpc();
return true;
}
return false;
};
private:
uint8_t m_HpPct;
};
}

View file

@ -16,6 +16,7 @@
#include "Manager/PlayerMgr.h" #include "Manager/PlayerMgr.h"
#include "Manager/MgrUtil.h" #include "Manager/MgrUtil.h"
#include "Manager/TerritoryMgr.h"
#include "Session.h" #include "Session.h"
#include "Network/GameConnection.h" #include "Network/GameConnection.h"
@ -23,7 +24,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 "Network/Util/PacketUtil.h"
#include <Logging/Logger.h> #include <Logging/Logger.h>
@ -67,6 +68,11 @@ uint32_t Action::Action::getId() const
return m_id; return m_id;
} }
uint32_t Action::Action::getResultId() const
{
return m_resultId;
}
bool Action::Action::init() bool Action::Action::init()
{ {
if( !m_actionData ) if( !m_actionData )
@ -80,8 +86,11 @@ bool Action::Action::init()
m_actionData = actionData; m_actionData = actionData;
} }
auto teriMgr = Common::Service< Manager::TerritoryMgr >::ref();
auto zone = teriMgr.getTerritoryByGuId( m_pSource->getTerritoryId() );
m_resultId = zone->getNextActionResultId();
m_effectBuilder = make_EffectBuilder( m_pSource, getId(), m_requestId ); m_actionResultBuilder = make_ActionResultBuilder( m_pSource, getId(), m_resultId, m_requestId );
m_castTimeMs = static_cast< uint32_t >( m_actionData->data().CastTime * 100 ); m_castTimeMs = static_cast< uint32_t >( m_actionData->data().CastTime * 100 );
m_recastTimeMs = static_cast< uint32_t >( m_actionData->data().RecastTime * 100 ); m_recastTimeMs = static_cast< uint32_t >( m_actionData->data().RecastTime * 100 );
@ -108,9 +117,9 @@ bool Action::Action::init()
{ {
case Common::ClassJob::Bard: case Common::ClassJob::Bard:
case Common::ClassJob::Archer: case Common::ClassJob::Archer:
case Common::ClassJob::Machinist:
m_range = 25; m_range = 25;
break; break;
// anything that isnt ranged
default: default:
m_range = 3; m_range = 3;
break; break;
@ -244,34 +253,34 @@ bool Action::Action::update()
// todo: check if the target is still in range // todo: check if the target is still in range
} }
uint64_t tickCount = Common::Util::getTimeMs(); auto tickCount = static_cast< time_t >( Common::Util::getTimeMs() );
uint32_t castTime = m_castTimeMs; auto startTime = static_cast< time_t >( m_startTime );
uint64_t castTime = m_castTimeMs;
if( auto player = m_pSource->getAsPlayer() ) if( auto player = m_pSource->getAsPlayer() )
{ {
uint64_t lastActionTick = player->getLastActionTick(); auto lastActionTick = static_cast< time_t >( player->getLastActionTick() );
uint32_t lastTickMs = 0; uint32_t lastTickMs = 0;
if( lastActionTick > 0 ) if( lastActionTick > 0 )
{ {
lastTickMs = static_cast< uint32_t >( std::difftime( static_cast< time_t >( tickCount ), static_cast< time_t >( lastActionTick ) ) ); lastTickMs = static_cast< uint32_t >( std::difftime( tickCount, lastActionTick ) );
if( lastTickMs > 100 ) //max 100ms if( lastTickMs > 100 ) //max 100ms
lastTickMs = 100; lastTickMs = 100;
} }
player->setLastActionTick( tickCount ); player->setLastActionTick( tickCount );
uint32_t delayMs = 100 - lastTickMs; uint64_t delayMs = 100 - lastTickMs;
castTime = ( m_castTimeMs + delayMs ); castTime = ( m_castTimeMs + delayMs );
m_castTimeRestMs = static_cast< uint64_t >( m_castTimeMs ) - m_castTimeRestMs = static_cast< uint64_t >( m_castTimeMs ) - static_cast< uint64_t >( std::difftime( tickCount, startTime ) );
static_cast< uint64_t >( std::difftime( static_cast< time_t >( tickCount ), static_cast< time_t >( m_startTime ) ) );
} }
if( !hasCastTime() || std::difftime( static_cast< time_t >( tickCount ), static_cast< time_t >( m_startTime ) ) > castTime ) if( !hasCastTime() || std::difftime( tickCount, startTime ) > castTime )
{ {
execute(); execute();
return true; return true;
} }
if( m_pTarget == nullptr && m_targetId != 0 ) if( !m_pTarget && m_targetId != 0 )
{ {
// try to search for the target actor // try to search for the target actor
for( const auto& actor : m_pSource->getInRangeActors( true ) ) for( const auto& actor : m_pSource->getInRangeActors( true ) )
@ -284,7 +293,7 @@ bool Action::Action::update()
} }
} }
if( m_pTarget != nullptr && !m_pTarget->isAlive() ) if( m_pTarget && !m_pTarget->isAlive() )
{ {
// interrupt the cast if target died // interrupt the cast if target died
setInterrupted( Common::ActionInterruptType::RegularInterrupt ); setInterrupted( Common::ActionInterruptType::RegularInterrupt );
@ -318,20 +327,20 @@ void Action::Action::start()
data.TargetPos[ 2 ] = Common::Util::floatToUInt16( m_pSource->getPos().z ); data.TargetPos[ 2 ] = Common::Util::floatToUInt16( m_pSource->getPos().z );
data.Dir = m_pSource->getRot(); data.Dir = m_pSource->getRot();
server().queueForPlayers( m_pSource->getInRangePlayerIds( true ), castPacket ); server().queueForPlayers( m_pSource->getInRangePlayerIds( m_pSource->isPlayer() ), castPacket );
if( player ) if( player )
{
player->setCondition( PlayerCondition::Casting ); player->setCondition( PlayerCondition::Casting );
}
} }
// todo: m_recastTimeMs needs to be adjusted for player sks/sps // todo: m_recastTimeMs needs to be adjusted for player sks/sps
auto actionStartPkt = makeActorControlSelf( m_pSource->getId(), ActorControlType::ActionStart, m_cooldownGroup, getId(), m_recastTimeMs / 10 ); auto actionStartPkt = makeActorControlSelf( m_pSource->getId(), ActorControlType::ActionStart, m_cooldownGroup, getId(), m_recastTimeMs / 10 );
player->setRecastGroup( m_cooldownGroup, static_cast< float >( m_castTimeMs ) / 1000.f ); if( player )
{
server().queueForPlayer( player->getCharacterId(), actionStartPkt ); player->setRecastGroup( m_cooldownGroup, static_cast< float >( m_castTimeMs ) / 1000.f );
server().queueForPlayer( player->getCharacterId(), actionStartPkt );
}
onStart(); onStart();
@ -365,7 +374,6 @@ void Action::Action::onStart()
void Action::Action::interrupt() void Action::Action::interrupt()
{ {
assert( m_pSource ); assert( m_pSource );
// things that aren't players don't care about cooldowns and state flags // things that aren't players don't care about cooldowns and state flags
if( m_pSource->isPlayer() ) if( m_pSource->isPlayer() )
{ {
@ -405,25 +413,20 @@ void Action::Action::onInterrupt()
void Action::Action::execute() void Action::Action::execute()
{ {
assert( m_pSource ); assert( m_pSource );
// subtract costs first, if somehow the caster stops meeting those requirements cancel the cast // subtract costs first, if somehow the caster stops meeting those requirements cancel the cast
if( !consumeResources() ) if( !consumeResources() )
{ {
interrupt(); interrupt();
return; return;
} }
auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref(); auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref();
if( hasCastTime() ) if( hasCastTime() && m_pSource->isPlayer() )
{ {
if( auto pPlayer = m_pSource->getAsPlayer(); pPlayer ) auto pPlayer = m_pSource->getAsPlayer();
{ pPlayer->setLastActionTick( 0 );
pPlayer->setLastActionTick( 0 ); pPlayer->removeCondition( PlayerCondition::Casting );
pPlayer->removeCondition( PlayerCondition::Casting );
}
} }
if( isCorrectCombo() ) if( isCorrectCombo() )
@ -433,13 +436,9 @@ void Action::Action::execute()
} }
if( !hasClientsideTarget() ) if( !hasClientsideTarget() )
{ buildActionResults();
handleAction();
}
else if( auto player = m_pSource->getAsPlayer() ) else if( auto player = m_pSource->getAsPlayer() )
{
scriptMgr.onEObjHit( *player, m_targetId, getId() ); scriptMgr.onEObjHit( *player, m_targetId, getId() );
}
// set currently casted action as the combo action if it interrupts a combo // set currently casted action as the combo action if it interrupts a combo
// ignore it otherwise (ogcds, etc.) // ignore it otherwise (ogcds, etc.)
@ -447,13 +446,9 @@ void Action::Action::execute()
{ {
// potential combo starter or correct combo from last action, must hit something to progress combo // potential combo starter or correct combo from last action, must hit something to progress combo
if( !m_hitActors.empty() && ( !isComboAction() || isCorrectCombo() ) ) if( !m_hitActors.empty() && ( !isComboAction() || isCorrectCombo() ) )
{
m_pSource->setLastComboActionId( getId() ); m_pSource->setLastComboActionId( getId() );
}
else // clear last combo action if the combo breaks else // clear last combo action if the combo breaks
{
m_pSource->setLastComboActionId( 0 ); m_pSource->setLastComboActionId( 0 );
}
} }
} }
@ -469,13 +464,13 @@ std::pair< uint32_t, Common::ActionHitSeverityType > Action::Action::calcDamage(
auto role = player->getRole(); auto role = player->getRole();
if( role == Common::Role::RangedMagical || role == Common::Role::Healer ) if( role == Common::Role::RangedMagical || role == Common::Role::Healer )
{
wepDmg = item->getMagicalDmg(); wepDmg = item->getMagicalDmg();
}
else else
{
wepDmg = item->getPhysicalDmg(); wepDmg = item->getPhysicalDmg();
}
// is auto attack
if( getId() == 7 || getId() == 8 )
return Math::CalcStats::calcAutoAttackDamage( *m_pSource->getAsPlayer() );
} }
return Math::CalcStats::calcActionDamage( *m_pSource, potency, wepDmg ); return Math::CalcStats::calcActionDamage( *m_pSource, potency, wepDmg );
@ -492,27 +487,34 @@ std::pair< uint32_t, Common::ActionHitSeverityType > Action::Action::calcHealing
auto role = player->getRole(); auto role = player->getRole();
if( role == Common::Role::RangedMagical || role == Common::Role::Healer ) if( role == Common::Role::RangedMagical || role == Common::Role::Healer )
{
wepDmg = item->getMagicalDmg(); wepDmg = item->getMagicalDmg();
}
else else
{
wepDmg = item->getPhysicalDmg(); wepDmg = item->getPhysicalDmg();
}
} }
return Math::CalcStats::calcActionHealing( *m_pSource, potency, wepDmg ); return Math::CalcStats::calcActionHealing( *m_pSource, potency, wepDmg );
} }
void Action::Action::applyStatusEffectSelf( uint16_t statusId, uint8_t param ) void Action::Action::applyStatusEffectSelf( StatusEntry& statusEntry, bool shouldOverride, uint8_t param )
{ {
if( m_hitActors.size() > 0 ) if( m_hitActors.size() > 0 )
getEffectbuilder()->applyStatusEffect( m_hitActors[ 0 ], statusId, param, true ); getActionResultBuilder()->applyStatusEffect( m_hitActors[ 0 ], statusEntry.id, statusEntry.duration, param,
statusEntry.modifiers, statusEntry.flag, shouldOverride, true );
else else
getEffectbuilder()->applyStatusEffect( m_pSource, statusId, param ); getActionResultBuilder()->applyStatusEffect( m_pSource, statusEntry.id, statusEntry.duration, param,
statusEntry.modifiers, statusEntry.flag, shouldOverride );
} }
void Action::Action::handleAction() void Action::Action::applyStatusEffectSelf( uint16_t statusId, int32_t duration, bool shouldOverride,
std::vector< StatusModifier > modifiers, uint8_t param )
{
if( m_hitActors.size() > 0 )
getActionResultBuilder()->applyStatusEffect( m_hitActors[ 0 ], statusId, duration, param, modifiers, shouldOverride, true );
else
getActionResultBuilder()->applyStatusEffect( m_pSource, statusId, duration, param, modifiers, shouldOverride );
}
void Action::Action::buildActionResults()
{ {
snapshotAffectedActors( m_hitActors ); snapshotAffectedActors( m_hitActors );
@ -523,22 +525,19 @@ void Action::Action::handleAction()
if( !hasScript && !hasLutEntry ) if( !hasScript && !hasLutEntry )
{ {
if( auto player = m_pSource->getAsPlayer() ) if( auto player = m_pSource->getAsPlayer() )
{
Manager::PlayerMgr::sendUrgent( *player, "missing lut entry for action#{}", getId() ); Manager::PlayerMgr::sendUrgent( *player, "missing lut entry for action#{}", getId() );
}
return; return;
} }
if( !hasScript ) if( !hasScript )
m_enableGenericHandler = true; m_enableGenericHandler = true;
Network::Util::Player::sendHudParam( *m_pSource->getAsPlayer() ); Network::Util::Packet::sendHudParam( *m_pSource );
if( !m_enableGenericHandler || !hasLutEntry || m_hitActors.empty() ) if( !m_enableGenericHandler || !hasLutEntry || m_hitActors.empty() )
{ {
// send any effect packet added by script or an empty one just to play animation for other players // send any effect packet added by script or an empty one just to play animation for other players
m_effectBuilder->buildAndSendPackets( m_hitActors ); m_actionResultBuilder->sendActionResults( {} );
return; return;
} }
@ -559,14 +558,14 @@ void Action::Action::handleAction()
if( m_lutEntry.potency > 0 ) if( m_lutEntry.potency > 0 )
{ {
auto dmg = calcDamage( isCorrectCombo() ? m_lutEntry.comboPotency : m_lutEntry.potency ); auto dmg = calcDamage( isCorrectCombo() ? m_lutEntry.comboPotency : m_lutEntry.potency );
m_effectBuilder->damage( m_pSource, actor, dmg.first, dmg.second ); m_actionResultBuilder->damage( m_pSource, actor, dmg.first, dmg.second );
if( dmg.first > 0 ) if( dmg.first > 0 )
actor->onActionHostile( m_pSource ); actor->onActionHostile( m_pSource );
if( isCorrectCombo() && shouldApplyComboSucceedEffect ) if( isCorrectCombo() && shouldApplyComboSucceedEffect )
{ {
m_effectBuilder->comboSucceed( m_pSource ); m_actionResultBuilder->comboSucceed( m_pSource );
shouldApplyComboSucceedEffect = false; shouldApplyComboSucceedEffect = false;
} }
@ -575,35 +574,33 @@ void Action::Action::handleAction()
if( m_lutEntry.curePotency > 0 ) // actions with self heal if( m_lutEntry.curePotency > 0 ) // actions with self heal
{ {
auto heal = calcHealing( m_lutEntry.curePotency ); auto heal = calcHealing( m_lutEntry.curePotency );
m_effectBuilder->heal( actor, m_pSource, heal.first, heal.second, Common::ActionEffectResultFlag::EffectOnSource ); m_actionResultBuilder->heal( actor, m_pSource, heal.first, heal.second, Common::ActionResultFlag::EffectOnSource );
} }
if( m_lutEntry.restoreMPPercentage > 0 && shouldRestoreMP ) if( m_lutEntry.restoreMPPercentage > 0 && shouldRestoreMP )
{ {
m_effectBuilder->restoreMP( actor, m_pSource, m_pSource->getMaxMp() * m_lutEntry.restoreMPPercentage / 100, Common::ActionEffectResultFlag::EffectOnSource ); m_actionResultBuilder->restoreMP( actor, m_pSource, m_pSource->getMaxMp() * m_lutEntry.restoreMPPercentage / 100, Common::ActionResultFlag::EffectOnSource );
shouldRestoreMP = false; shouldRestoreMP = false;
} }
if( !m_lutEntry.nextCombo.empty() ) // if we have a combo action followup if( !m_lutEntry.nextCombo.empty() ) // if we have a combo action followup
{ m_actionResultBuilder->startCombo( m_pSource, getId() ); // this is on all targets hit
m_effectBuilder->startCombo( m_pSource, getId() ); // this is on all targets hit
}
} }
} }
else if( m_lutEntry.curePotency > 0 ) else if( m_lutEntry.curePotency > 0 )
{ {
auto heal = calcHealing( m_lutEntry.curePotency ); auto heal = calcHealing( m_lutEntry.curePotency );
m_effectBuilder->heal( actor, actor, heal.first, heal.second ); m_actionResultBuilder->heal( actor, actor, heal.first, heal.second );
if( m_lutEntry.restoreMPPercentage > 0 && shouldRestoreMP ) if( m_lutEntry.restoreMPPercentage > 0 && shouldRestoreMP )
{ {
m_effectBuilder->restoreMP( actor, m_pSource, m_pSource->getMaxMp() * m_lutEntry.restoreMPPercentage / 100, Common::ActionEffectResultFlag::EffectOnSource ); m_actionResultBuilder->restoreMP( actor, m_pSource, m_pSource->getMaxMp() * m_lutEntry.restoreMPPercentage / 100, Common::ActionResultFlag::EffectOnSource );
shouldRestoreMP = false; shouldRestoreMP = false;
} }
} }
else if( m_lutEntry.restoreMPPercentage > 0 && shouldRestoreMP ) else if( m_lutEntry.restoreMPPercentage > 0 && shouldRestoreMP )
{ {
m_effectBuilder->restoreMP( actor, m_pSource, m_pSource->getMaxMp() * m_lutEntry.restoreMPPercentage / 100, Common::ActionEffectResultFlag::EffectOnSource ); m_actionResultBuilder->restoreMP( actor, m_pSource, m_pSource->getMaxMp() * m_lutEntry.restoreMPPercentage / 100, Common::ActionResultFlag::EffectOnSource );
shouldRestoreMP = false; shouldRestoreMP = false;
} }
} }
@ -619,7 +616,7 @@ void Action::Action::handleAction()
if( m_lutEntry.statuses.caster.size() > 0 || m_lutEntry.statuses.target.size() > 0 ) if( m_lutEntry.statuses.caster.size() > 0 || m_lutEntry.statuses.target.size() > 0 )
handleStatusEffects(); handleStatusEffects();
m_effectBuilder->buildAndSendPackets( m_hitActors ); m_actionResultBuilder->sendActionResults( m_hitActors );
// TODO: disabled, reset kills our queued actions // TODO: disabled, reset kills our queued actions
// at this point we're done with it and no longer need it // at this point we're done with it and no longer need it
@ -636,8 +633,7 @@ void Action::Action::handleStatusEffects()
{ {
for( auto& status : m_lutEntry.statuses.caster ) for( auto& status : m_lutEntry.statuses.caster )
{ {
applyStatusEffectSelf( status.id ); applyStatusEffectSelf( status, true );
m_pSource->addStatusEffectByIdIfNotExist( status.id, status.duration, *m_pSource, status );
} }
} }
@ -648,8 +644,7 @@ void Action::Action::handleStatusEffects()
{ {
for( auto& status : m_lutEntry.statuses.target ) for( auto& status : m_lutEntry.statuses.target )
{ {
getEffectbuilder()->applyStatusEffect( actor, status.id, 0 ); getActionResultBuilder()->applyStatusEffect( actor, status.id, status.duration, 0, status.modifiers, status.flag, true );
actor->addStatusEffectByIdIfNotExist( status.id, status.duration, *m_pSource, status );
} }
if( actor->getStatusEffectMap().size() > 0 ) if( actor->getStatusEffectMap().size() > 0 )
@ -748,9 +743,7 @@ bool Action::Action::isCorrectCombo() const
auto lastActionId = m_pSource->getLastComboActionId(); auto lastActionId = m_pSource->getLastComboActionId();
if( lastActionId == 0 ) if( lastActionId == 0 )
{
return false; return false;
}
return m_actionData->data().ComboParent == lastActionId; return m_actionData->data().ComboParent == lastActionId;
} }
@ -934,10 +927,7 @@ std::vector< Entity::CharaPtr >& Action::Action::getHitCharas()
Entity::CharaPtr Action::Action::getHitChara() Entity::CharaPtr Action::Action::getHitChara()
{ {
if( !m_hitActors.empty() ) if( !m_hitActors.empty() )
{
return m_hitActors.at( 0 ); return m_hitActors.at( 0 );
}
return nullptr; return nullptr;
} }
@ -948,9 +938,9 @@ bool Action::Action::hasValidLutEntry() const
m_lutEntry.statuses.caster.size() > 0 || m_lutEntry.statuses.target.size() > 0; m_lutEntry.statuses.caster.size() > 0 || m_lutEntry.statuses.target.size() > 0;
} }
Action::EffectBuilderPtr Action::Action::getEffectbuilder() Action::ActionResultBuilderPtr Action::Action::getActionResultBuilder()
{ {
return m_effectBuilder; return m_actionResultBuilder;
} }
uint8_t Action::Action::getActionKind() const uint8_t Action::Action::getActionKind() const

View file

@ -4,7 +4,7 @@
#include "ActionLut.h" #include "ActionLut.h"
#include "Util/ActorFilter.h" #include "Util/ActorFilter.h"
#include "ForwardsZone.h" #include "ForwardsZone.h"
#include "EffectBuilder.h" #include "ActionResultBuilder.h"
#include "Exd/Structs.h" #include "Exd/Structs.h"
namespace Sapphire::World::Action namespace Sapphire::World::Action
@ -23,6 +23,8 @@ namespace Sapphire::World::Action
uint32_t getId() const; uint32_t getId() const;
uint32_t getResultId() const;
bool init(); bool init();
void setPos( const Common::FFXIVARR_POSITION3& pos ); void setPos( const Common::FFXIVARR_POSITION3& pos );
@ -105,11 +107,14 @@ namespace Sapphire::World::Action
*/ */
bool snapshotAffectedActors( std::vector< Entity::CharaPtr >& actors ); bool snapshotAffectedActors( std::vector< Entity::CharaPtr >& actors );
EffectBuilderPtr getEffectbuilder(); ActionResultBuilderPtr getActionResultBuilder();
void applyStatusEffectSelf( uint16_t statusId, uint8_t param = 0 ); void applyStatusEffectSelf( StatusEntry& statusEntry, bool shouldOverride, uint8_t param = 0 );
void handleAction(); void applyStatusEffectSelf( uint16_t statusId, int32_t duration, bool shouldOverride,
std::vector< StatusModifier > modifiers = {}, uint8_t param = 0 );
void buildActionResults();
void handleStatusEffects(); void handleStatusEffects();
@ -180,6 +185,7 @@ namespace Sapphire::World::Action
uint8_t m_actionKind{}; uint8_t m_actionKind{};
uint16_t m_requestId{}; uint16_t m_requestId{};
uint32_t m_resultId{};
Common::ActionPrimaryCostType m_primaryCostType; Common::ActionPrimaryCostType m_primaryCostType;
uint16_t m_primaryCost{}; uint16_t m_primaryCost{};
@ -218,7 +224,7 @@ namespace Sapphire::World::Action
Common::FFXIVARR_POSITION3 m_pos{}; Common::FFXIVARR_POSITION3 m_pos{};
EffectBuilderPtr m_effectBuilder; ActionResultBuilderPtr m_actionResultBuilder;
std::vector< World::Util::ActorFilterPtr > m_actorFilters; std::vector< World::Util::ActorFilterPtr > m_actorFilters;
std::vector< Entity::CharaPtr > m_hitActors; std::vector< Entity::CharaPtr > m_hitActors;

View file

@ -0,0 +1,165 @@
#include "ActionResult.h"
#include <Util/Util.h>
#include <Service.h>
#include <Manager/PlayerMgr.h>
#include "Actor/Chara.h"
#include "Actor/Player.h"
#include "StatusEffect/StatusEffect.h"
using namespace Sapphire;
using namespace Sapphire::World::Action;
ActionResult::ActionResult( Entity::CharaPtr target, uint64_t runAfter ) :
m_target( std::move( target ) ),
m_delayMs( runAfter )
{
m_result.Arg0 = 0;
m_result.Arg1 = 0;
m_result.Arg2 = 0;
m_result.Value = 0;
m_result.Flag = static_cast< uint8_t >( Common::ActionResultFlag::None );
m_result.Type = Common::ActionEffectType::CALC_RESULT_TYPE_NONE;
}
Entity::CharaPtr ActionResult::getTarget() const
{
return m_target;
}
uint64_t ActionResult::getDelay()
{
return m_delayMs;
}
void ActionResult::damage( uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionResultFlag flag )
{
m_result.Arg0 = static_cast< uint8_t >( severity );
m_result.Value = static_cast< int16_t >( amount );
m_result.Flag = static_cast< uint8_t >( flag );
m_result.Type = Common::ActionEffectType::CALC_RESULT_TYPE_DAMAGE_HP;
}
void ActionResult::heal( uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionResultFlag flag )
{
m_result.Arg1 = static_cast< uint8_t >( severity );
m_result.Value = static_cast< int16_t >( amount );
m_result.Flag = static_cast< uint8_t >( flag );
m_result.Type = Common::ActionEffectType::CALC_RESULT_TYPE_RECOVER_HP;
}
void ActionResult::restoreMP( uint32_t amount, Common::ActionResultFlag flag )
{
m_result.Value = static_cast< int16_t >( amount );
m_result.Flag = static_cast< uint8_t >( flag );
m_result.Type = Common::ActionEffectType::CALC_RESULT_TYPE_RECOVER_MP;
}
void ActionResult::startCombo( uint16_t actionId )
{
m_result.Value = static_cast< int16_t >( actionId );
m_result.Flag = static_cast< uint8_t >( Common::ActionResultFlag::EffectOnSource );
m_result.Type = Common::ActionEffectType::CALC_RESULT_TYPE_COMBO;
}
void ActionResult::comboSucceed()
{
// no EffectOnSource flag on this
m_result.Type = Common::ActionEffectType::CALC_RESULT_TYPE_COMBO_HIT;
}
void ActionResult::applyStatusEffect( uint32_t id, int32_t duration, Entity::Chara& source, uint8_t param, bool shouldOverride, bool forSelf )
{
m_result.Value = static_cast< int16_t >( id );
m_result.Arg2 = param;
if( forSelf )
m_result.Flag = static_cast< uint8_t >( Common::ActionResultFlag::EffectOnSource );
m_result.Type = forSelf ? Common::ActionEffectType::CALC_RESULT_TYPE_SET_STATUS_ME : Common::ActionEffectType::CALC_RESULT_TYPE_SET_STATUS;
m_bOverrideStatus = shouldOverride;
m_pStatus = Sapphire::StatusEffect::make_StatusEffect( id, source.getAsChara(), m_target, duration, 3000 );
m_pStatus->setParam( param );
}
void ActionResult::applyStatusEffect( uint32_t id, int32_t duration, Entity::Chara& source, uint8_t param,
std::vector< StatusModifier > modifiers, uint32_t flag, bool shouldOverride, bool forSelf )
{
m_result.Value = static_cast< int16_t >( id );
m_result.Arg2 = param;
if( forSelf )
m_result.Flag = static_cast< uint8_t >( Common::ActionResultFlag::EffectOnSource );
m_result.Type = forSelf ? Common::ActionEffectType::CALC_RESULT_TYPE_SET_STATUS_ME : Common::ActionEffectType::CALC_RESULT_TYPE_SET_STATUS;
m_bOverrideStatus = shouldOverride;
m_pStatus = Sapphire::StatusEffect::make_StatusEffect( id, source.getAsChara(), m_target, duration, modifiers, flag, 3000 );
m_pStatus->setParam( param );
}
void ActionResult::mount( uint16_t mountId )
{
m_result.Value = static_cast< int16_t >( mountId );
m_result.Arg0 = 1;
m_result.Type = Common::ActionEffectType::CALC_RESULT_TYPE_MOUNT;
}
const Common::CalcResultParam& ActionResult::getCalcResultParam() const
{
return m_result;
}
const Sapphire::StatusEffect::StatusEffectPtr ActionResult::getStatusEffect() const
{
return m_pStatus;
}
void ActionResult::execute()
{
if( !m_target )
return;
switch( m_result.Type )
{
case Common::ActionEffectType::CALC_RESULT_TYPE_DAMAGE_HP:
{
m_target->takeDamage( m_result.Value );
break;
}
case Common::ActionEffectType::CALC_RESULT_TYPE_RECOVER_HP:
{
m_target->heal( m_result.Value );
break;
}
case Common::ActionEffectType::CALC_RESULT_TYPE_RECOVER_MP:
{
m_target->restoreMP( m_result.Value );
break;
}
case Common::ActionEffectType::CALC_RESULT_TYPE_SET_STATUS:
case Common::ActionEffectType::CALC_RESULT_TYPE_SET_STATUS_ME:
{
if( !m_bOverrideStatus )
m_target->addStatusEffectByIdIfNotExist( m_pStatus->getId(), m_pStatus->getDuration(), *m_pStatus->getSrcActor(),
m_pStatus->getStatusModifiers(), m_pStatus->getFlag(), m_pStatus->getParam() );
else
m_target->addStatusEffectById( m_pStatus->getId(), m_pStatus->getDuration(), *m_pStatus->getSrcActor(),
m_pStatus->getStatusModifiers(), m_pStatus->getFlag(), m_pStatus->getParam() );
break;
}
case Common::ActionEffectType::CALC_RESULT_TYPE_MOUNT:
{
auto pPlayer = m_target->getAsPlayer();
pPlayer->setMount( m_result.Value );
break;
}
default:
break;
}
}

View file

@ -0,0 +1,50 @@
#pragma once
#include <ForwardsZone.h>
#include <Common.h>
#include "ActionLut.h"
namespace Sapphire::World::Action
{
/*!
* @brief A container for the computed result of an effect on a single actor. Used to apply damage/healing dealt
* at a later point in time.
*/
class ActionResult
{
public:
explicit ActionResult( Entity::CharaPtr target, uint64_t delayMs );
void damage( uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionResultFlag flag = Common::ActionResultFlag::None );
void heal( uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionResultFlag flag = Common::ActionResultFlag::None );
void restoreMP( uint32_t amount, Common::ActionResultFlag flag = Common::ActionResultFlag::None );
void startCombo( uint16_t actionId );
void comboSucceed();
void applyStatusEffect( uint32_t id, int32_t duration, Entity::Chara& source, uint8_t param, bool shouldOverride, bool forSelf );
void applyStatusEffect( uint32_t id, int32_t duration, Entity::Chara& source, uint8_t param,
std::vector< World::Action::StatusModifier > modifiers, uint32_t flag, bool shouldOverride, bool forSelf );
void mount( uint16_t mountId );
Entity::CharaPtr getTarget() const;
uint64_t getDelay();
const Common::CalcResultParam& getCalcResultParam() const;
const Sapphire::StatusEffect::StatusEffectPtr getStatusEffect() const;
void execute();
private:
uint64_t m_delayMs;
Entity::CharaPtr m_target;
Common::CalcResultParam m_result;
bool m_bOverrideStatus { false };
Sapphire::StatusEffect::StatusEffectPtr m_pStatus;
};
using ActionResultList = std::vector< ActionResultPtr >;
}

View file

@ -0,0 +1,188 @@
#include "ActionResultBuilder.h"
#include "ActionResult.h"
#include <Actor/Player.h>
#include <Network/PacketWrappers/EffectPacket.h>
#include <Network/PacketWrappers/EffectPacket1.h>
#include <Territory/Territory.h>
#include <Util/Util.h>
#include <Util/UtilMath.h>
#include <Logging/Logger.h>
#include <Manager/TerritoryMgr.h>
#include <Manager/MgrUtil.h>
#include <Service.h>
#include <Manager/TaskMgr.h>
#include <Task/ActionIntegrityTask.h>
using namespace Sapphire;
using namespace Sapphire::World::Action;
using namespace Sapphire::World::Manager;
using namespace Sapphire::Network::Packets;
using namespace Sapphire::Network::Packets::WorldPackets::Server;
ActionResultBuilder::ActionResultBuilder( Entity::CharaPtr source, uint32_t actionId, uint32_t resultId, uint16_t requestId ) :
m_sourceChara( std::move( source ) ),
m_actionId( actionId ),
m_resultId( resultId ),
m_requestId( requestId )
{
}
void ActionResultBuilder::addResultToActor( Entity::CharaPtr& chara, ActionResultPtr result )
{
auto it = m_actorResultsMap.find( chara );
if( it == m_actorResultsMap.end() )
{
m_actorResultsMap[ chara ].push_back( std::move( result ) );
return;
}
it->second.push_back( std::move( result ) );
}
void ActionResultBuilder::heal( Entity::CharaPtr& effectTarget, Entity::CharaPtr& healingTarget, uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionResultFlag flag )
{
ActionResultPtr nextResult = make_ActionResult( healingTarget, 0 );
nextResult->heal( amount, severity, flag );
addResultToActor( effectTarget, nextResult );
}
void ActionResultBuilder::restoreMP( Entity::CharaPtr& target, Entity::CharaPtr& restoringTarget, uint32_t amount, Common::ActionResultFlag flag )
{
ActionResultPtr nextResult = make_ActionResult( restoringTarget, 0 ); // restore mp source actor
nextResult->restoreMP( amount, flag );
addResultToActor( target, nextResult );
}
void ActionResultBuilder::damage( Entity::CharaPtr& effectTarget, Entity::CharaPtr& damagingTarget, uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionResultFlag flag )
{
ActionResultPtr nextResult = make_ActionResult( damagingTarget, 0 );
nextResult->damage( amount, severity, flag );
addResultToActor( damagingTarget, nextResult );
}
void ActionResultBuilder::startCombo( Entity::CharaPtr& target, uint16_t actionId )
{
ActionResultPtr nextResult = make_ActionResult( target, 0 );
nextResult->startCombo( actionId );
addResultToActor( target, nextResult );
}
void ActionResultBuilder::comboSucceed( Entity::CharaPtr& target )
{
ActionResultPtr nextResult = make_ActionResult( target, 0 );
nextResult->comboSucceed();
addResultToActor( target, nextResult );
}
void ActionResultBuilder::applyStatusEffect( Entity::CharaPtr& target, uint16_t statusId, uint32_t duration, uint8_t param, bool shouldOverride, bool forSelf )
{
ActionResultPtr nextResult = make_ActionResult( target, 0 );
nextResult->applyStatusEffect( statusId, duration, *m_sourceChara, param, shouldOverride, forSelf );
addResultToActor( target, nextResult );
}
void ActionResultBuilder::applyStatusEffect( Entity::CharaPtr& target, uint16_t statusId, uint32_t duration, uint8_t param,
std::vector< World::Action::StatusModifier > modifiers, uint32_t flag,
bool shouldOverride, bool forSelf )
{
ActionResultPtr nextResult = make_ActionResult( target, 0 );
nextResult->applyStatusEffect( statusId, duration, *m_sourceChara, param, modifiers, flag, shouldOverride, forSelf );
addResultToActor( target, nextResult );
}
void ActionResultBuilder::mount( Entity::CharaPtr& target, uint16_t mountId )
{
ActionResultPtr nextResult = make_ActionResult( target, 0 );
nextResult->mount( mountId );
addResultToActor( target, nextResult );
}
void ActionResultBuilder::sendActionResults( const std::vector< Entity::CharaPtr >& targetList )
{
Logger::debug( "EffectBuilder result: " );
Logger::debug( "Targets afflicted: {}", targetList.size() );
do // we want to send at least one packet even nothing is hit so other players can see
{
auto packet = createActionResultPacket( targetList );
server().queueForPlayers( m_sourceChara->getInRangePlayerIds( true ), packet );
}
while( !m_actorResultsMap.empty() );
}
std::shared_ptr< FFXIVPacketBase > ActionResultBuilder::createActionResultPacket( const std::vector< Entity::CharaPtr >& targetList )
{
auto targetCount = targetList.size();
auto& taskMgr = Common::Service< World::Manager::TaskMgr >::ref();
auto& teriMgr = Common::Service< Sapphire::World::Manager::TerritoryMgr >::ref();
auto zone = teriMgr.getTerritoryByGuId( m_sourceChara->getTerritoryId() );
if( targetCount > 1 ) // use AoeEffect packets
{
auto actionResult = std::make_shared< EffectPacket >( m_sourceChara->getId(), targetList[ 0 ]->getId(), m_actionId );
actionResult->setRotation( Common::Util::floatToUInt16Rot( m_sourceChara->getRot() ) );
actionResult->setRequestId( m_requestId );
actionResult->setResultId( m_resultId );
uint8_t targetIndex = 0;
for( auto it = m_actorResultsMap.begin(); it != m_actorResultsMap.end(); ++it )
{
// get all effect results for an actor
auto actorResultList = it->second;
if( it->first )
taskMgr.queueTask( World::makeActionIntegrityTask( m_resultId, it->first, actorResultList, 300 ) );
for( auto& result : actorResultList )
{
auto effect = result->getCalcResultParam();
if( result->getTarget() == m_sourceChara )
actionResult->addSourceEffect( effect );
else
actionResult->addTargetEffect( effect, result->getTarget()->getId() );
}
targetIndex++;
if( targetIndex == 15 )
break;
}
return actionResult;
}
else // use Effect for single target
{
uint32_t mainTargetId = targetList.empty() ? m_sourceChara->getId() : targetList[ 0 ]->getId();
auto actionResult = std::make_shared< EffectPacket1 >( m_sourceChara->getId(), mainTargetId, m_actionId );
actionResult->setRotation( Common::Util::floatToUInt16Rot( m_sourceChara->getRot() ) );
actionResult->setRequestId( m_requestId );
actionResult->setResultId( m_resultId );
for( auto it = m_actorResultsMap.begin(); it != m_actorResultsMap.end(); ++it )
{
// get all effect results for an actor
auto actorResultList = it->second;
if( it->first )
taskMgr.queueTask( World::makeActionIntegrityTask( m_resultId, it->first, actorResultList, 300 ) );
for( auto& result : actorResultList )
{
auto effect = result->getCalcResultParam();
if( result->getTarget() == m_sourceChara )
actionResult->addSourceEffect( effect );
else
actionResult->addTargetEffect( effect );
}
}
m_actorResultsMap.clear();
return actionResult;
}
}

View file

@ -0,0 +1,52 @@
#pragma once
#include <ForwardsZone.h>
#include <Common.h>
#include "ActionLut.h"
namespace Sapphire::World::Action
{
class ActionResultBuilder
{
public:
ActionResultBuilder( Entity::CharaPtr source, uint32_t actionId, uint32_t resultId, uint16_t requestId );
void heal( Entity::CharaPtr& effectTarget, Entity::CharaPtr& healingTarget, uint32_t amount,
Common::ActionHitSeverityType severity = Common::ActionHitSeverityType::NormalHeal,
Common::ActionResultFlag flag = Common::ActionResultFlag::None );
void restoreMP( Entity::CharaPtr& effectTarget, Entity::CharaPtr& restoringTarget, uint32_t amount,
Common::ActionResultFlag flag = Common::ActionResultFlag::None );
void damage( Entity::CharaPtr& effectTarget, Entity::CharaPtr& damagingTarget, uint32_t amount,
Common::ActionHitSeverityType severity = Common::ActionHitSeverityType::NormalDamage,
Common::ActionResultFlag flag = Common::ActionResultFlag::None );
void startCombo( Entity::CharaPtr& target, uint16_t actionId );
void comboSucceed( Entity::CharaPtr& target );
void applyStatusEffect( Entity::CharaPtr& target, uint16_t statusId, uint32_t duration, uint8_t param, bool shouldOverride = false, bool forSelf = false );
void applyStatusEffect( Entity::CharaPtr& target, uint16_t statusId, uint32_t duration, uint8_t param,
std::vector< World::Action::StatusModifier > modifiers, uint32_t flag = 0, bool shouldOverride = false, bool forSelf = false );
void mount( Entity::CharaPtr& target, uint16_t mountId );
void sendActionResults( const std::vector< Entity::CharaPtr >& targetList );
private:
void addResultToActor( Entity::CharaPtr& chara, ActionResultPtr result );
Network::Packets::FFXIVPacketBasePtr createActionResultPacket( const std::vector< Entity::CharaPtr >& targetList );
private:
uint32_t m_actionId;
uint16_t m_requestId;
uint32_t m_resultId;
Entity::CharaPtr m_sourceChara;
std::unordered_map< Entity::CharaPtr, std::vector< ActionResultPtr > > m_actorResultsMap;
};
}

View file

@ -1,236 +0,0 @@
#include "EffectBuilder.h"
#include "EffectResult.h"
#include <Actor/Player.h>
#include <Network/PacketWrappers/EffectPacket.h>
#include <Network/PacketWrappers/EffectPacket1.h>
#include <Territory/Territory.h>
#include <Util/Util.h>
#include <Util/UtilMath.h>
#include <Logging/Logger.h>
#include <Manager/TerritoryMgr.h>
#include <Manager/MgrUtil.h>
#include <Service.h>
#include <Manager/TaskMgr.h>
#include <Task/ActionIntegrityTask.h>
using namespace Sapphire;
using namespace Sapphire::World::Action;
using namespace Sapphire::World::Manager;
using namespace Sapphire::Network::Packets;
using namespace Sapphire::Network::Packets::WorldPackets::Server;
EffectBuilder::EffectBuilder( Entity::CharaPtr source, uint32_t actionId, uint16_t requestId ) :
m_sourceChara( std::move( source ) ),
m_actionId( actionId ),
m_requestId( requestId )
{
}
uint64_t EffectBuilder::getResultDelayMs()
{
// todo: actually figure this retarded shit out
return Common::Util::getTimeMs() + 850;
}
void EffectBuilder::addResultToActor( Entity::CharaPtr& chara, EffectResultPtr result )
{
auto it = m_actorEffectsMap.find( chara->getId() );
if( it == m_actorEffectsMap.end() )
{
// create a new one
auto resultList = std::vector< EffectResultPtr >();
resultList.push_back( std::move( result ) );
m_actorEffectsMap[ chara->getId() ] = resultList;
return;
}
it->second.push_back( std::move( result ) );
}
void EffectBuilder::heal( Entity::CharaPtr& effectTarget, Entity::CharaPtr& healingTarget, uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionEffectResultFlag flag )
{
EffectResultPtr nextResult = make_EffectResult( healingTarget, getResultDelayMs() );
nextResult->heal( amount, severity, flag );
addResultToActor( effectTarget, nextResult );
}
void EffectBuilder::restoreMP( Entity::CharaPtr& target, Entity::CharaPtr& restoringTarget, uint32_t amount, Common::ActionEffectResultFlag flag )
{
EffectResultPtr nextResult = make_EffectResult( restoringTarget, getResultDelayMs() ); // restore mp source actor
nextResult->restoreMP( amount, flag );
addResultToActor( target, nextResult );
}
void EffectBuilder::damage( Entity::CharaPtr& effectTarget, Entity::CharaPtr& damagingTarget, uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionEffectResultFlag flag )
{
EffectResultPtr nextResult = make_EffectResult( damagingTarget, getResultDelayMs() );
nextResult->damage( amount, severity, flag );
addResultToActor( damagingTarget, nextResult );
}
void EffectBuilder::startCombo( Entity::CharaPtr& target, uint16_t actionId )
{
EffectResultPtr nextResult = make_EffectResult( target, 0 );
nextResult->startCombo( actionId );
addResultToActor( target, nextResult );
}
void EffectBuilder::comboSucceed( Entity::CharaPtr& target )
{
EffectResultPtr nextResult = make_EffectResult( target, 0 );
nextResult->comboSucceed();
addResultToActor( target, nextResult );
}
void EffectBuilder::applyStatusEffect( Entity::CharaPtr& target, uint16_t statusId, uint8_t param, bool forSelf )
{
EffectResultPtr nextResult = make_EffectResult( target, 0 );
nextResult->applyStatusEffect( statusId, param, forSelf );
addResultToActor( target, nextResult );
}
void EffectBuilder::mount( Entity::CharaPtr& target, uint16_t mountId )
{
EffectResultPtr nextResult = make_EffectResult( target, getResultDelayMs() );
nextResult->mount( mountId );
addResultToActor( target, nextResult );
}
void EffectBuilder::buildAndSendPackets( const std::vector< Entity::CharaPtr >& targetList )
{
Logger::debug( "EffectBuilder result: " );
Logger::debug( "Targets afflicted: {}", targetList.size() );
do // we want to send at least one packet even nothing is hit so other players can see
{
auto packet = buildNextEffectPacket( targetList );
server().queueForPlayers( m_sourceChara->getInRangePlayerIds( true ), packet );
}
while( !m_actorEffectsMap.empty() );
}
std::shared_ptr< FFXIVPacketBase > EffectBuilder::buildNextEffectPacket( const std::vector< Entity::CharaPtr >& targetList )
{
auto remainingTargetCount = targetList.size();
auto& teriMgr = Common::Service< Sapphire::World::Manager::TerritoryMgr >::ref();
auto zone = teriMgr.getTerritoryByGuId( m_sourceChara->getTerritoryId() );
auto resultId = zone->getNextEffectResultId();
if( remainingTargetCount > 1 ) // use AoeEffect packets
{
auto effectPacket = std::make_shared< EffectPacket >( m_sourceChara->getId(), m_actionId );
effectPacket->setRotation( Common::Util::floatToUInt16Rot( m_sourceChara->getRot() ) );
effectPacket->setRequestId( m_requestId );
effectPacket->setResultId( resultId );
effectPacket->setTargetActor( targetList[ 0 ]->getId() );
uint8_t targetIndex = 0;
for( auto it = m_actorEffectsMap.begin(); it != m_actorEffectsMap.end(); )
{
// get all effect results for an actor
auto actorResultList = it->second;
for( auto i = 0; i < actorResultList.size(); ++i )
{
auto result = actorResultList.data()[ i ];
auto effect = result->getCalcResultParam();
// if effect result is a source/caster effect
if( result->getTarget() == m_sourceChara )
{
effectPacket->addSourceEffect( effect );
}
else
{
effectPacket->addTargetEffect( effect, result->getTarget()->getId() );
auto& taskMgr = Common::Service< World::Manager::TaskMgr >::ref();
taskMgr.queueTask( Sapphire::World::makeActionIntegrityTask( resultId, result->getTarget(), 1000 ) );
}
zone->addEffectResult( std::move( result ) );
}
actorResultList.clear();
it = m_actorEffectsMap.erase( it );
targetIndex++;
if( targetIndex == 15 )
break;
}
return effectPacket;
}
else if( remainingTargetCount == 1 ) // use Effect for single target
{
Logger::debug( " - id: {}", targetList[0]->getId() );
Logger::debug( "------------------------------------------" );
auto effectPacket = std::make_shared< EffectPacket1 >( m_sourceChara->getId(), targetList[ 0 ]->getId(), m_actionId );
effectPacket->setRotation( Common::Util::floatToUInt16Rot( m_sourceChara->getRot() ) );
effectPacket->setRequestId( m_requestId );
effectPacket->setResultId( resultId );
for( auto it = m_actorEffectsMap.begin(); it != m_actorEffectsMap.end(); )
{
// get all effect results for an actor
auto actorResultList = it->second;
for( auto i = 0; i < actorResultList.size(); ++i )
{
auto result = actorResultList.data()[ i ];
auto effect = result->getCalcResultParam();
// if effect result is a source/caster effect
if( result->getTarget() == m_sourceChara )
{
effectPacket->addSourceEffect( effect );
}
else
{
effectPacket->addTargetEffect( effect );
auto& taskMgr = Common::Service< World::Manager::TaskMgr >::ref();
taskMgr.queueTask( Sapphire::World::makeActionIntegrityTask( resultId, result->getTarget(), 1000 ) );
}
zone->addEffectResult( std::move( result ) );
}
actorResultList.clear();
it = m_actorEffectsMap.erase( it );
}
m_actorEffectsMap.clear();
return effectPacket;
}
else // nothing is hit, this only happens when using aoe and AoeEffect8 is used on retail
{
auto effectPacket = makeZonePacket< FFXIVIpcActionResult1 >( m_sourceChara->getId() );
effectPacket->data().ActionKey = m_actionId;
effectPacket->data().Action = static_cast< uint16_t >( m_actionId );
effectPacket->data().Target = m_sourceChara->getId();
effectPacket->data().MainTarget = static_cast< uint64_t >( m_sourceChara->getId() );
effectPacket->data().DirTarget = Common::Util::floatToUInt16Rot( m_sourceChara->getRot() );
effectPacket->data().Flag = Common::ActionEffectDisplayType::HideActionName;
effectPacket->data().RequestId = m_requestId;
effectPacket->data().ResultId = resultId;
m_actorEffectsMap.clear();
return effectPacket;
}
}

View file

@ -1,49 +0,0 @@
#pragma once
#include <ForwardsZone.h>
#include <Common.h>
namespace Sapphire::World::Action
{
class EffectBuilder
{
public:
EffectBuilder( Entity::CharaPtr source, uint32_t actionId, uint16_t requestId );
void heal( Entity::CharaPtr& effectTarget, Entity::CharaPtr& healingTarget, uint32_t amount,
Common::ActionHitSeverityType severity = Common::ActionHitSeverityType::NormalHeal,
Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None );
void restoreMP( Entity::CharaPtr& effectTarget, Entity::CharaPtr& restoringTarget, uint32_t amount,
Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None );
void damage( Entity::CharaPtr& effectTarget, Entity::CharaPtr& damagingTarget, uint32_t amount,
Common::ActionHitSeverityType severity = Common::ActionHitSeverityType::NormalDamage,
Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None );
void startCombo( Entity::CharaPtr& target, uint16_t actionId );
void comboSucceed( Entity::CharaPtr& target );
void applyStatusEffect( Entity::CharaPtr& target, uint16_t statusId, uint8_t param, bool forSelf = false );
void mount( Entity::CharaPtr& target, uint16_t mountId );
void buildAndSendPackets( const std::vector< Entity::CharaPtr >& targetList );
private:
void addResultToActor( Entity::CharaPtr& chara, EffectResultPtr result );
uint64_t getResultDelayMs();
Network::Packets::FFXIVPacketBasePtr buildNextEffectPacket( const std::vector< Entity::CharaPtr >& targetList );
private:
uint32_t m_actionId;
uint16_t m_requestId;
Entity::CharaPtr m_sourceChara;
std::unordered_map< uint32_t, std::vector< EffectResultPtr > > m_actorEffectsMap;
};
}

View file

@ -1,126 +0,0 @@
#include "EffectResult.h"
#include <Util/Util.h>
#include <Service.h>
#include <Manager/PlayerMgr.h>
#include "Actor/Chara.h"
#include "Actor/Player.h"
using namespace Sapphire;
using namespace Sapphire::World::Action;
EffectResult::EffectResult( Entity::CharaPtr target, uint64_t runAfter ) :
m_target( std::move( target ) ),
m_delayMs( runAfter )
{
m_result.Arg0 = 0;
m_result.Arg1 = 0;
m_result.Arg2 = 0;
m_result.Value = 0;
m_result.Flag = static_cast< uint8_t >( Common::ActionEffectResultFlag::None );
m_result.Type = Common::ActionEffectType::CALC_RESULT_TYPE_NONE;
}
Entity::CharaPtr EffectResult::getTarget() const
{
return m_target;
}
uint64_t EffectResult::getDelay()
{
return m_delayMs;
}
void EffectResult::damage( uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionEffectResultFlag flag )
{
m_result.Arg0 = static_cast< uint8_t >( severity );
m_result.Value = static_cast< int16_t >( amount );
m_result.Flag = static_cast< uint8_t >( flag );
m_result.Type = Common::ActionEffectType::CALC_RESULT_TYPE_DAMAGE_HP;
}
void EffectResult::heal( uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionEffectResultFlag flag )
{
m_result.Arg1 = static_cast< uint8_t >( severity );
m_result.Value = static_cast< int16_t >( amount );
m_result.Flag = static_cast< uint8_t >( flag );
m_result.Type = Common::ActionEffectType::CALC_RESULT_TYPE_RECOVER_HP;
}
void EffectResult::restoreMP( uint32_t amount, Common::ActionEffectResultFlag flag )
{
m_result.Value = static_cast< int16_t >( amount );
m_result.Flag = static_cast< uint8_t >( flag );
m_result.Type = Common::ActionEffectType::CALC_RESULT_TYPE_RECOVER_MP;
}
void EffectResult::startCombo( uint16_t actionId )
{
m_result.Value = static_cast< int16_t >( actionId );
m_result.Flag = static_cast< uint8_t >( Common::ActionEffectResultFlag::EffectOnSource );
m_result.Type = Common::ActionEffectType::CALC_RESULT_TYPE_COMBO;
}
void EffectResult::comboSucceed()
{
// no EffectOnSource flag on this
m_result.Type = Common::ActionEffectType::CALC_RESULT_TYPE_COMBO_HIT;
}
void EffectResult::applyStatusEffect( uint16_t statusId, uint8_t param, bool forSelf )
{
m_result.Value = static_cast< int16_t >( statusId );
m_result.Arg2 = param;
if( forSelf )
m_result.Flag = static_cast< uint8_t >( Common::ActionEffectResultFlag::EffectOnSource );
m_result.Type = forSelf ? Common::ActionEffectType::CALC_RESULT_TYPE_SET_STATUS_ME : Common::ActionEffectType::CALC_RESULT_TYPE_SET_STATUS;
}
void EffectResult::mount( uint16_t mountId )
{
m_result.Value = static_cast< int16_t >( mountId );
m_result.Arg0 = 1;
m_result.Type = Common::ActionEffectType::CALC_RESULT_TYPE_MOUNT;
}
const Common::CalcResultParam& EffectResult::getCalcResultParam() const
{
return m_result;
}
void EffectResult::execute()
{
switch( m_result.Type )
{
case Common::ActionEffectType::CALC_RESULT_TYPE_DAMAGE_HP:
{
m_target->takeDamage( m_result.Value );
break;
}
case Common::ActionEffectType::CALC_RESULT_TYPE_RECOVER_HP:
{
m_target->heal( m_result.Value );
break;
}
case Common::ActionEffectType::CALC_RESULT_TYPE_RECOVER_MP:
{
m_target->restoreMP( m_result.Value );
break;
}
case Common::ActionEffectType::CALC_RESULT_TYPE_MOUNT:
{
auto pPlayer = m_target->getAsPlayer();
pPlayer->setMount( m_result.Value );
break;
}
default:
break;
}
}

View file

@ -1,41 +0,0 @@
#pragma once
#include <ForwardsZone.h>
#include <Common.h>
namespace Sapphire::World::Action
{
/*!
* @brief A container for the computed result of an effect on a single actor. Used to apply damage/healing dealt
* at a later point in time.
*/
class EffectResult
{
public:
explicit EffectResult( Entity::CharaPtr target, uint64_t delayMs );
void damage( uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None );
void heal( uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None );
void restoreMP( uint32_t amount, Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None );
void startCombo( uint16_t actionId );
void comboSucceed();
void applyStatusEffect( uint16_t statusId, uint8_t param, bool forSelf );
void mount( uint16_t mountId );
Entity::CharaPtr getTarget() const;
uint64_t getDelay();
const Common::CalcResultParam& getCalcResultParam() const;
void execute();
private:
uint64_t m_delayMs;
Entity::CharaPtr m_target;
Common::CalcResultParam m_result;
};
}

View file

@ -81,9 +81,8 @@ void ItemAction::handleVFXItem()
effect.Type = Common::ActionEffectType::CALC_RESULT_TYPE_CHECK_BARRIER; effect.Type = Common::ActionEffectType::CALC_RESULT_TYPE_CHECK_BARRIER;
effect.Value = m_itemAction->data().Calcu0Arg[ 0 ]; effect.Value = m_itemAction->data().Calcu0Arg[ 0 ];
auto effectPacket = std::make_shared< EffectPacket >( getSourceChara()->getId(), getId() ); auto effectPacket = std::make_shared< EffectPacket >( getSourceChara()->getId(), getSourceChara()->getId(), getId() );
effectPacket->setTargetActor( getSourceChara()->getId() ); effectPacket->setActionId( Common::ItemActionType::ItemActionVFX );
effectPacket->setAnimationId( Common::ItemActionType::ItemActionVFX );
effectPacket->setDisplayType( Common::ActionEffectDisplayType::ShowItemName ); effectPacket->setDisplayType( Common::ActionEffectDisplayType::ShowItemName );
effectPacket->addTargetEffect( effect, static_cast< uint64_t >( getSourceChara()->getId() ) ); effectPacket->addTargetEffect( effect, static_cast< uint64_t >( getSourceChara()->getId() ) );
server().queueForPlayers( m_pSource->getInRangePlayerIds( true ), effectPacket ); server().queueForPlayers( m_pSource->getInRangePlayerIds( true ), effectPacket );

View file

@ -40,7 +40,7 @@ void ItemManipulationAction::execute()
{ {
assert( m_pSource ); assert( m_pSource );
m_effectBuilder->buildAndSendPackets( m_hitActors ); m_actionResultBuilder->sendActionResults( m_hitActors );
} }
void ItemManipulationAction::onFinish() void ItemManipulationAction::onFinish()

View file

@ -60,7 +60,6 @@ void Warrior::handleWrath( Entity::Player& player, Action& action )
if( !player.hasStatusEffect( Infuriated ) ) if( !player.hasStatusEffect( Infuriated ) )
{ {
action.applyStatusEffectSelf( effectToApply ); action.applyStatusEffectSelf( effectToApply, 30000, false, { StatusModifier{ Common::ParamModifier::ParryPercent, parry } } );
player.addStatusEffectByIdIfNotExist( effectToApply, 30000, *asChara, { StatusModifier{ Common::ParamModifier::ParryPercent, parry } } );
} }
} }

View file

@ -69,6 +69,6 @@ void MountAction::execute()
assert( m_pSource ); assert( m_pSource );
m_pSource->getAsPlayer()->removeCondition( Common::PlayerCondition::Casting ); m_pSource->getAsPlayer()->removeCondition( Common::PlayerCondition::Casting );
m_effectBuilder->mount( m_pSource, m_mountId ); m_actionResultBuilder->mount( m_pSource, m_mountId );
m_effectBuilder->buildAndSendPackets( { m_pSource } ); m_actionResultBuilder->sendActionResults( { m_pSource } );
} }

View file

@ -18,7 +18,7 @@
#include "Network/PacketWrappers/ActorControlTargetPacket.h" #include "Network/PacketWrappers/ActorControlTargetPacket.h"
#include "Network/PacketWrappers/NpcSpawnPacket.h" #include "Network/PacketWrappers/NpcSpawnPacket.h"
#include "Network/PacketWrappers/MoveActorPacket.h" #include "Network/PacketWrappers/MoveActorPacket.h"
#include "Network/Util/PlayerUtil.h" #include "Network/Util/PacketUtil.h"
#include "Navi/NaviProvider.h" #include "Navi/NaviProvider.h"
@ -36,6 +36,7 @@
#include <Manager/PlayerMgr.h> #include <Manager/PlayerMgr.h>
#include <Manager/TaskMgr.h> #include <Manager/TaskMgr.h>
#include <Manager/MgrUtil.h> #include <Manager/MgrUtil.h>
#include <Manager/ActionMgr.h>
#include <Script/ScriptMgr.h> #include <Script/ScriptMgr.h>
#include <Task/RemoveBNpcTask.h> #include <Task/RemoveBNpcTask.h>
#include <Task/FadeBNpcTask.h> #include <Task/FadeBNpcTask.h>
@ -43,19 +44,24 @@
#include <Task/ActionIntegrityTask.h> #include <Task/ActionIntegrityTask.h>
#include <Service.h> #include <Service.h>
#include <Action/Action.h>
#include <AI/GambitRule.h>
#include <AI/GambitTargetCondition.h>
using namespace Sapphire;
using namespace Sapphire::World;
using namespace Sapphire::Common; using namespace Sapphire::Common;
using namespace Sapphire::Entity;
using namespace Sapphire::Network::Packets; using namespace Sapphire::Network::Packets;
using namespace Sapphire::Network::Packets::WorldPackets::Server; using namespace Sapphire::Network::Packets::WorldPackets::Server;
using namespace Sapphire::Network::ActorControl; using namespace Sapphire::Network::ActorControl;
using namespace Sapphire::World::Manager; using namespace Sapphire::World::Manager;
Sapphire::Entity::BNpc::BNpc() : BNpc::BNpc() : Npc( ObjKind::BattleNpc )
Npc( ObjKind::BattleNpc )
{ {
} }
Sapphire::Entity::BNpc::BNpc( uint32_t id, std::shared_ptr< Common::BNPCInstanceObject > pInfo, const Territory& zone ) : BNpc::BNpc( uint32_t id, std::shared_ptr< Common::BNPCInstanceObject > pInfo, const Territory& zone ) : Npc( ObjKind::BattleNpc )
Npc( ObjKind::BattleNpc )
{ {
m_id = id; m_id = id;
m_pInfo = pInfo; m_pInfo = pInfo;
@ -167,7 +173,7 @@ Sapphire::Entity::BNpc::BNpc( uint32_t id, std::shared_ptr< Common::BNPCInstance
} }
Sapphire::Entity::BNpc::BNpc( uint32_t id, std::shared_ptr< Common::BNPCInstanceObject > pInfo, const Territory& zone, uint32_t hp, Common::BNpcType type ) : BNpc::BNpc( uint32_t id, std::shared_ptr< Common::BNPCInstanceObject > pInfo, const Territory& zone, uint32_t hp, Common::BNpcType type ) :
Npc( ObjKind::BattleNpc ) Npc( ObjKind::BattleNpc )
{ {
m_id = id; m_id = id;
@ -269,81 +275,78 @@ Sapphire::Entity::BNpc::BNpc( uint32_t id, std::shared_ptr< Common::BNPCInstance
calculateStats(); calculateStats();
} }
Sapphire::Entity::BNpc::~BNpc() = default; BNpc::~BNpc() = default;
uint8_t Sapphire::Entity::BNpc::getAggressionMode() const uint8_t BNpc::getAggressionMode() const
{ {
return m_aggressionMode; return m_aggressionMode;
} }
float Sapphire::Entity::BNpc::getNaviTargetReachedDistance() const float BNpc::getNaviTargetReachedDistance() const
{ {
return m_naviTargetReachedDistance; return m_naviTargetReachedDistance;
} }
uint8_t Sapphire::Entity::BNpc::getEnemyType() const uint8_t BNpc::getEnemyType() const
{ {
return m_enemyType; return m_enemyType;
} }
uint64_t Sapphire::Entity::BNpc::getWeaponMain() const uint64_t BNpc::getWeaponMain() const
{ {
return m_weaponMain; return m_weaponMain;
} }
uint64_t Sapphire::Entity::BNpc::getWeaponSub() const uint64_t BNpc::getWeaponSub() const
{ {
return m_weaponSub; return m_weaponSub;
} }
uint16_t Sapphire::Entity::BNpc::getModelChara() const uint16_t BNpc::getModelChara() const
{ {
return m_modelChara; return m_modelChara;
} }
uint8_t Sapphire::Entity::BNpc::getLevel() const uint8_t BNpc::getLevel() const
{ {
return m_level; return m_level;
} }
uint32_t Sapphire::Entity::BNpc::getBNpcBaseId() const uint32_t BNpc::getBNpcBaseId() const
{ {
return m_bNpcBaseId; return m_bNpcBaseId;
} }
uint32_t Sapphire::Entity::BNpc::getBNpcNameId() const uint32_t BNpc::getBNpcNameId() const
{ {
return m_bNpcNameId; return m_bNpcNameId;
} }
void Sapphire::Entity::BNpc::spawn( PlayerPtr pTarget ) void BNpc::spawn( PlayerPtr pTarget )
{ {
m_lastRoamTargetReached = Util::getTimeSeconds(); m_lastRoamTargetReached = Common::Util::getTimeSeconds();
auto& server = Common::Service< World::WorldServer >::ref(); auto& server = Common::Service< World::WorldServer >::ref();
server.queueForPlayer( pTarget->getCharacterId(), std::make_shared< NpcSpawnPacket >( *this, *pTarget ) ); server.queueForPlayer( pTarget->getCharacterId(), std::make_shared< NpcSpawnPacket >( *this, *pTarget ) );
} }
void Sapphire::Entity::BNpc::despawn( PlayerPtr pTarget ) void BNpc::despawn( PlayerPtr pTarget )
{ {
pTarget->freePlayerSpawnId( getId() ); pTarget->freePlayerSpawnId( getId() );
Network::Util::Packet::sendActorControlSelf( *pTarget, getId(), WarpStart, 4, getId(), 1 );
auto& server = Common::Service< World::WorldServer >::ref();
server.queueForPlayer( pTarget->getCharacterId(), makeActorControlSelf( m_id, WarpStart, 0x04, getId(), 0x01 ) );
} }
Sapphire::Entity::BNpcState Sapphire::Entity::BNpc::getState() const BNpcState BNpc::getState() const
{ {
return m_state; return m_state;
} }
void Sapphire::Entity::BNpc::setState( BNpcState state ) void BNpc::setState( BNpcState state )
{ {
m_state = state; m_state = state;
} }
bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) bool BNpc::moveTo( const FFXIVARR_POSITION3& pos )
{ {
auto& teriMgr = Common::Service< World::Manager::TerritoryMgr >::ref(); auto& teriMgr = Common::Service< World::Manager::TerritoryMgr >::ref();
auto pZone = teriMgr.getTerritoryByGuId( getTerritoryId() ); auto pZone = teriMgr.getTerritoryByGuId( getTerritoryId() );
@ -357,7 +360,7 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos )
} }
auto pos1 = pNaviProvider->getMovePos( *this ); auto pos1 = pNaviProvider->getMovePos( *this );
auto distance = Util::distance( pos1, pos ); auto distance = Common::Util::distance( pos1, pos );
if( distance < getNaviTargetReachedDistance() ) if( distance < getNaviTargetReachedDistance() )
{ {
@ -380,7 +383,7 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos )
return false; return false;
} }
bool Sapphire::Entity::BNpc::moveTo( const Entity::Chara& targetChara ) bool BNpc::moveTo( const Chara& targetChara )
{ {
auto& teriMgr = Common::Service< World::Manager::TerritoryMgr >::ref(); auto& teriMgr = Common::Service< World::Manager::TerritoryMgr >::ref();
@ -395,7 +398,7 @@ bool Sapphire::Entity::BNpc::moveTo( const Entity::Chara& targetChara )
} }
auto pos1 = pNaviProvider->getMovePos( *this ); auto pos1 = pNaviProvider->getMovePos( *this );
auto distance = Util::distance( pos1, targetChara.getPos() ); auto distance = Common::Util::distance( pos1, targetChara.getPos() );
if( distance <= ( getNaviTargetReachedDistance() + targetChara.getRadius() ) ) if( distance <= ( getNaviTargetReachedDistance() + targetChara.getRadius() ) )
{ {
@ -418,7 +421,7 @@ bool Sapphire::Entity::BNpc::moveTo( const Entity::Chara& targetChara )
return false; return false;
} }
void Sapphire::Entity::BNpc::sendPositionUpdate() void BNpc::sendPositionUpdate()
{ {
uint8_t animationType = 2; uint8_t animationType = 2;
@ -429,7 +432,7 @@ void Sapphire::Entity::BNpc::sendPositionUpdate()
server().queueForPlayers( getInRangePlayerIds(), movePacket ); server().queueForPlayers( getInRangePlayerIds(), movePacket );
} }
void Sapphire::Entity::BNpc::hateListClear() void BNpc::hateListClear()
{ {
for( auto& listEntry : m_hateList ) for( auto& listEntry : m_hateList )
{ {
@ -439,7 +442,7 @@ void Sapphire::Entity::BNpc::hateListClear()
m_hateList.clear(); m_hateList.clear();
} }
uint32_t Sapphire::Entity::BNpc::hateListGetValue( const Sapphire::Entity::CharaPtr& pChara ) uint32_t BNpc::hateListGetValue( const Sapphire::Entity::CharaPtr& pChara )
{ {
for( const auto& listEntry : m_hateList ) for( const auto& listEntry : m_hateList )
{ {
@ -452,7 +455,7 @@ uint32_t Sapphire::Entity::BNpc::hateListGetValue( const Sapphire::Entity::Chara
return 0; return 0;
} }
uint32_t Sapphire::Entity::BNpc::hateListGetHighestValue() uint32_t BNpc::hateListGetHighestValue()
{ {
auto it = m_hateList.begin(); auto it = m_hateList.begin();
uint32_t maxHate = 0; uint32_t maxHate = 0;
@ -473,7 +476,7 @@ uint32_t Sapphire::Entity::BNpc::hateListGetHighestValue()
} }
Sapphire::Entity::CharaPtr Sapphire::Entity::BNpc::hateListGetHighest() CharaPtr BNpc::hateListGetHighest()
{ {
auto it = m_hateList.begin(); auto it = m_hateList.begin();
uint32_t maxHate = 0; uint32_t maxHate = 0;
@ -493,7 +496,7 @@ Sapphire::Entity::CharaPtr Sapphire::Entity::BNpc::hateListGetHighest()
return nullptr; return nullptr;
} }
void Sapphire::Entity::BNpc::hateListAdd( const Sapphire::Entity::CharaPtr& pChara, int32_t hateAmount ) void BNpc::hateListAdd( const CharaPtr& pChara, int32_t hateAmount )
{ {
auto hateEntry = std::make_shared< HateListEntry >(); auto hateEntry = std::make_shared< HateListEntry >();
hateEntry->m_hateAmount = static_cast< uint32_t >( hateAmount ); hateEntry->m_hateAmount = static_cast< uint32_t >( hateAmount );
@ -507,14 +510,14 @@ void Sapphire::Entity::BNpc::hateListAdd( const Sapphire::Entity::CharaPtr& pCha
} }
} }
void Sapphire::Entity::BNpc::hateListAddDelayed( const Sapphire::Entity::CharaPtr& pChara, int32_t hateAmount ) void BNpc::hateListAddDelayed( const CharaPtr& pChara, int32_t hateAmount )
{ {
auto& taskMgr = Common::Service< World::Manager::TaskMgr >::ref(); auto& taskMgr = Common::Service< World::Manager::TaskMgr >::ref();
auto delayedEmnityTask = std::make_shared< Sapphire::World::DelayedEmnityTask >( 5000, getAsBNpc(), pChara, hateAmount ); auto delayedEmnityTask = std::make_shared< World::DelayedEmnityTask >( 5000, getAsBNpc(), pChara, hateAmount );
taskMgr.queueTask( delayedEmnityTask ); taskMgr.queueTask( delayedEmnityTask );
} }
void Sapphire::Entity::BNpc::hateListUpdate( const Sapphire::Entity::CharaPtr& pChara, int32_t hateAmount ) void BNpc::hateListUpdate( const CharaPtr& pChara, int32_t hateAmount )
{ {
bool hasEntry = false; bool hasEntry = false;
@ -542,12 +545,12 @@ void Sapphire::Entity::BNpc::hateListUpdate( const Sapphire::Entity::CharaPtr& p
if( pChara->isPlayer() ) if( pChara->isPlayer() )
{ {
auto pPlayer = pChara->getAsPlayer(); auto pPlayer = pChara->getAsPlayer();
Network::Util::Player::sendHateList( *pPlayer ); Network::Util::Packet::sendHateList( *pPlayer );
} }
} }
} }
void Sapphire::Entity::BNpc::hateListRemove( const Sapphire::Entity::CharaPtr& pChara ) void BNpc::hateListRemove( const CharaPtr& pChara )
{ {
for( const auto& listEntry : m_hateList ) for( const auto& listEntry : m_hateList )
{ {
@ -565,33 +568,33 @@ void Sapphire::Entity::BNpc::hateListRemove( const Sapphire::Entity::CharaPtr& p
} }
} }
uint32_t Sapphire::Entity::BNpc::getTriggerOwnerId() const uint32_t BNpc::getTriggerOwnerId() const
{ {
return m_triggerOwnerId; return m_triggerOwnerId;
} }
void Sapphire::Entity::BNpc::setTriggerOwnerId( uint32_t triggerOwnerId ) void BNpc::setTriggerOwnerId( uint32_t triggerOwnerId )
{ {
m_triggerOwnerId = triggerOwnerId; m_triggerOwnerId = triggerOwnerId;
} }
bool Sapphire::Entity::BNpc::hateListHasActor( const Sapphire::Entity::CharaPtr& pChara ) bool BNpc::hateListHasActor( const Sapphire::Entity::CharaPtr& pChara )
{ {
return std::any_of( m_hateList.begin(), m_hateList.end(), return std::any_of( m_hateList.begin(), m_hateList.end(),
[ pChara ]( const auto& entry ) { return entry->m_pChara == pChara; } ); [ pChara ]( const auto& entry ) { return entry->m_pChara == pChara; } );
} }
void Sapphire::Entity::BNpc::aggro( const Sapphire::Entity::CharaPtr& pChara ) void BNpc::aggro( const Sapphire::Entity::CharaPtr& pChara )
{ {
auto& pRNGMgr = Common::Service< World::Manager::RNGMgr >::ref(); auto& pRNGMgr = Common::Service< World::Manager::RNGMgr >::ref();
auto variation = static_cast< uint32_t >( pRNGMgr.getRandGenerator< float >( 500, 1000 ).next() ); auto variation = static_cast< uint32_t >( pRNGMgr.getRandGenerator< float >( 500, 1000 ).next() );
m_lastAttack = Util::getTimeMs() + variation; m_lastAttack = Common::Util::getTimeMs() + variation;
setStance( Stance::Active ); setStance( Stance::Active );
m_state = BNpcState::Combat; m_state = BNpcState::Combat;
server().queueForPlayers( getInRangePlayerIds(), makeActorControl( getId(), ActorControlType::SetBattle, 1, 0, 0 ) ); Network::Util::Packet::sendActorControl( getInRangePlayerIds(), getId(), SetBattle, 1 );
changeTarget( pChara->getId() ); changeTarget( pChara->getId() );
@ -603,7 +606,7 @@ void Sapphire::Entity::BNpc::aggro( const Sapphire::Entity::CharaPtr& pChara )
} }
void Sapphire::Entity::BNpc::deaggro( const Sapphire::Entity::CharaPtr& pChara ) void BNpc::deaggro( const CharaPtr& pChara )
{ {
if( !hateListHasActor( pChara ) ) if( !hateListHasActor( pChara ) )
hateListRemove( pChara ); hateListRemove( pChara );
@ -611,8 +614,8 @@ void Sapphire::Entity::BNpc::deaggro( const Sapphire::Entity::CharaPtr& pChara )
if( pChara->isPlayer() ) if( pChara->isPlayer() )
{ {
PlayerPtr tmpPlayer = pChara->getAsPlayer(); PlayerPtr tmpPlayer = pChara->getAsPlayer();
server().queueForPlayers( getInRangePlayerIds(), makeActorControl( getId(), ActorControlType::ToggleWeapon, 0, 1, 1 ) ); Network::Util::Packet::sendActorControl( getInRangePlayerIds(), getId(), ToggleWeapon, 0, 1, 1 );
server().queueForPlayers( getInRangePlayerIds(), makeActorControl( getId(), ActorControlType::SetBattle, 0, 0, 0 ) ); Network::Util::Packet::sendActorControl( getInRangePlayerIds(), getId(), SetBattle );
tmpPlayer->onMobDeaggro( *this ); tmpPlayer->onMobDeaggro( *this );
if( getTriggerOwnerId() == pChara->getId() ) if( getTriggerOwnerId() == pChara->getId() )
@ -624,7 +627,7 @@ void Sapphire::Entity::BNpc::deaggro( const Sapphire::Entity::CharaPtr& pChara )
} }
} }
void Sapphire::Entity::BNpc::onTick() void BNpc::onTick()
{ {
Chara::onTick(); Chara::onTick();
if( m_state == BNpcState::Retreat ) if( m_state == BNpcState::Retreat )
@ -633,7 +636,7 @@ void Sapphire::Entity::BNpc::onTick()
} }
} }
void Sapphire::Entity::BNpc::update( uint64_t tickCount ) void BNpc::update( uint64_t tickCount )
{ {
auto& teriMgr = Common::Service< World::Manager::TerritoryMgr >::ref(); auto& teriMgr = Common::Service< World::Manager::TerritoryMgr >::ref();
auto pZone = teriMgr.getTerritoryByGuId( getTerritoryId() ); auto pZone = teriMgr.getTerritoryByGuId( getTerritoryId() );
@ -646,6 +649,9 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount )
if( !pNaviProvider ) if( !pNaviProvider )
return; return;
if( !checkAction() )
processGambits( tickCount );
switch( m_state ) switch( m_state )
{ {
case BNpcState::Dead: case BNpcState::Dead:
@ -665,7 +671,7 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount )
// retail doesn't seem to roam straight after retreating // retail doesn't seem to roam straight after retreating
// todo: perhaps requires more investigation? // todo: perhaps requires more investigation?
m_lastRoamTargetReached = Util::getTimeSeconds(); m_lastRoamTargetReached = Common::Util::getTimeSeconds();
// resetHp // resetHp
setHp( getMaxHp() ); setHp( getMaxHp() );
@ -684,7 +690,7 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount )
if( moveTo( m_roamPos ) ) if( moveTo( m_roamPos ) )
{ {
m_lastRoamTargetReached = Util::getTimeSeconds(); m_lastRoamTargetReached = Common::Util::getTimeSeconds();
m_state = BNpcState::Idle; m_state = BNpcState::Idle;
} }
@ -701,12 +707,12 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount )
if( pNaviProvider->syncPosToChara( *this ) ) if( pNaviProvider->syncPosToChara( *this ) )
sendPositionUpdate(); sendPositionUpdate();
if( !hasFlag( Immobile ) && ( Util::getTimeSeconds() - m_lastRoamTargetReached > roamTick ) ) if( !hasFlag( Immobile ) && ( Common::Util::getTimeSeconds() - m_lastRoamTargetReached > roamTick ) )
{ {
if( !pNaviProvider ) if( !pNaviProvider )
{ {
m_lastRoamTargetReached = Util::getTimeSeconds(); m_lastRoamTargetReached = Common::Util::getTimeSeconds();
break; break;
} }
if( m_pInfo->WanderingRange != 0 && getEnemyType() != 0 ) if( m_pInfo->WanderingRange != 0 && getEnemyType() != 0 )
@ -732,7 +738,7 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount )
pNaviProvider->updateAgentParameters( *this ); pNaviProvider->updateAgentParameters( *this );
auto distanceOrig = Util::distance( getPos().x, getPos().y, getPos().z, m_spawnPos.x, m_spawnPos.y, m_spawnPos.z ); auto distanceOrig = Common::Util::distance( getPos(), m_spawnPos );
if( pHatedActor && !pHatedActor->isAlive() ) if( pHatedActor && !pHatedActor->isAlive() )
{ {
@ -742,8 +748,7 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount )
if( pHatedActor ) if( pHatedActor )
{ {
auto distance = Util::distance( getPos().x, getPos().y, getPos().z, auto distance = Common::Util::distance( getPos(), pHatedActor->getPos() );
pHatedActor->getPos().x, pHatedActor->getPos().y, pHatedActor->getPos().z );
if( !hasFlag( NoDeaggro ) && ( ( distanceOrig > maxDistanceToOrigin ) || distance > 30.0f ) ) if( !hasFlag( NoDeaggro ) && ( ( distanceOrig > maxDistanceToOrigin ) || distance > 30.0f ) )
{ {
@ -794,7 +799,7 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount )
Chara::update( tickCount ); Chara::update( tickCount );
} }
void Sapphire::Entity::BNpc::restHp() void BNpc::restHp()
{ {
if( m_hp < getMaxHp() ) if( m_hp < getMaxHp() )
{ {
@ -806,10 +811,10 @@ void Sapphire::Entity::BNpc::restHp()
m_hp = getMaxHp(); m_hp = getMaxHp();
} }
sendHudParam(); Network::Util::Packet::sendHudParam( *this );
} }
void Sapphire::Entity::BNpc::onActionHostile( Sapphire::Entity::CharaPtr pSource ) void BNpc::onActionHostile( CharaPtr pSource )
{ {
if( !hateListGetHighest() ) if( !hateListGetHighest() )
aggro( pSource ); aggro( pSource );
@ -820,7 +825,7 @@ void Sapphire::Entity::BNpc::onActionHostile( Sapphire::Entity::CharaPtr pSource
setOwner( pSource ); setOwner( pSource );
} }
void Sapphire::Entity::BNpc::onDeath() void BNpc::onDeath()
{ {
auto& playerMgr = Common::Service< World::Manager::PlayerMgr >::ref(); auto& playerMgr = Common::Service< World::Manager::PlayerMgr >::ref();
auto& taskMgr = Common::Service< World::Manager::TaskMgr >::ref(); auto& taskMgr = Common::Service< World::Manager::TaskMgr >::ref();
@ -828,7 +833,7 @@ void Sapphire::Entity::BNpc::onDeath()
setTargetId( INVALID_GAME_OBJECT_ID64 ); setTargetId( INVALID_GAME_OBJECT_ID64 );
m_currentStance = Stance::Passive; m_currentStance = Stance::Passive;
m_state = BNpcState::Dead; m_state = BNpcState::Dead;
m_timeOfDeath = Util::getTimeSeconds(); m_timeOfDeath = Common::Util::getTimeSeconds();
setOwner( nullptr ); setOwner( nullptr );
taskMgr.queueTask( World::makeFadeBNpcTask( 10000, getAsBNpc() ) ); taskMgr.queueTask( World::makeFadeBNpcTask( 10000, getAsBNpc() ) );
@ -851,17 +856,17 @@ void Sapphire::Entity::BNpc::onDeath()
hateListClear(); hateListClear();
} }
uint32_t Sapphire::Entity::BNpc::getTimeOfDeath() const uint32_t BNpc::getTimeOfDeath() const
{ {
return m_timeOfDeath; return m_timeOfDeath;
} }
void Sapphire::Entity::BNpc::setTimeOfDeath( uint32_t timeOfDeath ) void BNpc::setTimeOfDeath( uint32_t timeOfDeath )
{ {
m_timeOfDeath = timeOfDeath; m_timeOfDeath = timeOfDeath;
} }
void Sapphire::Entity::BNpc::checkAggro() void BNpc::checkAggro()
{ {
// passive mobs should ignore players unless aggro'd // passive mobs should ignore players unless aggro'd
if( m_aggressionMode == 1 ) if( m_aggressionMode == 1 )
@ -885,7 +890,7 @@ void Sapphire::Entity::BNpc::checkAggro()
range = std::max< float >( 0.f, range - std::pow( 1.53f, static_cast< float >( levelDiff ) * 0.6f ) ); range = std::max< float >( 0.f, range - std::pow( 1.53f, static_cast< float >( levelDiff ) * 0.6f ) );
} }
auto distance = Util::distance( getPos(), pClosestChara->getPos() ); auto distance = Common::Util::distance( getPos(), pClosestChara->getPos() );
if( distance < range ) if( distance < range )
{ {
@ -916,7 +921,7 @@ void Sapphire::Entity::BNpc::checkAggro()
range = std::max< float >( 0.f, range - std::pow( 1.53f, static_cast< float >( levelDiff ) * 0.6f ) ); range = std::max< float >( 0.f, range - std::pow( 1.53f, static_cast< float >( levelDiff ) * 0.6f ) );
} }
auto distance = Util::distance( getPos(), pClosestChara->getPos() ); auto distance = Common::Util::distance( getPos(), pClosestChara->getPos() );
if( distance < range ) if( distance < range )
{ {
@ -925,7 +930,7 @@ void Sapphire::Entity::BNpc::checkAggro()
} }
} }
void Sapphire::Entity::BNpc::setOwner( const Sapphire::Entity::CharaPtr& m_pChara ) void BNpc::setOwner( const CharaPtr& m_pChara )
{ {
m_pOwner = m_pChara; m_pOwner = m_pChara;
auto targetId = static_cast< uint32_t >( INVALID_GAME_OBJECT_ID ); auto targetId = static_cast< uint32_t >( INVALID_GAME_OBJECT_ID );
@ -937,40 +942,39 @@ void Sapphire::Entity::BNpc::setOwner( const Sapphire::Entity::CharaPtr& m_pChar
setOwnerPacket->data().Id = targetId; setOwnerPacket->data().Id = targetId;
server().queueForPlayers( getInRangePlayerIds(), setOwnerPacket ); server().queueForPlayers( getInRangePlayerIds(), setOwnerPacket );
if( m_pChara != nullptr && m_pChara->isPlayer() ) if( m_pChara && m_pChara->isPlayer() )
{ Network::Util::Packet::sendActorControl( *m_pChara->getAsPlayer(), getId(), SetHateLetter, 1, getId(), 0 );
auto letter = makeActorControl( getId(), ActorControlType::SetHateLetter, 1, getId(), 0 );
server().queueForPlayer( m_pChara->getAsPlayer()->getCharacterId(), letter );
}
} }
void Sapphire::Entity::BNpc::setLevelId( uint32_t levelId ) void BNpc::setLevelId( uint32_t levelId )
{ {
m_levelId = levelId; m_levelId = levelId;
} }
uint32_t Sapphire::Entity::BNpc::getLevelId() const uint32_t BNpc::getLevelId() const
{ {
return m_levelId; return m_levelId;
} }
bool Sapphire::Entity::BNpc::hasFlag( uint32_t flag ) const bool BNpc::hasFlag( uint32_t flag ) const
{ {
return m_flags & flag; return m_flags & flag;
} }
void Sapphire::Entity::BNpc::setFlag( uint32_t flag ) void BNpc::setFlag( uint32_t flag )
{ {
m_flags |= flag; m_flags |= flag;
} }
void Sapphire::Entity::BNpc::autoAttack( CharaPtr pTarget ) void BNpc::autoAttack( CharaPtr pTarget )
{ {
auto& teriMgr = Common::Service< World::Manager::TerritoryMgr >::ref(); auto& teriMgr = Common::Service< World::Manager::TerritoryMgr >::ref();
auto pZone = teriMgr.getTerritoryByGuId( getTerritoryId() ); auto pZone = teriMgr.getTerritoryByGuId( getTerritoryId() );
auto& actionMgr = Common::Service< World::Manager::ActionMgr >::ref();
auto& exdData = Common::Service< Data::ExdData >::ref();
uint64_t tick = Util::getTimeMs(); uint64_t tick = Common::Util::getTimeMs();
// todo: this needs to use the auto attack delay for the equipped weapon // todo: this needs to use the auto attack delay for the equipped weapon
if( ( tick - m_lastAttack ) > 2500 ) if( ( tick - m_lastAttack ) > 2500 )
@ -978,30 +982,11 @@ void Sapphire::Entity::BNpc::autoAttack( CharaPtr pTarget )
pTarget->onActionHostile( getAsChara() ); pTarget->onActionHostile( getAsChara() );
m_lastAttack = tick; m_lastAttack = tick;
srand( static_cast< uint32_t >( tick ) ); srand( static_cast< uint32_t >( tick ) );
actionMgr.handleTargetedAction( *this, 7, exdData.getRow< Excel::Action >( 7 ), pTarget->getId(), 0 );
auto damage = Math::CalcStats::calcAutoAttackDamage( *this );
//damage.first = 1;
auto effectPacket = std::make_shared< EffectPacket1 >( getId(), pTarget->getId(), 7 );
effectPacket->setRotation( Util::floatToUInt16Rot( getRot() ) );
Common::CalcResultParam effectEntry{};
effectEntry.Value = static_cast< int16_t >( damage.first );
effectEntry.Type = ActionEffectType::CALC_RESULT_TYPE_DAMAGE_HP;
effectEntry.Arg0 = 3;
effectEntry.Arg1 = 7;
auto resultId = pZone->getNextEffectResultId();
effectPacket->setResultId( resultId );
effectPacket->addTargetEffect( effectEntry );
server().queueForPlayers( getInRangePlayerIds(), effectPacket );
pTarget->takeDamage( static_cast< uint16_t >( damage.first ) );
auto& taskMgr = Common::Service< World::Manager::TaskMgr >::ref();
taskMgr.queueTask( Sapphire::World::makeActionIntegrityTask( resultId, pTarget, 500 ) );
} }
} }
void Sapphire::Entity::BNpc::calculateStats() void BNpc::calculateStats()
{ {
auto level = getLevel(); auto level = getLevel();
auto job = static_cast< uint8_t >( getClass() ); auto job = static_cast< uint8_t >( getClass() );
@ -1044,28 +1029,61 @@ void Sapphire::Entity::BNpc::calculateStats()
} }
uint32_t Sapphire::Entity::BNpc::getRank() const uint32_t BNpc::getRank() const
{ {
return m_rank; return m_rank;
} }
uint32_t Sapphire::Entity::BNpc::getBoundInstanceId() const uint32_t BNpc::getBoundInstanceId() const
{ {
return m_boundInstanceId; return m_boundInstanceId;
} }
BNpcType Sapphire::Entity::BNpc::getBNpcType() const BNpcType BNpc::getBNpcType() const
{ {
return m_bnpcType; return m_bnpcType;
} }
uint32_t Sapphire::Entity::BNpc::getLayoutId() const uint32_t BNpc::getLayoutId() const
{ {
return m_layoutId; return m_layoutId;
} }
void Sapphire::Entity::BNpc::init() void BNpc::init()
{ {
m_maxHp = Sapphire::Math::CalcStats::calculateMaxHp( *getAsChara() ); auto& exdData = Common::Service< Data::ExdData >::ref();
m_maxHp = Math::CalcStats::calculateMaxHp( *getAsChara() );
m_hp = m_maxHp; m_hp = m_maxHp;
//setup a test gambit
auto testGambitRule = std::make_shared< AI::GambitRule >( std::make_shared< AI::TopHateTargetCondition >(),
Action::make_Action( getAsChara(), 88, 0, exdData.getRow< Excel::Action >( 88 ) ), 5000 );
auto testGambitRule1 = std::make_shared< AI::GambitRule >( std::make_shared< AI::HPSelfPctLessThan >( 50 ),
Action::make_Action( getAsChara(), 120, 0, exdData.getRow< Excel::Action >( 120 ) ), 5000 );
m_gambits.push_back( testGambitRule );
m_gambits.push_back( testGambitRule1 );
}
void BNpc::processGambits( uint64_t tickCount )
{
auto& exdData = Common::Service< Data::ExdData >::ref();
auto& actionMgr = Common::Service< World::Manager::ActionMgr >::ref();
for( auto& gambitRule : m_gambits )
{
if( !gambitRule->isEnabled() )
continue;
if( ( tickCount - gambitRule->getLastExecutionMs() ) > gambitRule->getCoolDown() )
{
if( !gambitRule->getGambitTargetCondition()->isConditionMet( *this ) )
continue;
gambitRule->setLastExecutionMs( tickCount );
actionMgr.handleTargetedAction( *this, gambitRule->getActionPtr()->getId(), exdData.getRow< Excel::Action >( gambitRule->getActionPtr()->getId() ),
gambitRule->getGambitTargetCondition()->getTarget()->getId(), 0 );
}
}
} }

View file

@ -3,6 +3,7 @@
#include <Common.h> #include <Common.h>
#include "Forwards.h" #include "Forwards.h"
#include "ForwardsZone.h"
#include "Chara.h" #include "Chara.h"
#include "Npc.h" #include "Npc.h"
#include <set> #include <set>
@ -148,6 +149,8 @@ namespace Sapphire::Entity
uint32_t getLayoutId() const; uint32_t getLayoutId() const;
void processGambits( uint64_t tickCount );
private: private:
uint32_t m_bNpcBaseId; uint32_t m_bNpcBaseId;
uint32_t m_bNpcNameId; uint32_t m_bNpcNameId;
@ -189,6 +192,7 @@ namespace Sapphire::Entity
Common::FFXIVARR_POSITION3 m_naviTarget; Common::FFXIVARR_POSITION3 m_naviTarget;
CharaPtr m_pOwner; CharaPtr m_pOwner;
std::vector< World::AI::GambitRulePtr > m_gambits;
}; };

View file

@ -12,11 +12,10 @@
#include "Network/GameConnection.h" #include "Network/GameConnection.h"
#include "Network/PacketWrappers/ActorControlPacket.h" #include "Network/PacketWrappers/ActorControlPacket.h"
#include "Network/PacketWrappers/ActorControlTargetPacket.h" #include "Network/PacketWrappers/ActorControlTargetPacket.h"
#include "Network/PacketWrappers/RestingPacket.h"
#include "Network/PacketWrappers/EffectPacket1.h" #include "Network/PacketWrappers/EffectPacket1.h"
#include "Network/PacketWrappers/HudParamPacket.h" #include "Network/PacketWrappers/HudParamPacket.h"
#include "Network/Util/PacketUtil.h"
#include "StatusEffect/StatusEffect.h"
#include "Action/Action.h" #include "Action/Action.h"
#include "WorldServer.h" #include "WorldServer.h"
#include "Session.h" #include "Session.h"
@ -28,13 +27,16 @@
#include "Manager/PlayerMgr.h" #include "Manager/PlayerMgr.h"
#include "Common.h" #include "Common.h"
using namespace Sapphire;
using namespace Sapphire::Common; using namespace Sapphire::Common;
using namespace Sapphire::Entity;
using namespace Sapphire::World;
using namespace Sapphire::World::Manager; using namespace Sapphire::World::Manager;
using namespace Sapphire::Network::Packets; using namespace Sapphire::Network::Packets;
using namespace Sapphire::Network::Packets::WorldPackets::Server; using namespace Sapphire::Network::Packets::WorldPackets::Server;
using namespace Sapphire::Network::ActorControl; using namespace Sapphire::Network::ActorControl;
Sapphire::Entity::Chara::Chara( ObjKind type ) : Chara::Chara( ObjKind type ) :
GameObject( type ), GameObject( type ),
m_pose( 0 ), m_pose( 0 ),
m_targetId( INVALID_GAME_OBJECT_ID64 ), m_targetId( INVALID_GAME_OBJECT_ID64 ),
@ -44,7 +46,7 @@ Sapphire::Entity::Chara::Chara( ObjKind type ) :
m_lastTickTime = 0; m_lastTickTime = 0;
m_lastUpdate = 0; m_lastUpdate = 0;
m_lastAttack = Util::getTimeMs(); m_lastAttack = Common::Util::getTimeMs();
m_bonusStats.fill( 0 ); m_bonusStats.fill( 0 );
@ -55,76 +57,75 @@ Sapphire::Entity::Chara::Chara( ObjKind type ) :
} }
} }
Sapphire::Entity::Chara::~Chara() Chara::~Chara() = default;
= default;
/*! \return the actors name */ /*! \return the actors name */
std::string Sapphire::Entity::Chara::getName() const std::string Chara::getName() const
{ {
return { m_name }; return { m_name };
} }
/*! \return current stance of the actors */ /*! \return current stance of the actors */
Sapphire::Common::Stance Sapphire::Entity::Chara::getStance() const Stance Chara::getStance() const
{ {
return m_currentStance; return m_currentStance;
} }
/*! \return actor stats */ /*! \return actor stats */
const Sapphire::Entity::Chara::ActorStatsArray& Sapphire::Entity::Chara::getStats() const const Chara::ActorStatsArray& Chara::getStats() const
{ {
return m_baseStats; return m_baseStats;
} }
/*! \return current HP */ /*! \return current HP */
uint32_t Sapphire::Entity::Chara::getHp() const uint32_t Chara::getHp() const
{ {
return m_hp; return m_hp;
} }
uint32_t Sapphire::Entity::Chara::getHpPercent() const uint32_t Chara::getHpPercent() const
{ {
return ( m_hp * 100 ) / m_maxHp; return ( m_hp * 100 ) / m_maxHp;
} }
/*! \return current MP */ /*! \return current MP */
uint32_t Sapphire::Entity::Chara::getMp() const uint32_t Chara::getMp() const
{ {
return m_mp; return m_mp;
} }
/*! \return current TP */ /*! \return current TP */
uint16_t Sapphire::Entity::Chara::getTp() const uint16_t Chara::getTp() const
{ {
return m_tp; return m_tp;
} }
/*! \return current GP */ /*! \return current GP */
uint16_t Sapphire::Entity::Chara::getGp() const uint16_t Chara::getGp() const
{ {
return m_gp; return m_gp;
} }
/*! \return current invincibility type */ /*! \return current invincibility type */
InvincibilityType Sapphire::Entity::Chara::getInvincibilityType() const InvincibilityType Chara::getInvincibilityType() const
{ {
return m_invincibilityType; return m_invincibilityType;
} }
/*! \return current class or job */ /*! \return current class or job */
Sapphire::Common::ClassJob Sapphire::Entity::Chara::getClass() const ClassJob Chara::getClass() const
{ {
return m_class; return m_class;
} }
/*! \param ClassJob to set */ /*! \param ClassJob to set */
void Sapphire::Entity::Chara::setClass( Common::ClassJob classJob ) void Chara::setClass( ClassJob classJob )
{ {
m_class = classJob; m_class = classJob;
} }
Sapphire::Common::Role Sapphire::Entity::Chara::getRole() const Role Chara::getRole() const
{ {
switch( getClass() ) switch( getClass() )
{ {
@ -181,67 +182,67 @@ Sapphire::Common::Role Sapphire::Entity::Chara::getRole() const
} }
/*! \param Id of the target to set */ /*! \param Id of the target to set */
void Sapphire::Entity::Chara::setTargetId( uint64_t targetId ) void Chara::setTargetId( uint64_t targetId )
{ {
m_targetId = targetId; m_targetId = targetId;
} }
/*! \return Id of the current target */ /*! \return Id of the current target */
uint64_t Sapphire::Entity::Chara::getTargetId() const uint64_t Chara::getTargetId() const
{ {
return m_targetId; return m_targetId;
} }
/*! \return True if the actor is alive */ /*! \return True if the actor is alive */
bool Sapphire::Entity::Chara::isAlive() const bool Chara::isAlive() const
{ {
return ( m_hp > 0 ); return ( m_hp > 0 );
} }
/*! \return max hp for the actor */ /*! \return max hp for the actor */
uint32_t Sapphire::Entity::Chara::getMaxHp() const uint32_t Chara::getMaxHp() const
{ {
return m_maxHp; return m_maxHp;
} }
/*! \return max mp for the actor */ /*! \return max mp for the actor */
uint32_t Sapphire::Entity::Chara::getMaxMp() const uint32_t Chara::getMaxMp() const
{ {
return m_maxMp; return m_maxMp;
} }
/*! \return reset hp to current max hp */ /*! \return reset hp to current max hp */
void Sapphire::Entity::Chara::resetHp() void Chara::resetHp()
{ {
m_hp = getMaxHp(); m_hp = getMaxHp();
} }
/*! \return reset mp to current max mp */ /*! \return reset mp to current max mp */
void Sapphire::Entity::Chara::resetMp() void Chara::resetMp()
{ {
m_mp = getMaxMp(); m_mp = getMaxMp();
} }
/*! \param hp amount to set ( caps to maxHp ) */ /*! \param hp amount to set ( caps to maxHp ) */
void Sapphire::Entity::Chara::setHp( uint32_t hp ) void Chara::setHp( uint32_t hp )
{ {
m_hp = hp < getMaxHp() ? hp : getMaxHp(); m_hp = hp < getMaxHp() ? hp : getMaxHp();
} }
/*! \param mp amount to set ( caps to maxMp ) */ /*! \param mp amount to set ( caps to maxMp ) */
void Sapphire::Entity::Chara::setMp( uint32_t mp ) void Chara::setMp( uint32_t mp )
{ {
m_mp = mp < getMaxMp() ? mp : getMaxMp(); m_mp = mp < getMaxMp() ? mp : getMaxMp();
} }
/*! \param gp amount to set*/ /*! \param gp amount to set*/
void Sapphire::Entity::Chara::setGp( uint32_t gp ) void Chara::setGp( uint32_t gp )
{ {
m_gp = static_cast< uint16_t >( gp ); m_gp = static_cast< uint16_t >( gp );
} }
/*! \param tp amount to set*/ /*! \param tp amount to set*/
void Sapphire::Entity::Chara::setTp( uint32_t tp ) void Chara::setTp( uint32_t tp )
{ {
m_tp = static_cast< uint16_t >( tp ); m_tp = static_cast< uint16_t >( tp );
} }
@ -253,13 +254,13 @@ void Sapphire::Entity::Chara::setInvincibilityType( Common::InvincibilityType ty
} }
/*! \return current status of the actor */ /*! \return current status of the actor */
Sapphire::Common::ActorStatus Sapphire::Entity::Chara::getStatus() const ActorStatus Chara::getStatus() const
{ {
return m_status; return m_status;
} }
/*! \param status to set */ /*! \param status to set */
void Sapphire::Entity::Chara::setStatus( ActorStatus status ) void Chara::setStatus( ActorStatus status )
{ {
m_status = status; m_status = status;
} }
@ -268,7 +269,7 @@ void Sapphire::Entity::Chara::setStatus( ActorStatus status )
Performs necessary steps to mark an actor dead. Performs necessary steps to mark an actor dead.
Sets hp/mp/tp, sets status, plays animation and fires onDeath event Sets hp/mp/tp, sets status, plays animation and fires onDeath event
*/ */
void Sapphire::Entity::Chara::die() void Chara::die()
{ {
m_status = ActorStatus::Dead; m_status = ActorStatus::Dead;
m_hp = 0; m_hp = 0;
@ -280,13 +281,18 @@ void Sapphire::Entity::Chara::die()
// if the actor is a player, the update needs to be send to himself too // if the actor is a player, the update needs to be send to himself too
bool selfNeedsUpdate = isPlayer(); bool selfNeedsUpdate = isPlayer();
Network::Util::Packet::sendActorControl( getInRangePlayerIds( selfNeedsUpdate ), getId(), SetStatus, static_cast< uint8_t >( ActorStatus::Dead ) );
Network::Util::Packet::sendActorControl( getInRangePlayerIds( selfNeedsUpdate ), getId(), DeathAnimation );
}
FFXIVPacketBasePtr packet = makeActorControl( m_id, SetStatus, static_cast< uint8_t >( ActorStatus::Dead ) ); uint64_t Chara::getLastAttack() const
server().queueForPlayers( getInRangePlayerIds( selfNeedsUpdate ), packet ); {
return m_lastAttack;
FFXIVPacketBasePtr packet1 = makeActorControl( m_id, DeathAnimation, 0, 0, 0, 0 ); }
server().queueForPlayers( getInRangePlayerIds( selfNeedsUpdate ), packet1 );
void Chara::setLastAttack( uint64_t tickCount )
{
m_lastAttack = tickCount;
} }
/*! /*!
@ -295,10 +301,10 @@ position
\param Position to look towards \param Position to look towards
*/ */
bool Sapphire::Entity::Chara::face( const Common::FFXIVARR_POSITION3& p ) bool Chara::face( const FFXIVARR_POSITION3& p )
{ {
float oldRot = getRot(); float oldRot = getRot();
float rot = Util::calcAngFrom( getPos().x, getPos().z, p.x, p.z ); float rot = Common::Util::calcAngFrom( getPos().x, getPos().z, p.x, p.z );
float newRot = PI - rot + ( PI / 2 ); float newRot = PI - rot + ( PI / 2 );
setRot( newRot ); setRot( newRot );
@ -312,12 +318,10 @@ Set and propagate the actor stance to in range players
\param stance to set \param stance to set
*/ */
void Sapphire::Entity::Chara::setStance( Stance stance ) void Chara::setStance( Stance stance )
{ {
m_currentStance = stance; m_currentStance = stance;
Network::Util::Packet::sendActorControl( getInRangePlayerIds(), getId(), ToggleWeapon, stance, 1 );
FFXIVPacketBasePtr packet = makeActorControl( m_id, ToggleWeapon, stance, 1 );
server().queueForPlayers( getInRangePlayerIds(), packet );
} }
/*! /*!
@ -326,7 +330,7 @@ and if fully performed, clean up again.
\return true if a queued action has been updated \return true if a queued action has been updated
*/ */
bool Sapphire::Entity::Chara::checkAction() bool Chara::checkAction()
{ {
if( m_pCurrentAction == nullptr ) if( m_pCurrentAction == nullptr )
@ -339,7 +343,7 @@ bool Sapphire::Entity::Chara::checkAction()
} }
void Sapphire::Entity::Chara::update( uint64_t tickCount ) void Chara::update( uint64_t tickCount )
{ {
updateStatusEffects(); updateStatusEffects();
@ -358,17 +362,16 @@ Change the current target and propagate to in range players
\param target actor id \param target actor id
*/ */
void Sapphire::Entity::Chara::changeTarget( uint64_t targetId ) void Chara::changeTarget( uint64_t targetId )
{ {
setTargetId( targetId ); setTargetId( targetId );
FFXIVPacketBasePtr packet = makeActorControlTarget( m_id, SetTarget, 0, 0, 0, 0, targetId ); Network::Util::Packet::sendActorControlTarget( getInRangePlayerIds(), getId(), ToggleWeapon, SetTarget, 0, 0, 0, 0, targetId );
server().queueForPlayers( getInRangePlayerIds(), packet );
} }
/*! /*!
Dummy function \return 0 Dummy function \return 0
*/ */
uint8_t Sapphire::Entity::Chara::getLevel() const uint8_t Chara::getLevel() const
{ {
return 0; return 0;
} }
@ -382,7 +385,7 @@ magical dmg and take status effects into account
\param amount of damage to be taken \param amount of damage to be taken
*/ */
void Sapphire::Entity::Chara::takeDamage( uint32_t damage ) void Chara::takeDamage( uint32_t damage )
{ {
if( damage >= m_hp ) if( damage >= m_hp )
{ {
@ -413,7 +416,7 @@ in range
\param amount of hp to be healed \param amount of hp to be healed
*/ */
void Sapphire::Entity::Chara::heal( uint32_t amount ) void Chara::heal( uint32_t amount )
{ {
if( ( m_hp + amount ) > getMaxHp() ) if( ( m_hp + amount ) > getMaxHp() )
{ {
@ -423,7 +426,7 @@ void Sapphire::Entity::Chara::heal( uint32_t amount )
m_hp += amount; m_hp += amount;
} }
void Sapphire::Entity::Chara::restoreMP( uint32_t amount ) void Chara::restoreMP( uint32_t amount )
{ {
if( ( m_mp + amount ) > getMaxMp() ) if( ( m_mp + amount ) > getMaxMp() )
{ {
@ -433,27 +436,14 @@ void Sapphire::Entity::Chara::restoreMP( uint32_t amount )
m_mp += amount; m_mp += amount;
} }
/*!
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 Sapphire::Entity::Chara::sendHudParam()
{
FFXIVPacketBasePtr packet = makeHudParam( *this );
server().queueForPlayers( getInRangePlayerIds( isPlayer() ), packet );
}
/*! \return ActionPtr of the currently registered action, or nullptr */ /*! \return ActionPtr of the currently registered action, or nullptr */
Sapphire::World::Action::ActionPtr Sapphire::Entity::Chara::getCurrentAction() const Action::ActionPtr Chara::getCurrentAction() const
{ {
return m_pCurrentAction; return m_pCurrentAction;
} }
/*! \param ActionPtr of the action to be registered */ /*! \param ActionPtr of the action to be registered */
void Sapphire::Entity::Chara::setCurrentAction( Sapphire::World::Action::ActionPtr pAction ) void Chara::setCurrentAction( Action::ActionPtr pAction )
{ {
m_pCurrentAction = std::move( pAction ); m_pCurrentAction = std::move( pAction );
} }
@ -467,9 +457,9 @@ Will have to be extended for ranged attacks.
\param GameObjectPtr the autoAttack is performed on \param GameObjectPtr the autoAttack is performed on
*/ */
void Sapphire::Entity::Chara::autoAttack( CharaPtr pTarget ) void Chara::autoAttack( CharaPtr pTarget )
{ {
uint64_t tick = Util::getTimeMs(); uint64_t tick = Common::Util::getTimeMs();
// todo: this needs to use the auto attack delay for the equipped weapon // todo: this needs to use the auto attack delay for the equipped weapon
if( ( tick - m_lastAttack ) > 2500 ) if( ( tick - m_lastAttack ) > 2500 )
@ -481,7 +471,7 @@ void Sapphire::Entity::Chara::autoAttack( CharaPtr pTarget )
auto damage = static_cast< uint16_t >( 10 + rand() % 12 ); auto damage = static_cast< uint16_t >( 10 + rand() % 12 );
auto effectPacket = std::make_shared< EffectPacket1 >( getId(), pTarget->getId(), 7 ); auto effectPacket = std::make_shared< EffectPacket1 >( getId(), pTarget->getId(), 7 );
effectPacket->setRotation( Util::floatToUInt16Rot( getRot() ) ); effectPacket->setRotation( Common::Util::floatToUInt16Rot( getRot() ) );
Common::CalcResultParam effectEntry{}; Common::CalcResultParam effectEntry{};
effectEntry.Value = static_cast< int16_t >( damage ); effectEntry.Value = static_cast< int16_t >( damage );
@ -497,9 +487,9 @@ void Sapphire::Entity::Chara::autoAttack( CharaPtr pTarget )
} }
/*! \param StatusEffectPtr to be applied to the actor */ /*! \param StatusEffectPtr to be applied to the actor */
void Sapphire::Entity::Chara::addStatusEffect( StatusEffect::StatusEffectPtr pEffect ) void Chara::addStatusEffect( StatusEffect::StatusEffectPtr pEffect )
{ {
auto& teriMgr = Common::Service< World::Manager::TerritoryMgr >::ref(); auto& teriMgr = Common::Service< Manager::TerritoryMgr >::ref();
auto pZone = teriMgr.getTerritoryByGuId( getTerritoryId() ); auto pZone = teriMgr.getTerritoryByGuId( getTerritoryId() );
int8_t nextSlot = getStatusEffectFreeSlot(); int8_t nextSlot = getStatusEffectFreeSlot();
@ -507,51 +497,29 @@ void Sapphire::Entity::Chara::addStatusEffect( StatusEffect::StatusEffectPtr pEf
if( nextSlot == -1 ) if( nextSlot == -1 )
return; return;
pEffect->setSlot( nextSlot );
m_statusEffectMap[ nextSlot ] = pEffect; m_statusEffectMap[ nextSlot ] = pEffect;
pEffect->applyStatus(); pEffect->applyStatus();
auto statusEffectAdd = makeZonePacket< FFXIVIpcActionIntegrity >( getId() );
statusEffectAdd->data().ResultId = pZone->getNextEffectResultId();
statusEffectAdd->data().Target = pEffect->getTargetActorId();
statusEffectAdd->data().Hp = getHp();
statusEffectAdd->data().Mp = static_cast< uint16_t >( getMp() );
statusEffectAdd->data().Tp = static_cast< uint16_t >( getTp() );
statusEffectAdd->data().HpMax = getMaxHp();
statusEffectAdd->data().MpMax = static_cast< uint16_t >( getMaxMp() );
statusEffectAdd->data().ClassJob = static_cast< uint8_t >( getClass() );
statusEffectAdd->data().StatusCount = 1;
statusEffectAdd->data().unknown_E0 = 0xE0;
// set all status sources to u32 invalid game obj
// todo: chara status effect map should be filled instead, since hudparam also uses invalid gameobj
for( int i = 0; i < 4; ++i )
{
statusEffectAdd->data().Status[ i ].Source = INVALID_GAME_OBJECT_ID;
}
auto& status = statusEffectAdd->data().Status[ 0 ];
status.Source = pEffect->getSrcActorId();
status.Time = static_cast< float >( pEffect->getDuration() ) / 1000;
status.Id = static_cast< uint16_t >( pEffect->getId() );
status.Slot = static_cast< uint8_t >( nextSlot );
status.SystemParam = static_cast< int16_t >( pEffect->getParam() );
server().queueForPlayers( getInRangePlayerIds( isPlayer() ), statusEffectAdd );
} }
/*! \param StatusEffectPtr to be applied to the actor */ /*! \param StatusEffectPtr to be applied to the actor */
void Sapphire::Entity::Chara::addStatusEffectById( uint32_t id, int32_t duration, Entity::Chara& source, uint16_t param ) void 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 ); auto effect = StatusEffect::make_StatusEffect( id, source.getAsChara(), getAsChara(), duration, 3000 );
effect->setParam( param ); effect->setParam( param );
addStatusEffect( effect ); addStatusEffect( effect );
} }
void Chara::addStatusEffectById( uint32_t id, int32_t duration, Entity::Chara& source,
std::vector< World::Action::StatusModifier > modifiers, uint32_t flag, uint16_t param )
{
auto effect = StatusEffect::make_StatusEffect( id, source.getAsChara(), getAsChara(), duration, modifiers, flag, 3000 );
effect->setParam( param );
addStatusEffect( effect );
}
/*! \param StatusEffectPtr to be applied to the actor */ /*! \param StatusEffectPtr to be applied to the actor */
void Sapphire::Entity::Chara::addStatusEffectByIdIfNotExist( uint32_t id, int32_t duration, Entity::Chara& source, void Chara::addStatusEffectByIdIfNotExist( uint32_t id, int32_t duration, Entity::Chara& source, uint16_t param )
uint16_t param )
{ {
if( hasStatusEffect( id ) ) if( hasStatusEffect( id ) )
return; return;
@ -562,28 +530,17 @@ void Sapphire::Entity::Chara::addStatusEffectByIdIfNotExist( uint32_t id, int32_
} }
void Sapphire::Entity::Chara::addStatusEffectByIdIfNotExist( uint32_t id, int32_t duration, Entity::Chara& source, void Sapphire::Entity::Chara::addStatusEffectByIdIfNotExist( uint32_t id, int32_t duration, Entity::Chara& source,
std::vector< World::Action::StatusModifier > modifiers, uint16_t param ) std::vector< World::Action::StatusModifier > modifiers, uint32_t flag, uint16_t param )
{ {
if( hasStatusEffect( id ) ) if( hasStatusEffect( id ) )
return; return;
auto effect = StatusEffect::make_StatusEffect( id, source.getAsChara(), getAsChara(), duration, modifiers, 3000 ); auto effect = StatusEffect::make_StatusEffect( id, source.getAsChara(), getAsChara(), duration, modifiers, flag, 3000 );
effect->setParam( param ); effect->setParam( param );
addStatusEffect( effect ); addStatusEffect( effect );
} }
void Sapphire::Entity::Chara::addStatusEffectByIdIfNotExist( uint32_t id, int32_t duration, Entity::Chara& source, int8_t Chara::getStatusEffectFreeSlot()
World::Action::StatusEntry& statusEntry, uint16_t param )
{
if( hasStatusEffect( id ) )
return;
auto effect = StatusEffect::make_StatusEffect( id, source.getAsChara(), getAsChara(), duration, statusEntry, 3000 );
effect->setParam( param );
addStatusEffect( effect );
}
int8_t Sapphire::Entity::Chara::getStatusEffectFreeSlot()
{ {
int8_t freeEffectSlot = -1; int8_t freeEffectSlot = -1;
@ -596,12 +553,12 @@ int8_t Sapphire::Entity::Chara::getStatusEffectFreeSlot()
return freeEffectSlot; return freeEffectSlot;
} }
void Sapphire::Entity::Chara::statusEffectFreeSlot( uint8_t slotId ) void Chara::statusEffectFreeSlot( uint8_t slotId )
{ {
m_statusEffectFreeSlotQueue.push( slotId ); m_statusEffectFreeSlotQueue.push( slotId );
} }
void Sapphire::Entity::Chara::replaceSingleStatusEffectById( uint32_t id ) void Chara::replaceSingleStatusEffectById( uint32_t id )
{ {
for( const auto& effectIt : m_statusEffectMap ) for( const auto& effectIt : m_statusEffectMap )
{ {
@ -613,7 +570,7 @@ void Sapphire::Entity::Chara::replaceSingleStatusEffectById( uint32_t id )
} }
} }
void Sapphire::Entity::Chara::removeSingleStatusEffectById( uint32_t id ) void Chara::removeSingleStatusEffectById( uint32_t id )
{ {
for( const auto& effectIt : m_statusEffectMap ) for( const auto& effectIt : m_statusEffectMap )
{ {
@ -625,7 +582,7 @@ void Sapphire::Entity::Chara::removeSingleStatusEffectById( uint32_t id )
} }
} }
void Sapphire::Entity::Chara::removeStatusEffectByFlag( Common::StatusEffectFlag flag ) void Chara::removeStatusEffectByFlag( Common::StatusEffectFlag flag )
{ {
for( auto effectIt = m_statusEffectMap.begin(); effectIt != m_statusEffectMap.end(); ) for( auto effectIt = m_statusEffectMap.begin(); effectIt != m_statusEffectMap.end(); )
{ {
@ -636,7 +593,7 @@ void Sapphire::Entity::Chara::removeStatusEffectByFlag( Common::StatusEffectFlag
} }
} }
std::map< uint8_t, Sapphire::StatusEffect::StatusEffectPtr >::iterator Sapphire::Entity::Chara::removeStatusEffect( uint8_t effectSlotId, bool sendOrder ) std::map< uint8_t, Sapphire::StatusEffect::StatusEffectPtr >::iterator Chara::removeStatusEffect( uint8_t effectSlotId, bool sendOrder )
{ {
auto pEffectIt = m_statusEffectMap.find( effectSlotId ); auto pEffectIt = m_statusEffectMap.find( effectSlotId );
if( pEffectIt == m_statusEffectMap.end() ) if( pEffectIt == m_statusEffectMap.end() )
@ -648,24 +605,19 @@ std::map< uint8_t, Sapphire::StatusEffect::StatusEffectPtr >::iterator Sapphire:
pEffect->removeStatus(); pEffect->removeStatus();
if( sendOrder ) if( sendOrder )
server().queueForPlayers( getInRangePlayerIds( isPlayer() ), makeActorControl( getId(), StatusEffectLose, pEffect->getId() ) ); Network::Util::Packet::sendActorControl( getInRangePlayerIds( isPlayer() ), getId(), StatusEffectLose, pEffect->getId() );
auto it = m_statusEffectMap.erase( pEffectIt ); auto it = m_statusEffectMap.erase( pEffectIt );
Network::Util::Packet::sendHudParam( *this );
if( isPlayer() )
server().queueForPlayers( getInRangePlayerIds( isPlayer() ), makeHudParam( *getAsPlayer() ) );
else if( isBattleNpc() )
server().queueForPlayers( getInRangePlayerIds( isPlayer() ), makeHudParam( *getAsBNpc() ) );
return it; return it;
} }
std::map< uint8_t, Sapphire::StatusEffect::StatusEffectPtr > Sapphire::Entity::Chara::getStatusEffectMap() const std::map< uint8_t, StatusEffect::StatusEffectPtr > Chara::getStatusEffectMap() const
{ {
return m_statusEffectMap; return m_statusEffectMap;
} }
Sapphire::StatusEffect::StatusEffectPtr Sapphire::Entity::Chara::getStatusEffectById( uint32_t id ) const Sapphire::StatusEffect::StatusEffectPtr Chara::getStatusEffectById( uint32_t id ) const
{ {
for( const auto& effectIt : m_statusEffectMap ) for( const auto& effectIt : m_statusEffectMap )
{ {
@ -676,29 +628,29 @@ Sapphire::StatusEffect::StatusEffectPtr Sapphire::Entity::Chara::getStatusEffect
return nullptr; return nullptr;
} }
const uint8_t* Sapphire::Entity::Chara::getLookArray() const const uint8_t* Chara::getLookArray() const
{ {
return m_customize; return m_customize;
} }
const uint32_t* Sapphire::Entity::Chara::getModelArray() const const uint32_t* Chara::getModelArray() const
{ {
return m_modelEquip; return m_modelEquip;
} }
uint8_t Sapphire::Entity::Chara::getPose() const uint8_t Chara::getPose() const
{ {
return m_pose; return m_pose;
} }
void Sapphire::Entity::Chara::setPose( uint8_t pose ) void Chara::setPose( uint8_t pose )
{ {
m_pose = pose; m_pose = pose;
} }
void Sapphire::Entity::Chara::sendStatusEffectUpdate() void Chara::sendStatusEffectUpdate()
{ {
uint64_t currentTimeMs = Util::getTimeMs(); uint64_t currentTimeMs = Common::Util::getTimeMs();
auto statusEffectList = makeZonePacket< FFXIVIpcStatus >( getId() ); auto statusEffectList = makeZonePacket< FFXIVIpcStatus >( getId() );
uint8_t slot = 0; uint8_t slot = 0;
@ -715,9 +667,9 @@ void Sapphire::Entity::Chara::sendStatusEffectUpdate()
server().queueForPlayers( getInRangePlayerIds( isPlayer() ), statusEffectList ); server().queueForPlayers( getInRangePlayerIds( isPlayer() ), statusEffectList );
} }
void Sapphire::Entity::Chara::updateStatusEffects() void Chara::updateStatusEffects()
{ {
uint64_t currentTimeMs = Util::getTimeMs(); uint64_t currentTimeMs = Common::Util::getTimeMs();
for( auto effectIt = m_statusEffectMap.begin(); effectIt != m_statusEffectMap.end(); ) for( auto effectIt = m_statusEffectMap.begin(); effectIt != m_statusEffectMap.end(); )
{ {
@ -742,7 +694,7 @@ void Sapphire::Entity::Chara::updateStatusEffects()
} }
} }
bool Sapphire::Entity::Chara::hasStatusEffect( uint32_t id ) bool Chara::hasStatusEffect( uint32_t id )
{ {
for( const auto& [ key, val ] : m_statusEffectMap ) for( const auto& [ key, val ] : m_statusEffectMap )
{ {
@ -753,23 +705,23 @@ bool Sapphire::Entity::Chara::hasStatusEffect( uint32_t id )
return false; return false;
} }
int64_t Sapphire::Entity::Chara::getLastUpdateTime() const int64_t Chara::getLastUpdateTime() const
{ {
return m_lastUpdate; return m_lastUpdate;
} }
void Sapphire::Entity::Chara::setLastComboActionId( uint32_t actionId ) void Chara::setLastComboActionId( uint32_t actionId )
{ {
m_lastComboActionId = actionId; m_lastComboActionId = actionId;
m_lastComboActionTime = Util::getTimeMs(); m_lastComboActionTime = Common::Util::getTimeMs();
} }
uint32_t Sapphire::Entity::Chara::getLastComboActionId() const uint32_t Chara::getLastComboActionId() const
{ {
// initially check for the time passed first, if it's more than the threshold just return 0 for the combo // initially check for the time passed first, if it's more than the threshold just return 0 for the combo
// we can hide the implementation detail this way and it just works:tm: for anything that uses it // we can hide the implementation detail this way and it just works:tm: for anything that uses it
if( std::difftime( static_cast< time_t >( Util::getTimeMs() ), if( std::difftime( static_cast< time_t >( Common::Util::getTimeMs() ),
static_cast< time_t >( m_lastComboActionTime ) ) > Common::MAX_COMBO_LENGTH ) static_cast< time_t >( m_lastComboActionTime ) ) > Common::MAX_COMBO_LENGTH )
{ {
return 0; return 0;
@ -778,43 +730,42 @@ uint32_t Sapphire::Entity::Chara::getLastComboActionId() const
return m_lastComboActionId; return m_lastComboActionId;
} }
uint32_t Sapphire::Entity::Chara::getDirectorId() const uint32_t Chara::getDirectorId() const
{ {
return m_directorId; return m_directorId;
} }
void Sapphire::Entity::Chara::setDirectorId( uint32_t directorId ) void Chara::setDirectorId( uint32_t directorId )
{ {
m_directorId = directorId; m_directorId = directorId;
} }
uint32_t Sapphire::Entity::Chara::getAgentId() const uint32_t Chara::getAgentId() const
{ {
return m_agentId; return m_agentId;
} }
void Sapphire::Entity::Chara::setAgentId( uint32_t agentId ) void Chara::setAgentId( uint32_t agentId )
{ {
m_agentId = agentId; m_agentId = agentId;
} }
float Chara::getRadius() const
float Sapphire::Entity::Chara::getRadius() const
{ {
return m_radius; return m_radius;
} }
Sapphire::Common::BaseParam Sapphire::Entity::Chara::getPrimaryStat() const Common::BaseParam Chara::getPrimaryStat() const
{ {
auto& exdData = Common::Service< Data::ExdData >::ref(); auto& exdData = Common::Service< Data::ExdData >::ref();
auto classJob = exdData.getRow< Excel::ClassJob >( static_cast< uint16_t >( getClass() ) ); auto classJob = exdData.getRow< Excel::ClassJob >( static_cast< uint16_t >( getClass() ) );
assert( classJob ); assert( classJob );
return static_cast< Sapphire::Common::BaseParam >( classJob->data().Role ); return static_cast< Common::BaseParam >( classJob->data().Role );
} }
uint32_t Sapphire::Entity::Chara::getStatValue( Sapphire::Common::BaseParam baseParam ) const uint32_t Chara::getStatValue( Common::BaseParam baseParam ) const
{ {
auto index = static_cast< uint32_t >( baseParam ); auto index = static_cast< uint32_t >( baseParam );
assert( index < m_baseStats.size() ); assert( index < m_baseStats.size() );
@ -822,7 +773,7 @@ uint32_t Sapphire::Entity::Chara::getStatValue( Sapphire::Common::BaseParam base
return m_baseStats[ index ] + m_bonusStats[ index ]; return m_baseStats[ index ] + m_bonusStats[ index ];
} }
float Sapphire::Entity::Chara::getStatValueFloat( Common::BaseParam baseParam ) const float Chara::getStatValueFloat( Common::BaseParam baseParam ) const
{ {
auto index = static_cast< uint32_t >( baseParam ); auto index = static_cast< uint32_t >( baseParam );
assert( index < m_baseStats.size() ); assert( index < m_baseStats.size() );
@ -830,7 +781,7 @@ float Sapphire::Entity::Chara::getStatValueFloat( Common::BaseParam baseParam )
return static_cast< float >( m_baseStats[ index ] + m_bonusStats[ index ] ); return static_cast< float >( m_baseStats[ index ] + m_bonusStats[ index ] );
} }
uint32_t Sapphire::Entity::Chara::getBonusStat( Sapphire::Common::BaseParam baseParam ) const uint32_t Chara::getBonusStat( Common::BaseParam baseParam ) const
{ {
auto index = static_cast< uint32_t >( baseParam ); auto index = static_cast< uint32_t >( baseParam );
assert( index < m_bonusStats.size() ); assert( index < m_bonusStats.size() );
@ -838,7 +789,7 @@ uint32_t Sapphire::Entity::Chara::getBonusStat( Sapphire::Common::BaseParam base
return m_bonusStats[ index ]; return m_bonusStats[ index ];
} }
void Sapphire::Entity::Chara::setStatValue( Common::BaseParam baseParam, uint32_t value ) void Chara::setStatValue( Common::BaseParam baseParam, uint32_t value )
{ {
auto index = static_cast< uint32_t >( baseParam ); auto index = static_cast< uint32_t >( baseParam );
assert( index < m_baseStats.size() ); assert( index < m_baseStats.size() );
@ -846,7 +797,7 @@ void Sapphire::Entity::Chara::setStatValue( Common::BaseParam baseParam, uint32_
m_baseStats[ index ] = value; m_baseStats[ index ] = value;
} }
float Sapphire::Entity::Chara::getModifier( Common::ParamModifier paramModifier ) const float Chara::getModifier( Common::ParamModifier paramModifier ) const
{ {
auto result = paramModifier >= Common::ParamModifier::StrengthPercent ? 1.0f : 0; auto result = paramModifier >= Common::ParamModifier::StrengthPercent ? 1.0f : 0;
@ -867,7 +818,7 @@ float Sapphire::Entity::Chara::getModifier( Common::ParamModifier paramModifier
return result; return result;
} }
void Sapphire::Entity::Chara::onTick() void Chara::onTick()
{ {
uint32_t thisTickDmg = 0; uint32_t thisTickDmg = 0;
uint32_t thisTickHeal = 0; uint32_t thisTickHeal = 0;
@ -896,24 +847,18 @@ void Sapphire::Entity::Chara::onTick()
if( thisTickDmg != 0 ) if( thisTickDmg != 0 )
{ {
takeDamage( thisTickDmg ); takeDamage( thisTickDmg );
server().queueForPlayers( getInRangePlayerIds( isPlayer() ), makeActorControl( getId(), HPFloatingText, 0, Network::Util::Packet::sendActorControl( getInRangePlayerIds( isPlayer() ), getId(), HPFloatingText, 0,
static_cast< uint8_t >( ActionEffectType::CALC_RESULT_TYPE_DAMAGE_HP ), ActionEffectType::CALC_RESULT_TYPE_DAMAGE_HP, thisTickDmg );
thisTickDmg ) );
if( isPlayer() ) Network::Util::Packet::sendHudParam( *this );
server().queueForPlayers( getInRangePlayerIds( isPlayer() ), makeHudParam( *getAsPlayer() ) );
else if( isBattleNpc() )
server().queueForPlayers( getInRangePlayerIds( isPlayer() ), makeHudParam( *getAsBNpc() ) );
} }
if( thisTickHeal != 0 ) if( thisTickHeal != 0 )
{ {
heal( thisTickHeal ); heal( thisTickHeal );
server().queueForPlayers( getInRangePlayerIds( isPlayer() ), makeActorControl( getId(), HPFloatingText, 0, Network::Util::Packet::sendActorControl( getInRangePlayerIds( isPlayer() ), getId(), HPFloatingText, 0,
static_cast< uint8_t >( ActionEffectType::CALC_RESULT_TYPE_RECOVER_HP ), ActionEffectType::CALC_RESULT_TYPE_RECOVER_HP, thisTickHeal );
thisTickHeal ) );
if( isPlayer() ) Network::Util::Packet::sendHudParam( *this );
server().queueForPlayers( getInRangePlayerIds( isPlayer() ), makeHudParam( *getAsPlayer() ) );
else if( isBattleNpc() )
server().queueForPlayers( getInRangePlayerIds( isPlayer() ), makeHudParam( *getAsBNpc() ) );
} }
} }

View file

@ -141,12 +141,12 @@ namespace Sapphire::Entity
// add a status effect by id // add a status effect by id
void addStatusEffectById( uint32_t id, int32_t duration, Entity::Chara& source, uint16_t param = 0 ); void addStatusEffectById( uint32_t id, int32_t duration, Entity::Chara& source, uint16_t param = 0 );
void addStatusEffectById( uint32_t id, int32_t duration, Entity::Chara& source,
std::vector< World::Action::StatusModifier > modifiers, uint32_t flag, uint16_t param = 0 );
// add a status effect by id if it doesn't exist // 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 ); void addStatusEffectByIdIfNotExist( uint32_t id, int32_t duration, Entity::Chara& source, uint16_t param = 0 );
void addStatusEffectByIdIfNotExist( uint32_t id, int32_t duration, Entity::Chara& source, std::vector< World::Action::StatusModifier > modifiers, void addStatusEffectByIdIfNotExist( uint32_t id, int32_t duration, Entity::Chara& source,
uint16_t param = 0 ); std::vector< World::Action::StatusModifier > modifiers, uint32_t flag, uint16_t param = 0 );
void addStatusEffectByIdIfNotExist( uint32_t id, int32_t duration, Entity::Chara& source, World::Action::StatusEntry& statusEntry,
uint16_t param = 0 );
// remove a status effect by id // remove a status effect by id
void removeSingleStatusEffectFromId( uint32_t id ); void removeSingleStatusEffectFromId( uint32_t id );
@ -216,6 +216,10 @@ namespace Sapphire::Entity
void die(); void die();
uint64_t getLastAttack() const;
void setLastAttack( uint64_t tickCount );
Common::ActorStatus getStatus() const; Common::ActorStatus getStatus() const;
void setStatus( Common::ActorStatus status ); void setStatus( Common::ActorStatus status );
@ -236,8 +240,6 @@ namespace Sapphire::Entity
virtual uint8_t getLevel() const; virtual uint8_t getLevel() const;
virtual void sendHudParam();
virtual void takeDamage( uint32_t damage ); virtual void takeDamage( uint32_t damage );
virtual void heal( uint32_t amount ); virtual void heal( uint32_t amount );

View file

@ -3,12 +3,10 @@
#include "Territory/InstanceContent.h" #include "Territory/InstanceContent.h"
#include "Actor/Player.h" #include "Actor/Player.h"
#include "Network/PacketWrappers/ActorControlPacket.h"
#include "Network/PacketWrappers/ActorControlTargetPacket.h"
#include <Logging/Logger.h> #include <Logging/Logger.h>
#include <Network/PacketDef/Zone/ServerZoneDef.h> #include <Network/PacketDef/Zone/ServerZoneDef.h>
#include <Network/CommonActorControl.h> #include <Network/CommonActorControl.h>
#include <Network/Util/PacketUtil.h>
#include <Util/UtilMath.h> #include <Util/UtilMath.h>
#include <Service.h> #include <Service.h>
@ -16,20 +14,19 @@
#include <utility> #include <utility>
#include "WorldServer.h" #include "WorldServer.h"
#include "Session.h" #include "Session.h"
#include "Network/GameConnection.h"
#include "Manager/MgrUtil.h" #include "Manager/MgrUtil.h"
using namespace Sapphire;
using namespace Sapphire::Common; using namespace Sapphire::Common;
using namespace Sapphire::Entity;
using namespace Sapphire::World::Manager; using namespace Sapphire::World::Manager;
using namespace Sapphire::Network::Packets; using namespace Sapphire::Network::Packets;
using namespace Sapphire::Network::Packets::WorldPackets::Server; using namespace Sapphire::Network::Packets::WorldPackets::Server;
using namespace Sapphire::Network::ActorControl; using namespace Sapphire::Network::ActorControl;
Sapphire::Entity::EventObject::EventObject( uint32_t actorId, uint32_t objectId, uint32_t gimmickId, uint32_t instanceId, EventObject::EventObject( uint32_t actorId, uint32_t objectId, uint32_t gimmickId, uint32_t instanceId, uint8_t initialState,
uint8_t initialState, Common::FFXIVARR_POSITION3 pos, FFXIVARR_POSITION3 pos, float rotation, const std::string& givenName, uint8_t permissionInv ) :
float rotation, const std::string& givenName, uint8_t permissionInv ) : GameObject( ObjKind::EventObj ),
Sapphire::Entity::GameObject( ObjKind::EventObj ),
m_gimmickId( gimmickId ), m_gimmickId( gimmickId ),
m_instanceId( instanceId ), m_instanceId( instanceId ),
m_state( initialState ), m_state( initialState ),
@ -37,7 +34,7 @@ Sapphire::Entity::EventObject::EventObject( uint32_t actorId, uint32_t objectId,
m_name( givenName ), m_name( givenName ),
m_housingLink( 0 ), m_housingLink( 0 ),
m_permissionInvisibility( permissionInv ), m_permissionInvisibility( permissionInv ),
m_ownerId( Common::INVALID_GAME_OBJECT_ID ) m_ownerId( INVALID_GAME_OBJECT_ID )
{ {
m_id = actorId; m_id = actorId;
m_pos.x = pos.x; m_pos.x = pos.x;
@ -46,78 +43,77 @@ Sapphire::Entity::EventObject::EventObject( uint32_t actorId, uint32_t objectId,
m_rot = rotation; m_rot = rotation;
} }
uint32_t Sapphire::Entity::EventObject::getGimmickId() const uint32_t EventObject::getGimmickId() const
{ {
return m_gimmickId; return m_gimmickId;
} }
uint32_t Sapphire::Entity::EventObject::getObjectId() const uint32_t EventObject::getObjectId() const
{ {
return m_objectId; return m_objectId;
} }
float Sapphire::Entity::EventObject::getScale() const float EventObject::getScale() const
{ {
return m_scale; return m_scale;
} }
void Sapphire::Entity::EventObject::setScale( float scale ) void EventObject::setScale( float scale )
{ {
m_scale = scale; m_scale = scale;
} }
Sapphire::Entity::EventObject::OnTalkEventHandler Sapphire::Entity::EventObject::getOnTalkHandler() const EventObject::OnTalkEventHandler EventObject::getOnTalkHandler() const
{ {
return m_onTalkEventHandler; return m_onTalkEventHandler;
} }
void Sapphire::Entity::EventObject::setOnTalkHandler( Sapphire::Entity::EventObject::OnTalkEventHandler handler ) void EventObject::setOnTalkHandler( EventObject::OnTalkEventHandler handler )
{ {
m_onTalkEventHandler = std::move( handler ); m_onTalkEventHandler = std::move( handler );
} }
void Sapphire::Entity::EventObject::setGimmickId( uint32_t gimmickId ) void EventObject::setGimmickId( uint32_t gimmickId )
{ {
m_gimmickId = gimmickId; m_gimmickId = gimmickId;
} }
uint8_t Sapphire::Entity::EventObject::getState() const uint8_t EventObject::getState() const
{ {
return m_state; return m_state;
} }
void Sapphire::Entity::EventObject::setState( uint8_t state ) void EventObject::setState( uint8_t state )
{ {
m_state = state; m_state = state;
} }
void Sapphire::Entity::EventObject::setAnimationFlag( uint32_t flag, uint32_t animationFlag ) void EventObject::setAnimationFlag( uint32_t flag, uint32_t animationFlag )
{ {
for( const auto& player : m_inRangePlayers ) Network::Util::Packet::sendActorControl( getInRangePlayerIds(), getId(), EObjAnimation, flag, animationFlag );
server().queueForPlayer( player->getCharacterId(), makeActorControl( getId(), EObjAnimation, flag, animationFlag ) );
} }
void Sapphire::Entity::EventObject::setHousingLink( uint32_t housingLink ) void EventObject::setHousingLink( uint32_t housingLink )
{ {
m_housingLink = housingLink; m_housingLink = housingLink;
} }
uint32_t Sapphire::Entity::EventObject::getHousingLink() const uint32_t EventObject::getHousingLink() const
{ {
return m_housingLink; return m_housingLink;
} }
void Sapphire::Entity::EventObject::setParentInstance( Sapphire::TerritoryPtr instance ) void EventObject::setParentInstance( Sapphire::TerritoryPtr instance )
{ {
m_parentInstance = std::move( instance ); m_parentInstance = std::move( instance );
} }
Sapphire::TerritoryPtr Sapphire::Entity::EventObject::getParentInstance() const TerritoryPtr EventObject::getParentInstance() const
{ {
return m_parentInstance; return m_parentInstance;
} }
void Sapphire::Entity::EventObject::spawn( Sapphire::Entity::PlayerPtr pTarget ) void EventObject::spawn( PlayerPtr pTarget )
{ {
auto spawnIndex = pTarget->getNextObjSpawnIndexForActorId( getId() ); auto spawnIndex = pTarget->getNextObjSpawnIndexForActorId( getId() );
if( !pTarget->isObjSpawnIndexValid( spawnIndex ) ) if( !pTarget->isObjSpawnIndexValid( spawnIndex ) )
@ -149,34 +145,31 @@ void Sapphire::Entity::EventObject::spawn( Sapphire::Entity::PlayerPtr pTarget )
} }
void Sapphire::Entity::EventObject::despawn( Sapphire::Entity::PlayerPtr pTarget ) void EventObject::despawn( PlayerPtr pTarget )
{ {
Logger::debug( "despawn eobj#{0}", getId() ); Logger::debug( "despawn eobj#{0}", getId() );
pTarget->freeObjSpawnIndexForActorId( getId() ); pTarget->freeObjSpawnIndexForActorId( getId() );
} }
const std::string& Sapphire::Entity::EventObject::getName() const const std::string& EventObject::getName() const
{ {
return m_name; return m_name;
} }
uint32_t Sapphire::Entity::EventObject::getInstanceId() const uint32_t EventObject::getInstanceId() const
{ {
return m_instanceId; return m_instanceId;
} }
uint8_t Sapphire::Entity::EventObject::getPermissionInvisibility() const uint8_t EventObject::getPermissionInvisibility() const
{ {
return m_permissionInvisibility; return m_permissionInvisibility;
} }
void Sapphire::Entity::EventObject::setPermissionInvisibility( uint8_t permissionInvisibility ) void EventObject::setPermissionInvisibility( uint8_t permissionInvisibility )
{ {
m_permissionInvisibility = permissionInvisibility; Network::Util::Packet::sendActorControl( getInRangePlayerIds(), getId(), DirectorEObjMod, permissionInvisibility );
auto& server = Common::Service< World::WorldServer >::ref();
auto inRangePlayerIds = getInRangePlayerIds();
server.queueForPlayers( inRangePlayerIds, makeActorControl( getId(), DirectorEObjMod, permissionInvisibility ) );
} }
uint32_t Sapphire::Entity::EventObject::getOwnerId() const uint32_t Sapphire::Entity::EventObject::getOwnerId() const

View file

@ -23,41 +23,42 @@
#include "StatusEffect/StatusEffect.h" #include "StatusEffect/StatusEffect.h"
using namespace Sapphire::Common; using namespace Sapphire::Common;
using namespace Sapphire::Entity;
using namespace Sapphire::Network::Packets; using namespace Sapphire::Network::Packets;
//using namespace Sapphire::Network::Packets::Server; //using namespace Sapphire::Network::Packets::Server;
Sapphire::Entity::GameObject::GameObject( ObjKind type ) : GameObject::GameObject( ObjKind type ) :
m_objKind( type ) m_objKind( type )
{ {
} }
uint32_t Sapphire::Entity::GameObject::getId() const uint32_t GameObject::getId() const
{ {
return m_id; return m_id;
} }
void Sapphire::Entity::GameObject::setId( uint32_t id ) void GameObject::setId( uint32_t id )
{ {
m_id = id; m_id = id;
} }
Sapphire::Common::ObjKind Sapphire::Entity::GameObject::getObjKind() const ObjKind GameObject::getObjKind() const
{ {
return m_objKind; return m_objKind;
} }
Sapphire::Common::FFXIVARR_POSITION3& Sapphire::Entity::GameObject::getPos() FFXIVARR_POSITION3& GameObject::getPos()
{ {
return m_pos; return m_pos;
} }
const Sapphire::Common::FFXIVARR_POSITION3& Sapphire::Entity::GameObject::getPos() const const FFXIVARR_POSITION3& GameObject::getPos() const
{ {
return m_pos; return m_pos;
} }
void Sapphire::Entity::GameObject::setPos( float x, float y, float z, bool broadcastUpdate ) void GameObject::setPos( float x, float y, float z, bool broadcastUpdate )
{ {
m_pos.x = x; m_pos.x = x;
m_pos.y = y; m_pos.y = y;
@ -72,7 +73,7 @@ void Sapphire::Entity::GameObject::setPos( float x, float y, float z, bool broad
} }
void Sapphire::Entity::GameObject::setPos( const Sapphire::Common::FFXIVARR_POSITION3& pos, bool broadcastUpdate ) void GameObject::setPos( const FFXIVARR_POSITION3& pos, bool broadcastUpdate )
{ {
m_pos = pos; m_pos = pos;
@ -84,92 +85,92 @@ void Sapphire::Entity::GameObject::setPos( const Sapphire::Common::FFXIVARR_POSI
} }
} }
float Sapphire::Entity::GameObject::getRot() const float GameObject::getRot() const
{ {
return m_rot; return m_rot;
} }
void Sapphire::Entity::GameObject::setRot( float rot ) void GameObject::setRot( float rot )
{ {
m_rot = rot; m_rot = rot;
} }
bool Sapphire::Entity::GameObject::isChara() const bool GameObject::isChara() const
{ {
return isPlayer() || isBattleNpc() || isEventNpc() || isRetainer() || isCompanion(); return isPlayer() || isBattleNpc() || isEventNpc() || isRetainer() || isCompanion();
} }
bool Sapphire::Entity::GameObject::isPlayer() const bool GameObject::isPlayer() const
{ {
return m_objKind == ObjKind::Player; return m_objKind == ObjKind::Player;
} }
bool Sapphire::Entity::GameObject::isEventNpc() const bool GameObject::isEventNpc() const
{ {
return m_objKind == ObjKind::EventNpc; return m_objKind == ObjKind::EventNpc;
} }
bool Sapphire::Entity::GameObject::isBattleNpc() const bool GameObject::isBattleNpc() const
{ {
return m_objKind == ObjKind::BattleNpc; return m_objKind == ObjKind::BattleNpc;
} }
bool Sapphire::Entity::GameObject::isRetainer() const bool GameObject::isRetainer() const
{ {
return m_objKind == ObjKind::Retainer; return m_objKind == ObjKind::Retainer;
} }
bool Sapphire::Entity::GameObject::isCompanion() const bool GameObject::isCompanion() const
{ {
return m_objKind == ObjKind::Companion; return m_objKind == ObjKind::Companion;
} }
bool Sapphire::Entity::GameObject::isEventObj() const bool GameObject::isEventObj() const
{ {
return m_objKind == ObjKind::EventObj; return m_objKind == ObjKind::EventObj;
} }
bool Sapphire::Entity::GameObject::isHousingEventObj() const bool GameObject::isHousingEventObj() const
{ {
return m_objKind == ObjKind::Housing; return m_objKind == ObjKind::Housing;
} }
bool Sapphire::Entity::GameObject::isAetheryte() const bool GameObject::isAetheryte() const
{ {
return m_objKind == ObjKind::Aetheryte; return m_objKind == ObjKind::Aetheryte;
} }
/*! \return pointer to this instance as GameObjectPtr */ /*! \return pointer to this instance as GameObjectPtr */
Sapphire::Entity::CharaPtr Sapphire::Entity::GameObject::getAsChara() CharaPtr GameObject::getAsChara()
{ {
if( !isChara() ) if( !isChara() )
return nullptr; return nullptr;
return std::dynamic_pointer_cast< Entity::Chara, Entity::GameObject >( shared_from_this() ); return std::dynamic_pointer_cast< Chara, GameObject >( shared_from_this() );
} }
/*! \return pointer to this instance as PlayerPtr */ /*! \return pointer to this instance as PlayerPtr */
Sapphire::Entity::PlayerPtr Sapphire::Entity::GameObject::getAsPlayer() PlayerPtr GameObject::getAsPlayer()
{ {
if( !isPlayer() ) if( !isPlayer() )
return nullptr; return nullptr;
return std::dynamic_pointer_cast< Entity::Player, Entity::GameObject >( shared_from_this() ); return std::dynamic_pointer_cast< Player, GameObject >( shared_from_this() );
} }
/*! \return pointer to this instance as EventObjPtr */ /*! \return pointer to this instance as EventObjPtr */
Sapphire::Entity::EventObjectPtr Sapphire::Entity::GameObject::getAsEventObj() EventObjectPtr GameObject::getAsEventObj()
{ {
if( !isEventObj() ) if( !isEventObj() )
return nullptr; return nullptr;
return std::dynamic_pointer_cast< Entity::EventObject, Entity::GameObject >( shared_from_this() ); return std::dynamic_pointer_cast< EventObject, GameObject >( shared_from_this() );
} }
/*! \return pointer to this instance as BNpcPtr */ /*! \return pointer to this instance as BNpcPtr */
Sapphire::Entity::BNpcPtr Sapphire::Entity::GameObject::getAsBNpc() BNpcPtr GameObject::getAsBNpc()
{ {
if( !isBattleNpc() ) if( !isBattleNpc() )
return nullptr; return nullptr;
return std::dynamic_pointer_cast< Entity::BNpc, Entity::GameObject >( shared_from_this() ); return std::dynamic_pointer_cast< BNpc, GameObject >( shared_from_this() );
} }
/*! /*!
@ -178,7 +179,7 @@ but also to the global actor map
\param GameObjectPtr to add \param GameObjectPtr to add
*/ */
void Sapphire::Entity::GameObject::addInRangeActor( GameObjectPtr pActor ) void GameObject::addInRangeActor( GameObjectPtr pActor )
{ {
// if this is null, something went wrong // if this is null, something went wrong
@ -211,7 +212,7 @@ but also to the global actor map
\param GameObjectPtr to remove \param GameObjectPtr to remove
*/ */
void Sapphire::Entity::GameObject::removeInRangeActor( GameObject& actor ) void GameObject::removeInRangeActor( GameObject& actor )
{ {
// call virtual event // call virtual event
onRemoveInRangeActor( actor ); onRemoveInRangeActor( actor );
@ -232,12 +233,12 @@ void Sapphire::Entity::GameObject::removeInRangeActor( GameObject& actor )
} }
/*! \return true if there is at least one actor in the in range set */ /*! \return true if there is at least one actor in the in range set */
bool Sapphire::Entity::GameObject::hasInRangeActor() const bool GameObject::hasInRangeActor() const
{ {
return ( !m_inRangeActor.empty() ); return ( !m_inRangeActor.empty() );
} }
void Sapphire::Entity::GameObject::removeFromInRange() void GameObject::removeFromInRange()
{ {
if( !hasInRangeActor() ) if( !hasInRangeActor() )
return; return;
@ -255,14 +256,14 @@ check if a given actor is in the actors in range set
\param GameObjectPtr to be checked for \param GameObjectPtr to be checked for
\return true if the actor was found \return true if the actor was found
*/ */
bool Sapphire::Entity::GameObject::isInRangeSet( GameObjectPtr pActor ) const bool GameObject::isInRangeSet( GameObjectPtr pActor ) const
{ {
return !( m_inRangeActor.find( pActor ) == m_inRangeActor.end() ); return !( m_inRangeActor.find( pActor ) == m_inRangeActor.end() );
} }
/*! \return GameObjectPtr of the closest actor in range, if none, nullptr */ /*! \return GameObjectPtr of the closest actor in range, if none, nullptr */
Sapphire::Entity::CharaPtr Sapphire::Entity::GameObject::getClosestChara() CharaPtr GameObject::getClosestChara()
{ {
if( m_inRangeActor.empty() ) if( m_inRangeActor.empty() )
// no actors in range, don't bother // no actors in range, don't bother
@ -275,8 +276,7 @@ Sapphire::Entity::CharaPtr Sapphire::Entity::GameObject::getClosestChara()
for( const auto& pCurAct : m_inRangeActor ) for( const auto& pCurAct : m_inRangeActor )
{ {
float distance = Util::distance( getPos().x, getPos().y, getPos().z, float distance = Util::distance( getPos().x, getPos().y, getPos().z, pCurAct->getPos().x, pCurAct->getPos().y, pCurAct->getPos().z );
pCurAct->getPos().x, pCurAct->getPos().y, pCurAct->getPos().z );
if( distance < minDistance ) if( distance < minDistance )
{ {
@ -289,7 +289,7 @@ Sapphire::Entity::CharaPtr Sapphire::Entity::GameObject::getClosestChara()
} }
/*! Clear the whole in range set, this does no cleanup */ /*! Clear the whole in range set, this does no cleanup */
void Sapphire::Entity::GameObject::clearInRangeSet() void GameObject::clearInRangeSet()
{ {
m_inRangeActor.clear(); m_inRangeActor.clear();
m_inRangePlayers.clear(); m_inRangePlayers.clear();
@ -297,7 +297,7 @@ void Sapphire::Entity::GameObject::clearInRangeSet()
} }
/*! \return list of actors currently in range */ /*! \return list of actors currently in range */
std::set< Sapphire::Entity::GameObjectPtr > Sapphire::Entity::GameObject::getInRangeActors( bool includeSelf ) std::set< GameObjectPtr > GameObject::getInRangeActors( bool includeSelf )
{ {
auto tempInRange = m_inRangeActor; auto tempInRange = m_inRangeActor;
@ -307,7 +307,7 @@ std::set< Sapphire::Entity::GameObjectPtr > Sapphire::Entity::GameObject::getInR
return tempInRange; return tempInRange;
} }
std::set< uint64_t > Sapphire::Entity::GameObject::getInRangePlayerIds( bool includeSelf ) std::set< uint64_t > GameObject::getInRangePlayerIds( bool includeSelf )
{ {
std::set< uint64_t > playerIds; std::set< uint64_t > playerIds;
for( auto& player : m_inRangePlayers ) for( auto& player : m_inRangePlayers )
@ -319,22 +319,22 @@ std::set< uint64_t > Sapphire::Entity::GameObject::getInRangePlayerIds( bool inc
return playerIds; return playerIds;
} }
uint32_t Sapphire::Entity::GameObject::getTerritoryTypeId() const uint32_t GameObject::getTerritoryTypeId() const
{ {
return m_territoryTypeId; return m_territoryTypeId;
} }
void Sapphire::Entity::GameObject::setTerritoryTypeId( uint32_t territoryTypeId ) void GameObject::setTerritoryTypeId( uint32_t territoryTypeId )
{ {
m_territoryTypeId = territoryTypeId; m_territoryTypeId = territoryTypeId;
} }
uint32_t Sapphire::Entity::GameObject::getTerritoryId() const uint32_t GameObject::getTerritoryId() const
{ {
return m_territoryId; return m_territoryId;
} }
void Sapphire::Entity::GameObject::setTerritoryId( uint32_t territoryId ) void GameObject::setTerritoryId( uint32_t territoryId )
{ {
m_territoryId = territoryId; m_territoryId = territoryId;
} }
@ -344,7 +344,7 @@ Get the current cellId of a region the actor is in
\return CellId \return CellId
*/ */
Sapphire::Common::CellId Sapphire::Entity::GameObject::getCellId() const CellId GameObject::getCellId() const
{ {
return m_cellId; return m_cellId;
} }
@ -354,7 +354,7 @@ Set the current cellId the actor is in
\param CellId for the cell to be set \param CellId for the cell to be set
*/ */
void Sapphire::Entity::GameObject::setCellId( Common::CellId cellId ) void GameObject::setCellId( CellId cellId )
{ {
m_cellId = cellId; m_cellId = cellId;
} }

View file

@ -1,20 +1,14 @@
#include <Network/PacketContainer.h>
#include "Action/Action.h"
#include "Territory/Territory.h"
#include "Player.h" #include "Player.h"
#include "Npc.h" #include "Npc.h"
#include "Common.h" #include "Common.h"
using namespace Sapphire::Entity;
using namespace Sapphire::Common; using namespace Sapphire::Common;
using namespace Sapphire::Network::Packets;
using namespace Sapphire::Network::Packets::WorldPackets::Server;
Sapphire::Entity::Npc::Npc( ObjKind type ) : Chara( type ) Npc::Npc( ObjKind type ) : Chara( type )
{ {
}
}
Npc::~Npc()
Sapphire::Entity::Npc::~Npc()
{ {
} }

View file

@ -35,7 +35,7 @@
#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 "Network/Util/PacketUtil.h"
#include "Action/Action.h" #include "Action/Action.h"
@ -264,7 +264,7 @@ void Player::addOnlineStatus( OnlineStatus status )
setOnlineStatusMask( newFlags ); setOnlineStatusMask( newFlags );
Network::Util::Player::sendOnlineStatus( *this ); Network::Util::Packet::sendOnlineStatus( *this );
} }
void Player::addOnlineStatus( const std::vector< Common::OnlineStatus >& status ) void Player::addOnlineStatus( const std::vector< Common::OnlineStatus >& status )
@ -278,7 +278,7 @@ void Player::addOnlineStatus( const std::vector< Common::OnlineStatus >& status
setOnlineStatusMask( newFlags ); setOnlineStatusMask( newFlags );
Network::Util::Player::sendOnlineStatus( *this ); Network::Util::Packet::sendOnlineStatus( *this );
} }
void Player::removeOnlineStatus( OnlineStatus status ) void Player::removeOnlineStatus( OnlineStatus status )
@ -292,7 +292,7 @@ void Player::removeOnlineStatus( OnlineStatus status )
setOnlineStatusMask( newFlags ); setOnlineStatusMask( newFlags );
setOnlineStatusCustomMask( newFlagsCustom ); setOnlineStatusCustomMask( newFlagsCustom );
Network::Util::Player::sendOnlineStatus( *this ); Network::Util::Packet::sendOnlineStatus( *this );
} }
void Player::removeOnlineStatus( const std::vector< Common::OnlineStatus >& status ) void Player::removeOnlineStatus( const std::vector< Common::OnlineStatus >& status )
@ -309,7 +309,7 @@ void Player::removeOnlineStatus( const std::vector< Common::OnlineStatus >& stat
setOnlineStatusMask( newFlags ); setOnlineStatusMask( newFlags );
setOnlineStatusCustomMask( newFlagsCustom ); setOnlineStatusCustomMask( newFlagsCustom );
Network::Util::Player::sendOnlineStatus( *this ); Network::Util::Packet::sendOnlineStatus( *this );
} }
void Player::calculateStats() void Player::calculateStats()
@ -457,7 +457,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;
Network::Util::Player::sendActorControlSelf( *this, LearnTeleport, aetheryteId, 1 ); Network::Util::Packet::sendActorControlSelf( *this, getId(), LearnTeleport, aetheryteId, 1 );
} }
bool Player::isAetheryteRegistered( uint8_t aetheryteId ) const bool Player::isAetheryteRegistered( uint8_t aetheryteId ) const
@ -560,7 +560,7 @@ void Player::setRewardFlag( Common::UnlockEntry unlockId )
m_unlocks[ index ] |= value; m_unlocks[ index ] |= value;
Network::Util::Player::sendActorControlSelf( *this, SetRewardFlag, unlock, 1 ); Network::Util::Packet::sendActorControlSelf( *this, getId(), SetRewardFlag, unlock, 1 );
} }
void Player::setBorrowAction( uint8_t slot, uint32_t action ) void Player::setBorrowAction( uint8_t slot, uint32_t action )
@ -587,7 +587,7 @@ void Player::learnSong( uint8_t songId, uint32_t itemId )
m_orchestrion[ index ] |= value; m_orchestrion[ index ] |= value;
Network::Util::Player::sendActorControlSelf( *this, ToggleOrchestrionUnlock, songId, 1, itemId ); Network::Util::Packet::sendActorControlSelf( *this, getId(), ToggleOrchestrionUnlock, songId, 1, itemId );
} }
bool Player::hasReward( Common::UnlockEntry unlockId ) const bool Player::hasReward( Common::UnlockEntry unlockId ) const
@ -624,7 +624,7 @@ void Player::gainExp( uint32_t amount )
{ {
setExp( 0 ); setExp( 0 );
if( currentExp != 0 ) if( currentExp != 0 )
Network::Util::Player::sendActorControlSelf( *this, UpdateUiExp, currentClass, 0 ); Network::Util::Packet::sendActorControlSelf( *this, getId(), UpdateUiExp, currentClass, 0 );
return; return;
} }
@ -648,8 +648,8 @@ void Player::gainExp( uint32_t amount )
else else
setExp( currentExp + amount ); setExp( currentExp + amount );
Network::Util::Player::sendActorControlSelf( *this, GainExpMsg, currentClass, amount ); Network::Util::Packet::sendActorControlSelf( *this, getId(), GainExpMsg, currentClass, amount );
Network::Util::Player::sendActorControlSelf( *this, UpdateUiExp, currentClass, getExp() ); Network::Util::Packet::sendActorControlSelf( *this, getId(), UpdateUiExp, currentClass, getExp() );
} }
void Player::levelUp() void Player::levelUp()
@ -658,7 +658,7 @@ void Player::levelUp()
m_mp = getMaxMp(); m_mp = getMaxMp();
setLevel( getLevel() + 1 ); setLevel( getLevel() + 1 );
Network::Util::Player::sendActorControl( getInRangePlayerIds( true ), *this, LevelUpEffect, static_cast< uint8_t >( getClass() ), getLevel(), getLevel() - 1 ); Network::Util::Packet::sendActorControl( getInRangePlayerIds( true ), getId(), LevelUpEffect, static_cast< uint8_t >( getClass() ), getLevel(), getLevel() - 1 );
auto& achvMgr = Common::Service< World::Manager::AchievementMgr >::ref(); auto& achvMgr = Common::Service< World::Manager::AchievementMgr >::ref();
achvMgr.progressAchievementByType< Common::Achievement::Type::Classjob >( *this, static_cast< uint32_t >( getClass() ) ); achvMgr.progressAchievementByType< Common::Achievement::Type::Classjob >( *this, static_cast< uint32_t >( getClass() ) );
@ -733,10 +733,10 @@ void Player::setClassJob( Common::ClassJob classJob )
m_tp = 0; m_tp = 0;
Network::Util::Player::sendChangeClass( *this ); Network::Util::Packet::sendChangeClass( *this );
Network::Util::Player::sendStatusUpdate( *this ); Network::Util::Packet::sendStatusUpdate( *this );
Network::Util::Player::sendActorControl( getInRangePlayerIds( true ), *this, ClassJobChange, 4 ); Network::Util::Packet::sendActorControl( getInRangePlayerIds( true ), getId(), ClassJobChange, 4 );
Network::Util::Player::sendHudParam( *this ); Network::Util::Packet::sendHudParam( *this );
Service< World::Manager::MapMgr >::ref().updateQuests( *this ); Service< World::Manager::MapMgr >::ref().updateQuests( *this );
} }
@ -747,9 +747,9 @@ void Player::setLevel( uint8_t level )
m_classArray[ classJobIndex ] = level; m_classArray[ classJobIndex ] = level;
calculateStats(); calculateStats();
Network::Util::Player::sendBaseParams( *this ); Network::Util::Packet::sendBaseParams( *this );
Network::Util::Player::sendHudParam( *this ); Network::Util::Packet::sendHudParam( *this );
Network::Util::Player::sendStatusUpdate( *this ); Network::Util::Packet::sendStatusUpdate( *this );
} }
void Player::setLevelForClass( uint8_t level, Common::ClassJob classjob ) void Player::setLevelForClass( uint8_t level, Common::ClassJob classjob )
@ -762,7 +762,7 @@ void Player::setLevelForClass( uint8_t level, Common::ClassJob classjob )
m_classArray[ classJobIndex ] = level; m_classArray[ classJobIndex ] = level;
Network::Util::Player::sendActorControlSelf( *this, ClassJobUpdate, static_cast< uint8_t >( classjob ), getLevelForClass( classjob ) ); Network::Util::Packet::sendActorControlSelf( *this, getId(), ClassJobUpdate, static_cast< uint8_t >( classjob ), getLevelForClass( classjob ) );
auto& achvMgr = Common::Service< World::Manager::AchievementMgr >::ref(); auto& achvMgr = Common::Service< World::Manager::AchievementMgr >::ref();
achvMgr.progressAchievementByType< Common::Achievement::Type::Classjob >( *this, static_cast< uint32_t >( classjob ) ); achvMgr.progressAchievementByType< Common::Achievement::Type::Classjob >( *this, static_cast< uint32_t >( classjob ) );
@ -835,7 +835,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() );
Network::Util::Player::sendActorControlSelf( *this, WarpStart, 4, getId(), 1 ); Network::Util::Packet::sendActorControlSelf( *this, getId(), WarpStart, 4, getId(), 1 );
} }
GameObjectPtr Player::lookupTargetById( uint64_t targetId ) GameObjectPtr Player::lookupTargetById( uint64_t targetId )
@ -865,13 +865,13 @@ void Player::setGrandCompany( uint8_t gc )
m_gc = gc; m_gc = gc;
if( m_gcRank[ gc ] == 0 ) if( m_gcRank[ gc ] == 0 )
m_gcRank[ gc ] = 1; m_gcRank[ gc ] = 1;
Network::Util::Player::sendGrandCompany( *this ); Network::Util::Packet::sendGrandCompany( *this );
} }
void Player::setGrandCompanyRankAt( 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 ); Network::Util::Packet::sendGrandCompany( *this );
} }
const Player::Condition& Player::getConditions() const const Player::Condition& Player::getConditions() const
@ -899,7 +899,7 @@ void Player::setCondition( Common::PlayerCondition flag )
Util::valueToFlagByteIndexValue( iFlag, value, index ); Util::valueToFlagByteIndexValue( iFlag, value, index );
m_condition[ index ] |= value; m_condition[ index ] |= value;
Network::Util::Player::sendCondition( *this ); Network::Util::Packet::sendCondition( *this );
} }
void Player::setConditions( const std::vector< Common::PlayerCondition >& flags ) void Player::setConditions( const std::vector< Common::PlayerCondition >& flags )
@ -914,7 +914,7 @@ void Player::setConditions( const std::vector< Common::PlayerCondition >& flags
m_condition[ index ] |= value; m_condition[ index ] |= value;
} }
Network::Util::Player::sendCondition( *this ); Network::Util::Packet::sendCondition( *this );
} }
void Player::removeCondition( Common::PlayerCondition flag ) void Player::removeCondition( Common::PlayerCondition flag )
@ -929,7 +929,7 @@ void Player::removeCondition( Common::PlayerCondition flag )
Util::valueToFlagByteIndexValue( iFlag, value, index ); Util::valueToFlagByteIndexValue( iFlag, value, index );
m_condition[ index ] ^= value; m_condition[ index ] ^= value;
Network::Util::Player::sendCondition( *this ); Network::Util::Packet::sendCondition( *this );
} }
void Player::update( uint64_t tickCount ) void Player::update( uint64_t tickCount )
@ -940,16 +940,6 @@ void Player::update( uint64_t tickCount )
Chara::update( tickCount ); Chara::update( tickCount );
} }
uint64_t Player::getLastAttack() const
{
return m_lastAttack;
}
void Player::setLastAttack( uint64_t tickCount )
{
m_lastAttack = tickCount;
}
void Player::freePlayerSpawnId( uint32_t actorId ) void Player::freePlayerSpawnId( uint32_t actorId )
{ {
auto spawnId = m_actorSpawnIndexAllocator.freeUsedSpawnIndex( actorId ); auto spawnId = m_actorSpawnIndexAllocator.freeUsedSpawnIndex( actorId );
@ -958,7 +948,7 @@ void Player::freePlayerSpawnId( uint32_t actorId )
if( spawnId == m_actorSpawnIndexAllocator.getAllocFailId() ) if( spawnId == m_actorSpawnIndexAllocator.getAllocFailId() )
return; return;
Network::Util::Player::sendDeletePlayer( *this, actorId, spawnId ); Network::Util::Packet::sendDeletePlayer( *this, actorId, spawnId );
} }
Player::AetheryteList& Player::getAetheryteArray() Player::AetheryteList& Player::getAetheryteArray()
@ -970,7 +960,7 @@ Player::AetheryteList& Player::getAetheryteArray()
void Player::setHomepoint( uint8_t aetheryteId ) void Player::setHomepoint( uint8_t aetheryteId )
{ {
m_homePoint = aetheryteId; m_homePoint = aetheryteId;
Network::Util::Player::sendActorControlSelf( *this, SetHomepoint, aetheryteId ); Network::Util::Packet::sendActorControlSelf( *this, getId(), SetHomepoint, aetheryteId );
} }
/*! get homepoint */ /*! get homepoint */
@ -1019,7 +1009,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 ) );
Network::Util::Player::sendActorControlSelf( *this, SetMountBitmask, mount->data().MountOrder, 1 ); Network::Util::Packet::sendActorControlSelf( *this, getId(), SetMountBitmask, mount->data().MountOrder, 1 );
} }
void Player::unlockCompanion( uint32_t companionId ) void Player::unlockCompanion( uint32_t companionId )
@ -1036,7 +1026,7 @@ void Player::unlockCompanion( uint32_t companionId )
m_minionGuide[ index ] |= value; m_minionGuide[ index ] |= value;
Network::Util::Player::sendActorControlSelf( *this, LearnCompanion, companionId, 1 ); Network::Util::Packet::sendActorControlSelf( *this, getId(), LearnCompanion, companionId, 1 );
} }
Player::MinionList& Player::getMinionGuideBitmask() Player::MinionList& Player::getMinionGuideBitmask()
@ -1126,7 +1116,7 @@ void Player::hateListAdd( const BNpc& bnpc )
uint8_t hateId = m_freeHateSlotQueue.front(); uint8_t hateId = m_freeHateSlotQueue.front();
m_freeHateSlotQueue.pop(); m_freeHateSlotQueue.pop();
m_actorIdTohateSlotMap[ bnpc.getId() ] = hateId; m_actorIdTohateSlotMap[ bnpc.getId() ] = hateId;
Network::Util::Player::sendHateList( *this ); Network::Util::Packet::sendHateList( *this );
} }
} }
@ -1141,7 +1131,7 @@ void Player::hateListRemove( const BNpc& bnpc )
uint8_t hateSlot = it->second; uint8_t hateSlot = it->second;
m_freeHateSlotQueue.push( hateSlot ); m_freeHateSlotQueue.push( hateSlot );
m_actorIdTohateSlotMap.erase( it ); m_actorIdTohateSlotMap.erase( it );
Network::Util::Player::sendHateList( *this ); Network::Util::Packet::sendHateList( *this );
return; return;
} }
} }
@ -1161,14 +1151,14 @@ const std::map< uint32_t, uint8_t >& Player::getActorIdToHateSlotMap()
void Player::onMobAggro( const BNpc& bnpc ) void Player::onMobAggro( const BNpc& bnpc )
{ {
hateListAdd( bnpc ); hateListAdd( bnpc );
Network::Util::Player::sendActorControl( *this, SetBattle, 1 ); Network::Util::Packet::sendActorControl( *this, getId(), SetBattle, 1 );
} }
void Player::onMobDeaggro( const BNpc& bnpc ) void Player::onMobDeaggro( const BNpc& bnpc )
{ {
hateListRemove( bnpc ); hateListRemove( bnpc );
if( m_actorIdTohateSlotMap.empty() ) if( m_actorIdTohateSlotMap.empty() )
Network::Util::Player::sendActorControl( *this, SetBattle, 0 ); Network::Util::Packet::sendActorControl( *this, getId(), SetBattle, 0 );
} }
bool Player::isLogin() const bool Player::isLogin() const
@ -1210,7 +1200,7 @@ void Player::setTitle( uint16_t titleId )
return; return;
m_activeTitle = titleId; m_activeTitle = titleId;
Network::Util::Player::sendActorControl( getInRangePlayerIds( true ), *this, SetTitle, titleId ); Network::Util::Packet::sendActorControl( getInRangePlayerIds( true ), getId(), SetTitle, titleId );
} }
const Player::AchievementData& Player::getAchievementData() const const Player::AchievementData& Player::getAchievementData() const
@ -1226,7 +1216,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 ); Network::Util::Packet::sendActorControlSelf( *this, getId(), SetMaxGearSets, m_equippedMannequin );
} }
void Player::addGearSet() void Player::addGearSet()
@ -1251,7 +1241,7 @@ uint8_t Player::getMaxGearSets() const
void Player::setConfigFlags( uint16_t state ) void Player::setConfigFlags( uint16_t state )
{ {
m_configFlags = static_cast< uint8_t >( state ); m_configFlags = static_cast< uint8_t >( state );
Network::Util::Player::sendConfigFlags( *this ); Network::Util::Packet::sendConfigFlags( *this );
} }
uint8_t Player::getConfigFlags() const uint8_t Player::getConfigFlags() const
@ -1262,7 +1252,7 @@ uint8_t Player::getConfigFlags() const
void Player::setMount( uint32_t mountId ) void Player::setMount( uint32_t mountId )
{ {
m_mount = mountId; m_mount = mountId;
Network::Util::Player::sendMount( *this ); Network::Util::Packet::sendMount( *this );
} }
void Player::setCompanion( uint8_t id ) void Player::setCompanion( uint8_t id )
@ -1275,7 +1265,7 @@ void Player::setCompanion( uint8_t id )
m_companionId = id; m_companionId = id;
Network::Util::Player::sendActorControl( getInRangePlayerIds( true ), *this, ToggleCompanion, id ); Network::Util::Packet::sendActorControl( getInRangePlayerIds( true ), getId(), ToggleCompanion, id );
} }
uint8_t Player::getCurrentCompanion() const uint8_t Player::getCurrentCompanion() const
@ -1312,9 +1302,9 @@ void Player::autoAttack( CharaPtr pTarget )
auto& RNGMgr = Common::Service< World::Manager::RNGMgr >::ref(); auto& RNGMgr = Common::Service< World::Manager::RNGMgr >::ref();
auto variation = static_cast< uint32_t >( RNGMgr.getRandGenerator< float >( 0, 3 ).next() ); auto variation = static_cast< uint32_t >( RNGMgr.getRandGenerator< float >( 0, 3 ).next() );
//actionMgr.handleTargetedPlayerAction( *this, 7, exdData.getRow< Excel::Action >( 7 ), pTarget->getId(), 0 ); actionMgr.handleTargetedAction( *this, 7, exdData.getRow< Excel::Action >( 7 ), pTarget->getId(), 0 );
auto damage = Math::CalcStats::calcAutoAttackDamage( *this ); /* auto damage = Math::CalcStats::calcAutoAttackDamage( *this );
auto effectPacket = std::make_shared< EffectPacket1 >( getId(), pTarget->getId(), 7 ); auto effectPacket = std::make_shared< EffectPacket1 >( getId(), pTarget->getId(), 7 );
@ -1328,7 +1318,7 @@ void Player::autoAttack( CharaPtr pTarget )
if( getClass() == ClassJob::Machinist || getClass() == ClassJob::Bard || getClass() == ClassJob::Archer ) if( getClass() == ClassJob::Machinist || getClass() == ClassJob::Bard || getClass() == ClassJob::Archer )
effectPacket->setActionId( 8 ); effectPacket->setActionId( 8 );
auto resultId = pZone->getNextEffectResultId(); auto resultId = pZone->getNextActionResultId();
effectPacket->setResultId( resultId ); effectPacket->setResultId( resultId );
effectPacket->setRotation( Util::floatToUInt16Rot( getRot() ) ); effectPacket->setRotation( Util::floatToUInt16Rot( getRot() ) );
effectPacket->addTargetEffect( entry ); effectPacket->addTargetEffect( entry );
@ -1337,8 +1327,8 @@ void Player::autoAttack( CharaPtr pTarget )
pTarget->takeDamage( static_cast< uint32_t >( damage.first ) ); pTarget->takeDamage( static_cast< uint32_t >( damage.first ) );
auto& taskMgr = Common::Service< TaskMgr >::ref(); auto& taskMgr = Common::Service< TaskMgr >::ref();*/
taskMgr.queueTask( Sapphire::World::makeActionIntegrityTask( resultId, pTarget, 500 ) ); //taskMgr.queueTask( Sapphire::World::makeActionIntegrityTask( resultId, pTarget, 500 ) );
} }
@ -1435,7 +1425,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;
Network::Util::Player::sendActorControlSelf( *this, OnExecuteTelepo, insufficientGil ? 2 : 0, aetheryteId ); Network::Util::Packet::sendActorControlSelf( *this, getId(), OnExecuteTelepo, insufficientGil ? 2 : 0, aetheryteId );
if( !insufficientGil ) if( !insufficientGil )
{ {
@ -1510,7 +1500,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 );
Network::Util::Player::sendActorControlSelf( *this, DyeMsg, itemToDye->getId(), shouldDye, invalidateGearSet ); Network::Util::Packet::sendActorControlSelf( *this, getId(), DyeMsg, itemToDye->getId(), shouldDye, invalidateGearSet );
} }
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 )
@ -1532,7 +1522,7 @@ void Player::glamourItemFromGlamouringInfo()
uint32_t glamourBagSlot = m_glamouringInfo.glamourBagSlot; uint32_t glamourBagSlot = m_glamouringInfo.glamourBagSlot;
bool shouldGlamour = m_glamouringInfo.shouldGlamour; bool shouldGlamour = m_glamouringInfo.shouldGlamour;
Network::Util::Player::sendCondition( *this ); Network::Util::Packet::sendCondition( *this );
auto itemToGlamour = getItemAt( itemToGlamourContainer, itemToGlamourSlot ); auto itemToGlamour = getItemAt( itemToGlamourContainer, itemToGlamourSlot );
auto glamourToUse = getItemAt( glamourBagContainer, glamourBagSlot ); auto glamourToUse = getItemAt( glamourBagContainer, glamourBagSlot );
@ -1564,9 +1554,9 @@ void Player::glamourItemFromGlamouringInfo()
writeItem( itemToGlamour ); writeItem( itemToGlamour );
if( shouldGlamour ) if( shouldGlamour )
Network::Util::Player::sendActorControlSelf( *this, GlamourCastMsg, itemToGlamour->getId(), glamourToUse->getId(), invalidateGearSet ); Network::Util::Packet::sendActorControlSelf( *this, getId(), GlamourCastMsg, itemToGlamour->getId(), glamourToUse->getId(), invalidateGearSet );
else else
Network::Util::Player::sendActorControlSelf( *this, GlamourRemoveMsg, itemToGlamour->getId(), invalidateGearSet ); Network::Util::Packet::sendActorControlSelf( *this, getId(), GlamourRemoveMsg, itemToGlamour->getId(), invalidateGearSet );
} }
void Player::resetObjSpawnIndex() void Player::resetObjSpawnIndex()
@ -1582,7 +1572,7 @@ void Player::freeObjSpawnIndexForActorId( uint32_t actorId )
if( spawnId == m_objSpawnIndexAllocator.getAllocFailId() ) if( spawnId == m_objSpawnIndexAllocator.getAllocFailId() )
return; return;
Network::Util::Player::sendDeleteObject( *this, spawnId ); Network::Util::Packet::sendDeleteObject( *this, spawnId );
} }
bool Player::isObjSpawnIndexValid( uint8_t index ) bool Player::isObjSpawnIndexValid( uint8_t index )
@ -1651,7 +1641,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 ]++;
Network::Util::Player::sendActorControlSelf( *this, HuntingLogEntryUpdate, monsterNoteId, x, logEntry.entries[ i - 1 ][ x ] ); Network::Util::Packet::sendActorControlSelf( *this, getId(), HuntingLogEntryUpdate, monsterNoteId, x, logEntry.entries[ i - 1 ][ x ] );
logChanged = true; logChanged = true;
sectionChanged = true; sectionChanged = true;
} }
@ -1660,7 +1650,7 @@ void Player::updateHuntingLog( uint16_t id )
} }
if( logChanged && sectionComplete && sectionChanged ) if( logChanged && sectionComplete && sectionChanged )
{ {
Network::Util::Player::sendActorControlSelf( *this, HuntingLogSectionFinish, monsterNoteId, i, 0 ); Network::Util::Packet::sendActorControlSelf( *this, getId(), HuntingLogSectionFinish, monsterNoteId, i, 0 );
gainExp( note->data().RewardExp ); gainExp( note->data().RewardExp );
} }
if( !sectionComplete ) if( !sectionComplete )
@ -1670,18 +1660,18 @@ void Player::updateHuntingLog( uint16_t id )
} }
if( logChanged && allSectionsComplete ) if( logChanged && allSectionsComplete )
{ {
Network::Util::Player::sendActorControlSelf( *this, HuntingLogRankFinish, 4 ); Network::Util::Packet::sendActorControlSelf( *this, getId(), 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 );
Network::Util::Player::sendActorControlSelf( *this, HuntingLogRankUnlock, currentClassId, logEntry.rank + 1, 0 ); Network::Util::Packet::sendActorControlSelf( *this, getId(), HuntingLogRankUnlock, currentClassId, logEntry.rank + 1, 0 );
} }
} }
if( logChanged ) if( logChanged )
Network::Util::Player::sendHuntingLog( *this ); Network::Util::Packet::sendHuntingLog( *this );
} }
void Player::setActiveLand( uint8_t land, uint8_t ward ) void Player::setActiveLand( uint8_t land, uint8_t ward )
@ -1744,7 +1734,7 @@ void Player::resetRecastGroups()
m_recast[ i ] = 0.0f; m_recast[ i ] = 0.0f;
m_recastMax[ i ] = 0.0f; m_recastMax[ i ] = 0.0f;
} }
Network::Util::Player::sendRecastGroups( *this ); Network::Util::Packet::sendRecastGroups( *this );
} }
bool Player::checkAction() bool Player::checkAction()
@ -1843,7 +1833,7 @@ void Player::setFalling( bool state, const Common::FFXIVARR_POSITION3& pos, bool
// no mercy on hated players // no mercy on hated players
takeDamage( damage ); takeDamage( damage );
} }
Network::Util::Player::sendActorControl( getInRangePlayerIds( true ), *this, SetFallDamage, damage ); Network::Util::Packet::sendActorControl( getInRangePlayerIds( true ), getId(), SetFallDamage, damage );
} }
} }
} }

View file

@ -84,12 +84,6 @@ namespace Sapphire::Entity
/*! Event called on every session iteration */ /*! Event called on every session iteration */
void update( uint64_t tickCount ) override; void update( uint64_t tickCount ) override;
/*! get last attack tick for player */
uint64_t getLastAttack() const;
/*! set last attack tick for player */
void setLastAttack( uint64_t tickCount );
// Quest // Quest
////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////
/*! load data for currently active quests */ /*! load data for currently active quests */

View file

@ -6,29 +6,30 @@
#include "Actor/Player.h" #include "Actor/Player.h"
#include "Territory/Territory.h" #include "Territory/Territory.h"
#include "WorldServer.h"
#include "Action/EventAction.h" #include "Action/EventAction.h"
#include "Manager/PlayerMgr.h" #include "Manager/PlayerMgr.h"
#include "Service.h" #include "Service.h"
#include <Network/PacketWrappers/RestingPacket.h> #include <Network/Util/PacketUtil.h>
using namespace Sapphire;
using namespace Sapphire::Common; using namespace Sapphire::Common;
using namespace Sapphire::Entity;
using namespace Sapphire::Network::Packets; using namespace Sapphire::Network::Packets;
using namespace Sapphire::Network::Packets::WorldPackets::Server; using namespace Sapphire::Network::Packets::WorldPackets::Server;
using namespace Sapphire::World::Manager; using namespace Sapphire::World::Manager;
void Sapphire::Entity::Player::addEvent( Event::EventHandlerPtr pEvent ) void Player::addEvent( Event::EventHandlerPtr pEvent )
{ {
m_eventHandlerMap[ pEvent->getId() ] = pEvent; m_eventHandlerMap[ pEvent->getId() ] = pEvent;
} }
std::map< uint32_t, Sapphire::Event::EventHandlerPtr >& Sapphire::Entity::Player::getEventListRef() std::map< uint32_t, Event::EventHandlerPtr >& Player::getEventListRef()
{ {
return m_eventHandlerMap; return m_eventHandlerMap;
} }
Sapphire::Event::EventHandlerPtr Sapphire::Entity::Player::getEvent( uint32_t eventId ) const Event::EventHandlerPtr Player::getEvent( uint32_t eventId ) const
{ {
auto it = m_eventHandlerMap.find( eventId ); auto it = m_eventHandlerMap.find( eventId );
if( it != m_eventHandlerMap.end() ) if( it != m_eventHandlerMap.end() )
@ -37,12 +38,12 @@ Sapphire::Event::EventHandlerPtr Sapphire::Entity::Player::getEvent( uint32_t ev
return nullptr; return nullptr;
} }
size_t Sapphire::Entity::Player::getEventCount() size_t Player::getEventCount()
{ {
return m_eventHandlerMap.size(); return m_eventHandlerMap.size();
} }
void Sapphire::Entity::Player::removeEvent( uint32_t eventId ) void Player::removeEvent( uint32_t eventId )
{ {
auto it = m_eventHandlerMap.find( eventId ); auto it = m_eventHandlerMap.find( eventId );
if( it != m_eventHandlerMap.end() ) if( it != m_eventHandlerMap.end() )
@ -53,13 +54,13 @@ void Sapphire::Entity::Player::removeEvent( uint32_t eventId )
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Sapphire::Entity::Player::onDeath() void Player::onDeath()
{ {
Service< World::Manager::PlayerMgr >::ref().onDeath( *this ); Service< World::Manager::PlayerMgr >::ref().onDeath( *this );
} }
// TODO: slightly ugly here and way too static. Needs too be done properly // TODO: slightly ugly here and way too static. Needs too be done properly
void Sapphire::Entity::Player::onTick() void Player::onTick()
{ {
Chara::onTick(); Chara::onTick();
// add 3 seconds to total play time // add 3 seconds to total play time
@ -71,10 +72,10 @@ void Sapphire::Entity::Player::onTick()
bool sendUpdate = performResting(); bool sendUpdate = performResting();
if( sendUpdate ) if( sendUpdate )
server().queueForPlayers( getInRangePlayerIds( true ), std::make_shared< RestingPacket >( *this ) ); Network::Util::Packet::sendRestingUpdate( *this );
} }
bool Sapphire::Entity::Player::performResting() bool Player::performResting()
{ {
bool sendUpdate = false; bool sendUpdate = false;
auto addHp = static_cast< uint32_t >( static_cast< float >( getMaxHp() ) * 0.1f + 1 ); auto addHp = static_cast< uint32_t >( static_cast< float >( getMaxHp() ) * 0.1f + 1 );

View file

@ -18,7 +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 <Network/Util/PacketUtil.h>
#include "Manager/InventoryMgr.h" #include "Manager/InventoryMgr.h"
#include "Manager/ItemMgr.h" #include "Manager/ItemMgr.h"
@ -27,6 +27,9 @@
#include <Service.h> #include <Service.h>
using namespace Sapphire;
using namespace Sapphire::Entity;
using namespace Sapphire::World;
using namespace Sapphire::Common; using namespace Sapphire::Common;
using namespace Sapphire::World::Manager; using namespace Sapphire::World::Manager;
using namespace Sapphire::Network::Packets; using namespace Sapphire::Network::Packets;
@ -34,7 +37,7 @@ using namespace Sapphire::Network::Packets::WorldPackets::Server;
using namespace Sapphire::Network::ActorControl; using namespace Sapphire::Network::ActorControl;
void Sapphire::Entity::Player::initInventory() void Player::initInventory()
{ {
const uint8_t inventorySize = 25; const uint8_t inventorySize = 25;
auto setupContainer = [ this ]( InventoryType type, uint8_t maxSize, const std::string& tableName, auto setupContainer = [ this ]( InventoryType type, uint8_t maxSize, const std::string& tableName,
@ -103,9 +106,9 @@ void Sapphire::Entity::Player::initInventory()
calculateItemLevel(); calculateItemLevel();
} }
void Sapphire::Entity::Player::equipWeapon( const Item& item ) void Player::equipWeapon( const Item& item )
{ {
auto& exdData = Common::Service< Sapphire::Data::ExdData >::ref(); auto& exdData = Common::Service< Data::ExdData >::ref();
auto itemInfo = exdData.getRow< Excel::Item >( item.getId() ); auto itemInfo = exdData.getRow< Excel::Item >( item.getId() );
auto itemClassJob = itemInfo->data().Class; auto itemClassJob = itemInfo->data().Class;
@ -119,9 +122,9 @@ void Sapphire::Entity::Player::equipWeapon( const Item& item )
} }
} }
void Sapphire::Entity::Player::equipSoulCrystal( const Item& item ) void Player::equipSoulCrystal( const Item& item )
{ {
auto& exdData = Common::Service< Sapphire::Data::ExdData >::ref(); auto& exdData = Common::Service< Data::ExdData >::ref();
auto itemInfo = exdData.getRow< Excel::Item >( item.getId() ); auto itemInfo = exdData.getRow< Excel::Item >( item.getId() );
auto itemClassJob = itemInfo->data().Class; auto itemClassJob = itemInfo->data().Class;
@ -131,7 +134,7 @@ void Sapphire::Entity::Player::equipSoulCrystal( const Item& item )
setClassJob( newClassJob ); setClassJob( newClassJob );
} }
void Sapphire::Entity::Player::updateModels( GearSetSlot equipSlotId, const Sapphire::Item& item ) void Player::updateModels( GearSetSlot equipSlotId, const Sapphire::Item& item )
{ {
uint64_t model = item.getModelId1(); uint64_t model = item.getModelId1();
uint64_t model2 = item.getModelId2(); uint64_t model2 = item.getModelId2();
@ -169,7 +172,7 @@ void Sapphire::Entity::Player::updateModels( GearSetSlot equipSlotId, const Sapp
} }
} }
Sapphire::Common::GearModelSlot Sapphire::Entity::Player::equipSlotToModelSlot( Common::GearSetSlot slot ) Common::GearModelSlot Player::equipSlotToModelSlot( Common::GearSetSlot slot )
{ {
switch( slot ) switch( slot )
{ {
@ -203,7 +206,7 @@ Sapphire::Common::GearModelSlot Sapphire::Entity::Player::equipSlotToModelSlot(
} }
// equip an item // equip an item
void Sapphire::Entity::Player::equipItem( Common::GearSetSlot equipSlotId, Item& item, bool sendUpdate ) void Player::equipItem( Common::GearSetSlot equipSlotId, Item& item, bool sendUpdate )
{ {
switch( equipSlotId ) switch( equipSlotId )
{ {
@ -225,15 +228,15 @@ void Sapphire::Entity::Player::equipItem( Common::GearSetSlot equipSlotId, Item&
calculateItemLevel(); calculateItemLevel();
if( sendUpdate ) if( sendUpdate )
{ {
Network::Util::Player::sendEquip( *this ); Network::Util::Packet::sendEquip( *this );
Network::Util::Player::sendActorControl( *this, SetItemLevel, getItemLevel() ); Network::Util::Packet::sendActorControl( *this, getId(), SetItemLevel, getItemLevel() );
Network::Util::Player::sendBaseParams( *this ); Network::Util::Packet::sendBaseParams( *this );
Network::Util::Player::sendHudParam( *this ); Network::Util::Packet::sendHudParam( *this );
} }
} }
void Sapphire::Entity::Player::unequipItem( Common::GearSetSlot equipSlotId, Item& item, bool sendUpdate ) void Player::unequipItem( Common::GearSetSlot equipSlotId, Item& item, bool sendUpdate )
{ {
auto modelSlot = equipSlotToModelSlot( equipSlotId ); auto modelSlot = equipSlotToModelSlot( equipSlotId );
if( modelSlot != GearModelSlot::ModelInvalid ) if( modelSlot != GearModelSlot::ModelInvalid )
@ -247,14 +250,14 @@ void Sapphire::Entity::Player::unequipItem( Common::GearSetSlot equipSlotId, Ite
if( sendUpdate ) if( sendUpdate )
{ {
Network::Util::Player::sendEquip( *this ); Network::Util::Packet::sendEquip( *this );
Network::Util::Player::sendActorControl( *this, SetItemLevel, getItemLevel() ); Network::Util::Packet::sendActorControl( *this, getId(), SetItemLevel, getItemLevel() );
Network::Util::Player::sendBaseParams( *this ); Network::Util::Packet::sendBaseParams( *this );
Network::Util::Player::sendHudParam( *this ); Network::Util::Packet::sendHudParam( *this );
} }
} }
void Sapphire::Entity::Player::unequipSoulCrystal() void Player::unequipSoulCrystal()
{ {
auto& exdData = Common::Service< Sapphire::Data::ExdData >::ref(); auto& exdData = Common::Service< Sapphire::Data::ExdData >::ref();
@ -263,7 +266,7 @@ void Sapphire::Entity::Player::unequipSoulCrystal()
setClassJob( parentClass ); setClassJob( parentClass );
} }
uint32_t Sapphire::Entity::Player::currencyTypeToItem( Common::CurrencyType type ) const uint32_t Player::currencyTypeToItem( Common::CurrencyType type ) const
{ {
switch( type ) switch( type )
{ {
@ -301,7 +304,7 @@ uint32_t Sapphire::Entity::Player::currencyTypeToItem( Common::CurrencyType type
} }
// TODO: these next functions are so similar that they could likely be simplified // TODO: these next functions are so similar that they could likely be simplified
void Sapphire::Entity::Player::addCurrency( CurrencyType type, uint32_t amount ) void Player::addCurrency( CurrencyType type, uint32_t amount )
{ {
auto slot = static_cast< uint8_t >( static_cast< uint8_t >( type ) - 1 ); auto slot = static_cast< uint8_t >( static_cast< uint8_t >( type ) - 1 );
auto currItem = m_storageMap[ Currency ]->getItem( slot ); auto currItem = m_storageMap[ Currency ]->getItem( slot );
@ -339,7 +342,7 @@ void Sapphire::Entity::Player::addCurrency( CurrencyType type, uint32_t amount )
server().queueForPlayer( getCharacterId(), invTransFinPacket ); server().queueForPlayer( getCharacterId(), invTransFinPacket );
} }
void Sapphire::Entity::Player::removeCurrency( Common::CurrencyType type, uint32_t amount ) void Player::removeCurrency( Common::CurrencyType type, uint32_t amount )
{ {
auto currItem = m_storageMap[ Currency ]->getItem( static_cast< uint8_t >( type ) - 1 ); auto currItem = m_storageMap[ Currency ]->getItem( static_cast< uint8_t >( type ) - 1 );
@ -373,7 +376,7 @@ void Sapphire::Entity::Player::removeCurrency( Common::CurrencyType type, uint32
} }
void Sapphire::Entity::Player::addCrystal( Common::CrystalType type, uint32_t amount ) void Player::addCrystal( Common::CrystalType type, uint32_t amount )
{ {
auto currItem = m_storageMap[ Crystal ]->getItem( static_cast< uint8_t >( type ) - 1 ); auto currItem = m_storageMap[ Crystal ]->getItem( static_cast< uint8_t >( type ) - 1 );
@ -412,7 +415,7 @@ void Sapphire::Entity::Player::addCrystal( Common::CrystalType type, uint32_t am
server().queueForPlayer( getCharacterId(), makeActorControlSelf( getId(), ItemObtainIcon, static_cast< uint8_t >( type ) + 1, amount ) ); server().queueForPlayer( getCharacterId(), makeActorControlSelf( getId(), ItemObtainIcon, static_cast< uint8_t >( type ) + 1, amount ) );
} }
void Sapphire::Entity::Player::removeCrystal( Common::CrystalType type, uint32_t amount ) void Player::removeCrystal( Common::CrystalType type, uint32_t amount )
{ {
auto currItem = m_storageMap[ Crystal ]->getItem( static_cast< uint8_t >( type ) - 1 ); auto currItem = m_storageMap[ Crystal ]->getItem( static_cast< uint8_t >( type ) - 1 );
@ -446,9 +449,9 @@ void Sapphire::Entity::Player::removeCrystal( Common::CrystalType type, uint32_t
server().queueForPlayer( getCharacterId(), invTransFinPacket ); server().queueForPlayer( getCharacterId(), invTransFinPacket );
} }
void Sapphire::Entity::Player::sendInventory() void Player::sendInventory()
{ {
auto& invMgr = Common::Service< World::Manager::InventoryMgr >::ref(); auto& invMgr = Common::Service< Manager::InventoryMgr >::ref();
for( auto& it : m_storageMap ) for( auto& it : m_storageMap )
{ {
@ -456,14 +459,14 @@ void Sapphire::Entity::Player::sendInventory()
} }
} }
void Sapphire::Entity::Player::sendGearInventory() void Player::sendGearInventory()
{ {
auto& invMgr = Common::Service< World::Manager::InventoryMgr >::ref(); auto& invMgr = Common::Service< Manager::InventoryMgr >::ref();
invMgr.sendInventoryContainer( *this, m_storageMap[ GearSet0 ] ); invMgr.sendInventoryContainer( *this, m_storageMap[ GearSet0 ] );
} }
Sapphire::Entity::Player::InvSlotPairVec Sapphire::Entity::Player::getSlotsOfItemsInInventory( uint32_t catalogId ) Player::InvSlotPairVec Player::getSlotsOfItemsInInventory( uint32_t catalogId )
{ {
InvSlotPairVec outVec; InvSlotPairVec outVec;
for( auto i : { Bag0, Bag1, Bag2, Bag3 } ) for( auto i : { Bag0, Bag1, Bag2, Bag3 } )
@ -478,7 +481,7 @@ Sapphire::Entity::Player::InvSlotPairVec Sapphire::Entity::Player::getSlotsOfIte
return outVec; return outVec;
} }
Sapphire::Entity::Player::InvSlotPair Sapphire::Entity::Player::getFreeBagSlot() Player::InvSlotPair Player::getFreeBagSlot()
{ {
for( auto i : { Bag0, Bag1, Bag2, Bag3 } ) for( auto i : { Bag0, Bag1, Bag2, Bag3 } )
{ {
@ -491,7 +494,7 @@ Sapphire::Entity::Player::InvSlotPair Sapphire::Entity::Player::getFreeBagSlot()
return std::make_pair( 0, -1 ); return std::make_pair( 0, -1 );
} }
Sapphire::Entity::Player::InvSlotPair Sapphire::Entity::Player::getFreeContainerSlot( uint32_t containerId ) Player::InvSlotPair Player::getFreeContainerSlot( uint32_t containerId )
{ {
auto freeSlot = static_cast< int8_t >( m_storageMap[ containerId ]->getFreeSlot() ); auto freeSlot = static_cast< int8_t >( m_storageMap[ containerId ]->getFreeSlot() );
@ -502,13 +505,13 @@ Sapphire::Entity::Player::InvSlotPair Sapphire::Entity::Player::getFreeContainer
return std::make_pair( 0, -1 ); return std::make_pair( 0, -1 );
} }
Sapphire::ItemPtr Sapphire::Entity::Player::getItemAt( uint16_t containerId, uint16_t slotId ) ItemPtr Player::getItemAt( uint16_t containerId, uint16_t slotId )
{ {
return m_storageMap[ containerId ]->getItem( slotId ); return m_storageMap[ containerId ]->getItem( slotId );
} }
uint32_t Sapphire::Entity::Player::getCurrency( CurrencyType type ) uint32_t Player::getCurrency( CurrencyType type )
{ {
auto currItem = m_storageMap[ Currency ]->getItem( static_cast< uint8_t >( type ) - 1 ); auto currItem = m_storageMap[ Currency ]->getItem( static_cast< uint8_t >( type ) - 1 );
@ -520,7 +523,7 @@ uint32_t Sapphire::Entity::Player::getCurrency( CurrencyType type )
} }
uint32_t Sapphire::Entity::Player::getCrystal( CrystalType type ) uint32_t Player::getCrystal( CrystalType type )
{ {
auto currItem = m_storageMap[ Crystal ]->getItem( static_cast< uint8_t >( type ) - 1 ); auto currItem = m_storageMap[ Crystal ]->getItem( static_cast< uint8_t >( type ) - 1 );
@ -532,7 +535,7 @@ uint32_t Sapphire::Entity::Player::getCrystal( CrystalType type )
} }
void Sapphire::Entity::Player::writeInventory( InventoryType type ) void Player::writeInventory( InventoryType type )
{ {
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
@ -561,7 +564,7 @@ void Sapphire::Entity::Player::writeInventory( InventoryType type )
db.execute( query ); db.execute( query );
} }
void Sapphire::Entity::Player::writeItem( Sapphire::ItemPtr pItem ) const void Player::writeItem( ItemPtr pItem ) const
{ {
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
auto stmt = db.getPreparedStatement( Db::CHARA_ITEMGLOBAL_UP ); auto stmt = db.getPreparedStatement( Db::CHARA_ITEMGLOBAL_UP );
@ -577,7 +580,7 @@ void Sapphire::Entity::Player::writeItem( Sapphire::ItemPtr pItem ) const
db.directExecute( stmt ); db.directExecute( stmt );
} }
void Sapphire::Entity::Player::writeCurrencyItem( CurrencyType type ) void Player::writeCurrencyItem( CurrencyType type )
{ {
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
@ -590,7 +593,7 @@ void Sapphire::Entity::Player::writeCurrencyItem( CurrencyType type )
db.execute( query ); db.execute( query );
} }
void Sapphire::Entity::Player::deleteItemDb( Sapphire::ItemPtr item ) const void Player::deleteItemDb( ItemPtr item ) const
{ {
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
auto stmt = db.getPreparedStatement( Db::CHARA_ITEMGLOBAL_DELETE ); auto stmt = db.getPreparedStatement( Db::CHARA_ITEMGLOBAL_DELETE );
@ -601,14 +604,14 @@ void Sapphire::Entity::Player::deleteItemDb( Sapphire::ItemPtr item ) const
} }
bool Sapphire::Entity::Player::isObtainable( uint32_t catalogId, uint8_t quantity ) bool Player::isObtainable( uint32_t catalogId, uint8_t quantity )
{ {
return true; return true;
} }
Sapphire::ItemPtr Sapphire::Entity::Player::addItem( uint32_t catalogId, uint32_t quantity, bool isHq, bool silent, bool canMerge ) ItemPtr Player::addItem( uint32_t catalogId, uint32_t quantity, bool isHq, bool silent, bool canMerge )
{ {
auto& exdData = Common::Service< Data::ExdData >::ref(); auto& exdData = Common::Service< Data::ExdData >::ref();
auto itemInfo = exdData.getRow< Excel::Item >( catalogId ); auto itemInfo = exdData.getRow< Excel::Item >( catalogId );
@ -741,7 +744,7 @@ Sapphire::ItemPtr Sapphire::Entity::Player::addItem( uint32_t catalogId, uint32_
return item; return item;
} }
bool Sapphire::Entity::Player::removeItem( uint32_t catalogId, uint32_t quantity, bool isHq ) bool Player::removeItem( uint32_t catalogId, uint32_t quantity, bool isHq )
{ {
std::vector< uint16_t > bags = { Bag0, Bag1, Bag2, Bag3 }; std::vector< uint16_t > bags = { Bag0, Bag1, Bag2, Bag3 };
@ -790,7 +793,7 @@ bool Sapphire::Entity::Player::removeItem( uint32_t catalogId, uint32_t quantity
} }
void void
Sapphire::Entity::Player::moveItem( uint16_t fromInventoryId, uint16_t fromSlotId, uint16_t toInventoryId, uint16_t toSlot ) Player::moveItem( uint16_t fromInventoryId, uint16_t fromSlotId, uint16_t toInventoryId, uint16_t toSlot )
{ {
auto tmpItem = m_storageMap[ fromInventoryId ]->getItem( fromSlotId ); auto tmpItem = m_storageMap[ fromInventoryId ]->getItem( fromSlotId );
@ -819,9 +822,9 @@ Sapphire::Entity::Player::moveItem( uint16_t fromInventoryId, uint16_t fromSlotI
sendStatusEffectUpdate(); // send if any equip is changed sendStatusEffectUpdate(); // send if any equip is changed
} }
bool Sapphire::Entity::Player::updateContainer( uint16_t storageId, uint16_t slotId, ItemPtr pItem ) bool Player::updateContainer( uint16_t storageId, uint16_t slotId, ItemPtr pItem )
{ {
auto containerType = World::Manager::ItemMgr::getContainerType( storageId ); auto containerType = Manager::ItemMgr::getContainerType( storageId );
auto pOldItem = getItemAt( storageId, slotId ); auto pOldItem = getItemAt( storageId, slotId );
m_storageMap[ storageId ]->setItem( slotId, pItem ); m_storageMap[ storageId ]->setItem( slotId, pItem );
@ -857,8 +860,7 @@ bool Sapphire::Entity::Player::updateContainer( uint16_t storageId, uint16_t slo
return true; return true;
} }
void Sapphire::Entity::Player::splitItem( uint16_t fromInventoryId, uint16_t fromSlotId, void Player::splitItem( uint16_t fromInventoryId, uint16_t fromSlotId, uint16_t toInventoryId, uint16_t toSlot, uint16_t itemCount )
uint16_t toInventoryId, uint16_t toSlot, uint16_t itemCount )
{ {
if( itemCount == 0 ) if( itemCount == 0 )
return; return;
@ -890,8 +892,7 @@ void Sapphire::Entity::Player::splitItem( uint16_t fromInventoryId, uint16_t fro
writeItem( fromItem ); writeItem( fromItem );
} }
void Sapphire::Entity::Player::mergeItem( uint16_t fromInventoryId, uint16_t fromSlotId, void Player::mergeItem( uint16_t fromInventoryId, uint16_t fromSlotId, uint16_t toInventoryId, uint16_t toSlot )
uint16_t toInventoryId, uint16_t toSlot )
{ {
auto fromItem = m_storageMap[ fromInventoryId ]->getItem( fromSlotId ); auto fromItem = m_storageMap[ fromInventoryId ]->getItem( fromSlotId );
auto toItem = m_storageMap[ toInventoryId ]->getItem( toSlot ); auto toItem = m_storageMap[ toInventoryId ]->getItem( toSlot );
@ -925,8 +926,7 @@ void Sapphire::Entity::Player::mergeItem( uint16_t fromInventoryId, uint16_t fro
updateContainer( toInventoryId, toSlot, toItem ); updateContainer( toInventoryId, toSlot, toItem );
} }
void Sapphire::Entity::Player::swapItem( uint16_t fromInventoryId, uint16_t fromSlotId, void Player::swapItem( uint16_t fromInventoryId, uint16_t fromSlotId, uint16_t toInventoryId, uint16_t toSlot )
uint16_t toInventoryId, uint16_t toSlot )
{ {
auto fromItem = m_storageMap[ fromInventoryId ]->getItem( fromSlotId ); auto fromItem = m_storageMap[ fromInventoryId ]->getItem( fromSlotId );
auto toItem = m_storageMap[ toInventoryId ]->getItem( toSlot ); auto toItem = m_storageMap[ toInventoryId ]->getItem( toSlot );
@ -959,7 +959,7 @@ void Sapphire::Entity::Player::swapItem( uint16_t fromInventoryId, uint16_t from
sendStatusEffectUpdate(); // send if any equip is changed sendStatusEffectUpdate(); // send if any equip is changed
} }
void Sapphire::Entity::Player::discardItem( uint16_t fromInventoryId, uint16_t fromSlotId ) void Player::discardItem( uint16_t fromInventoryId, uint16_t fromSlotId )
{ {
// i am not entirely sure how this should be generated or if it even is important for us... // i am not entirely sure how this should be generated or if it even is important for us...
uint32_t sequence = getNextInventorySequence(); uint32_t sequence = getNextInventorySequence();
@ -988,7 +988,7 @@ void Sapphire::Entity::Player::discardItem( uint16_t fromInventoryId, uint16_t f
server().queueForPlayer( getCharacterId(), invTransFinPacket ); server().queueForPlayer( getCharacterId(), invTransFinPacket );
} }
uint16_t Sapphire::Entity::Player::calculateItemLevel() uint16_t Player::calculateItemLevel()
{ {
uint32_t iLvlResult = 0; uint32_t iLvlResult = 0;
@ -1020,7 +1020,7 @@ uint16_t Sapphire::Entity::Player::calculateItemLevel()
return ilvl; return ilvl;
} }
void Sapphire::Entity::Player::calculateBonusStats() void Player::calculateBonusStats()
{ {
m_bonusStats.fill( 0 ); m_bonusStats.fill( 0 );
@ -1052,12 +1052,12 @@ void Sapphire::Entity::Player::calculateBonusStats()
} }
Sapphire::ItemPtr Sapphire::Entity::Player::getEquippedWeapon() ItemPtr Player::getEquippedWeapon()
{ {
return m_storageMap[ GearSet0 ]->getItem( GearSetSlot::MainHand ); return m_storageMap[ GearSet0 ]->getItem( GearSetSlot::MainHand );
} }
uint16_t Sapphire::Entity::Player::getFreeSlotsInBags() uint16_t Player::getFreeSlotsInBags()
{ {
uint16_t slots = 0; uint16_t slots = 0;
for( uint8_t container : { Bag0, Bag1, Bag2, Bag3 } ) for( uint8_t container : { Bag0, Bag1, Bag2, Bag3 } )
@ -1068,7 +1068,7 @@ uint16_t Sapphire::Entity::Player::getFreeSlotsInBags()
return slots; return slots;
} }
bool Sapphire::Entity::Player::collectHandInItems( std::vector< uint32_t > itemIds ) bool Player::collectHandInItems( std::vector< uint32_t > itemIds )
{ {
// todo: figure out how the game gets the required stack count // todo: figure out how the game gets the required stack count
const auto& container = m_storageMap[ HandIn ]; const auto& container = m_storageMap[ HandIn ];
@ -1102,12 +1102,12 @@ bool Sapphire::Entity::Player::collectHandInItems( std::vector< uint32_t > itemI
return true; return true;
} }
uint32_t Sapphire::Entity::Player::getNextInventorySequence() uint32_t Player::getNextInventorySequence()
{ {
return m_inventorySequence++; return m_inventorySequence++;
} }
Sapphire::ItemPtr Sapphire::Entity::Player::dropInventoryItem( Sapphire::Common::InventoryType storageId, uint8_t slotId ) ItemPtr Player::dropInventoryItem( Sapphire::Common::InventoryType storageId, uint8_t slotId )
{ {
auto& container = m_storageMap[ storageId ]; auto& container = m_storageMap[ storageId ];
@ -1141,24 +1141,24 @@ Sapphire::ItemPtr Sapphire::Entity::Player::dropInventoryItem( Sapphire::Common:
return item; return item;
} }
void Sapphire::Entity::Player::addSoldItem( uint32_t itemId, uint8_t stackSize ) void Player::addSoldItem( uint32_t itemId, uint8_t stackSize )
{ {
if( m_soldItems.size() > 10 ) if( m_soldItems.size() > 10 )
m_soldItems.pop_back(); m_soldItems.pop_back();
m_soldItems.emplace_front( itemId, stackSize ); m_soldItems.emplace_front( itemId, stackSize );
} }
std::deque< std::pair< uint32_t, uint8_t > > *Sapphire::Entity::Player::getSoldItems() std::deque< std::pair< uint32_t, uint8_t > >* Player::getSoldItems()
{ {
return &m_soldItems; return &m_soldItems;
} }
void Sapphire::Entity::Player::clearSoldItems() void Player::clearSoldItems()
{ {
m_soldItems.clear(); m_soldItems.clear();
} }
bool Sapphire::Entity::Player::getFreeInventoryContainerSlot( Inventory::InventoryContainerPair& containerPair ) const bool Player::getFreeInventoryContainerSlot( Inventory::InventoryContainerPair& containerPair ) const
{ {
for( auto bagId : { Bag0, Bag1, Bag2, Bag3 } ) for( auto bagId : { Bag0, Bag1, Bag2, Bag3 } )
{ {
@ -1182,8 +1182,7 @@ bool Sapphire::Entity::Player::getFreeInventoryContainerSlot( Inventory::Invento
return false; return false;
} }
void Sapphire::Entity::Player::insertInventoryItem( Sapphire::Common::InventoryType type, uint16_t slot, void Player::insertInventoryItem( Common::InventoryType type, uint16_t slot, const ItemPtr item )
const Sapphire::ItemPtr item )
{ {
updateContainer( type, slot, item ); updateContainer( type, slot, item );
@ -1199,8 +1198,7 @@ void Sapphire::Entity::Player::insertInventoryItem( Sapphire::Common::InventoryT
server().queueForPlayer( getCharacterId(), invTransFinPacket ); server().queueForPlayer( getCharacterId(), invTransFinPacket );
} }
bool Sapphire::Entity::Player::findFirstItemWithId( uint32_t catalogId, bool Player::findFirstItemWithId( uint32_t catalogId, Inventory::InventoryContainerPair& location, std::initializer_list< InventoryType > bags )
Inventory::InventoryContainerPair& location, std::initializer_list< InventoryType > bags )
{ {
for( auto bagId : bags ) for( auto bagId : bags )
{ {

View file

@ -7,16 +7,18 @@
#include "Player.h" #include "Player.h"
using namespace Sapphire;
using namespace Sapphire::Common; using namespace Sapphire::Common;
using namespace Sapphire::Entity;
using namespace Sapphire::World;
using namespace Sapphire::Network::Packets; using namespace Sapphire::Network::Packets;
using namespace Sapphire::Network::Packets::WorldPackets::Server; using namespace Sapphire::Network::Packets::WorldPackets::Server;
void Sapphire::Entity::Player::finishQuest( uint16_t questId, uint32_t optionalChoice ) void Player::finishQuest( uint16_t questId, uint32_t optionalChoice )
{ {
removeQuest( questId ); removeQuest( questId );
auto& questMgr = Common::Service< World::Manager::QuestMgr >::ref(); auto& questMgr = Common::Service< Manager::QuestMgr >::ref();
updateQuestsCompleted( questId ); updateQuestsCompleted( questId );
@ -24,14 +26,14 @@ void Sapphire::Entity::Player::finishQuest( uint16_t questId, uint32_t optionalC
questMgr.onCompleteQuest( *this, questId, optionalChoice ); questMgr.onCompleteQuest( *this, questId, optionalChoice );
} }
void Sapphire::Entity::Player::unfinishQuest( uint16_t questId ) void Player::unfinishQuest( uint16_t questId )
{ {
removeQuestsCompleted( questId ); removeQuestsCompleted( questId );
auto& questMgr = Common::Service< World::Manager::QuestMgr >::ref(); auto& questMgr = Common::Service< Manager::QuestMgr >::ref();
questMgr.sendQuestsInfo( *this ); questMgr.sendQuestsInfo( *this );
} }
void Sapphire::Entity::Player::removeQuest( uint16_t questId ) void Player::removeQuest( uint16_t questId )
{ {
int8_t idx = getQuestIndex( questId ); int8_t idx = getQuestIndex( questId );
@ -41,8 +43,8 @@ void Sapphire::Entity::Player::removeQuest( uint16_t questId )
return; return;
} }
auto& questMgr = Common::Service< World::Manager::QuestMgr >::ref(); auto& questMgr = Common::Service< Manager::QuestMgr >::ref();
auto& mapMgr = Common::Service< World::Manager::MapMgr >::ref(); auto& mapMgr = Common::Service< Manager::MapMgr >::ref();
m_quests[ idx ] = World::Quest(); m_quests[ idx ] = World::Quest();
removeQuestTracking( idx ); removeQuestTracking( idx );
@ -53,7 +55,7 @@ void Sapphire::Entity::Player::removeQuest( uint16_t questId )
} }
void Sapphire::Entity::Player::removeQuestTracking( int8_t idx ) void Player::removeQuestTracking( int8_t idx )
{ {
for( int32_t ii = 0; ii < 5; ii++ ) for( int32_t ii = 0; ii < 5; ii++ )
{ {
@ -62,12 +64,12 @@ void Sapphire::Entity::Player::removeQuestTracking( int8_t idx )
} }
} }
bool Sapphire::Entity::Player::hasQuest( uint32_t questId ) bool Player::hasQuest( uint32_t questId )
{ {
return ( getQuestIndex( static_cast< uint16_t >( questId ) ) > -1 ); return ( getQuestIndex( static_cast< uint16_t >( questId ) ) > -1 );
} }
int8_t Sapphire::Entity::Player::getQuestIndex( uint16_t questId ) int8_t Player::getQuestIndex( uint16_t questId )
{ {
for( size_t pos = 0; pos < 30; ++pos ) for( size_t pos = 0; pos < 30; ++pos )
{ {
@ -77,7 +79,7 @@ int8_t Sapphire::Entity::Player::getQuestIndex( uint16_t questId )
return -1; return -1;
} }
void Sapphire::Entity::Player::updateQuest( const World::Quest& quest ) void Player::updateQuest( const World::Quest& quest )
{ {
auto& questMgr = Common::Service< World::Manager::QuestMgr >::ref(); auto& questMgr = Common::Service< World::Manager::QuestMgr >::ref();
auto& mapMgr = Common::Service< World::Manager::MapMgr >::ref(); auto& mapMgr = Common::Service< World::Manager::MapMgr >::ref();
@ -93,7 +95,7 @@ void Sapphire::Entity::Player::updateQuest( const World::Quest& quest )
addQuest( quest ); addQuest( quest );
} }
bool Sapphire::Entity::Player::addQuest( const World::Quest& quest ) bool Player::addQuest( const World::Quest& quest )
{ {
int8_t idx = getFreeQuestSlot(); int8_t idx = getFreeQuestSlot();
@ -103,8 +105,8 @@ bool Sapphire::Entity::Player::addQuest( const World::Quest& quest )
return false; return false;
} }
auto& questMgr = Common::Service< World::Manager::QuestMgr >::ref(); auto& questMgr = Common::Service< Manager::QuestMgr >::ref();
auto& mapMgr = Common::Service< World::Manager::MapMgr >::ref(); auto& mapMgr = Common::Service< Manager::MapMgr >::ref();
m_quests[ idx ] = quest; m_quests[ idx ] = quest;
@ -117,7 +119,7 @@ bool Sapphire::Entity::Player::addQuest( const World::Quest& quest )
return true; return true;
} }
std::optional< Sapphire::World::Quest > Sapphire::Entity::Player::getQuest( uint32_t questId ) std::optional< World::Quest > Player::getQuest( uint32_t questId )
{ {
if( !hasQuest( questId ) ) if( !hasQuest( questId ) )
return std::nullopt; return std::nullopt;
@ -128,7 +130,7 @@ std::optional< Sapphire::World::Quest > Sapphire::Entity::Player::getQuest( uint
return { quest }; return { quest };
} }
int8_t Sapphire::Entity::Player::getFreeQuestSlot() int8_t Player::getFreeQuestSlot()
{ {
int8_t result = -1; int8_t result = -1;
for( int8_t idx = 0; idx < 30; idx++ ) for( int8_t idx = 0; idx < 30; idx++ )
@ -141,7 +143,7 @@ int8_t Sapphire::Entity::Player::getFreeQuestSlot()
return result; return result;
} }
void Sapphire::Entity::Player::addQuestTracking( uint8_t idx ) void Player::addQuestTracking( uint8_t idx )
{ {
for( int32_t ii = 0; ii < 5; ii++ ) for( int32_t ii = 0; ii < 5; ii++ )
{ {
@ -153,7 +155,7 @@ void Sapphire::Entity::Player::addQuestTracking( uint8_t idx )
} }
} }
void Sapphire::Entity::Player::updateQuestsCompleted( uint32_t questId ) void Player::updateQuestsCompleted( uint32_t questId )
{ {
uint8_t index = questId / 8; uint8_t index = questId / 8;
uint8_t bitIndex = ( questId ) % 8; uint8_t bitIndex = ( questId ) % 8;
@ -163,7 +165,7 @@ void Sapphire::Entity::Player::updateQuestsCompleted( uint32_t questId )
m_questCompleteFlags[ index ] |= value; m_questCompleteFlags[ index ] |= value;
} }
bool Sapphire::Entity::Player::isQuestCompleted( uint32_t questId ) bool Player::isQuestCompleted( uint32_t questId )
{ {
uint8_t index = questId / 8; uint8_t index = questId / 8;
uint8_t bitIndex = ( questId ) % 8; uint8_t bitIndex = ( questId ) % 8;
@ -173,7 +175,7 @@ bool Sapphire::Entity::Player::isQuestCompleted( uint32_t questId )
return m_questCompleteFlags[ index ] & value; return m_questCompleteFlags[ index ] & value;
} }
void Sapphire::Entity::Player::removeQuestsCompleted( uint32_t questId ) void Player::removeQuestsCompleted( uint32_t questId )
{ {
uint8_t index = questId / 8; uint8_t index = questId / 8;
uint8_t bitIndex = ( questId ) % 8; uint8_t bitIndex = ( questId ) % 8;
@ -182,27 +184,27 @@ void Sapphire::Entity::Player::removeQuestsCompleted( uint32_t questId )
m_questCompleteFlags[ index ] ^= value; m_questCompleteFlags[ index ] ^= value;
Common::Service< World::Manager::MapMgr >::ref().updateQuests( *this ); Common::Service< Manager::MapMgr >::ref().updateQuests( *this );
} }
Sapphire::World::Quest& Sapphire::Entity::Player::getQuestByIndex( uint16_t index ) World::Quest& Player::getQuestByIndex( uint16_t index )
{ {
return m_quests[ index ]; return m_quests[ index ];
} }
std::array< Sapphire::World::Quest, 30 >& Sapphire::Entity::Player::getQuestArrayRef() std::array< World::Quest, 30 >& Player::getQuestArrayRef()
{ {
return m_quests; return m_quests;
} }
int16_t Sapphire::Entity::Player::getQuestTracking( uint8_t index ) const int16_t Player::getQuestTracking( uint8_t index ) const
{ {
if( index < 0 || index >= 5 ) if( index < 0 || index >= 5 )
return -1; return -1;
return m_questTracking[ index ]; return m_questTracking[ index ];
} }
Sapphire::Entity::Player::QuestComplete& Sapphire::Entity::Player::getQuestCompleteFlags() Player::QuestComplete& Player::getQuestCompleteFlags()
{ {
return m_questCompleteFlags; return m_questCompleteFlags;
} }

View file

@ -16,12 +16,14 @@
#include "WorldServer.h" #include "WorldServer.h"
using namespace Sapphire;
using namespace Sapphire::Entity;
using namespace Sapphire::Common; using namespace Sapphire::Common;
using namespace Sapphire::Network::Packets; using namespace Sapphire::Network::Packets;
using namespace Sapphire::Network::Packets::WorldPackets::Server; using namespace Sapphire::Network::Packets::WorldPackets::Server;
using namespace Sapphire::World::Manager; using namespace Sapphire::World::Manager;
bool Sapphire::Entity::Player::loadFromDb( uint64_t characterId ) bool Player::loadFromDb( uint64_t characterId )
{ {
m_characterId = characterId; m_characterId = characterId;
@ -181,7 +183,7 @@ bool Sapphire::Entity::Player::loadFromDb( uint64_t characterId )
return true; return true;
} }
bool Sapphire::Entity::Player::loadActiveQuests() bool Player::loadActiveQuests()
{ {
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
auto stmt = db.getPreparedStatement( Db::ZoneDbStatements::CHARA_SEL_QUEST ); auto stmt = db.getPreparedStatement( Db::ZoneDbStatements::CHARA_SEL_QUEST );
@ -194,7 +196,6 @@ bool Sapphire::Entity::Player::loadActiveQuests()
while( res->next() ) while( res->next() )
{ {
auto slotId = res->getUInt8( 2 ); auto slotId = res->getUInt8( 2 );
auto quest = World::Quest( res->getUInt16( 3 ), res->getUInt8( 4 ), res->getUInt8( 5 ) ); auto quest = World::Quest( res->getUInt16( 3 ), res->getUInt8( 4 ), res->getUInt8( 5 ) );
@ -205,14 +206,13 @@ bool Sapphire::Entity::Player::loadActiveQuests()
quest.setUI8E( res->getUInt8( 10 ) ); quest.setUI8E( res->getUInt8( 10 ) );
quest.setUI8F( res->getUInt8( 11 ) ); quest.setUI8F( res->getUInt8( 11 ) );
m_quests[ slotId ] = quest; m_quests[ slotId ] = quest;
} }
return true; return true;
} }
bool Sapphire::Entity::Player::loadAchievements() bool Player::loadAchievements()
{ {
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
auto stmt = db.getPreparedStatement( Db::ZoneDbStatements::CHARA_ACHIEV_SEL ); auto stmt = db.getPreparedStatement( Db::ZoneDbStatements::CHARA_ACHIEV_SEL );
@ -255,7 +255,7 @@ bool Sapphire::Entity::Player::loadAchievements()
return true; return true;
} }
bool Sapphire::Entity::Player::loadClassData() bool Player::loadClassData()
{ {
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
// ClassIdx, Exp, Lvl, BorrowAction // ClassIdx, Exp, Lvl, BorrowAction
@ -278,7 +278,7 @@ bool Sapphire::Entity::Player::loadClassData()
return true; return true;
} }
bool Sapphire::Entity::Player::loadSearchInfo() bool Player::loadSearchInfo()
{ {
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
auto stmt = db.getPreparedStatement( Db::ZoneDbStatements::CHARA_SEL_SEARCHINFO ); auto stmt = db.getPreparedStatement( Db::ZoneDbStatements::CHARA_SEL_SEARCHINFO );
@ -303,7 +303,7 @@ bool Sapphire::Entity::Player::loadSearchInfo()
} }
bool Sapphire::Entity::Player::loadHuntingLog() bool Player::loadHuntingLog()
{ {
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
auto stmt = db.getPreparedStatement( Db::ZoneDbStatements::CHARA_MONSTERNOTE_SEL ); auto stmt = db.getPreparedStatement( Db::ZoneDbStatements::CHARA_MONSTERNOTE_SEL );
@ -326,7 +326,7 @@ bool Sapphire::Entity::Player::loadHuntingLog()
return true; return true;
} }
void Sapphire::Entity::Player::updateSql() void Player::updateSql()
{ {
////// Update player data ////// Update player data
updateDbChara(); updateDbChara();
@ -356,7 +356,7 @@ void Sapphire::Entity::Player::updateSql()
syncLastDBWrite(); syncLastDBWrite();
} }
void Sapphire::Entity::Player::updateDbChara() const void Player::updateDbChara() const
{ {
auto& db = Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
/*"Hp 1, Mp 2, Tp 3, Gp 4, Mode 5, Mount 6, InvincibleGM 7, Voice 8, " /*"Hp 1, Mp 2, Tp 3, Gp 4, Mode 5, Mount 6, InvincibleGM 7, Voice 8, "
@ -484,7 +484,7 @@ void Sapphire::Entity::Player::updateDbChara() const
db.execute( stmt ); db.execute( stmt );
} }
void Sapphire::Entity::Player::updateDbClass() const void Player::updateDbClass() const
{ {
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
auto& exdData = Common::Service< Data::ExdData >::ref(); auto& exdData = Common::Service< Data::ExdData >::ref();
@ -505,7 +505,7 @@ void Sapphire::Entity::Player::updateDbClass() const
db.execute( stmtS ); db.execute( stmtS );
} }
void Sapphire::Entity::Player::updateDbMonsterNote() void Player::updateDbMonsterNote()
{ {
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
// Category_0-11 // Category_0-11
@ -523,7 +523,7 @@ void Sapphire::Entity::Player::updateDbMonsterNote()
db.execute( stmt ); db.execute( stmt );
} }
void Sapphire::Entity::Player::updateDbFriendList() void Player::updateDbFriendList()
{ {
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
@ -541,7 +541,7 @@ void Sapphire::Entity::Player::updateDbFriendList()
} }
void Sapphire::Entity::Player::updateDbBlacklist() void Player::updateDbBlacklist()
{ {
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
@ -555,7 +555,7 @@ void Sapphire::Entity::Player::updateDbBlacklist()
db.execute( stmt ); db.execute( stmt );
} }
void Sapphire::Entity::Player::updateDbAchievement() void Player::updateDbAchievement()
{ {
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
@ -585,7 +585,7 @@ void Sapphire::Entity::Player::updateDbAchievement()
} }
void Sapphire::Entity::Player::insertDbClass( const uint8_t classJobIndex, uint8_t level ) const void Player::insertDbClass( const uint8_t classJobIndex, uint8_t level ) const
{ {
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
auto stmtClass = db.getPreparedStatement( Db::CHARA_CLASS_INS ); auto stmtClass = db.getPreparedStatement( Db::CHARA_CLASS_INS );
@ -600,7 +600,7 @@ void Sapphire::Entity::Player::insertDbClass( const uint8_t classJobIndex, uint8
db.directExecute( stmtClass ); db.directExecute( stmtClass );
} }
void Sapphire::Entity::Player::updateDbSearchInfo() const void Player::updateDbSearchInfo() const
{ {
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
auto stmtS = db.getPreparedStatement( Db::CHARA_SEARCHINFO_UP_SELECTCLASS ); auto stmtS = db.getPreparedStatement( Db::CHARA_SEARCHINFO_UP_SELECTCLASS );
@ -619,7 +619,7 @@ void Sapphire::Entity::Player::updateDbSearchInfo() const
db.execute( stmtS2 ); db.execute( stmtS2 );
} }
void Sapphire::Entity::Player::updateDbAllQuests() const void Player::updateDbAllQuests() const
{ {
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
for( int32_t i = 0; i < 30; i++ ) for( int32_t i = 0; i < 30; i++ )
@ -645,7 +645,7 @@ void Sapphire::Entity::Player::updateDbAllQuests() const
} }
} }
void Sapphire::Entity::Player::deleteDbQuest( uint16_t questId ) const void Player::deleteDbQuest( uint16_t questId ) const
{ {
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
auto stmt = db.getPreparedStatement( Db::CHARA_QUEST_DEL ); auto stmt = db.getPreparedStatement( Db::CHARA_QUEST_DEL );
@ -654,7 +654,7 @@ void Sapphire::Entity::Player::deleteDbQuest( uint16_t questId ) const
db.execute( stmt ); db.execute( stmt );
} }
void Sapphire::Entity::Player::insertDbQuest( uint16_t questId, uint8_t index, uint8_t seq ) const void Player::insertDbQuest( uint16_t questId, uint8_t index, uint8_t seq ) const
{ {
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
auto stmt = db.getPreparedStatement( Db::CHARA_QUEST_INS ); auto stmt = db.getPreparedStatement( Db::CHARA_QUEST_INS );
@ -673,7 +673,7 @@ void Sapphire::Entity::Player::insertDbQuest( uint16_t questId, uint8_t index, u
db.execute( stmt ); db.execute( stmt );
} }
void Sapphire::Entity::Player::insertDbQuest( const World::Quest& quest, uint8_t index ) const void Player::insertDbQuest( const World::Quest& quest, uint8_t index ) const
{ {
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
auto stmt = db.getPreparedStatement( Db::CHARA_QUEST_INS ); auto stmt = db.getPreparedStatement( Db::CHARA_QUEST_INS );
@ -692,7 +692,7 @@ void Sapphire::Entity::Player::insertDbQuest( const World::Quest& quest, uint8_t
db.execute( stmt ); db.execute( stmt );
} }
Sapphire::ItemPtr Sapphire::Entity::Player::createItem( uint32_t catalogId, uint32_t quantity ) ItemPtr Player::createItem( uint32_t catalogId, uint32_t quantity )
{ {
auto& exdData = Common::Service< Data::ExdData >::ref(); auto& exdData = Common::Service< Data::ExdData >::ref();
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
@ -719,7 +719,7 @@ Sapphire::ItemPtr Sapphire::Entity::Player::createItem( uint32_t catalogId, uint
return pItem; return pItem;
} }
bool Sapphire::Entity::Player::loadInventory() bool Player::loadInventory()
{ {
auto& itemMgr = Common::Service< World::Manager::ItemMgr >::ref(); auto& itemMgr = Common::Service< World::Manager::ItemMgr >::ref();
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
@ -818,7 +818,7 @@ bool Sapphire::Entity::Player::loadInventory()
return true; return true;
} }
bool Sapphire::Entity::Player::loadFriendList() bool Player::loadFriendList()
{ {
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
auto stmt = db.getPreparedStatement( Db::ZoneDbStatements::CHARA_FRIENDLIST_SEL ); auto stmt = db.getPreparedStatement( Db::ZoneDbStatements::CHARA_FRIENDLIST_SEL );
@ -843,7 +843,7 @@ bool Sapphire::Entity::Player::loadFriendList()
return true; return true;
} }
bool Sapphire::Entity::Player::loadBlacklist() bool Player::loadBlacklist()
{ {
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
auto stmt = db.getPreparedStatement( Db::ZoneDbStatements::CHARA_BLACKLIST_SEL ); auto stmt = db.getPreparedStatement( Db::ZoneDbStatements::CHARA_BLACKLIST_SEL );
@ -865,7 +865,7 @@ bool Sapphire::Entity::Player::loadBlacklist()
} }
bool Sapphire::Entity::Player::syncLastDBWrite() bool Player::syncLastDBWrite()
{ {
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
auto res = db.query( "SELECT UNIX_TIMESTAMP(UPDATE_DATE) FROM charainfo WHERE characterid = " + std::to_string( m_characterId ) ); auto res = db.query( "SELECT UNIX_TIMESTAMP(UPDATE_DATE) FROM charainfo WHERE characterid = " + std::to_string( m_characterId ) );

View file

@ -8,6 +8,7 @@ file( GLOB SERVER_SOURCE_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
Actor/*.cpp Actor/*.cpp
Action/*.cpp Action/*.cpp
Action/Job/*.cpp Action/Job/*.cpp
AI/*.cpp
ContentFinder/*.cpp ContentFinder/*.cpp
DebugCommand/*.cpp DebugCommand/*.cpp
Event/*.cpp Event/*.cpp

View file

@ -18,13 +18,15 @@
#include <WorldServer.h> #include <WorldServer.h>
using namespace Sapphire;
using namespace Sapphire::World;
using namespace Sapphire::Common; using namespace Sapphire::Common;
using namespace Sapphire::Network::Packets; using namespace Sapphire::Network::Packets;
using namespace Sapphire::Network::Packets::WorldPackets; using namespace Sapphire::Network::Packets::WorldPackets;
using namespace Sapphire::Network::Packets::WorldPackets::Server; using namespace Sapphire::Network::Packets::WorldPackets::Server;
using namespace Sapphire::World::Manager; using namespace Sapphire::World::Manager;
void Sapphire::World::ContentFinder::update() void World::ContentFinder::update()
{ {
auto& exdData = Service< Data::ExdData >::ref(); auto& exdData = Service< Data::ExdData >::ref();
auto& server = Service< WorldServer >::ref(); auto& server = Service< WorldServer >::ref();
@ -114,19 +116,19 @@ void Sapphire::World::ContentFinder::update()
} }
void Sapphire::World::ContentFinder::registerContentsRequest( Sapphire::Entity::Player &player, const std::vector< uint32_t >& contentIds ) void World::ContentFinder::registerContentsRequest( Entity::Player &player, const std::vector< uint32_t >& contentIds )
{ {
queueForContent( player, contentIds ); queueForContent( player, contentIds );
completeRegistration( player ); completeRegistration( player );
} }
void Sapphire::World::ContentFinder::registerContentRequest( Sapphire::Entity::Player &player, uint32_t contentId, uint8_t flags ) void World::ContentFinder::registerContentRequest( Entity::Player &player, uint32_t contentId, uint8_t flags )
{ {
queueForContent( player, { contentId } ); queueForContent( player, { contentId } );
completeRegistration( player, flags ); completeRegistration( player, flags );
} }
void Sapphire::World::ContentFinder::registerRandomContentRequest( Sapphire::Entity::Player &player, uint32_t randomContentTypeId ) void World::ContentFinder::registerRandomContentRequest( Entity::Player &player, uint32_t randomContentTypeId )
{ {
auto& exdData = Service< Data::ExdData >::ref(); auto& exdData = Service< Data::ExdData >::ref();
auto contentListIds = exdData.getIdList< Excel::ContentFinderCondition >(); auto contentListIds = exdData.getIdList< Excel::ContentFinderCondition >();
@ -146,9 +148,8 @@ void Sapphire::World::ContentFinder::registerRandomContentRequest( Sapphire::Ent
completeRegistration( player ); completeRegistration( player );
} }
void Sapphire::World::ContentFinder::completeRegistration( const Sapphire::Entity::Player &player, uint8_t flags ) void World::ContentFinder::completeRegistration( const Entity::Player &player, uint8_t flags )
{ {
auto& server = Service< WorldServer >::ref(); auto& server = Service< WorldServer >::ref();
auto queuedContent = m_queuedContent[ m_queuedPlayer[ player.getId() ]->getActiveRegisterId() ]; auto queuedContent = m_queuedContent[ m_queuedPlayer[ player.getId() ]->getActiveRegisterId() ];
@ -182,7 +183,7 @@ void Sapphire::World::ContentFinder::completeRegistration( const Sapphire::Entit
} }
} }
void Sapphire::World::ContentFinder::queueForContent( Sapphire::Entity::Player &player, const std::vector< uint32_t >& contentIds ) void World::ContentFinder::queueForContent( Entity::Player &player, const std::vector< uint32_t >& contentIds )
{ {
for( auto contentId : contentIds ) for( auto contentId : contentIds )
{ {
@ -215,7 +216,7 @@ void Sapphire::World::ContentFinder::queueForContent( Sapphire::Entity::Player &
} }
} }
void Sapphire::World::QueuedContent::queuePlayer( const std::shared_ptr< QueuedPlayer >& pQPlayer ) void World::QueuedContent::queuePlayer( const std::shared_ptr< QueuedPlayer >& pQPlayer )
{ {
m_players.push_back( pQPlayer ); m_players.push_back( pQPlayer );
m_partyMemberCount++; m_partyMemberCount++;
@ -241,7 +242,7 @@ void Sapphire::World::QueuedContent::queuePlayer( const std::shared_ptr< QueuedP
} }
} }
bool Sapphire::World::QueuedContent::withdrawPlayer( const std::shared_ptr< QueuedPlayer >& pQPlayer ) bool World::QueuedContent::withdrawPlayer( const std::shared_ptr< QueuedPlayer >& pQPlayer )
{ {
auto preSize = m_players.size(); auto preSize = m_players.size();
auto it = m_players.begin(); auto it = m_players.begin();
@ -282,12 +283,12 @@ bool Sapphire::World::QueuedContent::withdrawPlayer( const std::shared_ptr< Queu
return true; return true;
} }
uint32_t Sapphire::World::ContentFinder::getNextRegisterId() uint32_t World::ContentFinder::getNextRegisterId()
{ {
return ++m_nextRegisterId; return ++m_nextRegisterId;
} }
Sapphire::World::ContentFinder::QueuedContentPtrList Sapphire::World::ContentFinder::getMatchingContentList( Sapphire::Entity::Player &player, uint32_t contentFinderId ) World::ContentFinder::QueuedContentPtrList World::ContentFinder::getMatchingContentList( Entity::Player &player, uint32_t contentFinderId )
{ {
QueuedContentPtrList outVec; QueuedContentPtrList outVec;
for( auto& it : m_queuedContent ) for( auto& it : m_queuedContent )
@ -361,7 +362,7 @@ Sapphire::World::ContentFinder::QueuedContentPtrList Sapphire::World::ContentFin
return outVec; return outVec;
} }
void Sapphire::World::ContentFinder::accept( Entity::Player& player ) void World::ContentFinder::accept( Entity::Player& player )
{ {
auto& server = Service< WorldServer >::ref(); auto& server = Service< WorldServer >::ref();
auto& exdData = Service< Data::ExdData >::ref(); auto& exdData = Service< Data::ExdData >::ref();
@ -408,7 +409,7 @@ void Sapphire::World::ContentFinder::accept( Entity::Player& player )
queuedContent->setState( Accepted ); queuedContent->setState( Accepted );
} }
void Sapphire::World::ContentFinder::withdraw( Entity::Player& player ) void World::ContentFinder::withdraw( Entity::Player& player )
{ {
auto& server = Service< WorldServer >::ref(); auto& server = Service< WorldServer >::ref();
auto& exdData = Service< Data::ExdData >::ref(); auto& exdData = Service< Data::ExdData >::ref();
@ -471,7 +472,7 @@ void Sapphire::World::ContentFinder::withdraw( Entity::Player& player )
} }
std::shared_ptr< Sapphire::World::QueuedContent > Sapphire::World::ContentFinder::findContentByRegisterId( uint32_t registerId ) std::shared_ptr< World::QueuedContent > World::ContentFinder::findContentByRegisterId( uint32_t registerId )
{ {
auto it = m_queuedContent.find( registerId ); auto it = m_queuedContent.find( registerId );
if( it != m_queuedContent.end() ) if( it != m_queuedContent.end() )
@ -479,7 +480,7 @@ std::shared_ptr< Sapphire::World::QueuedContent > Sapphire::World::ContentFinder
return nullptr; return nullptr;
} }
bool Sapphire::World::ContentFinder::removeContentByRegisterId( uint32_t registerId ) bool World::ContentFinder::removeContentByRegisterId( uint32_t registerId )
{ {
auto it = m_queuedContent.find( registerId ); auto it = m_queuedContent.find( registerId );
if( it == m_queuedContent.end() ) if( it == m_queuedContent.end() )
@ -490,21 +491,21 @@ bool Sapphire::World::ContentFinder::removeContentByRegisterId( uint32_t registe
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
uint32_t Sapphire::World::QueuedContent::getInstanceId() const uint32_t World::QueuedContent::getInstanceId() const
{ {
return m_contentFinderId; return m_contentFinderId;
} }
uint32_t Sapphire::World::QueuedContent::getRegisterId() const uint32_t World::QueuedContent::getRegisterId() const
{ {
return m_registerId; return m_registerId;
} }
Sapphire::World::QueuedContent::QueuedContent( uint32_t registerId, uint32_t contentId ) : World::QueuedContent::QueuedContent( uint32_t registerId, uint32_t contentId ) :
m_registerId( registerId ), m_registerId( registerId ),
m_contentFinderId( contentId ), m_contentFinderId( contentId ),
m_state( QueuedContentState::MatchingInProgress ), m_state( QueuedContentState::MatchingInProgress ),
m_contentPopTime( 0 ) m_contentPopTime( 0 )
{ {
// auto& exdData = Common::Service< Data::ExdData >::ref(); // auto& exdData = Common::Service< Data::ExdData >::ref();
// auto content = exdData.getRow< Excel::InstanceContent >( contentId ); // auto content = exdData.getRow< Excel::InstanceContent >( contentId );
@ -512,7 +513,7 @@ Sapphire::World::QueuedContent::QueuedContent( uint32_t registerId, uint32_t con
} }
uint8_t Sapphire::World::QueuedContent::getRoleCount( Sapphire::Common::Role role ) const uint8_t World::QueuedContent::getRoleCount( Common::Role role ) const
{ {
switch( role ) switch( role )
{ {
@ -533,12 +534,12 @@ uint8_t Sapphire::World::QueuedContent::getRoleCount( Sapphire::Common::Role rol
return 0; return 0;
} }
Sapphire::World::QueuedContentState Sapphire::World::QueuedContent::getState() const World::QueuedContentState World::QueuedContent::getState() const
{ {
return m_state; return m_state;
} }
void Sapphire::World::QueuedContent::setState( Sapphire::World::QueuedContentState state ) void World::QueuedContent::setState( World::QueuedContentState state )
{ {
m_state = state; m_state = state;
} }
@ -546,7 +547,7 @@ void Sapphire::World::QueuedContent::setState( Sapphire::World::QueuedContentSta
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
Sapphire::World::QueuedPlayer::QueuedPlayer( const Entity::Player &player, uint8_t registerId ) World::QueuedPlayer::QueuedPlayer( const Entity::Player &player, uint8_t registerId )
{ {
m_characterId = player.getCharacterId(); m_characterId = player.getCharacterId();
m_classJob = static_cast< uint32_t >( player.getClass() ); m_classJob = static_cast< uint32_t >( player.getClass() );
@ -556,27 +557,27 @@ Sapphire::World::QueuedPlayer::QueuedPlayer( const Entity::Player &player, uint8
m_entityId = player.getId(); m_entityId = player.getId();
} }
Sapphire::Common::Role Sapphire::World::QueuedPlayer::getRole() const Common::Role World::QueuedPlayer::getRole() const
{ {
return m_role; return m_role;
} }
void Sapphire::World::QueuedPlayer::setActiveRegisterId( uint8_t registerId ) void World::QueuedPlayer::setActiveRegisterId( uint8_t registerId )
{ {
m_activeRegisterId = registerId; m_activeRegisterId = registerId;
} }
uint8_t Sapphire::World::QueuedPlayer::getActiveRegisterId() const uint8_t World::QueuedPlayer::getActiveRegisterId() const
{ {
return m_activeRegisterId; return m_activeRegisterId;
} }
uint64_t Sapphire::World::QueuedPlayer::getCharacterId() const uint64_t World::QueuedPlayer::getCharacterId() const
{ {
return m_characterId; return m_characterId;
} }
uint32_t Sapphire::World::QueuedPlayer::getEntityId() const uint32_t World::QueuedPlayer::getEntityId() const
{ {
return m_entityId; return m_entityId;
} }

View file

@ -5,17 +5,19 @@
#include <Network/PacketWrappers/EventLogMessagePacket.h> #include <Network/PacketWrappers/EventLogMessagePacket.h>
#include <Network/PacketDef/Zone/ServerZoneDef.h> #include <Network/PacketDef/Zone/ServerZoneDef.h>
#include <Network/CommonActorControl.h> #include <Network/CommonActorControl.h>
#include "Network/PacketWrappers/ActorControlPacket.h"
#include "Network/PacketWrappers/ActorControlSelfPacket.h"
#include "Network/GameConnection.h"
#include "Network/Util/PacketUtil.h"
#include "Actor/Player.h" #include "Actor/Player.h"
#include "Network/PacketWrappers/ActorControlPacket.h"
#include "Network/PacketWrappers/ActorControlSelfPacket.h"
#include <Logging/Logger.h> #include <Logging/Logger.h>
#include <Service.h> #include <Service.h>
#include "WorldServer.h" #include "WorldServer.h"
#include "Session.h" #include "Session.h"
#include "Network/GameConnection.h"
using namespace Sapphire::Common; using namespace Sapphire::Common;
using namespace Sapphire::Network::Packets; using namespace Sapphire::Network::Packets;
@ -83,8 +85,7 @@ void Sapphire::Event::Director::sendEventLogMessage( Sapphire::Entity::Player& p
void Sapphire::Event::Director::sendDirectorClear( Sapphire::Entity::Player& player ) const void Sapphire::Event::Director::sendDirectorClear( Sapphire::Entity::Player& player ) const
{ {
auto& server = Common::Service< World::WorldServer >::ref(); Network::Util::Packet::sendActorControlSelf( player, player.getId(), DirectorClear, m_directorId );
server.queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), DirectorClear, m_directorId ) );
} }
void Sapphire::Event::Director::sendDirectorVars( Sapphire::Entity::Player& player ) const void Sapphire::Event::Director::sendDirectorVars( Sapphire::Entity::Player& player ) const
@ -102,8 +103,7 @@ void Sapphire::Event::Director::sendDirectorVars( Sapphire::Entity::Player& play
void Sapphire::Event::Director::sendDirectorInit( Sapphire::Entity::Player& player ) const void Sapphire::Event::Director::sendDirectorInit( Sapphire::Entity::Player& player ) const
{ {
Logger::debug( "[{}] directorInit: directorId#{}, contextId#{}", player.getId(), m_directorId, m_contextId ); Logger::debug( "[{}] directorInit: directorId#{}, contextId#{}", player.getId(), m_directorId, m_contextId );
auto& server = Common::Service< World::WorldServer >::ref(); Network::Util::Packet::sendActorControlSelf( player, player.getId(), DirectorInit, m_directorId, m_contextId );
server.queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), DirectorInit, m_directorId, m_contextId ) );
} }
Sapphire::Event::Director::DirectorType Sapphire::Event::Director::getType() const Sapphire::Event::Director::DirectorType Sapphire::Event::Director::getType() const

View file

@ -2,8 +2,9 @@
#include <utility> #include <utility>
Sapphire::Event::EventHandler::EventHandler( uint64_t actorId, uint32_t eventId, using namespace Sapphire;
EventType eventType, uint32_t eventParam ) :
Event::EventHandler::EventHandler( uint64_t actorId, uint32_t eventId, EventType eventType, uint32_t eventParam ) :
m_actorId( actorId ), m_actorId( actorId ),
m_eventId( eventId ), m_eventId( eventId ),
m_eventType( eventType ), m_eventType( eventType ),
@ -15,107 +16,107 @@ Sapphire::Event::EventHandler::EventHandler( uint64_t actorId, uint32_t eventId,
m_returnCallback = nullptr; m_returnCallback = nullptr;
} }
uint64_t Sapphire::Event::EventHandler::getActorId() const uint64_t Event::EventHandler::getActorId() const
{ {
return m_actorId; return m_actorId;
} }
uint32_t Sapphire::Event::EventHandler::getId() const uint32_t Event::EventHandler::getId() const
{ {
return m_eventId; return m_eventId;
} }
uint8_t Sapphire::Event::EventHandler::getEventType() const uint8_t Event::EventHandler::getEventType() const
{ {
return m_eventType; return m_eventType;
} }
uint16_t Sapphire::Event::EventHandler::getType() const uint16_t Event::EventHandler::getType() const
{ {
return m_type; return m_type;
} }
uint16_t Sapphire::Event::EventHandler::getEntryId() const uint16_t Event::EventHandler::getEntryId() const
{ {
return m_entryId; return m_entryId;
} }
uint32_t Sapphire::Event::EventHandler::getEventParam() const uint32_t Event::EventHandler::getEventParam() const
{ {
return m_eventParam; return m_eventParam;
} }
Sapphire::Event::EventHandler::SceneReturnCallback Sapphire::Event::EventHandler::getEventReturnCallback() const Event::EventHandler::SceneReturnCallback Event::EventHandler::getEventReturnCallback() const
{ {
return m_returnCallback; return m_returnCallback;
} }
void Sapphire::Event::EventHandler::setEventReturnCallback( SceneReturnCallback callback ) void Event::EventHandler::setEventReturnCallback( SceneReturnCallback callback )
{ {
m_returnCallback = std::move( callback ); m_returnCallback = std::move( callback );
} }
Sapphire::Event::EventHandler::QuestSceneReturnCallback Sapphire::Event::EventHandler::getQuestEventReturnCallback() const Event::EventHandler::QuestSceneReturnCallback Event::EventHandler::getQuestEventReturnCallback() const
{ {
return m_questReturnCallback; return m_questReturnCallback;
} }
void Sapphire::Event::EventHandler::setQuestEventReturnCallback( QuestSceneReturnCallback callback ) void Event::EventHandler::setQuestEventReturnCallback( QuestSceneReturnCallback callback )
{ {
m_questReturnCallback = std::move( callback ); m_questReturnCallback = std::move( callback );
} }
Sapphire::Event::EventHandler::SceneChainCallback Sapphire::Event::EventHandler::getSceneChainCallback() const Event::EventHandler::SceneChainCallback Event::EventHandler::getSceneChainCallback() const
{ {
return m_chainCallback; return m_chainCallback;
} }
void Sapphire::Event::EventHandler::setSceneChainCallback( Sapphire::Event::EventHandler::SceneChainCallback callback ) void Event::EventHandler::setSceneChainCallback( Event::EventHandler::SceneChainCallback callback )
{ {
m_chainCallback = std::move( callback ); m_chainCallback = std::move( callback );
} }
Sapphire::Event::EventHandler::QuestSceneChainCallback Sapphire::Event::EventHandler::getQuestSceneChainCallback() const Event::EventHandler::QuestSceneChainCallback Event::EventHandler::getQuestSceneChainCallback() const
{ {
return m_questChainCallback; return m_questChainCallback;
} }
void Sapphire::Event::EventHandler::setQuestSceneChainCallback( Sapphire::Event::EventHandler::QuestSceneChainCallback callback ) void Event::EventHandler::setQuestSceneChainCallback( Event::EventHandler::QuestSceneChainCallback callback )
{ {
m_questChainCallback = std::move( callback ); m_questChainCallback = std::move( callback );
} }
Sapphire::Event::EventHandler::EventFinishCallback Sapphire::Event::EventHandler::getEventFinishCallback() const Event::EventHandler::EventFinishCallback Event::EventHandler::getEventFinishCallback() const
{ {
return m_finishCallback; return m_finishCallback;
} }
void Sapphire::Event::EventHandler::setEventFinishCallback( EventFinishCallback callback ) void Event::EventHandler::setEventFinishCallback( EventFinishCallback callback )
{ {
m_finishCallback = std::move( callback ); m_finishCallback = std::move( callback );
} }
bool Sapphire::Event::EventHandler::hasPlayedScene() const bool Event::EventHandler::hasPlayedScene() const
{ {
return m_playedScene; return m_playedScene;
} }
void Sapphire::Event::EventHandler::setPlayedScene( bool playedScene ) void Event::EventHandler::setPlayedScene( bool playedScene )
{ {
m_playedScene = playedScene; m_playedScene = playedScene;
} }
bool Sapphire::Event::EventHandler::hasNestedEvent() const bool Event::EventHandler::hasNestedEvent() const
{ {
return m_pNestedEvent != nullptr; return m_pNestedEvent != nullptr;
} }
void Sapphire::Event::EventHandler::removeNestedEvent() void Event::EventHandler::removeNestedEvent()
{ {
m_pNestedEvent.reset(); m_pNestedEvent.reset();
} }
Sapphire::Event::ScenePlayParam *Sapphire::Event::EventHandler::getScenePlayParams() Event::ScenePlayParam* Event::EventHandler::getScenePlayParams()
{ {
return &m_scenePlayParams; return &m_scenePlayParams;
} }

View file

@ -47,6 +47,12 @@ namespace World::Territory::Housing
TYPE_FORWARD( HousingInteriorTerritory ); TYPE_FORWARD( HousingInteriorTerritory );
} }
namespace World::AI
{
TYPE_FORWARD( GambitTargetCondition );
TYPE_FORWARD( GambitRule );
}
namespace Inventory namespace Inventory
{ {
using InventoryContainerPair = std::pair< Common::InventoryType, uint8_t >; using InventoryContainerPair = std::pair< Common::InventoryType, uint8_t >;
@ -88,8 +94,8 @@ TYPE_FORWARD( ItemAction );
TYPE_FORWARD( EventItemAction ); TYPE_FORWARD( EventItemAction );
TYPE_FORWARD( MountAction ); TYPE_FORWARD( MountAction );
TYPE_FORWARD( ItemManipulationAction ); TYPE_FORWARD( ItemManipulationAction );
TYPE_FORWARD( EffectBuilder ); TYPE_FORWARD( ActionResultBuilder );
TYPE_FORWARD( EffectResult ); TYPE_FORWARD( ActionResult );
using ActionCallback = std::function< void( Entity::Player&, uint32_t, uint64_t ) >; using ActionCallback = std::function< void( Entity::Player&, uint32_t, uint64_t ) >;
} }

View file

@ -2,7 +2,9 @@
#include <utility> #include <utility>
Sapphire::FreeCompany::FreeCompany( uint64_t id, std::string name, std::string tag, uint64_t masterId, uint64_t chatChannelId ) : using namespace Sapphire;
FreeCompany::FreeCompany( uint64_t id, std::string name, std::string tag, uint64_t masterId, uint64_t chatChannelId ) :
m_id( id ), m_id( id ),
m_name( std::move( name ) ), m_name( std::move( name ) ),
m_tag( std::move( tag ) ), m_tag( std::move( tag ) ),
@ -12,211 +14,211 @@ Sapphire::FreeCompany::FreeCompany( uint64_t id, std::string name, std::string t
} }
uint64_t Sapphire::FreeCompany::getId() const uint64_t FreeCompany::getId() const
{ {
return m_id; return m_id;
} }
const std::string& Sapphire::FreeCompany::getName() const const std::string& FreeCompany::getName() const
{ {
return m_name; return m_name;
} }
void Sapphire::FreeCompany::setName( std::string name ) void FreeCompany::setName( std::string name )
{ {
m_name = std::move( name ); m_name = std::move( name );
} }
const std::string& Sapphire::FreeCompany::getTag() const const std::string& FreeCompany::getTag() const
{ {
return m_tag; return m_tag;
} }
void Sapphire::FreeCompany::setTag( std::string tag ) void FreeCompany::setTag( std::string tag )
{ {
m_tag = std::move( tag ); m_tag = std::move( tag );
} }
uint64_t Sapphire::FreeCompany::getMasterId() const uint64_t FreeCompany::getMasterId() const
{ {
return m_masterCharacterId; return m_masterCharacterId;
} }
void Sapphire::FreeCompany::setMasterId( uint64_t masterId ) void FreeCompany::setMasterId( uint64_t masterId )
{ {
m_masterCharacterId = masterId; m_masterCharacterId = masterId;
} }
uint64_t Sapphire::FreeCompany::getCredit() const uint64_t FreeCompany::getCredit() const
{ {
return m_credit; return m_credit;
} }
void Sapphire::FreeCompany::setCredit( uint64_t credit ) void FreeCompany::setCredit( uint64_t credit )
{ {
m_credit = credit; m_credit = credit;
} }
uint64_t Sapphire::FreeCompany::getCreditAccumulated() const uint64_t FreeCompany::getCreditAccumulated() const
{ {
return m_creditAccumulated; return m_creditAccumulated;
} }
void Sapphire::FreeCompany::setCreditAccumulated( uint64_t credit ) void FreeCompany::setCreditAccumulated( uint64_t credit )
{ {
m_creditAccumulated = credit; m_creditAccumulated = credit;
} }
uint8_t Sapphire::FreeCompany::getRank() const uint8_t FreeCompany::getRank() const
{ {
return m_rank; return m_rank;
} }
void Sapphire::FreeCompany::setRank( uint8_t rank ) void FreeCompany::setRank( uint8_t rank )
{ {
m_rank = rank; m_rank = rank;
} }
uint64_t Sapphire::FreeCompany::getPoints() const uint64_t FreeCompany::getPoints() const
{ {
return m_points; return m_points;
} }
void Sapphire::FreeCompany::setPoints( uint64_t points ) void FreeCompany::setPoints( uint64_t points )
{ {
m_points = points; m_points = points;
} }
uint64_t Sapphire::FreeCompany::getCrest() const uint64_t FreeCompany::getCrest() const
{ {
return m_crest; return m_crest;
} }
void Sapphire::FreeCompany::setCrest( uint64_t crest ) void FreeCompany::setCrest( uint64_t crest )
{ {
m_crest = crest; m_crest = crest;
} }
uint32_t Sapphire::FreeCompany::getCreateDate() const uint32_t FreeCompany::getCreateDate() const
{ {
return m_createDate; return m_createDate;
} }
void Sapphire::FreeCompany::setCreateDate( uint32_t createDate ) void FreeCompany::setCreateDate( uint32_t createDate )
{ {
m_createDate = createDate; m_createDate = createDate;
} }
uint8_t Sapphire::FreeCompany::getGrandCompany() const uint8_t FreeCompany::getGrandCompany() const
{ {
return m_gc; return m_gc;
} }
void Sapphire::FreeCompany::setGrandCompany( uint8_t gcIndex ) void FreeCompany::setGrandCompany( uint8_t gcIndex )
{ {
if( gcIndex > 2 ) if( gcIndex > 2 )
return; return;
m_gc = gcIndex; m_gc = gcIndex;
} }
uint64_t Sapphire::FreeCompany::getGcReputation( uint8_t gcIndex ) const uint64_t FreeCompany::getGcReputation( uint8_t gcIndex ) const
{ {
if( gcIndex > 2 ) if( gcIndex > 2 )
return 0; return 0;
return m_gcReputation[ gcIndex ]; return m_gcReputation[ gcIndex ];
} }
void Sapphire::FreeCompany::setGcReputation( uint8_t gcIndex, uint64_t reputation ) void FreeCompany::setGcReputation( uint8_t gcIndex, uint64_t reputation )
{ {
if( gcIndex > 2 ) if( gcIndex > 2 )
return; return;
m_gcReputation[ gcIndex ] = reputation; m_gcReputation[ gcIndex ] = reputation;
} }
Sapphire::Common::FreeCompanyStatus Sapphire::FreeCompany::getFcStatus() const Common::FreeCompanyStatus FreeCompany::getFcStatus() const
{ {
return m_status; return m_status;
} }
void Sapphire::FreeCompany::setFcStatus( Sapphire::Common::FreeCompanyStatus status ) void FreeCompany::setFcStatus( Common::FreeCompanyStatus status )
{ {
m_status = status; m_status = status;
} }
const std::string& Sapphire::FreeCompany::getFcBoard() const const std::string& FreeCompany::getFcBoard() const
{ {
return m_fcBoard; return m_fcBoard;
} }
void Sapphire::FreeCompany::setFcBoard( const std::string& board ) void FreeCompany::setFcBoard( const std::string& board )
{ {
m_fcBoard = board; m_fcBoard = board;
} }
const std::string& Sapphire::FreeCompany::getFcMotto() const const std::string& FreeCompany::getFcMotto() const
{ {
return m_fcMotto; return m_fcMotto;
} }
void Sapphire::FreeCompany::setFcMotto( const std::string& motto ) void FreeCompany::setFcMotto( const std::string& motto )
{ {
m_fcMotto = motto; m_fcMotto = motto;
} }
uint32_t Sapphire::FreeCompany::getFcVersion() const uint32_t FreeCompany::getFcVersion() const
{ {
return m_fcVersion; return m_fcVersion;
} }
void Sapphire::FreeCompany::setFcVersion( uint32_t version ) void FreeCompany::setFcVersion( uint32_t version )
{ {
m_fcVersion = version; m_fcVersion = version;
} }
const std::array< uint64_t, 3 >& Sapphire::FreeCompany::getActiveActionIdArr() const const std::array< uint64_t, 3 >& FreeCompany::getActiveActionIdArr() const
{ {
return m_activeActionId; return m_activeActionId;
} }
const std::array< uint64_t, 3 >& Sapphire::FreeCompany::getActiveActionTimeLeftArr() const const std::array< uint64_t, 3 >& FreeCompany::getActiveActionTimeLeftArr() const
{ {
return m_activeActionTimeLeft; return m_activeActionTimeLeft;
} }
const std::array< uint64_t, 15 >& Sapphire::FreeCompany::getActionStockArr() const const std::array< uint64_t, 15 >& FreeCompany::getActionStockArr() const
{ {
return m_actionStock; return m_actionStock;
} }
uint64_t Sapphire::FreeCompany::getChatChannel() const uint64_t FreeCompany::getChatChannel() const
{ {
return m_chatChannelId; return m_chatChannelId;
} }
const std::set< uint64_t >& Sapphire::FreeCompany::getMemberIdList() const const std::set< uint64_t >& FreeCompany::getMemberIdList() const
{ {
return m_memberIds; return m_memberIds;
} }
std::set< uint64_t >& Sapphire::FreeCompany::getMemberIdList() std::set< uint64_t >& FreeCompany::getMemberIdList()
{ {
return m_memberIds; return m_memberIds;
} }
void Sapphire::FreeCompany::addMember( uint64_t memberId, uint8_t hierarchyId, uint32_t lastLogout ) void FreeCompany::addMember( uint64_t memberId, uint8_t hierarchyId, uint32_t lastLogout )
{ {
FcMember member{ memberId, hierarchyId, lastLogout }; FcMember member{ memberId, hierarchyId, lastLogout };
m_memberDetails[ memberId ] = member; m_memberDetails[ memberId ] = member;
m_memberIds.insert( memberId ); m_memberIds.insert( memberId );
} }
void Sapphire::FreeCompany::removeMember( uint64_t memberId ) void FreeCompany::removeMember( uint64_t memberId )
{ {
m_memberDetails.erase( memberId ); m_memberDetails.erase( memberId );
m_memberIds.erase( memberId ); m_memberIds.erase( memberId );
} }
void Sapphire::FreeCompany::setChatChannel( uint64_t chatChannelId ) void FreeCompany::setChatChannel( uint64_t chatChannelId )
{ {
m_chatChannelId = chatChannelId; m_chatChannelId = chatChannelId;
} }

View file

@ -2,7 +2,7 @@
#include <Util/Util.h> #include <Util/Util.h>
#include "AchievementMgr.h" #include "AchievementMgr.h"
#include <Network/Util/PlayerUtil.h> #include <Network/Util/PacketUtil.h>
#include <Network/CommonActorControl.h> #include <Network/CommonActorControl.h>
using namespace Sapphire; using namespace Sapphire;
@ -69,9 +69,9 @@ void AchievementMgr::unlockAchievement( Entity::Player& player, uint32_t achieve
// fire packets // fire packets
player.setAchievementData( achvData ); player.setAchievementData( achvData );
Network::Util::Player::sendAchievementList( player ); Network::Util::Packet::sendAchievementList( player );
Network::Util::Player::sendActorControl( player, AchievementComplete, achievementId ); Network::Util::Packet::sendActorControl( player, player.getId(), AchievementComplete, achievementId );
Network::Util::Player::sendActorControl( player, AchievementObtainMsg, achievementId ); Network::Util::Packet::sendActorControl( player, player.getId(), AchievementObtainMsg, achievementId );
// check and add title to player // check and add title to player
auto achvTitleId = achvExd->data().Title; auto achvTitleId = achvExd->data().Title;

View file

@ -59,19 +59,18 @@ void ActionMgr::handleItemManipulationAction( Entity::Player& player, uint32_t a
action->start(); action->start();
} }
void ActionMgr::handleTargetedPlayerAction( Entity::Player& player, uint32_t actionId, void ActionMgr::handleTargetedAction( Entity::Chara& src, uint32_t actionId,
Excel::ExcelStructPtr< Excel::Action > actionData, uint64_t targetId, uint16_t requestId ) Excel::ExcelStructPtr< Excel::Action > actionData, uint64_t targetId, uint16_t requestId )
{ {
auto action = Action::make_Action( player.getAsPlayer(), actionId, requestId, actionData ); auto action = Action::make_Action( src.getAsChara(), actionId, requestId, actionData );
action->setTargetId( targetId ); action->setTargetId( targetId );
action->setPos( src.getPos() );
action->setPos( player.getPos() );
if( !action->init() ) if( !action->init() )
return; return;
bootstrapAction( player, action, actionData ); bootstrapAction( src, action, actionData );
} }
void ActionMgr::handleItemAction( Sapphire::Entity::Player& player, uint32_t itemId, void ActionMgr::handleItemAction( Sapphire::Entity::Player& player, uint32_t itemId,
@ -118,7 +117,7 @@ void ActionMgr::handleMountAction( Entity::Player& player, uint16_t mountId,
bootstrapAction( player, action, actionData ); bootstrapAction( player, action, actionData );
} }
void ActionMgr::bootstrapAction( Entity::Player& player, Action::ActionPtr currentAction, void ActionMgr::bootstrapAction( Entity::Chara& src, Action::ActionPtr currentAction,
Excel::ExcelStructPtr< Excel::Action > actionData ) Excel::ExcelStructPtr< Excel::Action > actionData )
{ {
/* /*
@ -131,22 +130,25 @@ void ActionMgr::bootstrapAction( Entity::Player& player, Action::ActionPtr curre
} }
*/ */
if( player.getCurrentAction() ) if( src.getCurrentAction() )
{ {
PlayerMgr::sendDebug( player, "Skill queued: {0}", currentAction->getId() ); if( src.isPlayer() )
player.setQueuedAction( currentAction ); {
auto& player = *src.getAsPlayer();
PlayerMgr::sendDebug( player, "Skill queued: {0}", currentAction->getId() );
player.setQueuedAction( currentAction );
}
} }
else else
{ {
// if we have a cast time we want to associate the action with the player so update is called // if we have a cast time we want to associate the action with the player so update is called
if( currentAction->hasCastTime() ) if( currentAction->hasCastTime() )
{ src.setCurrentAction( currentAction );
player.setCurrentAction( currentAction );
}
// todo: what do in cases of swiftcast/etc? script callback? // todo: what do in cases of swiftcast/etc? script callback?
currentAction->start(); currentAction->start();
player.setLastAttack( Common::Util::getTimeMs() ); src.setLastAttack( Common::Util::getTimeMs() );
} }
} }

View file

@ -24,8 +24,8 @@ namespace Sapphire::World::Manager
void handleItemManipulationAction( Entity::Player& player, uint32_t actionId, Excel::ExcelStructPtr< Excel::Action > actionData, uint16_t sequence ); void handleItemManipulationAction( Entity::Player& player, uint32_t actionId, Excel::ExcelStructPtr< Excel::Action > actionData, uint16_t sequence );
void handleTargetedPlayerAction( Entity::Player& player, uint32_t actionId, void handleTargetedAction( Entity::Chara& chara, uint32_t actionId,
std::shared_ptr< Excel::ExcelStruct< Excel::Action > > actionData, uint64_t targetId, uint16_t requestId ); std::shared_ptr< Excel::ExcelStruct< Excel::Action > > actionData, uint64_t targetId, uint16_t requestId );
void handlePlacedPlayerAction( Entity::Player& player, uint32_t actionId, void handlePlacedPlayerAction( Entity::Player& player, uint32_t actionId,
std::shared_ptr< Excel::ExcelStruct< Excel::Action > > actionData, Common::FFXIVARR_POSITION3 pos, uint16_t sequence ); std::shared_ptr< Excel::ExcelStruct< Excel::Action > > actionData, Common::FFXIVARR_POSITION3 pos, uint16_t sequence );
@ -40,7 +40,7 @@ namespace Sapphire::World::Manager
bool actionHasCastTime( uint32_t actionId ); bool actionHasCastTime( uint32_t actionId );
private: private:
void bootstrapAction( Entity::Player& player, Action::ActionPtr currentAction, std::shared_ptr< Excel::ExcelStruct< Excel::Action > > actionData ); void bootstrapAction( Entity::Chara& src, Action::ActionPtr currentAction, std::shared_ptr< Excel::ExcelStruct< Excel::Action > > actionData );
// item action handlers // item action handlers
void handleItemActionVFX( Entity::Player& player, uint32_t itemId, uint16_t vfxId ); void handleItemActionVFX( Entity::Player& player, uint32_t itemId, uint16_t vfxId );

View file

@ -529,9 +529,8 @@ void DebugCommandMgr::add( char* data, Entity::Player& player, std::shared_ptr<
uint16_t param1; uint16_t param1;
sscanf( params.c_str(), "%hu", &param1 ); sscanf( params.c_str(), "%hu", &param1 );
auto effectPacket = std::make_shared< EffectPacket >( player.getId(), param1 ); auto effectPacket = std::make_shared< EffectPacket >( player.getId(), static_cast< uint32_t >( player.getTargetId() ), param1 );
effectPacket->setRotation( Common::Util::floatToUInt16Rot( player.getRot() ) ); effectPacket->setRotation( Common::Util::floatToUInt16Rot( player.getRot() ) );
effectPacket->setTargetActor( static_cast< uint32_t >( player.getTargetId() ) );
Common::CalcResultParam entry{}; Common::CalcResultParam entry{};
entry.Value = static_cast< int16_t >( param1 ); entry.Value = static_cast< int16_t >( param1 );
@ -539,7 +538,7 @@ void DebugCommandMgr::add( char* data, Entity::Player& player, std::shared_ptr<
entry.Arg0 = static_cast< uint8_t >( Common::ActionHitSeverityType::NormalDamage ); entry.Arg0 = static_cast< uint8_t >( Common::ActionHitSeverityType::NormalDamage );
effectPacket->addTargetEffect( entry, static_cast< uint64_t >( player.getId() ) ); effectPacket->addTargetEffect( entry, static_cast< uint64_t >( player.getId() ) );
effectPacket->setResultId( pCurrentZone->getNextEffectResultId() ); effectPacket->setResultId( pCurrentZone->getNextActionResultId() );
server().queueForPlayer( player.getCharacterId(), effectPacket ); server().queueForPlayer( player.getCharacterId(), effectPacket );
} }

View file

@ -8,6 +8,7 @@
#include <Network/PacketWrappers/ActorControlSelfPacket.h> #include <Network/PacketWrappers/ActorControlSelfPacket.h>
#include <Network/CommonActorControl.h> #include <Network/CommonActorControl.h>
#include <Network/GameConnection.h> #include <Network/GameConnection.h>
#include <Network/Util/PacketUtil.h>
#include <unordered_map> #include <unordered_map>
#include <cstring> #include <cstring>
@ -288,7 +289,6 @@ uint32_t HousingMgr::toLandSetId( int16_t territoryTypeId, int16_t wardId ) cons
return ( static_cast< uint32_t >( territoryTypeId ) << 16 ) | wardId; return ( static_cast< uint32_t >( territoryTypeId ) << 16 ) | wardId;
} }
LandPtr HousingMgr::getLandByOwnerId( uint64_t id ) LandPtr HousingMgr::getLandByOwnerId( uint64_t id )
{ {
@ -404,7 +404,7 @@ LandPurchaseResult HousingMgr::purchaseLand( Entity::Player& player, HousingZone
pLand->setStatus( Common::HouseStatus::Sold ); pLand->setStatus( Common::HouseStatus::Sold );
pLand->setLandType( Common::LandType::Private ); pLand->setLandType( Common::LandType::Private );
player.setLandFlags( Common::LandFlagsSlot::Private, 0x00, pLand->getLandIdent() ); player.setLandFlags( Common::LandFlagsSlot::Private, 0, pLand->getLandIdent() );
sendLandFlagsSlot( player, Common::LandFlagsSlot::Private ); sendLandFlagsSlot( player, Common::LandFlagsSlot::Private );
@ -432,10 +432,9 @@ bool HousingMgr::relinquishLand( Entity::Player& player, HousingZone& zone, uint
// can't relinquish when you are not the owner // can't relinquish when you are not the owner
// TODO: actually use permissions here for FC houses // TODO: actually use permissions here for FC houses
if( !hasPermission( player, *pLand, 0 ) ) if( !pLand || !hasPermission( player, *pLand, 0 ) )
{ {
auto msgPkt = makeActorControlSelf( player.getId(), ActorControl::LogMsg, 3304, 0 ); Network::Util::Packet::sendActorControlSelf( player, player.getId(), ActorControl::LogMsg, 3304 );
server.queueForPlayer( player.getCharacterId(), msgPkt );
return false; return false;
} }
@ -443,8 +442,7 @@ bool HousingMgr::relinquishLand( Entity::Player& player, HousingZone& zone, uint
// TODO: additionally check for yard items // TODO: additionally check for yard items
if( pLand->getHouse() ) if( pLand->getHouse() )
{ {
auto msgPkt = makeActorControlSelf( player.getId(), ActorControl::LogMsg, 3315, 0 ); Network::Util::Packet::sendActorControlSelf( player, player.getId(), ActorControl::LogMsg, 3315 );
server.queueForPlayer( player.getCharacterId(), msgPkt );
return false; return false;
} }
@ -456,15 +454,12 @@ bool HousingMgr::relinquishLand( Entity::Player& player, HousingZone& zone, uint
Common::LandIdent ident { 0xFF, 0xFF, 0xFF, 0xFF }; Common::LandIdent ident { 0xFF, 0xFF, 0xFF, 0xFF };
player.setLandFlags( Common::LandFlagsSlot::Private, 0x00, ident ); player.setLandFlags( Common::LandFlagsSlot::Private, 0, ident );
sendLandFlagsSlot( player, Common::LandFlagsSlot::Private ); sendLandFlagsSlot( player, Common::LandFlagsSlot::Private );
auto screenMsgPkt2 = makeActorControlSelf( player.getId(), ActorControl::LogMsg, 3351, 0x1AA, Network::Util::Packet::sendActorControlSelf( player, player.getId(), ActorControl::LogMsg, 3351, 0x1AA, pLand->getLandIdent().wardNum + 1, plot + 1 );
pLand->getLandIdent().wardNum + 1, plot + 1 );
server.queueForPlayer( player.getCharacterId(), screenMsgPkt2 );
zone.sendLandUpdate( plot ); zone.sendLandUpdate( plot );
return true; return true;
} }
@ -680,10 +675,7 @@ void HousingMgr::buildPresetEstate( Entity::Player& player, HousingZone& zone, u
auto& server = Common::Service< World::WorldServer >::ref(); auto& server = Common::Service< World::WorldServer >::ref();
auto pLand = zone.getLand( plotNum ); auto pLand = zone.getLand( plotNum );
if( !pLand ) if( !pLand || !hasPermission( player, *pLand, 0 ) )
return;
if( !hasPermission( player, *pLand, 0 ) )
return; return;
// create house // create house
@ -708,9 +700,7 @@ void HousingMgr::buildPresetEstate( Entity::Player& player, HousingZone& zone, u
pLand->setLandType( Common::LandType::Private ); pLand->setLandType( Common::LandType::Private );
zone.sendLandUpdate( plotNum ); zone.sendLandUpdate( plotNum );
auto pSuccessBuildingPacket = makeActorControl( player.getId(), ActorControl::BuildPresetResponse, plotNum ); Network::Util::Packet::sendActorControl( player, player.getId(), ActorControl::BuildPresetResponse, plotNum );
server.queueForPlayer( player.getCharacterId(), pSuccessBuildingPacket );
pLand->updateLandDb(); pLand->updateLandDb();
@ -790,10 +780,7 @@ void HousingMgr::updateEstateGreeting( Entity::Player& player, const Common::Lan
return; return;
auto land = hZone->getLand( static_cast< uint8_t >( ident.landId ) ); auto land = hZone->getLand( static_cast< uint8_t >( ident.landId ) );
if( !land ) if( !land || !hasPermission( player, *land, 0 ) )
return;
if( !hasPermission( player, *land, 0 ) )
return; return;
auto house = land->getHouse(); auto house = land->getHouse();
@ -819,10 +806,7 @@ void HousingMgr::requestEstateEditGuestAccess( Entity::Player& player, const Com
return; return;
auto land = hZone->getLand( ident.landId ); auto land = hZone->getLand( ident.landId );
if( !land ) if( !land || !hasPermission( player, *land, 0 ) )
return;
if( !hasPermission( player, *land, 0 ) )
return; return;
auto packet = makeZonePacket< FFXIVIpcHousingWelcome >( player.getId() ); auto packet = makeZonePacket< FFXIVIpcHousingWelcome >( player.getId() );
@ -886,10 +870,7 @@ void HousingMgr::sendEstateInventory( Entity::Player& player, uint16_t inventory
targetLand = zone->getLand( plotNum ); targetLand = zone->getLand( plotNum );
} }
if( !targetLand ) if( !targetLand || !hasPermission( player, *targetLand, 0 ) )
return;
if( !hasPermission( player, *targetLand, 0 ) )
return; return;
auto& containers = getEstateInventory( targetLand->getLandIdent() ); auto& containers = getEstateInventory( targetLand->getLandIdent() );
@ -1024,10 +1005,7 @@ void HousingMgr::reqPlaceHousingItem( Entity::Player& player, uint16_t landId, u
else else
return; return;
if( !land ) if( !land || !hasPermission( player, *land, 0 ) )
return;
if( !hasPermission( player, *land, 0 ) )
return; return;
// todo: check item position and make sure it's not outside the plot // todo: check item position and make sure it's not outside the plot
@ -1065,7 +1043,7 @@ void HousingMgr::reqPlaceHousingItem( Entity::Player& player, uint16_t landId, u
status = placeInteriorItem( player, item ); status = placeInteriorItem( player, item );
if( status ) if( status )
server.queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), 0x3f3 ) ); Network::Util::Packet::sendActorControlSelf( player, player.getId(), 0x3f3 );
else else
PlayerMgr::sendUrgent( player, "An internal error occurred when placing the item." ); PlayerMgr::sendUrgent( player, "An internal error occurred when placing the item." );
} }
@ -1281,10 +1259,7 @@ void HousingMgr::reqMoveHousingItem( Entity::Player& player, Common::LandIdent i
auto hZone = std::dynamic_pointer_cast< HousingZone >( pTeri ); auto hZone = std::dynamic_pointer_cast< HousingZone >( pTeri );
auto land = hZone->getLand( static_cast< uint8_t >( ident.landId ) ); auto land = hZone->getLand( static_cast< uint8_t >( ident.landId ) );
if( !land ) if( !land || !hasPermission( player, *land, 0 ) )
return;
if( !hasPermission( player, *land, 0 ) )
return; return;
auto pZone = teriMgr.getTerritoryByGuId( player.getTerritoryId() ); auto pZone = teriMgr.getTerritoryByGuId( player.getTerritoryId() );
@ -1343,7 +1318,7 @@ bool HousingMgr::moveInternalItem( Entity::Player& player, Common::LandIdent ide
// send confirmation to player // send confirmation to player
uint32_t param1 = static_cast< uint32_t >( ( ident.landId << 16 ) | containerId ); uint32_t param1 = static_cast< uint32_t >( ( ident.landId << 16 ) | containerId );
server.queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), ActorControl::HousingItemMoveConfirm, param1, slotIdx ) ); Network::Util::Packet::sendActorControlSelf( player, player.getId(), ActorControl::HousingItemMoveConfirm, param1, slotIdx );
return true; return true;
} }
@ -1353,8 +1328,7 @@ bool HousingMgr::moveExternalItem( Entity::Player& player, Common::LandIdent ide
auto& server = Common::Service< World::WorldServer >::ref(); auto& server = Common::Service< World::WorldServer >::ref();
auto land = terri.getLand( static_cast< uint8_t >( ident.landId ) ); auto land = terri.getLand( static_cast< uint8_t >( ident.landId ) );
if( !land || !hasPermission( player, *land, 0 ) )
if( !hasPermission( player, *land, 0 ) )
return false; return false;
auto& containers = getEstateInventory( ident ); auto& containers = getEstateInventory( ident );
@ -1377,7 +1351,7 @@ bool HousingMgr::moveExternalItem( Entity::Player& player, Common::LandIdent ide
terri.updateYardObjectPos( player, slot, static_cast< uint16_t >( ident.landId ), *item ); terri.updateYardObjectPos( player, slot, static_cast< uint16_t >( ident.landId ), *item );
uint32_t param1 = static_cast< uint32_t >( ( ident.landId << 16 ) | Common::InventoryType::HousingExteriorPlacedItems ); uint32_t param1 = static_cast< uint32_t >( ( ident.landId << 16 ) | Common::InventoryType::HousingExteriorPlacedItems );
server.queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), ActorControl::HousingItemMoveConfirm, param1, slot ) ); Network::Util::Packet::sendActorControlSelf( player, player.getId(), ActorControl::HousingItemMoveConfirm, param1, slot );
return true; return true;
} }
@ -1396,11 +1370,7 @@ void HousingMgr::reqRemoveHousingItem( Entity::Player& player, uint16_t plot, ui
auto hZone = std::dynamic_pointer_cast< HousingZone >( pTeri ); auto hZone = std::dynamic_pointer_cast< HousingZone >( pTeri );
auto land = hZone->getLand( static_cast< uint8_t >( ident.landId ) ); auto land = hZone->getLand( static_cast< uint8_t >( ident.landId ) );
if( !land || !hasPermission( player, *land, 0 ) )
if( !land )
return;
if( !hasPermission( player, *land, 0 ) )
return; return;
removeInternalItem( player, *terri, containerId, slot, sendToStoreroom ); removeInternalItem( player, *terri, containerId, slot, sendToStoreroom );
@ -1408,10 +1378,7 @@ void HousingMgr::reqRemoveHousingItem( Entity::Player& player, uint16_t plot, ui
else if( auto terri = std::dynamic_pointer_cast< HousingZone >( pZone ) ) else if( auto terri = std::dynamic_pointer_cast< HousingZone >( pZone ) )
{ {
auto land = terri->getLand( static_cast< uint8_t >( plot ) ); auto land = terri->getLand( static_cast< uint8_t >( plot ) );
if( !land ) if( !land || !hasPermission( player, *land, 0 ) )
return;
if( !hasPermission( player, *land, 0 ) )
return; return;
auto containerType = static_cast< Common::InventoryType >( containerId ); auto containerType = static_cast< Common::InventoryType >( containerId );
@ -1614,9 +1581,7 @@ void HousingMgr::reqEstateExteriorRemodel( Entity::Player& player, uint16_t plot
invMgr.sendInventoryContainer( player, it->second ); invMgr.sendInventoryContainer( player, it->second );
auto pkt = makeActorControlSelf( player.getId(), Network::ActorControl::ShowEstateExternalAppearanceUI, plot ); Network::Util::Packet::sendActorControlSelf( player, player.getId(), ActorControl::ShowEstateExternalAppearanceUI, plot );
server.queueForPlayer( player.getCharacterId(), pkt );
} }
void HousingMgr::reqEstateInteriorRemodel( Entity::Player& player ) void HousingMgr::reqEstateInteriorRemodel( Entity::Player& player )
@ -1653,8 +1618,7 @@ void HousingMgr::reqEstateInteriorRemodel( Entity::Player& player )
invMgr.sendInventoryContainer( player, it->second ); invMgr.sendInventoryContainer( player, it->second );
auto pkt = makeActorControlSelf( player.getId(), Network::ActorControl::ShowEstateInternalAppearanceUI ); Network::Util::Packet::sendActorControlSelf( player, player.getId(), ActorControl::ShowEstateInternalAppearanceUI );
server.queueForPlayer( player.getCharacterId(), pkt );
} }
bool HousingMgr::hasPermission( Entity::Player& player, Sapphire::Land& land, uint32_t permission ) bool HousingMgr::hasPermission( Entity::Player& player, Sapphire::Land& land, uint32_t permission )
@ -1697,8 +1661,7 @@ void HousingMgr::removeHouse( Entity::Player& player, uint16_t plot )
// TODO: actually use permissions here for FC houses // TODO: actually use permissions here for FC houses
if( !hasPermission( player, *pLand, 0 ) ) if( !hasPermission( player, *pLand, 0 ) )
{ {
auto msgPkt = makeActorControlSelf( player.getId(), ActorControl::LogMsg, 3305, 0 ); Network::Util::Packet::sendActorControlSelf( player, player.getId(), ActorControl::LogMsg, 3305 );
server.queueForPlayer( player.getCharacterId(), msgPkt );
return; return;
} }

View file

@ -200,7 +200,7 @@ void PartyMgr::onMemberDisconnect( Entity::Player& disconnectingPlayer )
{ {
// TODO: 2nd argument here makes it automatically send passing leadership message // TODO: 2nd argument here makes it automatically send passing leadership message
server.queueForPlayer( member->getCharacterId(), { makePcPartyUpdate( disconnectingPlayer, UpdateStatus::OFFLINE_MEMBER, party->PartyCount ), server.queueForPlayer( member->getCharacterId(), { makePcPartyUpdate( disconnectingPlayer, UpdateStatus::OFFLINE_MEMBER, party->PartyCount ),
makeZonePacket< FFXIVIpcUpdateParty >( member->getId() ) } ); makeZonePacket< FFXIVIpcUpdateParty >( member->getId() ) } );
} }
sendPartyUpdate( *party ); sendPartyUpdate( *party );

View file

@ -7,8 +7,6 @@
#include <Territory/Land.h> #include <Territory/Land.h>
#include <Manager/TerritoryMgr.h> #include <Manager/TerritoryMgr.h>
#include <Manager/AchievementMgr.h>
#include <Manager/PartyMgr.h>
#include <Manager/HousingMgr.h> #include <Manager/HousingMgr.h>
#include <Manager/QuestMgr.h> #include <Manager/QuestMgr.h>
@ -18,18 +16,8 @@
#include <Database/ZoneDbConnection.h> #include <Database/ZoneDbConnection.h>
#include <Database/DbWorkerPool.h> #include <Database/DbWorkerPool.h>
#include <Network/GameConnection.h>
#include <Network/CommonActorControl.h> #include <Network/CommonActorControl.h>
#include <Network/PacketDef/Zone/ServerZoneDef.h> #include <Network/Util/PacketUtil.h>
#include <Network/PacketWrappers/ActorControlPacket.h>
#include <Network/PacketWrappers/ActorControlSelfPacket.h>
#include <Network/PacketWrappers/ActorControlTargetPacket.h>
#include <Network/PacketWrappers/InitZonePacket.h>
#include <Network/PacketWrappers/PlayerSetupPacket.h>
#include <Network/PacketWrappers/ServerNoticePacket.h>
#include <Network/PacketWrappers/ChatPacket.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>
@ -218,9 +206,7 @@ void PlayerMgr::onMobKill( Entity::Player& player, Entity::BNpc& bnpc )
scriptMgr.onBNpcKill( player, bnpc ); scriptMgr.onBNpcKill( player, bnpc );
if( player.hasReward( Common::UnlockEntry::HuntingLog ) ) if( player.hasReward( Common::UnlockEntry::HuntingLog ) )
{
player.updateHuntingLog( bnpc.getBNpcNameId() ); player.updateHuntingLog( bnpc.getBNpcNameId() );
}
} }
void PlayerMgr::sendLoginMessage( Entity::Player& player ) void PlayerMgr::sendLoginMessage( Entity::Player& player )
@ -262,48 +248,48 @@ void PlayerMgr::onMoveZone( Sapphire::Entity::Player& player )
} }
auto& teri = *pZone; auto& teri = *pZone;
Network::Util::Player::sendLogin( player ); Network::Util::Packet::sendLogin( player );
player.sendInventory(); player.sendInventory();
if( player.isLogin() ) if( player.isLogin() )
{ {
Network::Util::Player::sendActorControlSelf( player, SetConfigFlags, player.getConfigFlags(), 1 ); Network::Util::Packet::sendActorControlSelf( player, player.getId(), SetConfigFlags, player.getConfigFlags(), 1 );
Network::Util::Player::sendActorControlSelf( player, SetMaxGearSets, player.getMaxGearSets() ); Network::Util::Packet::sendActorControlSelf( player, player.getId(), SetMaxGearSets, player.getMaxGearSets() );
} }
// set flags, will be reset automatically by zoning ( only on client side though ) // set flags, will be reset automatically by zoning ( only on client side though )
//setStateFlag( PlayerStateFlag::BetweenAreas ); //setStateFlag( PlayerStateFlag::BetweenAreas );
//setStateFlag( PlayerStateFlag::BetweenAreas1 ); //setStateFlag( PlayerStateFlag::BetweenAreas1 );
Network::Util::Player::sendHuntingLog( player ); Network::Util::Packet::sendHuntingLog( player );
if( player.isLogin() ) if( player.isLogin() )
Network::Util::Player::sendPlayerSetup( player ); Network::Util::Packet::sendPlayerSetup( player );
Network::Util::Player::sendRecastGroups( player ); Network::Util::Packet::sendRecastGroups( player );
Network::Util::Player::sendBaseParams( player ); Network::Util::Packet::sendBaseParams( player );
Network::Util::Player::sendActorControl( player, SetItemLevel, player.getItemLevel() ); Network::Util::Packet::sendActorControl( player, player.getId(), SetItemLevel, player.getItemLevel() );
if( player.isLogin() ) if( player.isLogin() )
{ {
Network::Util::Player::sendChangeClass( player ); Network::Util::Packet::sendChangeClass( player );
Network::Util::Player::sendActorControl( player, 0x112, 0x24 ); // unknown Network::Util::Packet::sendActorControl( player, player.getId(), 0x112, 0x24 ); // unknown
Network::Util::Player::sendContentAttainFlags( player ); Network::Util::Packet::sendContentAttainFlags( player );
player.clearSoldItems(); player.clearSoldItems();
} }
housingMgr.sendLandFlags( player ); housingMgr.sendLandFlags( player );
Network::Util::Player::sendInitZone( player ); Network::Util::Packet::sendInitZone( player );
if( player.isLogin() ) if( player.isLogin() )
{ {
Network::Util::Player::sendDailyQuests( player ); Network::Util::Packet::sendDailyQuests( player );
Network::Util::Player::sendQuestRepeatFlags( player ); Network::Util::Packet::sendQuestRepeatFlags( player );
auto &questMgr = Common::Service< World::Manager::QuestMgr >::ref(); auto &questMgr = Common::Service< World::Manager::QuestMgr >::ref();
questMgr.sendQuestsInfo( player ); questMgr.sendQuestsInfo( player );
Network::Util::Player::sendGrandCompany( player ); Network::Util::Packet::sendGrandCompany( player );
} }
teri.onPlayerZoneIn( player ); teri.onPlayerZoneIn( player );
@ -321,35 +307,38 @@ void PlayerMgr::onUpdate( Entity::Player& player, uint64_t tickCount )
if( !player.isAlive() ) if( !player.isAlive() )
return; return;
auto mainWeap = player.getItemAt( Common::GearSet0, Common::GearSetSlot::MainHand ); checkAutoAttack( player, tickCount );
if( mainWeap && !player.checkAction() && ( player.getTargetId() && player.getStance() == Common::Stance::Active && player.isAutoattackOn() ) ) }
void PlayerMgr::checkAutoAttack( Entity::Player& player, uint64_t tickCount ) const
{
auto mainWeap = player.getItemAt( Common::GearSet0, Common::MainHand );
if( !mainWeap || !player.isAutoattackOn() || player.checkAction() || !player.getTargetId() || player.getStance() != Common::Active )
return;
for( const auto& actor : player.getInRangeActors() )
{ {
// @TODO i dislike this, iterating over all in range actors when you already know the id of the actor you need... if( actor->getId() != player.getTargetId() || !actor->getAsChara()->isAlive() )
for( const auto& actor : player.getInRangeActors() ) continue;
auto chara = actor->getAsChara();
// default autoattack range
float range = 3.f + chara->getRadius() + player.getRadius() * 0.5f;
// default autoattack range for ranged classes
auto classJob = player.getClass();
if( classJob == Common::ClassJob::Machinist || classJob == Common::ClassJob::Bard || classJob == Common::ClassJob::Archer )
range = 25.f + chara->getRadius() + player.getRadius() * 0.5f;
if( ( Common::Util::distance( player.getPos(), actor->getPos() ) <= range ) &&
( ( tickCount - player.getLastAttack() ) > mainWeap->getDelay() ) )
{ {
if( actor->getId() != player.getTargetId() || !actor->getAsChara()->isAlive() ) player.setLastAttack( tickCount );
continue; player.autoAttack( actor->getAsChara() );
auto chara = actor->getAsChara();
// default autoattack range
float range = 3.f + chara->getRadius() + player.getRadius() * 0.5f;
// default autoattack range for ranged classes
auto classJob = player.getClass();
if( classJob == Common::ClassJob::Machinist || classJob == Common::ClassJob::Bard || classJob == Common::ClassJob::Archer )
range = 25.f + chara->getRadius() + player.getRadius() * 0.5f;
if( Common::Util::distance( player.getPos(), actor->getPos() ) <= range )
{
if( ( tickCount - player.getLastAttack() ) > mainWeap->getDelay() )
{
player.setLastAttack( tickCount );
player.autoAttack( actor->getAsChara() );
}
}
} }
} }
} }
@ -357,22 +346,21 @@ void PlayerMgr::onUpdate( Entity::Player& player, uint64_t tickCount )
void PlayerMgr::sendServerNotice( Entity::Player& player, const std::string& message ) //Purple Text void PlayerMgr::sendServerNotice( Entity::Player& player, const std::string& message ) //Purple Text
{ {
server().queueForPlayer( player.getCharacterId(), std::make_shared< ServerNoticePacket >( player.getId(), message ) ); Network::Util::Packet::sendServerNotice( player, message );
} }
void PlayerMgr::sendUrgent( Entity::Player& player, const std::string& message ) //Red Text void PlayerMgr::sendUrgent( Entity::Player& player, const std::string& message ) //Red Text
{ {
server().queueForPlayer( player.getCharacterId(), std::make_shared< ChatPacket >( player, Common::ChatType::ServerUrgent, message ) ); Network::Util::Packet::sendChat( player, Common::ChatType::ServerUrgent, message );
} }
void PlayerMgr::sendDebug( Entity::Player& player, const std::string& message ) //Grey Text void PlayerMgr::sendDebug( Entity::Player& player, const std::string& message ) //Grey Text
{ {
server().queueForPlayer( player.getCharacterId(), std::make_shared< ChatPacket >( player, Common::ChatType::SystemMessage, message ) ); Network::Util::Packet::sendChat( player, Common::ChatType::SystemMessage, message );
} }
void PlayerMgr::sendLogMessage( Entity::Player& player, uint32_t messageId, uint32_t param2, uint32_t param3, void PlayerMgr::sendLogMessage( Entity::Player& player, uint32_t messageId, uint32_t param2, uint32_t param3,
uint32_t param4, uint32_t param5, uint32_t param6 ) uint32_t param4, uint32_t param5, uint32_t param6 )
{ {
server().queueForPlayer( player.getCharacterId(), makeActorControlTarget( player.getId(), ActorControlType::LogMsg, messageId, Network::Util::Packet::sendActorControlTarget( player, player.getId(), LogMsg, messageId, param2, param3, param4, param5, param6 );
param2, param3, param4, param5, param6 ) );
} }

View file

@ -65,6 +65,8 @@ namespace Sapphire::World::Manager
std::map< uint32_t, Entity::PlayerPtr > m_playerMapById; std::map< uint32_t, Entity::PlayerPtr > m_playerMapById;
std::map< uint64_t, Entity::PlayerPtr > m_playerMapByCharacterId; std::map< uint64_t, Entity::PlayerPtr > m_playerMapByCharacterId;
std::map< std::string, Entity::PlayerPtr > m_playerMapByName; std::map< std::string, Entity::PlayerPtr > m_playerMapByName;
void checkAutoAttack( Entity::Player& player, uint64_t tickCount ) const;
}; };

View file

@ -9,27 +9,32 @@ using namespace Sapphire::World;
void TaskMgr::update( uint64_t tickCount ) void TaskMgr::update( uint64_t tickCount )
{ {
std::vector< TaskPtr > tmpTaskList;
for( auto it = m_taskList.begin(); it != m_taskList.end(); ) for( const auto& pTask : m_taskList )
{ {
auto pTask = *it;
// is the task ready for execution? // is the task ready for execution?
if( ( tickCount - pTask->getQueueTimeMs() ) >= pTask->getDelayTimeMs() ) if( ( tickCount - pTask->getQueueTimeMs() ) >= pTask->getDelayTimeMs() )
{ {
Logger::info( "[TaskMgr] " + pTask->toString() ); Logger::info( "[TaskMgr] " + pTask->toString() );
pTask->execute(); pTask->execute();
it = m_taskList.erase( it );
} }
else else
++it; tmpTaskList.push_back( pTask );
} }
m_taskList = tmpTaskList;
m_lastTick = tickCount; m_lastTick = tickCount;
while( !m_deferredTasks.empty() )
{
auto pTask = m_deferredTasks.front();
m_deferredTasks.pop();
m_taskList.push_back( pTask );
}
} }
void TaskMgr::queueTask( const TaskPtr& pTask ) void TaskMgr::queueTask( const TaskPtr& pTask )
{ {
pTask->onQueue(); pTask->onQueue();
m_taskList.push_back( pTask ); m_deferredTasks.push( pTask );
} }

View file

@ -2,6 +2,7 @@
#include <cstdint> #include <cstdint>
#include <string> #include <string>
#include <queue>
#include <ForwardsZone.h> #include <ForwardsZone.h>
#include <Util/Util.h> #include <Util/Util.h>
@ -45,6 +46,7 @@ namespace Sapphire::World::Manager
private: private:
uint64_t m_lastTick{}; uint64_t m_lastTick{};
std::vector< TaskPtr > m_taskList; std::vector< TaskPtr > m_taskList;
std::queue< TaskPtr > m_deferredTasks;
}; };

View file

@ -14,6 +14,7 @@
#include <Network/CommonActorControl.h> #include <Network/CommonActorControl.h>
#include <Network/PacketWrappers/ActorControlSelfPacket.h> #include <Network/PacketWrappers/ActorControlSelfPacket.h>
#include <Network/PacketWrappers/ActorControlPacket.h> #include <Network/PacketWrappers/ActorControlPacket.h>
#include <Network/Util/PacketUtil.h>
#include <Manager/PlayerMgr.h> #include <Manager/PlayerMgr.h>
#include <Manager/MapMgr.h> #include <Manager/MapMgr.h>
@ -90,10 +91,8 @@ void WarpMgr::requestWarp( Entity::Player& player, Common::WarpType warpType, Co
{ {
m_entityIdToWarpInfoMap[ player.getId() ] = { 0, warpType, targetPos, targetRot }; m_entityIdToWarpInfoMap[ player.getId() ] = { 0, warpType, targetPos, targetRot };
server().queueForPlayers( player.getInRangePlayerIds( true ), Network::Util::Packet::sendActorControlSelf( player.getInRangePlayerIds( true ), player.getId(), WarpStart, warpType, warpType, 0, player.getTerritoryTypeId(), 1 );
makeActorControlSelf( player.getId(), WarpStart, warpType, warpType, 0, player.getTerritoryTypeId(), 1 ) ); Network::Util::Packet::sendActorControl( player.getInRangePlayerIds(), player.getId(), ActorDespawnEffect, warpType, player.getTerritoryTypeId() );
server().queueForPlayers( player.getInRangePlayerIds(),
makeActorControl( player.getId(), ActorDespawnEffect, warpType, player.getTerritoryTypeId() ) );
auto& taskMgr = Common::Service< TaskMgr >::ref(); auto& taskMgr = Common::Service< TaskMgr >::ref();
taskMgr.queueTask( makeWarpTask( player, warpType, targetPos, targetRot, 1000 ) ); taskMgr.queueTask( makeWarpTask( player, warpType, targetPos, targetRot, 1000 ) );
@ -127,14 +126,11 @@ void WarpMgr::finishWarp( Entity::Player& player )
auto warpFinishAnim = warpType - 1; auto warpFinishAnim = warpType - 1;
auto zoneInPacket = makeActorControlSelf( player.getId(), Appear, warpFinishAnim, raiseAnim, 0, 0 );
auto setStatusPacket = makeActorControl( player.getId(), SetStatus, static_cast< uint8_t >( Common::ActorStatus::Idle ) );
if( !player.getGmInvis() ) if( !player.getGmInvis() )
server().queueForPlayers( player.getInRangePlayerIds(), zoneInPacket ); Network::Util::Packet::sendActorControlSelf( player.getInRangePlayerIds(), player.getId(), Appear, warpFinishAnim, raiseAnim );
server().queueForPlayer( player.getCharacterId(), zoneInPacket ); Network::Util::Packet::sendActorControlSelf( player, player.getId(), Appear, warpFinishAnim, raiseAnim );
server().queueForPlayers( player.getInRangePlayerIds( true ), setStatusPacket ); Network::Util::Packet::sendActorControl( player.getInRangePlayerIds( true ), player.getId(), SetStatus, static_cast< uint8_t >( Common::ActorStatus::Idle ) );
player.removeCondition( PlayerCondition::BetweenAreas ); player.removeCondition( PlayerCondition::BetweenAreas );

View file

@ -52,7 +52,7 @@ void Sapphire::Network::GameConnection::actionRequest( const Packets::FFXIVARR_P
if( category == Common::ActionCategory::ItemManipulation ) if( category == Common::ActionCategory::ItemManipulation )
actionMgr.handleItemManipulationAction( player, actionId, action, requestId ); actionMgr.handleItemManipulationAction( player, actionId, action, requestId );
else else
actionMgr.handleTargetedPlayerAction( player, actionId, action, targetId, requestId ); actionMgr.handleTargetedAction( player, actionId, action, targetId, requestId );
break; break;
} }

View file

@ -17,7 +17,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 "Network/Util/PacketUtil.h"
#include "Action/Action.h" #include "Action/Action.h"
@ -388,15 +388,9 @@ void examineHandler( Sapphire::Entity::Player& player, uint32_t targetId )
return; return;
if( pPlayer->isActingAsGm() || pPlayer->getTerritoryTypeId() != player.getTerritoryTypeId() ) if( pPlayer->isActingAsGm() || pPlayer->getTerritoryTypeId() != player.getTerritoryTypeId() )
{ Network::Util::Packet::sendActorControl( player, player.getId(), ExamineError );
server().queueForPlayer( player.getCharacterId(), makeActorControl( player.getId(), ActorControlType::ExamineError ) );
}
else else
{
server().queueForPlayer( player.getCharacterId(), std::make_shared< InspectPacket >( player, pPlayer ) ); server().queueForPlayer( player.getCharacterId(), std::make_shared< InspectPacket >( player, pPlayer ) );
}
} }
void Sapphire::Network::GameConnection::commandHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player ) void Sapphire::Network::GameConnection::commandHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
@ -424,7 +418,7 @@ void Sapphire::Network::GameConnection::commandHandler( const Packets::FFXIVARR_
player.setStance( Stance::Passive ); player.setStance( Stance::Passive );
player.setAutoattack( false ); player.setAutoattack( false );
} }
server().queueForPlayers( player.getInRangePlayerIds(), makeActorControl( player.getId(), 0, data.Arg0, 1 ) ); Network::Util::Packet::sendActorControl( player.getInRangePlayerIds(), player.getId(), ToggleWeapon, data.Arg0, 1 );
break; break;
} }
case PacketCommand::AUTO_ATTACK: // Toggle auto-attack case PacketCommand::AUTO_ATTACK: // Toggle auto-attack
@ -437,7 +431,7 @@ void Sapphire::Network::GameConnection::commandHandler( const Packets::FFXIVARR_
else else
player.setAutoattack( false ); player.setAutoattack( false );
server().queueForPlayers( player.getInRangePlayerIds(), makeActorControl( player.getId(), 1, data.Arg0, 1 ) ); Network::Util::Packet::sendActorControl( player.getInRangePlayerIds(), player.getId(), AutoAttack, data.Arg0, 1 );
break; break;
} }
@ -494,7 +488,7 @@ void Sapphire::Network::GameConnection::commandHandler( const Packets::FFXIVARR_
} }
case PacketCommand::TITLE_LIST: // Get title list case PacketCommand::TITLE_LIST: // Get title list
{ {
Network::Util::Player::sendTitleList( player ); Network::Util::Packet::sendTitleList( player );
break; break;
} }
case PacketCommand::BORROW_ACTION: case PacketCommand::BORROW_ACTION:
@ -509,7 +503,7 @@ void Sapphire::Network::GameConnection::commandHandler( const Packets::FFXIVARR_
} }
case PacketCommand::SET_CUTSCENE: case PacketCommand::SET_CUTSCENE:
{ {
server().queueForPlayer( player.getCharacterId(), makeActorControl( player.getId(), ActorControlType::SetCutsceneFlag, data.Arg0, 1 ) ); Network::Util::Packet::sendActorControl( player, player.getId(), SetCutsceneFlag, data.Arg0, 1 );
break; break;
} }
case PacketCommand::EMOTE: // emote case PacketCommand::EMOTE: // emote
@ -524,8 +518,7 @@ void Sapphire::Network::GameConnection::commandHandler( const Packets::FFXIVARR_
if( !emoteData ) if( !emoteData )
return; return;
server().queueForPlayers( player.getInRangePlayerIds(), Network::Util::Packet::sendActorControlTarget( player.getInRangePlayerIds(), player.getId(), Emote, emoteId, 0, isSilent ? 1 : 0, 0, targetId );
makeActorControlTarget( player.getId(), ActorControlType::Emote, emoteId, 0, isSilent ? 1 : 0, 0, targetId ) );
bool isPersistent = emoteData->data().Mode != 0; bool isPersistent = emoteData->data().Mode != 0;
@ -536,9 +529,8 @@ void Sapphire::Network::GameConnection::commandHandler( const Packets::FFXIVARR_
player.setPersistentEmote( emoteData->data().Mode ); player.setPersistentEmote( emoteData->data().Mode );
player.setStatus( ActorStatus::EmoteMode ); player.setStatus( ActorStatus::EmoteMode );
server().queueForPlayers( player.getInRangePlayerIds( true ), makeActorControl( player.getId(), ActorControlType::SetStatus, Network::Util::Packet::sendActorControl( player.getInRangePlayerIds( true ), player.getId(), SetStatus, static_cast< uint8_t >( ActorStatus::EmoteMode ),
static_cast< uint8_t >( ActorStatus::EmoteMode ), emoteData->data().IsEndEmoteMode ? 1 : 0 );
emoteData->data().IsEndEmoteMode ? 1 : 0 ) );
} }
if( emoteData->data().IsAvailableWhenDrawn ) if( emoteData->data().IsAvailableWhenDrawn )
@ -550,7 +542,7 @@ void Sapphire::Network::GameConnection::commandHandler( const Packets::FFXIVARR_
} }
case PacketCommand::EMOTE_CANCEL: // emote case PacketCommand::EMOTE_CANCEL: // emote
{ {
server().queueForPlayers( player.getInRangePlayerIds(), makeActorControl( player.getId(), ActorControlType::EmoteInterrupt ) ); Network::Util::Packet::sendActorControl( player.getInRangePlayerIds(), player.getId(), EmoteModeInterrupt );
break; break;
} }
case PacketCommand::EMOTE_MODE_CANCEL: case PacketCommand::EMOTE_MODE_CANCEL:
@ -561,8 +553,9 @@ void Sapphire::Network::GameConnection::commandHandler( const Packets::FFXIVARR_
player.setStatus( ActorStatus::Idle ); player.setStatus( ActorStatus::Idle );
server().queueForPlayers( player.getInRangePlayerIds(), std::make_shared< MoveActorPacket >( player, player.getRot(), 2, 0, 0, 0x5A / 4 ) ); server().queueForPlayers( player.getInRangePlayerIds(), std::make_shared< MoveActorPacket >( player, player.getRot(), 2, 0, 0, 0x5A / 4 ) );
server().queueForPlayers( player.getInRangePlayerIds(), makeActorControl( player.getId(), ActorControlType::EmoteModeInterrupt ) );
server().queueForPlayers( player.getInRangePlayerIds(), makeActorControl( player.getId(), SetStatus, static_cast< uint8_t >( ActorStatus::Idle ) ) ); Network::Util::Packet::sendActorControl( player.getInRangePlayerIds(), player.getId(), EmoteModeInterrupt );
Network::Util::Packet::sendActorControl( player.getInRangePlayerIds(), player.getId(), SetStatus, static_cast< uint8_t >( ActorStatus::Idle ) );
} }
break; break;
} }
@ -570,7 +563,7 @@ void Sapphire::Network::GameConnection::commandHandler( const Packets::FFXIVARR_
case PacketCommand::POSE_EMOTE_WORK: // reapply pose case PacketCommand::POSE_EMOTE_WORK: // reapply pose
{ {
player.setPose( static_cast< uint8_t >( data.Arg1 ) ); player.setPose( static_cast< uint8_t >( data.Arg1 ) );
server().queueForPlayers( player.getInRangePlayerIds( true ), makeActorControl( player.getId(), SetPose, data.Arg0, data.Arg1 ) ); Network::Util::Packet::sendActorControl( player.getInRangePlayerIds( true ), player.getId(), SetPose, data.Arg0, data.Arg1 );
break; break;
} }
case PacketCommand::POSE_EMOTE_CANCEL: // cancel pose case PacketCommand::POSE_EMOTE_CANCEL: // cancel pose
@ -609,12 +602,12 @@ void Sapphire::Network::GameConnection::commandHandler( const Packets::FFXIVARR_
auto achievementId = data.Arg0; auto achievementId = data.Arg0;
auto& achvMgr = Common::Service< AchievementMgr >::ref(); auto& achvMgr = Common::Service< AchievementMgr >::ref();
auto achvProgress = achvMgr.getAchievementDataById( player, achievementId ); auto achvProgress = achvMgr.getAchievementDataById( player, achievementId );
Network::Util::Player::sendActorControl( player, AchievementSetRate, achievementId, achvProgress.first, achvProgress.second ); Network::Util::Packet::sendActorControl( player, player.getId(), AchievementSetRate, achievementId, achvProgress.first, achvProgress.second );
break; break;
} }
case PacketCommand::ACHIEVEMENT_REQUEST: case PacketCommand::ACHIEVEMENT_REQUEST:
{ {
Network::Util::Player::sendAchievementList( player ); Network::Util::Packet::sendAchievementList( player );
break; break;
} }
case PacketCommand::TELEPO_INQUIRY: // Teleport case PacketCommand::TELEPO_INQUIRY: // Teleport
@ -675,7 +668,7 @@ void Sapphire::Network::GameConnection::commandHandler( const Packets::FFXIVARR_
player.setActiveLand( static_cast< uint8_t >( data.Arg0 ), hZone->getWardNum() ); player.setActiveLand( static_cast< uint8_t >( data.Arg0 ), hZone->getWardNum() );
server().queueForPlayer( player.getCharacterId(), makeActorControl( player.getId(), ShowBuildPresetUI, data.Arg0 ) ); Network::Util::Packet::sendActorControl( player, player.getId(), ShowBuildPresetUI, data.Arg0 );
break; break;
} }
case PacketCommand::HOUSING_AUCTION_INFO: case PacketCommand::HOUSING_AUCTION_INFO:
@ -753,8 +746,7 @@ void Sapphire::Network::GameConnection::commandHandler( const Packets::FFXIVARR_
uint8_t ward = ( data.Arg1 >> 16 ) & 0xFF; uint8_t ward = ( data.Arg1 >> 16 ) & 0xFF;
uint8_t plot = ( data.Arg1 & 0xFF ); uint8_t plot = ( data.Arg1 & 0xFF );
server().queueForPlayer( player.getCharacterId(), makeActorControl( player.getId(), ShowHousingItemUI, 0, plot ) ); Network::Util::Packet::sendActorControl( player, player.getId(), ShowHousingItemUI, 0, plot );
//TODO: show item housing container //TODO: show item housing container
break; break;

View file

@ -29,6 +29,7 @@
#include "Network/PacketWrappers/ActorControlSelfPacket.h" #include "Network/PacketWrappers/ActorControlSelfPacket.h"
#include "Network/PacketWrappers/ActorControlTargetPacket.h" #include "Network/PacketWrappers/ActorControlTargetPacket.h"
#include "Network/PacketWrappers/UpdateInventorySlotPacket.h" #include "Network/PacketWrappers/UpdateInventorySlotPacket.h"
#include "Network/Util/PacketUtil.h"
#include "Manager/DebugCommandMgr.h" #include "Manager/DebugCommandMgr.h"
#include "Manager/MarketMgr.h" #include "Manager/MarketMgr.h"
@ -83,8 +84,7 @@ void Sapphire::Network::GameConnection::setProfileHandler( const Packets::FFXIVA
strcpy( searchInfoPacket->data().SearchComment, player.getSearchMessage() ); strcpy( searchInfoPacket->data().SearchComment, player.getSearchMessage() );
queueOutPacket( searchInfoPacket ); queueOutPacket( searchInfoPacket );
server().queueForPlayers( player.getInRangePlayerIds( true ), makeActorControl( player.getId(), SetStatusIcon, Network::Util::Packet::sendActorControl( player.getInRangePlayerIds( true ), player.getId(), SetStatusIcon, static_cast< uint8_t >( player.getOnlineStatus() ) );
static_cast< uint8_t >( player.getOnlineStatus() ) ) );
} }
void Sapphire::Network::GameConnection::getProfileHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player ) void Sapphire::Network::GameConnection::getProfileHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
@ -103,17 +103,15 @@ void Sapphire::Network::GameConnection::getSearchCommentHandler( const Packets::
Logger::debug( "getSearchCommentHandler: {0}", targetId ); Logger::debug( "getSearchCommentHandler: {0}", targetId );
if( pPlayer ) if( !pPlayer || pPlayer->isActingAsGm() || pPlayer->getTerritoryTypeId() != player.getTerritoryTypeId() )
{ return;
if( pPlayer->isActingAsGm() || pPlayer->getTerritoryTypeId() != player.getTerritoryTypeId() )
return; // retail sends the requester's id as both (isForSelf)
auto searchInfoPacket = makeZonePacket< FFXIVIpcGetSearchCommentResult >( player.getId() );
searchInfoPacket->data().TargetEntityID = targetId;
strcpy( searchInfoPacket->data().SearchComment, pPlayer->getSearchMessage() );
server().queueForPlayer( player.getCharacterId(), searchInfoPacket );
// retail sends the requester's id as both (isForSelf)
auto searchInfoPacket = makeZonePacket< FFXIVIpcGetSearchCommentResult >( player.getId() );
searchInfoPacket->data().TargetEntityID = targetId;
strcpy( searchInfoPacket->data().SearchComment, pPlayer->getSearchMessage() );
server().queueForPlayer( player.getCharacterId(), searchInfoPacket );
}
} }
void Sapphire::Network::GameConnection::reqExamineFcInfo( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player ) void Sapphire::Network::GameConnection::reqExamineFcInfo( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
@ -236,7 +234,7 @@ void Sapphire::Network::GameConnection::moveHandler( const Packets::FFXIVARR_PAC
unknownRotation = 0x7F; unknownRotation = 0x7F;
} }
uint64_t currentTime = Util::getTimeMs(); uint64_t currentTime = Common::Util::getTimeMs();
player.m_lastMoveTime = currentTime; player.m_lastMoveTime = currentTime;
player.m_lastMoveflag = animationType; player.m_lastMoveflag = animationType;
@ -313,14 +311,14 @@ void Sapphire::Network::GameConnection::newDiscoveryHandler( const Packets::FFXI
PlayerMgr::sendDebug( player, "Discovery ref pos id#{0}", layoutId ); PlayerMgr::sendDebug( player, "Discovery ref pos id#{0}", layoutId );
if( pRefInfo ) if( !pRefInfo )
{ return;
auto discoveryPacket = makeZonePacket< FFXIVIpcDiscoveryReply >( player.getId() );
discoveryPacket->data().mapId = tInfo->data().Map; auto discoveryPacket = makeZonePacket< FFXIVIpcDiscoveryReply >( player.getId() );
discoveryPacket->data().mapPartId = pRefInfo->data.discoveryIndex; discoveryPacket->data().mapId = tInfo->data().Map;
server().queueForPlayer( player.getCharacterId(), discoveryPacket ); discoveryPacket->data().mapPartId = pRefInfo->data.discoveryIndex;
player.discover( tInfo->data().Map, pRefInfo->data.discoveryIndex ); server().queueForPlayer( player.getCharacterId(), discoveryPacket );
} player.discover( tInfo->data().Map, pRefInfo->data.discoveryIndex );
} }
@ -363,9 +361,7 @@ void Sapphire::Network::GameConnection::setLanguageHandler( const Packets::FFXIV
// if this is a login event // if this is a login event
if( player.isLogin() ) if( player.isLogin() )
{
playerMgr().sendLoginMessage( player ); playerMgr().sendLoginMessage( player );
}
// spawn the player for himself // spawn the player for himself
player.spawn( player.getAsPlayer() ); player.spawn( player.getAsPlayer() );
@ -619,9 +615,7 @@ void Sapphire::Network::GameConnection::gearSetEquip( const Packets::FFXIVARR_PA
player.sendGearInventory(); player.sendGearInventory();
if( packet.data().contextId < 0xFE ) if( packet.data().contextId < 0xFE )
{ Network::Util::Packet::sendActorControlSelf( player, player.getId(), GearSetEquipMsg, packet.data().contextId );
server().queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), Network::ActorControl::GearSetEquipMsg, packet.data().contextId ) );
}
auto invTransFinPacket = makeZonePacket< FFXIVIpcItemOperationBatch >( player.getId() ); auto invTransFinPacket = makeZonePacket< FFXIVIpcItemOperationBatch >( player.getId() );
invTransFinPacket->data().contextId = contextId; invTransFinPacket->data().contextId = contextId;

View file

@ -13,15 +13,15 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
class EffectPacket : public ZoneChannelPacket< FFXIVIpcActionResult > class EffectPacket : public ZoneChannelPacket< FFXIVIpcActionResult >
{ {
public: public:
EffectPacket( uint64_t sourceId, uint32_t actionId ) : EffectPacket( uint64_t sourceId, uint32_t mainTarget, uint32_t actionId ) :
ZoneChannelPacket< FFXIVIpcActionResult >( static_cast< uint32_t >( sourceId ) ) ZoneChannelPacket< FFXIVIpcActionResult >( static_cast< uint32_t >( sourceId ), mainTarget )
{ {
m_data.Flag = 0; m_data.Flag = 0;
m_data.ActionKey = actionId; m_data.ActionKey = actionId;
m_data.Action = static_cast< uint16_t >( actionId ); m_data.Action = static_cast< uint16_t >( actionId );
m_data.ActionKind = 1; m_data.ActionKind = 1;
m_data.MainTarget = Common::INVALID_GAME_OBJECT_ID; m_data.MainTarget = static_cast< uint64_t >( mainTarget );
m_data.BallistaEntityId = Common::INVALID_GAME_OBJECT_ID; m_data.BallistaEntityId = Common::INVALID_GAME_OBJECT_ID;
m_data.LockTime = 0.6f; m_data.LockTime = 0.6f;
@ -58,9 +58,9 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
std::memcpy( &m_data.CalcResult[ m_data.TargetCount - 1 ].CalcResultCt[ m_sourceEffectCount++ ], &effect, sizeof( Common::CalcResultParam ) ); std::memcpy( &m_data.CalcResult[ m_data.TargetCount - 1 ].CalcResultCt[ m_sourceEffectCount++ ], &effect, sizeof( Common::CalcResultParam ) );
} }
void setAnimationId( uint16_t animationId ) void setActionId( uint16_t actionId )
{ {
m_data.Action = animationId; m_data.Action = actionId;
} }
void setDisplayType( Common::ActionEffectDisplayType displayType ) void setDisplayType( Common::ActionEffectDisplayType displayType )
@ -78,13 +78,6 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
m_data.DirTarget = rotation; m_data.DirTarget = rotation;
} }
void setTargetActor( const uint32_t targetId )
{
m_data.MainTarget = static_cast< uint64_t >( targetId );
FFXIVPacketBase::setTargetActor( targetId );
}
void setRequestId( uint16_t requestId ) void setRequestId( uint16_t requestId )
{ {
m_data.RequestId = static_cast< uint32_t >( requestId ); m_data.RequestId = static_cast< uint32_t >( requestId );

View file

@ -1,4 +1,4 @@
#include "PlayerUtil.h" #include "PacketUtil.h"
#include <Exd/ExdData.h> #include <Exd/ExdData.h>
@ -18,23 +18,25 @@
#include <Network/PacketWrappers/RestingPacket.h> #include <Network/PacketWrappers/RestingPacket.h>
#include <Network/PacketWrappers/PlayerSetupPacket.h> #include <Network/PacketWrappers/PlayerSetupPacket.h>
#include <Network/PacketWrappers/InitZonePacket.h> #include <Network/PacketWrappers/InitZonePacket.h>
#include <Network/PacketWrappers/ServerNoticePacket.h>
#include <Network/PacketWrappers/ChatPacket.h>
using namespace Sapphire; using namespace Sapphire;
using namespace Sapphire::World::Manager; using namespace Sapphire::World::Manager;
using namespace Sapphire::Network; using namespace Sapphire::Network;
using namespace Sapphire::Network::Util::Player; using namespace Sapphire::Network::Util::Packet;
using namespace Sapphire::Network::Packets; using namespace Sapphire::Network::Packets;
using namespace Sapphire::Network::Packets::WorldPackets::Server; using namespace Sapphire::Network::Packets::WorldPackets::Server;
using namespace Sapphire::Network::ActorControl; using namespace Sapphire::Network::ActorControl;
void Util::Player::sendConfigFlags( Entity::Player& player ) void Util::Packet::sendConfigFlags( Entity::Player& player )
{ {
auto paramPacket = makeZonePacket< FFXIVIpcConfig >( player.getId() ); auto paramPacket = makeZonePacket< FFXIVIpcConfig >( player.getId() );
paramPacket->data().flag = player.getConfigFlags(); paramPacket->data().flag = player.getConfigFlags();
server().queueForPlayers( player.getInRangePlayerIds( true ), paramPacket ); server().queueForPlayers( player.getInRangePlayerIds( true ), paramPacket );
} }
void Util::Player::sendOnlineStatus( Entity::Player& player ) void Util::Packet::sendOnlineStatus( Entity::Player& player )
{ {
auto statusPacket = makeZonePacket< FFXIVIpcSetOnlineStatus >( player.getId() ); auto statusPacket = makeZonePacket< FFXIVIpcSetOnlineStatus >( player.getId() );
statusPacket->data().onlineStatusFlags = player.getFullOnlineStatusMask(); statusPacket->data().onlineStatusFlags = player.getFullOnlineStatusMask();
@ -44,7 +46,7 @@ void Util::Player::sendOnlineStatus( Entity::Player& player )
makeActorControl( player.getId(), SetStatusIcon, static_cast< uint8_t >( player.getOnlineStatus() ) ) ); makeActorControl( player.getId(), SetStatusIcon, static_cast< uint8_t >( player.getOnlineStatus() ) ) );
} }
void Util::Player::sendBaseParams( Entity::Player& player ) void Util::Packet::sendBaseParams( Entity::Player& player )
{ {
std::array< uint32_t, 50 > statParams{}; std::array< uint32_t, 50 > statParams{};
std::fill( std::begin( statParams ), std::end( statParams ), 0 ); std::fill( std::begin( statParams ), std::end( statParams ), 0 );
@ -67,13 +69,17 @@ void Util::Player::sendBaseParams( Entity::Player& player )
server().queueForPlayer( player.getCharacterId(), statPacket ); server().queueForPlayer( player.getCharacterId(), statPacket );
} }
void Util::Player::sendHudParam( Entity::Player& player ) void Util::Packet::sendHudParam( Entity::Chara& source )
{ {
auto hudParamPacket = makeHudParam( player ); if( source.isPlayer() )
server().queueForPlayer( player.getCharacterId(), hudParamPacket ); server().queueForPlayers( source.getInRangePlayerIds( true ), makeHudParam( *source.getAsPlayer() ) );
else if( source.isBattleNpc() )
server().queueForPlayers( source.getInRangePlayerIds( false ), makeHudParam( *source.getAsBNpc() ) );
else
server().queueForPlayers( source.getInRangePlayerIds( false ), makeHudParam( source ) );
} }
void Util::Player::sendStatusUpdate( Entity::Player& player ) void Util::Packet::sendStatusUpdate( Entity::Player& player )
{ {
auto playerStatusUpdate = makeZonePacket< FFXIVIpcPlayerStatusUpdate >( player.getId() ); auto playerStatusUpdate = makeZonePacket< FFXIVIpcPlayerStatusUpdate >( player.getId() );
playerStatusUpdate->data().ClassJob = static_cast< uint8_t >( player.getClass() ); playerStatusUpdate->data().ClassJob = static_cast< uint8_t >( player.getClass() );
@ -85,7 +91,7 @@ void Util::Player::sendStatusUpdate( Entity::Player& player )
server().queueForPlayer( player.getCharacterId(), playerStatusUpdate ); server().queueForPlayer( player.getCharacterId(), playerStatusUpdate );
} }
void Util::Player::sendHuntingLog( Entity::Player& player ) void Util::Packet::sendHuntingLog( Entity::Player& player )
{ {
auto& exdData = Common::Service< Data::ExdData >::ref(); auto& exdData = Common::Service< Data::ExdData >::ref();
for( auto entryCount = 0; entryCount < Common::ARRSIZE_MONSTERNOTE; ++entryCount ) for( auto entryCount = 0; entryCount < Common::ARRSIZE_MONSTERNOTE; ++entryCount )
@ -128,37 +134,49 @@ void Util::Player::sendHuntingLog( Entity::Player& player )
} }
} }
void Util::Player::sendActorControlSelf( Entity::Player& player, uint16_t category, uint32_t param1, uint32_t param2, uint32_t param3, void Util::Packet::sendActorControlSelf( Entity::Player& player, uint32_t srcId, uint16_t category, uint32_t param1, uint32_t param2, uint32_t param3,
uint32_t param4, uint32_t param5 ) uint32_t param4, uint32_t param5 )
{ {
server().queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), category, param1, param2, param3, param4, param5 ) ); server().queueForPlayer( player.getCharacterId(), makeActorControlSelf( srcId, 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, void Util::Packet::sendActorControlSelf( const std::set< uint64_t >& characterIds, uint32_t srcId, uint16_t category, uint32_t param1,
uint32_t param2, uint32_t param3, uint32_t param4, uint32_t param5 ) uint32_t param2, uint32_t param3, uint32_t param4, uint32_t param5 )
{ {
server().queueForPlayers( characterIds, makeActorControlSelf( player.getId(), category, param1, param2, param3, param4, param5 ) ); server().queueForPlayers( characterIds, makeActorControlSelf( srcId, 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 ) void Util::Packet::sendActorControl( Entity::Player& player, uint32_t srcId, 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 ) ); server().queueForPlayer( player.getCharacterId(), makeActorControl( srcId, category, param1, param2, param3, param4 ) );
} }
void Util::Player::sendActorControl( const std::set< uint64_t >& characterIds, Entity::Player& player, uint16_t category, uint32_t param1, void Util::Packet::sendActorControl( const std::set< uint64_t >& characterIds, uint32_t srcId, uint16_t category, uint32_t param1,
uint32_t param2, uint32_t param3, uint32_t param4 ) uint32_t param2, uint32_t param3, uint32_t param4 )
{ {
server().queueForPlayers( characterIds, makeActorControl( player.getId(), category, param1, param2, param3, param4 ) ); server().queueForPlayers( characterIds, makeActorControl( srcId, category, param1, param2, param3, param4 ) );
} }
void Util::Player::sendTitleList( Entity::Player& player ) void Util::Packet::sendActorControlTarget( Entity::Player& player, uint32_t srcId, uint16_t category, uint32_t param1, uint32_t param2, uint32_t param3,
uint32_t param4, uint32_t param5, uint32_t param6 )
{
server().queueForPlayer( player.getCharacterId(), makeActorControlTarget( srcId, category, param1, param2, param3, param4, param5, param6 ) );
}
void Util::Packet::sendActorControlTarget( const std::set< uint64_t >& characterIds, uint32_t srcId, uint16_t category, uint32_t param1,
uint32_t param2, uint32_t param3, uint32_t param4, uint32_t param5, uint32_t param6 )
{
server().queueForPlayers( characterIds, makeActorControlTarget( srcId, category, param1, param2, param3, param4, param5, param6 ) );
}
void Util::Packet::sendTitleList( Entity::Player& player )
{ {
auto titleListPacket = makeZonePacket< FFXIVIpcTitleList >( player.getId() ); auto titleListPacket = makeZonePacket< FFXIVIpcTitleList >( player.getId() );
memcpy( titleListPacket->data().TitleFlagsArray, player.getTitleList().data(), sizeof( titleListPacket->data().TitleFlagsArray ) ); memcpy( titleListPacket->data().TitleFlagsArray, player.getTitleList().data(), sizeof( titleListPacket->data().TitleFlagsArray ) );
server().queueForPlayer( player.getCharacterId(), titleListPacket ); server().queueForPlayer( player.getCharacterId(), titleListPacket );
} }
void Util::Player::sendGrandCompany( Entity::Player& player ) void Util::Packet::sendGrandCompany( Entity::Player& player )
{ {
auto gcAffPacket = makeZonePacket< FFXIVIpcGrandCompany >( player.getId() ); auto gcAffPacket = makeZonePacket< FFXIVIpcGrandCompany >( player.getId() );
gcAffPacket->data().ActiveCompanyId = player.getGc(); gcAffPacket->data().ActiveCompanyId = player.getGc();
@ -168,7 +186,7 @@ void Util::Player::sendGrandCompany( Entity::Player& player )
server().queueForPlayer( player.getCharacterId(), gcAffPacket ); server().queueForPlayer( player.getCharacterId(), gcAffPacket );
} }
void Util::Player::sendDeletePlayer( Entity::Player& player, uint32_t actorId, uint8_t spawnIndex ) void Util::Packet::sendDeletePlayer( Entity::Player& player, uint32_t actorId, uint8_t spawnIndex )
{ {
auto freeActorSpawnPacket = makeZonePacket< FFXIVIpcActorFreeSpawn >( player.getId() ); auto freeActorSpawnPacket = makeZonePacket< FFXIVIpcActorFreeSpawn >( player.getId() );
freeActorSpawnPacket->data().actorId = actorId; freeActorSpawnPacket->data().actorId = actorId;
@ -176,14 +194,14 @@ void Util::Player::sendDeletePlayer( Entity::Player& player, uint32_t actorId, u
server().queueForPlayer( player.getCharacterId(), freeActorSpawnPacket ); server().queueForPlayer( player.getCharacterId(), freeActorSpawnPacket );
} }
void Util::Player::sendDeleteObject( Entity::Player& player, uint8_t spawnIndex ) void Util::Packet::sendDeleteObject( Entity::Player& player, uint8_t spawnIndex )
{ {
auto freeObjectSpawnPacket = makeZonePacket< FFXIVIpcDeleteObject >( player.getId() ); auto freeObjectSpawnPacket = makeZonePacket< FFXIVIpcDeleteObject >( player.getId() );
freeObjectSpawnPacket->data().Index = spawnIndex; freeObjectSpawnPacket->data().Index = spawnIndex;
server().queueForPlayer( player.getCharacterId(), freeObjectSpawnPacket ); server().queueForPlayer( player.getCharacterId(), freeObjectSpawnPacket );
} }
void Util::Player::sendHateList( Entity::Player& player ) void Util::Packet::sendHateList( Entity::Player& player )
{ {
auto& teriMgr = Common::Service< World::Manager::TerritoryMgr >::ref(); auto& teriMgr = Common::Service< World::Manager::TerritoryMgr >::ref();
@ -211,7 +229,7 @@ void Util::Player::sendHateList( Entity::Player& player )
if( hateValue == 0 ) if( hateValue == 0 )
continue; continue;
auto hatePercent = ( hateValue / static_cast< float >( pBNpc->hateListGetHighestValue() ) ) * 100.f; auto hatePercent = ( static_cast< float >( hateValue ) / static_cast< float >( pBNpc->hateListGetHighestValue() ) ) * 100.f;
hateListPacket->data().List[ i ].Id = player.getId(); hateListPacket->data().List[ i ].Id = player.getId();
hateListPacket->data().List[ i ].Value = hateValue; hateListPacket->data().List[ i ].Value = hateValue;
@ -223,36 +241,36 @@ void Util::Player::sendHateList( Entity::Player& player )
server().queueForPlayer( player.getCharacterId(), { hateListPacket, hateRankPacket } ); server().queueForPlayer( player.getCharacterId(), { hateListPacket, hateRankPacket } );
} }
void Util::Player::sendMount( Entity::Player& player ) void Util::Packet::sendMount( Entity::Player& player )
{ {
auto mountId = player.getCurrentMount(); auto mountId = player.getCurrentMount();
auto inRangePlayerIds = player.getInRangePlayerIds( true ); auto inRangePlayerIds = player.getInRangePlayerIds( true );
if( mountId != 0 ) if( mountId != 0 )
{ {
Network::Util::Player::sendActorControl( inRangePlayerIds, player, SetStatus, static_cast< uint8_t >( Common::ActorStatus::Mounted ) ); Network::Util::Packet::sendActorControl( inRangePlayerIds, player.getId(), SetStatus, static_cast< uint8_t >( Common::ActorStatus::Mounted ) );
Network::Util::Player::sendActorControlSelf( inRangePlayerIds, player, 0x39e, 12 ); Network::Util::Packet::sendActorControlSelf( inRangePlayerIds, player.getId(), 0x39e, 12 );
} }
else else
{ {
Network::Util::Player::sendActorControl( inRangePlayerIds, player, SetStatus, static_cast< uint8_t >( Common::ActorStatus::Idle ) ); Network::Util::Packet::sendActorControl( inRangePlayerIds, player.getId(), SetStatus, static_cast< uint8_t >( Common::ActorStatus::Idle ) );
Network::Util::Player::sendActorControlSelf( inRangePlayerIds, player, Dismount, 1 ); Network::Util::Packet::sendActorControlSelf( inRangePlayerIds, player.getId(), Dismount, 1 );
} }
auto mountPacket = makeZonePacket< FFXIVIpcMount >( player.getId() ); auto mountPacket = makeZonePacket< FFXIVIpcMount >( player.getId() );
mountPacket->data().id = mountId; mountPacket->data().id = mountId;
server().queueForPlayers( inRangePlayerIds, mountPacket ); server().queueForPlayers( inRangePlayerIds, mountPacket );
} }
void Util::Player::sendEquip( Entity::Player& player ) void Util::Packet::sendEquip( Entity::Player& player )
{ {
server().queueForPlayers( player.getInRangePlayerIds( true ), std::make_shared< ModelEquipPacket >( player ) ); server().queueForPlayers( player.getInRangePlayerIds( true ), std::make_shared< ModelEquipPacket >( player ) );
} }
void Util::Player::sendCondition( Entity::Player& player ) void Util::Packet::sendCondition( Entity::Player& player )
{ {
server().queueForPlayer( player.getCharacterId(), std::make_shared< ConditionPacket >( player ) ); server().queueForPlayer( player.getCharacterId(), std::make_shared< ConditionPacket >( player ) );
} }
void Util::Player::sendRecastGroups( Entity::Player& player ) void Util::Packet::sendRecastGroups( Entity::Player& player )
{ {
const auto& recastGroups = player.getRecastGroups(); const auto& recastGroups = player.getRecastGroups();
const auto& recastGroupsMax = player.getRecastGroupsMax(); const auto& recastGroupsMax = player.getRecastGroupsMax();
@ -262,7 +280,7 @@ void Util::Player::sendRecastGroups( Entity::Player& player )
server().queueForPlayer( player.getCharacterId(), recastGroupPaket ); server().queueForPlayer( player.getCharacterId(), recastGroupPaket );
} }
void Util::Player::sendAchievementList( Entity::Player& player ) void Util::Packet::sendAchievementList( Entity::Player& player )
{ {
auto achvData = player.getAchievementData(); auto achvData = player.getAchievementData();
auto achvPacket = makeZonePacket< FFXIVIpcAchievement >( player.getId() ); auto achvPacket = makeZonePacket< FFXIVIpcAchievement >( player.getId() );
@ -271,24 +289,24 @@ void Util::Player::sendAchievementList( Entity::Player& player )
server().queueForPlayer( player.getCharacterId(), achvPacket ); server().queueForPlayer( player.getCharacterId(), achvPacket );
} }
void Util::Player::sendRestingUpdate( Entity::Player& player ) void Util::Packet::sendRestingUpdate( Entity::Player& player )
{ {
server().queueForPlayers( player.getInRangePlayerIds( true ), std::make_shared< RestingPacket >( player ) ); server().queueForPlayers( player.getInRangePlayerIds( true ), std::make_shared< RestingPacket >( player ) );
} }
void Util::Player::sendLogin( Entity::Player& player ) void Util::Packet::sendLogin( Entity::Player& player )
{ {
auto initPacket = makeZonePacket< FFXIVIpcLogin >( player.getId() ); auto initPacket = makeZonePacket< FFXIVIpcLogin >( player.getId() );
initPacket->data().playerActorId = player.getId(); initPacket->data().playerActorId = player.getId();
server().queueForPlayer( player.getCharacterId(), initPacket ); server().queueForPlayer( player.getCharacterId(), initPacket );
} }
void Util::Player::sendPlayerSetup( Entity::Player& player ) void Util::Packet::sendPlayerSetup( Entity::Player& player )
{ {
server().queueForPlayer( player.getCharacterId(), makePlayerSetup( player ) ); server().queueForPlayer( player.getCharacterId(), makePlayerSetup( player ) );
} }
void Util::Player::sendChangeClass( Entity::Player& player ) void Util::Packet::sendChangeClass( Entity::Player& player )
{ {
auto classInfo = makeZonePacket< FFXIVIpcChangeClass >( player.getId() ); auto classInfo = makeZonePacket< FFXIVIpcChangeClass >( player.getId() );
auto& borrowAction = player.getBorrowAction(); auto& borrowAction = player.getBorrowAction();
@ -300,7 +318,7 @@ void Util::Player::sendChangeClass( Entity::Player& player )
server().queueForPlayer( player.getCharacterId(), classInfo ); server().queueForPlayer( player.getCharacterId(), classInfo );
} }
void Util::Player::sendContentAttainFlags( Entity::Player& player ) void Util::Packet::sendContentAttainFlags( Entity::Player& player )
{ {
// todo - fill with actual data from player // todo - fill with actual data from player
auto contentFinderList = makeZonePacket< FFXIVIpcContentAttainFlags >( player.getId() ); auto contentFinderList = makeZonePacket< FFXIVIpcContentAttainFlags >( player.getId() );
@ -308,7 +326,7 @@ void Util::Player::sendContentAttainFlags( Entity::Player& player )
server().queueForPlayer( player.getCharacterId(), contentFinderList ); server().queueForPlayer( player.getCharacterId(), contentFinderList );
} }
void Util::Player::sendInitZone( Entity::Player& player ) void Util::Packet::sendInitZone( Entity::Player& player )
{ {
auto& teriMgr = Common::Service< World::Manager::TerritoryMgr >::ref(); auto& teriMgr = Common::Service< World::Manager::TerritoryMgr >::ref();
auto pZone = teriMgr.getTerritoryByGuId( player.getTerritoryId() ); auto pZone = teriMgr.getTerritoryByGuId( player.getTerritoryId() );
@ -321,12 +339,22 @@ void Util::Player::sendInitZone( Entity::Player& player )
server().queueForPlayer( player.getCharacterId(), makeInitZone( player, teri ) ); server().queueForPlayer( player.getCharacterId(), makeInitZone( player, teri ) );
} }
void Util::Player::sendDailyQuests( Entity::Player& player ) void Util::Packet::sendDailyQuests( Entity::Player& player )
{ {
server().queueForPlayer( player.getCharacterId(), makeZonePacket< FFXIVIpcDailyQuests >( player.getId() ) ); server().queueForPlayer( player.getCharacterId(), makeZonePacket< FFXIVIpcDailyQuests >( player.getId() ) );
} }
void Util::Player::sendQuestRepeatFlags( Entity::Player& player ) void Util::Packet::sendQuestRepeatFlags( Entity::Player& player )
{ {
server().queueForPlayer( player.getCharacterId(), makeZonePacket< FFXIVIpcQuestRepeatFlags >( player.getId() ) ); server().queueForPlayer( player.getCharacterId(), makeZonePacket< FFXIVIpcQuestRepeatFlags >( player.getId() ) );
} }
void Util::Packet::sendServerNotice( Entity::Player& player, const std::string& message )
{
server().queueForPlayer( player.getCharacterId(), std::make_shared< ServerNoticePacket >( player.getId(), message ) );
}
void Util::Packet::sendChat( Entity::Player& player, Common::ChatType chatType, const std::string& message )
{
server().queueForPlayer( player.getCharacterId(), std::make_shared< ChatPacket >( player, chatType, message ) );
}

View file

@ -5,12 +5,12 @@
#include <Actor/Player.h> #include <Actor/Player.h>
#include "Forwards.h" #include "Forwards.h"
namespace Sapphire::Network::Util::Player namespace Sapphire::Network::Util::Packet
{ {
void sendConfigFlags( Entity::Player& player ); void sendConfigFlags( Entity::Player& player );
void sendOnlineStatus( Entity::Player& player ); void sendOnlineStatus( Entity::Player& player );
void sendBaseParams( Entity::Player& player ); void sendBaseParams( Entity::Player& player );
void sendHudParam( Entity::Player& player ); void sendHudParam( Entity::Chara& player );
void sendStatusUpdate( Entity::Player& player ); void sendStatusUpdate( Entity::Player& player );
void sendHuntingLog( Entity::Player& player ); void sendHuntingLog( Entity::Player& player );
@ -48,15 +48,24 @@ namespace Sapphire::Network::Util::Player
void sendDailyQuests( Entity::Player& player ); void sendDailyQuests( Entity::Player& player );
void sendQuestRepeatFlags( Entity::Player& player ); void sendQuestRepeatFlags( Entity::Player& player );
void sendActorControlSelf( Entity::Player& player, uint16_t category, uint32_t param1 = 0, uint32_t param2 = 0, uint32_t param3 = 0, void sendServerNotice( Entity::Player& player, const std::string& message );
void sendChat( Entity::Player& player, Common::ChatType chatType, const std::string& message );
void sendActorControlSelf( Entity::Player& player, uint32_t srcId, uint16_t category, uint32_t param1 = 0, uint32_t param2 = 0, uint32_t param3 = 0,
uint32_t param4 = 0, uint32_t param5 = 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, void sendActorControlSelf( const std::set< uint64_t >& characterIds, uint32_t srcId, uint16_t category, uint32_t param1 = 0,
uint32_t param2 = 0, uint32_t param3 = 0, uint32_t param4 = 0, uint32_t param5 = 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( Entity::Player& player, uint32_t srcId, 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, void sendActorControl( const std::set< uint64_t >& characterIds, uint32_t srcId, uint16_t category, uint32_t param1 = 0, uint32_t param2 = 0,
uint32_t param3 = 0, uint32_t param4 = 0 ); uint32_t param3 = 0, uint32_t param4 = 0 );
void sendActorControlTarget( Entity::Player& player, uint32_t srcId, uint16_t category, uint32_t param1 = 0, uint32_t param2 = 0, uint32_t param3 = 0,
uint32_t param4 = 0, uint32_t param5 = 0, uint32_t param6 = 0 );
void sendActorControlTarget( const std::set< uint64_t >& characterIds, uint32_t srcId, uint16_t category, uint32_t param1 = 0,
uint32_t param2 = 0, uint32_t param3 = 0, uint32_t param4 = 0, uint32_t param5 = 0, uint32_t param6 = 0 );
} }

View file

@ -204,27 +204,35 @@ void Sapphire::World::Session::sendReplayInfo()
PlayerMgr::sendDebug( *getPlayer(), message ); PlayerMgr::sendDebug( *getPlayer(), message );
} }
void Sapphire::World::Session::processOutQueue()
{
if( !m_pZoneConnection )
return;
m_pZoneConnection->processOutQueue();
}
void Sapphire::World::Session::update() void Sapphire::World::Session::update()
{ {
if( m_isReplaying ) if( m_isReplaying )
processReplay(); processReplay();
if( m_pZoneConnection ) if( !m_pZoneConnection )
return;
m_pZoneConnection->processInQueue();
// SESSION LOGIC
m_pPlayer->update( Common::Util::getTimeMs() );
if( Common::Util::getTimeSeconds() - static_cast< uint32_t >( getLastSqlTime() ) > 10 )
{ {
m_pZoneConnection->processInQueue(); updateLastSqlTime();
m_pPlayer->updateSql();
// SESSION LOGIC
m_pPlayer->update( Common::Util::getTimeMs() );
if( Common::Util::getTimeSeconds() - static_cast< uint32_t >( getLastSqlTime() ) > 10 )
{
updateLastSqlTime();
m_pPlayer->updateSql();
}
m_pZoneConnection->processOutQueue();
} }
m_pZoneConnection->processOutQueue();
if( m_pChatConnection ) if( m_pChatConnection )
{ {
m_pChatConnection->processInQueue(); m_pChatConnection->processInQueue();

View file

@ -47,6 +47,8 @@ namespace Sapphire::World
void update(); void update();
void processOutQueue();
bool isValid() const; bool isValid() const;
Entity::PlayerPtr getPlayer() const; Entity::PlayerPtr getPlayer() const;

View file

@ -22,18 +22,12 @@ using namespace Sapphire::Network::Packets;
//using namespace Sapphire::Network::Packets::WorldPackets::Server; //using namespace Sapphire::Network::Packets::WorldPackets::Server;
Sapphire::StatusEffect::StatusEffect::StatusEffect( uint32_t id, Entity::CharaPtr sourceActor, Entity::CharaPtr targetActor, Sapphire::StatusEffect::StatusEffect::StatusEffect( uint32_t id, Entity::CharaPtr sourceActor, Entity::CharaPtr targetActor,
uint32_t duration, std::vector< World::Action::StatusModifier >& modifiers, uint32_t tickRate ) : uint32_t duration,std::vector< World::Action::StatusModifier >& modifiers,
uint32_t flag, uint32_t tickRate ) :
StatusEffect( id, sourceActor, targetActor, duration, tickRate ) StatusEffect( id, sourceActor, targetActor, duration, tickRate )
{ {
m_statusModifiers = std::move( modifiers ); m_statusModifiers = std::move( modifiers );
} m_flag = flag;
Sapphire::StatusEffect::StatusEffect::StatusEffect( uint32_t id, Entity::CharaPtr sourceActor, Entity::CharaPtr targetActor,
uint32_t duration, World::Action::StatusEntry& statusEntry, uint32_t tickRate ) :
StatusEffect( id, sourceActor, targetActor, duration, tickRate )
{
m_statusModifiers = statusEntry.modifiers;
m_flag |= statusEntry.flag;
} }
Sapphire::StatusEffect::StatusEffect::StatusEffect( uint32_t id, Entity::CharaPtr sourceActor, Entity::CharaPtr targetActor, Sapphire::StatusEffect::StatusEffect::StatusEffect( uint32_t id, Entity::CharaPtr sourceActor, Entity::CharaPtr targetActor,
@ -100,6 +94,11 @@ uint32_t Sapphire::StatusEffect::StatusEffect::getSrcActorId() const
return m_sourceActor->getId(); return m_sourceActor->getId();
} }
Sapphire::Entity::CharaPtr Sapphire::StatusEffect::StatusEffect::getSrcActor() const
{
return m_sourceActor;
}
uint32_t Sapphire::StatusEffect::StatusEffect::getTargetActorId() const uint32_t Sapphire::StatusEffect::StatusEffect::getTargetActorId() const
{ {
return m_targetActor->getId(); return m_targetActor->getId();
@ -153,24 +152,6 @@ void Sapphire::StatusEffect::StatusEffect::applyStatus()
m_targetActor->calculateStats(); m_targetActor->calculateStats();
// this is only right when an action is being used by the player
// else you probably need to use an actorcontrol
//GamePacketNew< FFXIVIpcEffect > effectPacket( m_sourceActor->getId() );
//effectPacket.data().targetId = m_sourceActor->getId();
//effectPacket.data().actionAnimationId = 3;
//effectPacket.data().unknown_3 = 1;
//effectPacket.data().actionTextId = 3;
//effectPacket.data().unknown_5 = 1;
//effectPacket.data().unknown_6 = 321;
//effectPacket.data().rotation = ( uint16_t ) ( 0x8000 * ( ( m_sourceActor->getPos().getR() + 3.1415926 ) ) / 3.1415926 );
//effectPacket.data().effectTargetId = m_sourceActor->getId();
//effectPacket.data().effects[4].unknown_1 = 17;
//effectPacket.data().effects[4].bonusPercent = 30;
//effectPacket.data().effects[4].param1 = m_id;
//effectPacket.data().effects[4].unknown_5 = 0x80;
//m_sourceActor->sendToInRangeSet( effectPacket, true );
scriptMgr.onStatusReceive( m_targetActor, m_id ); scriptMgr.onStatusReceive( m_targetActor, m_id );
} }
@ -215,6 +196,11 @@ uint32_t Sapphire::StatusEffect::StatusEffect::getFlag() const
return m_flag; return m_flag;
} }
std::vector< World::Action::StatusModifier > Sapphire::StatusEffect::StatusEffect::getStatusModifiers() const
{
return m_statusModifiers;
}
void Sapphire::StatusEffect::StatusEffect::setFlag( uint32_t flag ) void Sapphire::StatusEffect::StatusEffect::setFlag( uint32_t flag )
{ {
m_flag = flag; m_flag = flag;
@ -234,3 +220,13 @@ const std::string& Sapphire::StatusEffect::StatusEffect::getName() const
{ {
return m_name; return m_name;
} }
uint8_t Sapphire::StatusEffect::StatusEffect::getSlot() const
{
return m_slot;
}
void Sapphire::StatusEffect::StatusEffect::setSlot( uint8_t slot )
{
m_slot = slot;
}

View file

@ -12,10 +12,7 @@ class StatusEffect
{ {
public: public:
StatusEffect( uint32_t id, Entity::CharaPtr sourceActor, Entity::CharaPtr targetActor, StatusEffect( uint32_t id, Entity::CharaPtr sourceActor, Entity::CharaPtr targetActor,
uint32_t duration, std::vector< World::Action::StatusModifier >& modifiers, uint32_t tickRate ); uint32_t duration, std::vector< World::Action::StatusModifier >& modifiers, uint32_t flag, uint32_t tickRate );
StatusEffect( uint32_t id, Entity::CharaPtr sourceActor, Entity::CharaPtr targetActor,
uint32_t duration, World::Action::StatusEntry& statusEntry, uint32_t tickRate );
StatusEffect( uint32_t id, Entity::CharaPtr sourceActor, Entity::CharaPtr targetActor, StatusEffect( uint32_t id, Entity::CharaPtr sourceActor, Entity::CharaPtr targetActor,
uint32_t duration, uint32_t tickRate ); uint32_t duration, uint32_t tickRate );
@ -41,6 +38,7 @@ public:
uint32_t getTickRate() const; uint32_t getTickRate() const;
uint32_t getSrcActorId() const; uint32_t getSrcActorId() const;
Entity::CharaPtr getSrcActor() const;
uint32_t getTargetActorId() const; uint32_t getTargetActorId() const;
@ -52,6 +50,8 @@ public:
uint32_t getFlag() const; uint32_t getFlag() const;
std::vector< World::Action::StatusModifier > getStatusModifiers() const;
void setLastTick( uint64_t lastTick ); void setLastTick( uint64_t lastTick );
void setParam( uint16_t param ); void setParam( uint16_t param );
@ -64,6 +64,9 @@ public:
const std::string& getName() const; const std::string& getName() const;
uint8_t getSlot() const;
void setSlot( uint8_t slot );
private: private:
uint32_t m_id; uint32_t m_id;
Entity::CharaPtr m_sourceActor; Entity::CharaPtr m_sourceActor;
@ -78,6 +81,8 @@ private:
std::pair< Common::ParamModifier, uint32_t > m_currTickEffect; std::pair< Common::ParamModifier, uint32_t > m_currTickEffect;
std::vector< World::Action::StatusModifier > m_statusModifiers; std::vector< World::Action::StatusModifier > m_statusModifiers;
std::unordered_map< Common::ParamModifier, int32_t > m_modifiers; std::unordered_map< Common::ParamModifier, int32_t > m_modifiers;
uint8_t m_slot;
}; };
} }

View file

@ -6,6 +6,7 @@
#include <WorldServer.h> #include <WorldServer.h>
#include <Service.h> #include <Service.h>
#include <Network/PacketWrappers/WarpPacket.h> #include <Network/PacketWrappers/WarpPacket.h>
#include <StatusEffect/StatusEffect.h>
#include <utility> #include <utility>
@ -14,10 +15,11 @@ using namespace Sapphire::World::Manager;
using namespace Sapphire::Network::Packets; using namespace Sapphire::Network::Packets;
using namespace Sapphire::Network::Packets::WorldPackets::Server; using namespace Sapphire::Network::Packets::WorldPackets::Server;
ActionIntegrityTask::ActionIntegrityTask( uint32_t resultId, Entity::CharaPtr pTarget, uint64_t delayTime ) : Task( delayTime ) ActionIntegrityTask::ActionIntegrityTask( uint32_t resultId, Entity::CharaPtr pTarget, Action::ActionResultList& results, uint64_t delayTime ) : Task( delayTime )
{ {
m_resultId = resultId; m_resultId = resultId;
m_pTarget = std::move( pTarget ); m_pTarget = std::move( pTarget );
m_results = results;
} }
void ActionIntegrityTask::onQueue() void ActionIntegrityTask::onQueue()
@ -27,6 +29,9 @@ void ActionIntegrityTask::onQueue()
void ActionIntegrityTask::execute() void ActionIntegrityTask::execute()
{ {
if( !m_pTarget )
return;
auto& server = Common::Service< WorldServer >::ref(); auto& server = Common::Service< WorldServer >::ref();
auto inRangePlayers = m_pTarget->getInRangePlayerIds( true ); auto inRangePlayers = m_pTarget->getInRangePlayerIds( true );
@ -37,6 +42,28 @@ void ActionIntegrityTask::execute()
auto integrityPacket = makeZonePacket< FFXIVIpcActionIntegrity >( 0 ); auto integrityPacket = makeZonePacket< FFXIVIpcActionIntegrity >( 0 );
auto& data = integrityPacket->data(); auto& data = integrityPacket->data();
integrityPacket->setSourceActor( m_pTarget->getId() ); integrityPacket->setSourceActor( m_pTarget->getId() );
for( int i = 0; i < 4; ++i )
data.Status[ i ].Source = Common::INVALID_GAME_OBJECT_ID;
int statusIdx = 0;
for( auto& actionResult : m_results )
{
if( actionResult->getCalcResultParam().Type == Common::CALC_RESULT_TYPE_SET_STATUS )
{
auto& status = data.Status[ statusIdx++ ];
auto pEffect = actionResult->getStatusEffect();
status.Source = pEffect->getSrcActorId();
status.Time = static_cast< float >( pEffect->getDuration() ) / 1000;
status.Id = static_cast< uint16_t >( pEffect->getId() );
status.Slot = static_cast< uint8_t >( pEffect->getSlot() );
status.SystemParam = static_cast< int16_t >( pEffect->getParam() );
}
if( actionResult && actionResult->getTarget() )
actionResult->execute();
}
data.Hp = m_pTarget->getHp(); data.Hp = m_pTarget->getHp();
data.HpMax = m_pTarget->getMaxHp(); data.HpMax = m_pTarget->getMaxHp();
data.Mp = m_pTarget->getMp(); data.Mp = m_pTarget->getMp();
@ -44,6 +71,9 @@ void ActionIntegrityTask::execute()
data.Tp = m_pTarget->getTp(); data.Tp = m_pTarget->getTp();
data.ResultId = m_resultId; data.ResultId = m_resultId;
data.Target = m_pTarget->getId(); data.Target = m_pTarget->getId();
data.StatusCount = statusIdx;
data.ClassJob = static_cast< uint8_t >( m_pTarget->getClass() );
data.unknown_E0 = 0xE0;
server.queueForPlayers( inRangePlayers, integrityPacket ); server.queueForPlayers( inRangePlayers, integrityPacket );
@ -51,7 +81,7 @@ void ActionIntegrityTask::execute()
std::string ActionIntegrityTask::toString() std::string ActionIntegrityTask::toString()
{ {
return fmt::format( "ActionIntegrityTask: ResultId#{}, TargetId#{}, ElapsedTimeMs: {}", m_resultId, m_pTarget->getId(), getDelayTimeMs() ); return fmt::format( "ActionIntegrityTask: ResultId#{}, TargetId#{}, ElapsedTimeMs: {}", m_resultId, m_pTarget ? m_pTarget->getId() : 0, getDelayTimeMs() );
} }

View file

@ -4,6 +4,7 @@
#include <string> #include <string>
#include <ForwardsZone.h> #include <ForwardsZone.h>
#include "Task.h" #include "Task.h"
#include <Action/ActionResult.h>
namespace Sapphire::World namespace Sapphire::World
{ {
@ -11,7 +12,7 @@ namespace Sapphire::World
class ActionIntegrityTask : public Task class ActionIntegrityTask : public Task
{ {
public: public:
ActionIntegrityTask( uint32_t resultId, Entity::CharaPtr pTarget, uint64_t delayTime ); ActionIntegrityTask( uint32_t resultId, Entity::CharaPtr pTarget, Action::ActionResultList& results, uint64_t delayTime );
void onQueue() override; void onQueue() override;
void execute() override; void execute() override;
@ -20,6 +21,7 @@ public:
private: private:
uint32_t m_resultId; uint32_t m_resultId;
Entity::CharaPtr m_pTarget; Entity::CharaPtr m_pTarget;
Action::ActionResultList m_results;
}; };
template< typename... Args > template< typename... Args >

View file

@ -29,7 +29,7 @@
#include "Actor/Player.h" #include "Actor/Player.h"
#include "Actor/EventObject.h" #include "Actor/EventObject.h"
#include "Action/EffectResult.h" #include "Action/ActionResult.h"
#include "Network/GameConnection.h" #include "Network/GameConnection.h"
@ -466,8 +466,6 @@ bool Territory::update( uint64_t tickCount )
updateSessions( tickCount, changedWeather ); updateSessions( tickCount, changedWeather );
onUpdate( tickCount ); onUpdate( tickCount );
processEffectResults( tickCount );
if( !m_playerMap.empty() ) if( !m_playerMap.empty() )
m_lastActivityTime = tickCount; m_lastActivityTime = tickCount;
@ -824,7 +822,7 @@ void Territory::updateSpawnPoints()
} }
} }
uint32_t Territory::getNextEffectResultId() uint32_t Territory::getNextActionResultId()
{ {
return m_effectCounter++; return m_effectCounter++;
} }
@ -875,30 +873,6 @@ std::shared_ptr< World::Navi::NaviProvider > Territory::getNaviProvider()
return m_pNaviProvider; return m_pNaviProvider;
} }
void Territory::addEffectResult( World::Action::EffectResultPtr result )
{
m_effectResults.emplace_back( std::move( result ) );
}
void Territory::processEffectResults( uint64_t tickCount )
{
// todo: move this to generic territory/instance delay wrapper cause it might be useful scheduling other things
for( auto it = m_effectResults.begin(); it != m_effectResults.end(); )
{
auto effect = *it;
if( tickCount < effect->getDelay() )
{
++it;
continue;
}
effect->execute();
it = m_effectResults.erase( it );
}
}
bool Territory::loadBNpcs() bool Territory::loadBNpcs()
{ {
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();

View file

@ -72,8 +72,6 @@ namespace Sapphire
uint32_t m_effectCounter{}; uint32_t m_effectCounter{};
std::shared_ptr< World::Navi::NaviProvider > m_pNaviProvider; std::shared_ptr< World::Navi::NaviProvider > m_pNaviProvider;
std::vector< World::Action::EffectResultPtr > m_effectResults;
Common::TerritoryIdent m_ident; Common::TerritoryIdent m_ident;
float m_inRangeDistance; float m_inRangeDistance;
@ -194,13 +192,9 @@ namespace Sapphire
void updateSpawnPoints(); void updateSpawnPoints();
uint32_t getNextEffectResultId(); uint32_t getNextActionResultId();
std::shared_ptr< World::Navi::NaviProvider > getNaviProvider(); std::shared_ptr< World::Navi::NaviProvider > getNaviProvider();
void addEffectResult( World::Action::EffectResultPtr result );
void processEffectResults( uint64_t tickCount );
}; };
} }

View file

@ -386,20 +386,21 @@ void WorldServer::mainLoop()
{ {
auto tickCount = Common::Util::getTimeMs(); auto tickCount = Common::Util::getTimeMs();
auto currTime = Common::Util::getTimeSeconds();
taskMgr.update( tickCount );
updateSessions( currTime );
if( tickCount - m_lastServerTick < 300 ) if( tickCount - m_lastServerTick < 300 )
{ {
std::this_thread::sleep_for( std::chrono::milliseconds( 50 ) ); std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
continue; continue;
} }
m_lastServerTick = tickCount; m_lastServerTick = tickCount;
auto currTime = Common::Util::getTimeSeconds();
taskMgr.update( tickCount );
terriMgr.updateTerritoryInstances( tickCount ); terriMgr.updateTerritoryInstances( tickCount );
scriptMgr.update(); scriptMgr.update();
contentFinder.update(); contentFinder.update();
updateSessions( currTime );
DbKeepAlive( currTime ); DbKeepAlive( currTime );
} }