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

add teleporting back in, remove action targeting for now

This commit is contained in:
NotAdam 2019-03-07 21:58:12 +11:00
parent fc62be84a2
commit 2f4ca9b589
14 changed files with 227 additions and 112 deletions

View file

@ -539,7 +539,7 @@ namespace Sapphire::Common
enum class ActionPrimaryCostType : uint8_t enum class ActionPrimaryCostType : uint8_t
{ {
// None = 0, // ? None = 0, // ?
MagicPoints = 3, MagicPoints = 3,
TacticsPoints = 5, TacticsPoints = 5,
// WARGauge = 22, // WARGauge = 22,
@ -931,6 +931,12 @@ namespace Sapphire::Common
IsFreeCompanyEstate = 16, IsFreeCompanyEstate = 16,
}; };
struct PlayerTeleportQuery
{
uint16_t targetAetheryte;
uint16_t cost;
};
using PlayerStateFlagList = std::vector< PlayerStateFlag >; using PlayerStateFlagList = std::vector< PlayerStateFlag >;
} }

View file

@ -12,12 +12,12 @@ public:
{ {
} }
void onFinish( Sapphire::Action::Action& currentAction ) override void onExecute( Sapphire::Action::Action& action ) override
{ {
if( !currentAction.getSourceChara()->isPlayer() ) if( !action.getSourceChara()->isPlayer() )
return; return;
currentAction.getSourceChara()->getAsPlayer()->returnToHomepoint(); action.getSourceChara()->getAsPlayer()->returnToHomepoint();
} }
}; };

View file

