1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-28 15:17:46 +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
{
// None = 0, // ?
None = 0, // ?
MagicPoints = 3,
TacticsPoints = 5,
// WARGauge = 22,
@ -931,6 +931,12 @@ namespace Sapphire::Common
IsFreeCompanyEstate = 16,
};
struct PlayerTeleportQuery
{
uint16_t targetAetheryte;
uint16_t cost;
};
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;
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() )
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?" );
}

View file

@ -26,28 +26,53 @@ using namespace Sapphire::Network::ActorControl;
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,
Data::ActionPtr actionData, FrameworkPtr fw ) :
m_pSource( std::move( caster ) ),
m_pFw( std::move( fw ) ),
m_actionData( std::move( actionData ) ),
m_id( actionId ),
m_targetId( 0 ),
m_startTime( 0 ),
m_interruptType( Common::ActionInterruptType::None ),
m_hasResidentTarget( false )
m_interruptType( Common::ActionInterruptType::None )
{
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 );
uint32_t Sapphire::Action::Action::getId() const
{
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 >( actionData->classJob ) )
switch( static_cast< Common::ClassJob >( m_actionData->classJob ) )
{
case Common::ClassJob::Bard:
case Common::ClassJob::Archer:
@ -59,17 +84,12 @@ Sapphire::Action::Action::Action( Entity::CharaPtr caster, uint32_t actionId,
}
}
m_primaryCostType = static_cast< Common::ActionPrimaryCostType >( actionData->costType );
m_primaryCost = actionData->cost;
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
calculateActionCost();
}
uint32_t Sapphire::Action::Action::getId() const
{
return m_id;
return true;
}
void Sapphire::Action::Action::setPos( Sapphire::Common::FFXIVARR_POSITION3 pos )
@ -82,29 +102,19 @@ Sapphire::Common::FFXIVARR_POSITION3 Sapphire::Action::Action::getPos() const
return m_pos;
}
void Sapphire::Action::Action::setTargetChara( Sapphire::Entity::CharaPtr chara )
{
assert( chara );
m_pTarget = chara;
m_targetId = chara->getId();
m_hasResidentTarget = false;
}
void Sapphire::Action::Action::setResidentTargetId( uint64_t targetId )
void Sapphire::Action::Action::setTargetId( uint64_t 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
@ -149,7 +159,7 @@ bool Sapphire::Action::Action::update()
return true;
}
if( !hasResidentTarget() )
if( !hasClientsideTarget() )
{
// 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 );
}
else if( auto player = m_pSource->getAsPlayer() )
@ -282,18 +291,20 @@ void Sapphire::Action::Action::calculateActionCost()
// check primary cost
switch( m_primaryCostType )
{
case ActionPrimaryCostType::None:
{
break;
}
case ActionPrimaryCostType::MagicPoints:
{
calculateMPCost( m_primaryCost );
break;
}
case ActionPrimaryCostType::TacticsPoints:
{
break;
}
default:
{
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
// todo: check what actions send when targeting an enemy
if( m_actionData->canTargetSelf &&
!m_actionData->canTargetFriendly &&
!m_actionData->canTargetHostile &&
!m_actionData->canTargetParty )
{
setTargetChara( getSourceChara() );
}
// if( m_actionData->canTargetSelf &&
// !m_actionData->canTargetFriendly &&
// !m_actionData->canTargetHostile &&
// !m_actionData->canTargetParty )
// {
// setTargetId( getSourceChara() );
// }
// todo: party/enemy validation
@ -449,5 +460,17 @@ bool Sapphire::Action::Action::playerPrecheck( Entity::Player& player )
// todo: validate costs/conditionals here
calculateActionCost();
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:
Action();
Action( Entity::CharaPtr caster, uint32_t actionId, FrameworkPtr fw );
Action( Entity::CharaPtr caster, uint32_t actionId, Data::ActionPtr actionData, FrameworkPtr fw );
virtual ~Action();
uint32_t getId() const;
bool init();
void setPos( Common::FFXIVARR_POSITION3 pos );
Common::FFXIVARR_POSITION3 getPos() const;
void setTargetChara( Entity::CharaPtr chara );
void setResidentTargetId( uint64_t targetId );
Entity::CharaPtr getTargetChara() const;
void setTargetId( uint64_t targetId );
uint64_t getTargetId() const;
Entity::CharaPtr getSourceChara() const;
bool isInterrupted() const;
@ -40,11 +42,14 @@ namespace Sapphire::Action
uint32_t getCastTime() const;
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
* @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
@ -101,11 +106,11 @@ namespace Sapphire::Action
uint8_t m_effectRange;
Common::ActionAspect m_aspect;
uint32_t m_additionalData;
Entity::CharaPtr m_pSource;
Entity::CharaPtr m_pTarget;
uint64_t m_targetId;
bool m_hasResidentTarget;
Common::ActionInterruptType m_interruptType;

View file

@ -34,6 +34,8 @@
#include "Script/ScriptMgr.h"
#include "Action/Action.h"
#include "Math/CalcStats.h"
#include "Math/CalcBattle.h"
@ -1830,8 +1832,47 @@ void Sapphire::Entity::Player::emoteInterrupt()
void Sapphire::Entity::Player::teleportQuery( uint16_t aetheryteId )
{
m_teleportTargetAetheryte = aetheryteId;
sendDebug( "requested aetheryte destination: {0}", aetheryteId );
auto pExdData = m_pFw->get< Data::ExdDataGenerated >();
// 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 )

View file

@ -533,6 +533,10 @@ namespace Sapphire::Entity
/*! query teleport of a specified type */
void teleportQuery( uint16_t aetheryteId );
Common::PlayerTeleportQuery getTeleportQuery() const;
void clearTeleportQuery();
/*! prepares zoning / fades out the screen */
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_emoteMode;
uint16_t m_teleportTargetAetheryte;
Common::PlayerTeleportQuery m_teleportQuery;
Util::SpawnIndexAllocator< uint8_t > m_objSpawnIndexAllocator;
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() );
action->setPos( pos );
if( !action->init() )
return;
if( !actionData->targetArea )
{
@ -33,6 +35,8 @@ void World::Manager::ActionMgr::handleAoEPlayerAction( Entity::Player& player, u
return;
}
action->setPos( pos );
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() );
if( !action->init() )
return;
// cancel any aoe actions casted with this packet
if( actionData->targetArea )
{
@ -48,24 +55,7 @@ void World::Manager::ActionMgr::handleTargetedPlayerAction( Entity::Player& play
return;
}
if( targetId == 0 )
{
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 );
}
}
action->setTargetId( targetId );
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:
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;
}
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 )
{
script->onFinish( currentAction );
script->onExecute( action );
return true;
}
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 )
{
script->onInterrupt( currentAction );
script->onInterrupt( action );
return true;
}
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 )
{
script->onStart( currentAction );
script->onStart( action );
return true;
}

View file

@ -72,11 +72,11 @@ namespace Sapphire::Scripting
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 );