mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-05-01 16:37:45 +00:00
basic action sanity checking, partial casting support, some cleanup
This commit is contained in:
parent
2cf1b5aaf7
commit
370261591e
5 changed files with 106 additions and 28 deletions
|
@ -22,30 +22,39 @@ using namespace Sapphire::Network::ActorControl;
|
||||||
Sapphire::Action::Action::Action() = default;
|
Sapphire::Action::Action::Action() = default;
|
||||||
Sapphire::Action::Action::~Action() = default;
|
Sapphire::Action::Action::~Action() = default;
|
||||||
|
|
||||||
Sapphire::Action::Action::Action( Entity::CharaPtr caster, Entity::CharaPtr target,
|
Sapphire::Action::Action::Action( Entity::CharaPtr caster, uint32_t actionId,
|
||||||
uint16_t actionId, FrameworkPtr fw ) :
|
Data::ActionPtr action, FrameworkPtr fw ) :
|
||||||
|
|
||||||
m_pSource( std::move( caster ) ),
|
m_pSource( std::move( caster ) ),
|
||||||
m_pTarget( std::move( target ) ),
|
|
||||||
m_pFw( std::move( fw ) ),
|
m_pFw( std::move( fw ) ),
|
||||||
m_id( actionId ),
|
m_id( actionId ),
|
||||||
m_startTime( 0 )
|
m_startTime( 0 )
|
||||||
{
|
{
|
||||||
auto exdData = m_pFw->get< Data::ExdDataGenerated >();
|
m_castTime = static_cast< uint32_t >( action->cast100ms ) * 100;
|
||||||
assert( exdData );
|
|
||||||
|
|
||||||
auto actionData = exdData->get< Data::Action >( actionId );
|
|
||||||
// todo: clients can crash the server here, ideally we do this check outside of the action anyway
|
|
||||||
assert( actionData );
|
|
||||||
|
|
||||||
m_castTime = actionData->cast100ms * 100;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t Sapphire::Action::Action::getId() const
|
uint32_t Sapphire::Action::Action::getId() const
|
||||||
{
|
{
|
||||||
return m_id;
|
return m_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Sapphire::Common::ActionType Sapphire::Action::Action::getType() const
|
||||||
|
{
|
||||||
|
return m_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sapphire::Action::Action::setType( Sapphire::Common::ActionType type )
|
||||||
|
{
|
||||||
|
m_type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sapphire::Action::Action::setTargetChara( Sapphire::Entity::CharaPtr chara )
|
||||||
|
{
|
||||||
|
assert( chara );
|
||||||
|
|
||||||
|
m_pTarget = chara;
|
||||||
|
m_targetId = chara->getId();
|
||||||
|
}
|
||||||
|
|
||||||
Sapphire::Entity::CharaPtr Sapphire::Action::Action::getTargetChara() const
|
Sapphire::Entity::CharaPtr Sapphire::Action::Action::getTargetChara() const
|
||||||
{
|
{
|
||||||
return m_pTarget;
|
return m_pTarget;
|
||||||
|
@ -102,7 +111,7 @@ bool Sapphire::Action::Action::update()
|
||||||
|
|
||||||
uint64_t currTime = Util::getTimeMs();
|
uint64_t currTime = Util::getTimeMs();
|
||||||
|
|
||||||
if( ( currTime - m_startTime ) > m_castTime )
|
if( !isCastedAction() || ( currTime - m_startTime ) > m_castTime )
|
||||||
{
|
{
|
||||||
onFinish();
|
onFinish();
|
||||||
return true;
|
return true;
|
||||||
|
@ -117,7 +126,6 @@ void Sapphire::Action::Action::onStart()
|
||||||
if( isCastedAction() )
|
if( isCastedAction() )
|
||||||
{
|
{
|
||||||
m_pSource->getAsPlayer()->sendDebug( "onStart()" );
|
m_pSource->getAsPlayer()->sendDebug( "onStart()" );
|
||||||
m_startTime = Util::getTimeMs();
|
|
||||||
|
|
||||||
auto castPacket = makeZonePacket< FFXIVIpcActorCast >( getId() );
|
auto castPacket = makeZonePacket< FFXIVIpcActorCast >( getId() );
|
||||||
|
|
||||||
|
@ -125,7 +133,7 @@ void Sapphire::Action::Action::onStart()
|
||||||
castPacket->data().skillType = Common::SkillType::Normal;
|
castPacket->data().skillType = Common::SkillType::Normal;
|
||||||
castPacket->data().unknown_1 = m_id;
|
castPacket->data().unknown_1 = m_id;
|
||||||
// This is used for the cast bar above the target bar of the caster.
|
// This is used for the cast bar above the target bar of the caster.
|
||||||
castPacket->data().cast_time = static_cast< float >( m_castTime / 1000.f );
|
castPacket->data().cast_time = m_castTime / 1000.f;
|
||||||
castPacket->data().target_id = m_pTarget->getId();
|
castPacket->data().target_id = m_pTarget->getId();
|
||||||
|
|
||||||
m_pSource->sendToInRangeSet( castPacket, true );
|
m_pSource->sendToInRangeSet( castPacket, true );
|
||||||
|
|
|
@ -4,6 +4,12 @@
|
||||||
#include <Common.h>
|
#include <Common.h>
|
||||||
#include "ForwardsZone.h"
|
#include "ForwardsZone.h"
|
||||||
|
|
||||||
|
namespace Sapphire::Data
|
||||||
|
{
|
||||||
|
struct Action;
|
||||||
|
using ActionPtr = std::shared_ptr< Action >;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Sapphire::Action
|
namespace Sapphire::Action
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -12,12 +18,16 @@ namespace Sapphire::Action
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Action();
|
Action();
|
||||||
Action( Entity::CharaPtr caster, Entity::CharaPtr target, uint16_t actionId, FrameworkPtr fw );
|
Action( Entity::CharaPtr caster, uint32_t actionId, Data::ActionPtr action, FrameworkPtr fw );
|
||||||
|
|
||||||
virtual ~Action();
|
virtual ~Action();
|
||||||
|
|
||||||
uint16_t getId() const;
|
uint32_t getId() const;
|
||||||
|
|
||||||
|
Common::ActionType getType() const;
|
||||||
|
void setType( Common::ActionType type );
|
||||||
|
|
||||||
|
void setTargetChara( Entity::CharaPtr chara );
|
||||||
Entity::CharaPtr getTargetChara() const;
|
Entity::CharaPtr getTargetChara() const;
|
||||||
Entity::CharaPtr getActionSource() const;
|
Entity::CharaPtr getActionSource() const;
|
||||||
|
|
||||||
|
@ -43,13 +53,16 @@ namespace Sapphire::Action
|
||||||
virtual bool update();
|
virtual bool update();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint16_t m_id;
|
uint32_t m_id;
|
||||||
|
|
||||||
|
Common::ActionType m_type;
|
||||||
|
|
||||||
uint64_t m_startTime;
|
uint64_t m_startTime;
|
||||||
uint32_t m_castTime;
|
uint32_t m_castTime;
|
||||||
|
|
||||||
Entity::CharaPtr m_pSource;
|
Entity::CharaPtr m_pSource;
|
||||||
Entity::CharaPtr m_pTarget;
|
Entity::CharaPtr m_pTarget;
|
||||||
|
uint64_t m_targetId;
|
||||||
|
|
||||||
bool m_bInterrupt;
|
bool m_bInterrupt;
|
||||||
|
|
||||||
|
|
|
@ -16,13 +16,64 @@ World::Manager::ActionMgr::ActionMgr( Sapphire::FrameworkPtr pFw ) :
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::Manager::ActionMgr::handleAoEPlayerAction( Entity::Player& player, uint8_t type,
|
void World::Manager::ActionMgr::handleAoEPlayerAction( Entity::Player& player, uint8_t type,
|
||||||
Data::ActionPtr action, Common::FFXIVARR_POSITION3 pos )
|
uint32_t actionId, Data::ActionPtr actionData,
|
||||||
|
Common::FFXIVARR_POSITION3 pos )
|
||||||
{
|
{
|
||||||
player.sendDebug( "got aoe act: {0}", action->name );
|
player.sendDebug( "got aoe act: {0}", actionData->name );
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::Manager::ActionMgr::handleTargetedPlayerAction( Entity::Player& player, uint8_t type,
|
void World::Manager::ActionMgr::handleTargetedPlayerAction( Entity::Player& player, uint8_t type,
|
||||||
Data::ActionPtr action, uint64_t targetId )
|
uint32_t actionId, Data::ActionPtr actionData, uint64_t targetId )
|
||||||
{
|
{
|
||||||
player.sendDebug( "got act: {0}", action->name );
|
player.sendDebug( "got act: {0}", actionData->name );
|
||||||
|
|
||||||
|
auto action = Action::make_Action( player.getAsPlayer(), nullptr, actionId, actionData, framework() );
|
||||||
|
action->setType( static_cast< Common::ActionType >( type ) );
|
||||||
|
|
||||||
|
bootstrapAction( player, action, *actionData );
|
||||||
|
}
|
||||||
|
|
||||||
|
void World::Manager::ActionMgr::bootstrapAction( Entity::Player& player,
|
||||||
|
Action::ActionPtr currentAction,
|
||||||
|
Data::Action& actionData )
|
||||||
|
{
|
||||||
|
if( !canPlayerUseAction( player, *currentAction, actionData ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// instantly cast and finish actions that have no cast time
|
||||||
|
// not worth adding it to the player
|
||||||
|
// todo: what do in cases of swiftcast/etc? script callback?
|
||||||
|
if( !currentAction->isCastedAction() )
|
||||||
|
{
|
||||||
|
currentAction->start();
|
||||||
|
currentAction->onFinish();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise, set the action on the player and start it
|
||||||
|
player.setCurrentAction( currentAction );
|
||||||
|
currentAction->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool World::Manager::ActionMgr::canPlayerUseAction( Entity::Player& player,
|
||||||
|
Action::Action& currentAction,
|
||||||
|
Data::Action& actionData )
|
||||||
|
{
|
||||||
|
// lol
|
||||||
|
if( !player.isAlive() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// npc actions/non player actions
|
||||||
|
if( actionData.classJob == -1 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// todo: check class/job reqs
|
||||||
|
|
||||||
|
// todo: min tp
|
||||||
|
// todo: min mp
|
||||||
|
|
||||||
|
// todo: script callback for action conditionals?
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
namespace Sapphire::Data
|
namespace Sapphire::Data
|
||||||
{
|
{
|
||||||
class Action;
|
struct Action;
|
||||||
using ActionPtr = std::shared_ptr< Action >;
|
using ActionPtr = std::shared_ptr< Action >;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,8 +18,14 @@ namespace Sapphire::World::Manager
|
||||||
explicit ActionMgr( FrameworkPtr pFw );
|
explicit ActionMgr( FrameworkPtr pFw );
|
||||||
~ActionMgr() = default;
|
~ActionMgr() = default;
|
||||||
|
|
||||||
void handleTargetedPlayerAction( Entity::Player& player, uint8_t type, Data::ActionPtr action, uint64_t targetId );
|
void handleTargetedPlayerAction( Entity::Player& player, uint8_t type, uint32_t actionId,
|
||||||
void handleAoEPlayerAction( Entity::Player& player, uint8_t type, Data::ActionPtr action, Common::FFXIVARR_POSITION3 pos );
|
Data::ActionPtr actionData, uint64_t targetId );
|
||||||
|
void handleAoEPlayerAction( Entity::Player& player, uint8_t type, uint32_t actionId,
|
||||||
|
Data::ActionPtr actionData, Common::FFXIVARR_POSITION3 pos );
|
||||||
|
|
||||||
|
private:
|
||||||
|
void bootstrapAction( Entity::Player& player, Action::ActionPtr currentAction, Data::Action& actionData );
|
||||||
|
bool canPlayerUseAction( Entity::Player& player, Action::Action& currentAction, Data::Action& actionData );
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ void Sapphire::Network::GameConnection::actionHandler( FrameworkPtr pFw,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto actionMgr = pFw->get< World::Manager::ActionMgr >();
|
auto actionMgr = pFw->get< World::Manager::ActionMgr >();
|
||||||
actionMgr->handleTargetedPlayerAction( player, type, action, targetId );
|
actionMgr->handleTargetedPlayerAction( player, type, actionId, action, targetId );
|
||||||
|
|
||||||
player.sendDebug( "Skill type: {0}, sequence: {1}, actionId: {2}, targetId: {3}", type, sequence, actionId, targetId );
|
player.sendDebug( "Skill type: {0}, sequence: {1}, actionId: {2}, targetId: {3}", type, sequence, actionId, targetId );
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ void Sapphire::Network::GameConnection::aoeActionHandler( FrameworkPtr pFw,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto actionMgr = pFw->get< World::Manager::ActionMgr >();
|
auto actionMgr = pFw->get< World::Manager::ActionMgr >();
|
||||||
actionMgr->handleAoEPlayerAction( player, type, action, pos );
|
actionMgr->handleAoEPlayerAction( player, type, actionId, action, pos );
|
||||||
|
|
||||||
player.sendDebug( "Skill type: {0}, sequence: {1}, actionId: {2}, x:{3}, y:{4}, z:{5}",
|
player.sendDebug( "Skill type: {0}, sequence: {1}, actionId: {2}, x:{3}, y:{4}, z:{5}",
|
||||||
type, sequence, actionId, pos.x, pos.y, pos.z );
|
type, sequence, actionId, pos.x, pos.y, pos.z );
|
||||||
|
|
Loading…
Add table
Reference in a new issue