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

Converted autoattacks to the action system

This commit is contained in:
Mordred 2023-03-11 20:52:52 +01:00
parent 7c4a053bea
commit 5cc7b0c87b
15 changed files with 93 additions and 100 deletions

View file

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

View file

@ -333,9 +333,11 @@ void Action::Action::start()
// 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 );
player->setRecastGroup( m_cooldownGroup, static_cast< float >( m_castTimeMs ) / 1000.f );
server().queueForPlayer( player->getCharacterId(), actionStartPkt );
if( player )
{
player->setRecastGroup( m_cooldownGroup, static_cast< float >( m_castTimeMs ) / 1000.f );
server().queueForPlayer( player->getCharacterId(), actionStartPkt );
}
onStart();
@ -369,7 +371,6 @@ void Action::Action::onStart()
void Action::Action::interrupt()
{
assert( m_pSource );
// things that aren't players don't care about cooldowns and state flags
if( m_pSource->isPlayer() )
{
@ -409,7 +410,6 @@ void Action::Action::onInterrupt()
void Action::Action::execute()
{
assert( m_pSource );
// subtract costs first, if somehow the caster stops meeting those requirements cancel the cast
if( !consumeResources() )
{
@ -464,6 +464,10 @@ std::pair< uint32_t, Common::ActionHitSeverityType > Action::Action::calcDamage(
wepDmg = item->getMagicalDmg();
else
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 );
@ -574,7 +578,6 @@ void Action::Action::buildActionResults()
shouldRestoreMP = false;
}
}
m_actionResultBuilder->sendActionResults( m_hitActors );
// TODO: disabled, reset kills our queued actions

View file

@ -36,6 +36,7 @@
#include <Manager/PlayerMgr.h>
#include <Manager/TaskMgr.h>
#include <Manager/MgrUtil.h>
#include <Manager/ActionMgr.h>
#include <Script/ScriptMgr.h>
#include <Task/RemoveBNpcTask.h>
#include <Task/FadeBNpcTask.h>
@ -643,6 +644,8 @@ void BNpc::update( uint64_t tickCount )
if( !pNaviProvider )
return;
checkAction();
switch( m_state )
{
case BNpcState::Dead:
@ -803,7 +806,7 @@ void BNpc::restHp()
m_hp = getMaxHp();
}
sendHudParam();
Network::Util::Packet::sendHudParam( *this );
}
void BNpc::onActionHostile( CharaPtr pSource )
@ -963,6 +966,8 @@ void BNpc::autoAttack( CharaPtr pTarget )
{
auto& teriMgr = Common::Service< World::Manager::TerritoryMgr >::ref();
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();
@ -972,26 +977,7 @@ void BNpc::autoAttack( CharaPtr pTarget )
pTarget->onActionHostile( getAsChara() );
m_lastAttack = tick;
srand( static_cast< uint32_t >( tick ) );
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->getNextActionResultId();
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 ) );
actionMgr.handleTargetedAction( *this, 7, exdData.getRow< Excel::Action >( 7 ), pTarget->getId(), 0 );
}
}

View file

@ -285,6 +285,16 @@ void Chara::die()
Network::Util::Packet::sendActorControl( getInRangePlayerIds( selfNeedsUpdate ), getId(), DeathAnimation );
}
uint64_t Chara::getLastAttack() const
{
return m_lastAttack;
}
void Chara::setLastAttack( uint64_t tickCount )
{
m_lastAttack = tickCount;
}
/*!
Calculates and sets the rotation to look towards a specified
position
@ -426,18 +436,6 @@ void Chara::restoreMP( uint32_t 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 Chara::sendHudParam()
{
Network::Util::Packet::sendHudParam( *this );
}
/*! \return ActionPtr of the currently registered action, or nullptr */
Action::ActionPtr Chara::getCurrentAction() const
{

View file

@ -203,6 +203,10 @@ namespace Sapphire::Entity
void die();
uint64_t getLastAttack() const;
void setLastAttack( uint64_t tickCount );
Common::ActorStatus getStatus() const;
void setStatus( Common::ActorStatus status );
@ -223,8 +227,6 @@ namespace Sapphire::Entity
virtual uint8_t getLevel() const;
virtual void sendHudParam();
virtual void takeDamage( uint32_t damage );
virtual void heal( uint32_t amount );

View file

@ -923,16 +923,6 @@ void Player::update( uint64_t 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 )
{
auto spawnId = m_actorSpawnIndexAllocator.freeUsedSpawnIndex( actorId );
@ -1295,9 +1285,9 @@ void Player::autoAttack( CharaPtr pTarget )
auto& RNGMgr = Common::Service< World::Manager::RNGMgr >::ref();
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 );
@ -1320,7 +1310,7 @@ void Player::autoAttack( CharaPtr pTarget )
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 ) );
}