@ -11,9 +11,9 @@ public:
{ {
} }
void onFinish( Sapphire::Action::Action& currentAction ) override void onExecute( Sapphire::Action::Action& action ) override
{ {
auto sourceChara = currentAction.getSourceChara(); auto sourceChara = action.getSourceChara();
if( !sourceChara->isPlayer() ) if( !sourceChara->isPlayer() )
return; return;

View file

@ -0,0 +1,46 @@
#include <Script/NativeScriptApi.h>
#include <ScriptObject.h>
#include <Actor/Player.h>
#include <Action/Action.h>
using namespace Sapphire;
class ActionTeleport5 :
public Sapphire::ScriptAPI::ActionScript
{
public:
ActionTeleport5() :
Sapphire::ScriptAPI::ActionScript( 5 )
{
}
void onExecute( Sapphire::Action::Action& action ) override
{
auto player = action.getSourceChara()->getAsPlayer();
if( !player )
return;
auto teleportQuery = player->getTeleportQuery();
if( player->getCurrency( Common::CurrencyType::Gil ) < teleportQuery.cost )
{
action.interrupt();
return;
}
if( teleportQuery.targetAetheryte == 0 )
{
action.interrupt();
}
player->removeCurrency( Common::CurrencyType::Gil, teleportQuery.cost );
player->setZoningType( Common::ZoneingType::Teleport );
player->teleport( static_cast< uint16_t >( teleportQuery.targetAetheryte ) );
player->clearTeleportQuery();
}
};
EXPOSE_SCRIPT( ActionTeleport5 );

View file

@ -12,9 +12,9 @@ public:
{ {
} }
void onFinish( Sapphire::Action::Action& currentAction ) override void onExecute( Sapphire::Action::Action& action ) override
{ {
if( auto player = currentAction.getSourceChara()->getAsPlayer() ) if( auto player = action.getSourceChara()->getAsPlayer() )
player->sendDebug( "Imagine you just hit an enemy for 150 potency. Incredible, right?" ); player->sendDebug( "Imagine you just hit an enemy for 150 potency. Incredible, right?" );
} }

View file

@ -26,45 +26,21 @@ 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, uint32_t actionId, FrameworkPtr fw ) :
Action( std::move( caster ), actionId, nullptr, std::move( fw ) )
{
}
Sapphire::Action::Action::Action( Entity::CharaPtr caster, uint32_t actionId, Sapphire::Action::Action::Action( Entity::CharaPtr caster, uint32_t actionId,
Data::ActionPtr actionData, FrameworkPtr fw ) : Data::ActionPtr actionData, FrameworkPtr fw ) :
m_pSource( std::move( caster ) ), m_pSource( std::move( caster ) ),
m_pFw( std::move( fw ) ), m_pFw( std::move( fw ) ),
m_actionData( std::move( actionData ) ),
m_id( actionId ), m_id( actionId ),
m_targetId( 0 ),
m_startTime( 0 ), m_startTime( 0 ),
m_interruptType( Common::ActionInterruptType::None ), m_interruptType( Common::ActionInterruptType::None )
m_hasResidentTarget( false )
{ {
m_actionData = actionData;
m_castTime = static_cast< uint32_t >( actionData->cast100ms * 100 );
m_recastTime = static_cast< uint16_t >( actionData->recast100ms * 100 );
m_cooldownGroup = actionData->cooldownGroup;
m_range = actionData->range;
m_effectRange = actionData->effectRange;
m_aspect = static_cast< Common::ActionAspect >( actionData->aspect );
// a default range is set by the game for the class/job
if( m_range == -1 )
{
switch( static_cast< Common::ClassJob >( actionData->classJob ) )
{
case Common::ClassJob::Bard:
case Common::ClassJob::Archer:
m_range = 25;
// anything that isnt ranged
default:
m_range = 3;
}
}
m_primaryCostType = static_cast< Common::ActionPrimaryCostType >( actionData->costType );
m_primaryCost = actionData->cost;
// todo: add missing rows for secondaryCostType/secondaryCostType and rename the current rows to primaryCostX
calculateActionCost();
} }
uint32_t Sapphire::Action::Action::getId() const uint32_t Sapphire::Action::Action::getId() const
@ -72,6 +48,50 @@ uint32_t Sapphire::Action::Action::getId() const
return m_id; return m_id;
} }
bool Sapphire::Action::Action::init()
{
if( !m_actionData )
{
// need to get actionData
auto exdData = m_pFw->get< Data::ExdDataGenerated >();
assert( exdData );
auto actionData = exdData->get< Data::Action >( m_id );
assert( actionData );
m_actionData = actionData;
}
m_castTime = static_cast< uint32_t >( m_actionData->cast100ms * 100 );
m_recastTime = static_cast< uint16_t >( m_actionData->recast100ms * 100 );
m_cooldownGroup = m_actionData->cooldownGroup;
m_range = m_actionData->range;
m_effectRange = m_actionData->effectRange;
m_aspect = static_cast< Common::ActionAspect >( m_actionData->aspect );
// a default range is set by the game for the class/job
if( m_range == -1 )
{
switch( static_cast< Common::ClassJob >( m_actionData->classJob ) )
{
case Common::ClassJob::Bard:
case Common::ClassJob::Archer:
m_range = 25;
// anything that isnt ranged
default:
m_range = 3;
}
}
m_primaryCostType = static_cast< Common::ActionPrimaryCostType >( m_actionData->costType );
m_primaryCost = m_actionData->cost;
// todo: add missing rows for secondaryCostType/secondaryCostType and rename the current rows to primaryCostX
return true;
}
void Sapphire::Action::Action::setPos( Sapphire::Common::FFXIVARR_POSITION3 pos ) void Sapphire::Action::Action::setPos( Sapphire::Common::FFXIVARR_POSITION3 pos )
{ {
m_pos = pos; m_pos = pos;
@ -82,29 +102,19 @@ Sapphire::Common::FFXIVARR_POSITION3 Sapphire::Action::Action::getPos() const
return m_pos; return m_pos;
} }
void Sapphire::Action::Action::setTargetChara( Sapphire::Entity::CharaPtr chara ) void Sapphire::Action::Action::setTargetId( uint64_t targetId )
{
assert( chara );
m_pTarget = chara;
m_targetId = chara->getId();
m_hasResidentTarget = false;
}
void Sapphire::Action::Action::setResidentTargetId( uint64_t targetId )
{ {
m_targetId = targetId; m_targetId = targetId;
m_hasResidentTarget = true;
} }
bool Sapphire::Action::Action::hasResidentTarget() const uint64_t Sapphire::Action::Action::getTargetId() const
{ {
return m_hasResidentTarget; return m_targetId;
} }
Sapphire::Entity::CharaPtr Sapphire::Action::Action::getTargetChara() const bool Sapphire::Action::Action::hasClientsideTarget() const
{ {
return m_pTarget; return m_targetId > 0xFFFFFFFF;
} }
bool Sapphire::Action::Action::isInterrupted() const bool Sapphire::Action::Action::isInterrupted() const
@ -149,7 +159,7 @@ bool Sapphire::Action::Action::update()
return true; return true;
} }
if( !hasResidentTarget() ) if( !hasClientsideTarget() )
{ {
// todo: check if the target is still in range // todo: check if the target is still in range
} }
@ -264,9 +274,8 @@ void Sapphire::Action::Action::execute()
} }
if( !hasResidentTarget() ) if( !hasClientsideTarget() )
{ {
assert( m_pTarget );
pScriptMgr->onExecute( *this ); pScriptMgr->onExecute( *this );
} }
else if( auto player = m_pSource->getAsPlayer() ) else if( auto player = m_pSource->getAsPlayer() )
@ -282,18 +291,20 @@ void Sapphire::Action::Action::calculateActionCost()
// check primary cost // check primary cost
switch( m_primaryCostType ) switch( m_primaryCostType )
{ {
case ActionPrimaryCostType::None:
{
break;
}
case ActionPrimaryCostType::MagicPoints: case ActionPrimaryCostType::MagicPoints:
{ {
calculateMPCost( m_primaryCost ); calculateMPCost( m_primaryCost );
break; break;
} }
case ActionPrimaryCostType::TacticsPoints: case ActionPrimaryCostType::TacticsPoints:
{ {
break; break;
} }
default: default:
{ {
if( auto player = m_pSource->getAsPlayer() ) if( auto player = m_pSource->getAsPlayer() )
@ -434,13 +445,13 @@ bool Sapphire::Action::Action::playerPrecheck( Entity::Player& player )
// reset target on actions that can only be casted on yourself while having a target set // reset target on actions that can only be casted on yourself while having a target set
// todo: check what actions send when targeting an enemy // todo: check what actions send when targeting an enemy
if( m_actionData->canTargetSelf && // if( m_actionData->canTargetSelf &&
!m_actionData->canTargetFriendly && // !m_actionData->canTargetFriendly &&
!m_actionData->canTargetHostile && // !m_actionData->canTargetHostile &&
!m_actionData->canTargetParty ) // !m_actionData->canTargetParty )
{ // {
setTargetChara( getSourceChara() ); // setTargetId( getSourceChara() );
} // }
// todo: party/enemy validation // todo: party/enemy validation
@ -449,5 +460,17 @@ bool Sapphire::Action::Action::playerPrecheck( Entity::Player& player )
// todo: validate costs/conditionals here // todo: validate costs/conditionals here
calculateActionCost();
return true; return true;
} }
uint32_t Sapphire::Action::Action::getAdditionalData() const
{
return m_additionalData;
}
void Sapphire::Action::Action::setAdditionalData( uint32_t data )
{
m_additionalData = data;
}

View file

@ -20,18 +20,20 @@ namespace Sapphire::Action
public: public:
Action(); Action();
Action( Entity::CharaPtr caster, uint32_t actionId, FrameworkPtr fw );
Action( Entity::CharaPtr caster, uint32_t actionId, Data::ActionPtr actionData, FrameworkPtr fw ); Action( Entity::CharaPtr caster, uint32_t actionId, Data::ActionPtr actionData, FrameworkPtr fw );
virtual ~Action(); virtual ~Action();
uint32_t getId() const; uint32_t getId() const;
bool init();
void setPos( Common::FFXIVARR_POSITION3 pos ); void setPos( Common::FFXIVARR_POSITION3 pos );
Common::FFXIVARR_POSITION3 getPos() const; Common::FFXIVARR_POSITION3 getPos() const;
void setTargetChara( Entity::CharaPtr chara ); void setTargetId( uint64_t targetId );
void setResidentTargetId( uint64_t targetId ); uint64_t getTargetId() const;
Entity::CharaPtr getTargetChara() const;
Entity::CharaPtr getSourceChara() const; Entity::CharaPtr getSourceChara() const;
bool isInterrupted() const; bool isInterrupted() const;
@ -40,11 +42,14 @@ namespace Sapphire::Action
uint32_t getCastTime() const; uint32_t getCastTime() const;
void setCastTime( uint32_t castTime ); void setCastTime( uint32_t castTime );
uint32_t getAdditionalData() const;
void setAdditionalData( uint32_t data );
/*! /*!
* @brief Checks if the action *may* target a resident instead of an actor * @brief Checks if the action *may* target a resident instead of an actor
* @return true if the target *may* be a resident and not an actor, otherwise false. * @return true if the target *may* be a resident and not an actor, otherwise false.
*/ */
bool hasResidentTarget() const; bool hasClientsideTarget() const;
/*! /*!
* @brief Tests whether the action is instantly usable or has a cast assoc'd with it * @brief Tests whether the action is instantly usable or has a cast assoc'd with it
@ -101,11 +106,11 @@ namespace Sapphire::Action
uint8_t m_effectRange; uint8_t m_effectRange;
Common::ActionAspect m_aspect; Common::ActionAspect m_aspect;
uint32_t m_additionalData;
Entity::CharaPtr m_pSource; Entity::CharaPtr m_pSource;
Entity::CharaPtr m_pTarget; Entity::CharaPtr m_pTarget;
uint64_t m_targetId; uint64_t m_targetId;
bool m_hasResidentTarget;
Common::ActionInterruptType m_interruptType; Common::ActionInterruptType m_interruptType;

View file

@ -34,6 +34,8 @@
#include "Script/ScriptMgr.h" #include "Script/ScriptMgr.h"
#include "Action/Action.h"
#include "Math/CalcStats.h" #include "Math/CalcStats.h"
#include "Math/CalcBattle.h" #include "Math/CalcBattle.h"
@ -1830,8 +1832,47 @@ void Sapphire::Entity::Player::emoteInterrupt()
void Sapphire::Entity::Player::teleportQuery( uint16_t aetheryteId ) void Sapphire::Entity::Player::teleportQuery( uint16_t aetheryteId )
{ {
m_teleportTargetAetheryte = aetheryteId; auto pExdData = m_pFw->get< Data::ExdDataGenerated >();
sendDebug( "requested aetheryte destination: {0}", aetheryteId ); // TODO: only register this action if enough gil is in possession
auto targetAetheryte = pExdData->get< Sapphire::Data::Aetheryte >( aetheryteId );
if( targetAetheryte )
{
auto fromAetheryte = pExdData->get< Sapphire::Data::Aetheryte >(
pExdData->get< Sapphire::Data::TerritoryType >( getZoneId() )->aetheryte );
// calculate cost - does not apply for favorite points or homepoints neither checks for aether tickets
auto cost = static_cast< uint16_t > (
( std::sqrt( std::pow( fromAetheryte->aetherstreamX - targetAetheryte->aetherstreamX, 2 ) +
std::pow( fromAetheryte->aetherstreamY - targetAetheryte->aetherstreamY, 2 ) ) / 2 ) + 100 );
// cap at 999 gil
cost = std::min< uint16_t >( 999, cost );
bool insufficientGil = getCurrency( Common::CurrencyType::Gil ) < cost;
// TODO: figure out what param1 really does
queuePacket( makeActorControl143( getId(), TeleportStart, insufficientGil ? 2 : 0, aetheryteId ) );
if( !insufficientGil )
{
m_teleportQuery.targetAetheryte = aetheryteId;
m_teleportQuery.cost = cost;
}
else
{
clearTeleportQuery();
}
}
}
Sapphire::Common::PlayerTeleportQuery Sapphire::Entity::Player::getTeleportQuery() const
{
return m_teleportQuery;
}
void Sapphire::Entity::Player::clearTeleportQuery()
{
memset( &m_teleportQuery, 0x0, sizeof( Common::PlayerTeleportQuery ) );
} }
uint8_t Sapphire::Entity::Player::getNextObjSpawnIndexForActorId( uint32_t actorId ) uint8_t Sapphire::Entity::Player::getNextObjSpawnIndexForActorId( uint32_t actorId )

View file

@ -533,6 +533,10 @@ namespace Sapphire::Entity
/*! query teleport of a specified type */ /*! query teleport of a specified type */
void teleportQuery( uint16_t aetheryteId ); void teleportQuery( uint16_t aetheryteId );
Common::PlayerTeleportQuery getTeleportQuery() const;
void clearTeleportQuery();
/*! prepares zoning / fades out the screen */ /*! prepares zoning / fades out the screen */
void prepareZoning( uint16_t targetZone, bool fadeOut, uint8_t fadeOutTime = 0, uint16_t animation = 0 ); void prepareZoning( uint16_t targetZone, bool fadeOut, uint8_t fadeOutTime = 0, uint16_t animation = 0 );
@ -1086,7 +1090,7 @@ namespace Sapphire::Entity
uint32_t m_mount; uint32_t m_mount;
uint32_t m_emoteMode; uint32_t m_emoteMode;
uint16_t m_teleportTargetAetheryte; Common::PlayerTeleportQuery m_teleportQuery;
Util::SpawnIndexAllocator< uint8_t > m_objSpawnIndexAllocator; Util::SpawnIndexAllocator< uint8_t > m_objSpawnIndexAllocator;
Util::SpawnIndexAllocator< uint8_t > m_actorSpawnIndexAllocator; Util::SpawnIndexAllocator< uint8_t > m_actorSpawnIndexAllocator;

View file

@ -24,7 +24,9 @@ void World::Manager::ActionMgr::handleAoEPlayerAction( Entity::Player& player, u
auto action = Action::make_Action( player.getAsPlayer(), actionId, actionData, framework() ); auto action = Action::make_Action( player.getAsPlayer(), actionId, actionData, framework() );
action->setPos( pos );
if( !action->init() )
return;
if( !actionData->targetArea ) if( !actionData->targetArea )
{ {
@ -33,6 +35,8 @@ void World::Manager::ActionMgr::handleAoEPlayerAction( Entity::Player& player, u
return; return;
} }
action->setPos( pos );
bootstrapAction( player, action, *actionData ); bootstrapAction( player, action, *actionData );
} }
@ -41,6 +45,9 @@ void World::Manager::ActionMgr::handleTargetedPlayerAction( Entity::Player& play
{ {
auto action = Action::make_Action( player.getAsPlayer(), actionId, actionData, framework() ); auto action = Action::make_Action( player.getAsPlayer(), actionId, actionData, framework() );
if( !action->init() )
return;
// cancel any aoe actions casted with this packet // cancel any aoe actions casted with this packet
if( actionData->targetArea ) if( actionData->targetArea )
{ {
@ -48,24 +55,7 @@ void World::Manager::ActionMgr::handleTargetedPlayerAction( Entity::Player& play
return; return;
} }
if( targetId == 0 ) action->setTargetId( targetId );
{
action->setTargetChara( player.getAsChara() );
}
else if( targetId != player.getId() )
{
auto target = player.lookupTargetById( targetId );
if( !target )
{
// an eobj?
player.sendDebug( "Unable to find actor for targetId#{0}, passing through to event scripts...", targetId );
action->setResidentTargetId( targetId );
}
else if( auto chara = target->getAsChara() )
{
action->setTargetChara( chara );
}
}
bootstrapAction( player, action, *actionData ); bootstrapAction( player, action, *actionData );
} }

View file

@ -88,15 +88,15 @@ namespace Sapphire::ScriptAPI
{ {
} }
void ActionScript::onStart( Sapphire::Action::Action& currentAction ) void ActionScript::onStart( Sapphire::Action::Action& action )
{ {
} }
void ActionScript::onFinish( Sapphire::Action::Action& currentAction ) void ActionScript::onExecute( Sapphire::Action::Action& action )
{ {
} }
void ActionScript::onInterrupt( Sapphire::Action::Action& currentAction ) void ActionScript::onInterrupt( Sapphire::Action::Action& action )
{ {
} }

View file

@ -140,11 +140,11 @@ namespace Sapphire::ScriptAPI
public: public:
explicit ActionScript( uint32_t abilityId ); explicit ActionScript( uint32_t abilityId );
virtual void onStart( Sapphire::Action::Action& currentAction ); virtual void onStart( Sapphire::Action::Action& action );
virtual void onFinish( Sapphire::Action::Action& currentAction ); virtual void onExecute( Sapphire::Action::Action& action );
virtual void onInterrupt( Sapphire::Action::Action& currentAction ); virtual void onInterrupt( Sapphire::Action::Action& action );
}; };
/*! /*!

View file

@ -328,37 +328,37 @@ bool Sapphire::Scripting::ScriptMgr::onEObjHit( Sapphire::Entity::Player& player
return didCallScript; return didCallScript;
} }
bool Sapphire::Scripting::ScriptMgr::onExecute( Action::Action& currentAction ) bool Sapphire::Scripting::ScriptMgr::onExecute( Action::Action& action )
{ {
auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::ActionScript >( currentAction.getId() ); auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::ActionScript >( action.getId() );
if( script ) if( script )
{ {
script->onFinish( currentAction ); script->onExecute( action );
return true; return true;
} }
return false; return false;
} }
bool Sapphire::Scripting::ScriptMgr::onInterrupt( Action::Action& currentAction ) bool Sapphire::Scripting::ScriptMgr::onInterrupt( Action::Action& action )
{ {
auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::ActionScript >( currentAction.getId() ); auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::ActionScript >( action.getId() );
if( script ) if( script )
{ {
script->onInterrupt( currentAction ); script->onInterrupt( action );
return true; return true;
} }
return false; return false;
} }
bool Sapphire::Scripting::ScriptMgr::onStart( Action::Action& currentAction ) bool Sapphire::Scripting::ScriptMgr::onStart( Action::Action& action )
{ {
auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::ActionScript >( currentAction.getId() ); auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::ActionScript >( action.getId() );
if( script ) if( script )
{ {
script->onStart( currentAction ); script->onStart( action );
return true; return true;
} }

View file

@ -72,11 +72,11 @@ namespace Sapphire::Scripting
bool onEObjHit( Entity::Player& player, uint64_t actorId ); bool onEObjHit( Entity::Player& player, uint64_t actorId );
bool onStart( Action::Action& currentAction ); bool onStart( Action::Action& action );
bool onInterrupt( Action::Action& currentAction ); bool onInterrupt( Action::Action& action );
bool onExecute( Action::Action& currentAction ); bool onExecute( Action::Action& action );
bool onStatusReceive( Entity::CharaPtr pActor, uint32_t effectId ); bool onStatusReceive( Entity::CharaPtr pActor, uint32_t effectId );