View file

@ -83,12 +83,6 @@ namespace Sapphire::Entity
/*! Event called on every session iteration */
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
//////////////////////////////////////////////////////////////////////////////////////////////////////
/*! load data for currently active quests */

View file

@ -59,13 +59,13 @@ void ActionMgr::handleItemManipulationAction( Entity::Player& player, uint32_t a
action->start();
}
void ActionMgr::handleTargetedPlayerAction( Entity::Player& player, uint32_t actionId,
Excel::ExcelStructPtr< Excel::Action > actionData, uint64_t targetId, uint16_t requestId )
void ActionMgr::handleTargetedAction( Entity::Chara& src, uint32_t actionId,
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->setPos( player.getPos() );
action->setPos( src.getPos() );
if( !action->init() )
return;
@ -77,7 +77,7 @@ void ActionMgr::handleTargetedPlayerAction( Entity::Player& player, uint32_t act
return;
}
bootstrapAction( player, action, actionData );
bootstrapAction( src, action, actionData );
}
void ActionMgr::handleItemAction( Sapphire::Entity::Player& player, uint32_t itemId,
@ -124,7 +124,7 @@ void ActionMgr::handleMountAction( Entity::Player& player, uint16_t mountId,
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 )
{
/*
@ -137,20 +137,25 @@ void ActionMgr::bootstrapAction( Entity::Player& player, Action::ActionPtr curre
}
*/
if( player.getCurrentAction() )
if( src.getCurrentAction() )
{
PlayerMgr::sendDebug( player, "Skill queued: {0}", currentAction->getId() );
player.setQueuedAction( currentAction );
if( src.isPlayer() )
{
auto& player = *src.getAsPlayer();
PlayerMgr::sendDebug( player, "Skill queued: {0}", currentAction->getId() );
player.setQueuedAction( currentAction );
}
}
else
{
// if we have a cast time we want to associate the action with the player so update is called
if( currentAction->hasCastTime() )
player.setCurrentAction( currentAction );
src.setCurrentAction( currentAction );
// todo: what do in cases of swiftcast/etc? script callback?
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 handleTargetedPlayerAction( Entity::Player& player, uint32_t actionId,
std::shared_ptr< Excel::ExcelStruct< Excel::Action > > actionData, uint64_t targetId, uint16_t requestId );
void handleTargetedAction( Entity::Chara& chara, uint32_t actionId,
std::shared_ptr< Excel::ExcelStruct< Excel::Action > > actionData, uint64_t targetId, uint16_t requestId );
void handlePlacedPlayerAction( Entity::Player& player, uint32_t actionId,
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 );
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
void handleItemActionVFX( Entity::Player& player, uint32_t itemId, uint16_t vfxId );

View file

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

View file

@ -71,8 +71,12 @@ void Util::Packet::sendBaseParams( Entity::Player& player )
void Util::Packet::sendHudParam( Entity::Chara& source )
{
auto hudParamPacket = makeHudParam( source );
server().queueForPlayers( source.getInRangePlayerIds( source.isPlayer() ), hudParamPacket );
if( source.isPlayer() )
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::Packet::sendStatusUpdate( Entity::Player& player )

View file

@ -204,27 +204,35 @@ void Sapphire::World::Session::sendReplayInfo()
PlayerMgr::sendDebug( *getPlayer(), message );
}
void Sapphire::World::Session::processOutQueue()
{
if( !m_pZoneConnection )
return;
m_pZoneConnection->processOutQueue();
}
void Sapphire::World::Session::update()
{
if( m_isReplaying )
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();
// 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();
updateLastSqlTime();
m_pPlayer->updateSql();
}
m_pZoneConnection->processOutQueue();
if( m_pChatConnection )
{
m_pChatConnection->processInQueue();

View file

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

View file

@ -49,9 +49,6 @@ void ActionIntegrityTask::execute()
int statusIdx = 0;
for( auto& actionResult : m_results )
{
if( actionResult && actionResult->getTarget() && actionResult->getTarget()->isAlive() )
actionResult->execute();
if( actionResult->getCalcResultParam().Type == Common::CALC_RESULT_TYPE_SET_STATUS )
{
auto& status = data.Status[ statusIdx++ ];
@ -62,6 +59,9 @@ void ActionIntegrityTask::execute()
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();

View file

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