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

Merge pull request #631 from collett8192/mount

Implement mount action.
This commit is contained in:
Adam 2020-01-26 21:00:31 +11:00 committed by GitHub
commit 3aafea9edf
16 changed files with 156 additions and 12 deletions

View file

@ -632,10 +632,10 @@ namespace Sapphire::Common
* @param flags Required to be 128, doesn't show combo rings on hotbars otherwise * @param flags Required to be 128, doesn't show combo rings on hotbars otherwise
* @param value The actionid that starts/continues the combo. eg, 3617 will start a spinning slash and/or syphon strike combo * @param value The actionid that starts/continues the combo. eg, 3617 will start a spinning slash and/or syphon strike combo
*/ */
StartActionCombo = 28, StartActionCombo = 28, // actually this is more likely "ActionComplete" or something like that
ComboSucceed = 29, ComboSucceed = 29,
Knockback = 33, Knockback = 33,
Mount = 38, Mount = 39,
VFX = 59, // links to VFX sheet VFX = 59, // links to VFX sheet
}; };
@ -1009,6 +1009,7 @@ namespace Sapphire::Common
{ {
SingleTarget = 1, SingleTarget = 1,
CircularAOE = 2, CircularAOE = 2,
Type3 = 3, // another single target? no idea how to call it
RectangularAOE = 4, RectangularAOE = 4,
CircularAoEPlaced = 7 CircularAoEPlaced = 7
}; };

View file

@ -207,7 +207,7 @@ namespace Sapphire::Network::Packets
QuestTracker = 0x0289, // updated 5.18 QuestTracker = 0x0289, // updated 5.18
Mount = 0x02F0, // updated 5.18 Mount = 0x038F, // updated 5.18
DirectorVars = 0x00E6, // updated 5.18 DirectorVars = 0x00E6, // updated 5.18
SomeDirectorUnk1 = 0x0084, // updated 5.18 SomeDirectorUnk1 = 0x0084, // updated 5.18

View file

@ -835,10 +835,11 @@ namespace Sapphire::Network::Packets::Server
uint16_t action_id; uint16_t action_id;
Common::SkillType skillType; Common::SkillType skillType;
uint8_t unknown; uint8_t unknown;
uint32_t unknown_1; // Also action id uint32_t unknown_1; // action id or mount id
float cast_time; float cast_time;
uint32_t target_id; uint32_t target_id;
float rotation; // In radians uint16_t rotation;
uint16_t flag; // 1 = interruptible blinking cast bar
uint32_t unknown_2; uint32_t unknown_2;
uint16_t posX; uint16_t posX;
uint16_t posY; uint16_t posY;
@ -1022,9 +1023,8 @@ namespace Sapphire::Network::Packets::Server
unsigned char companionDefRank; unsigned char companionDefRank;
unsigned char companionAttRank; unsigned char companionAttRank;
unsigned char companionHealRank; unsigned char companionHealRank;
unsigned char u19[2]; unsigned char u19[8];
unsigned char mountGuideMask[19]; unsigned char mountGuideMask[22];
uint8_t unk1[9];
char name[32]; char name[32];
unsigned char unknownOword[16]; unsigned char unknownOword[16];
unsigned char unknownOw; unsigned char unknownOw;

View file

@ -275,7 +275,7 @@ void Action::Action::start()
data.posX = Common::Util::floatToUInt16( pos.x ); data.posX = Common::Util::floatToUInt16( pos.x );
data.posY = Common::Util::floatToUInt16( pos.y ); data.posY = Common::Util::floatToUInt16( pos.y );
data.posZ = Common::Util::floatToUInt16( pos.z ); data.posZ = Common::Util::floatToUInt16( pos.z );
data.rotation = m_pSource->getRot(); data.rotation = Common::Util::floatToUInt16Rot( m_pSource->getRot() );
m_pSource->sendToInRangeSet( castPacket, true ); m_pSource->sendToInRangeSet( castPacket, true );
@ -736,6 +736,7 @@ void Action::Action::addDefaultActorFilters()
switch( m_castType ) switch( m_castType )
{ {
case Common::CastType::SingleTarget: case Common::CastType::SingleTarget:
case Common::CastType::Type3:
{ {
auto filter = std::make_shared< World::Util::ActorFilterSingleTarget >( static_cast< uint32_t >( m_targetId ) ); auto filter = std::make_shared< World::Util::ActorFilterSingleTarget >( static_cast< uint32_t >( m_targetId ) );

View file

@ -80,7 +80,7 @@ namespace Sapphire::World::Action
* @brief Tests if an action is castable by the current source chara * @brief Tests if an action is castable by the current source chara
* @return true if castable, false if the caster doesn't meet the requirements * @return true if castable, false if the caster doesn't meet the requirements
*/ */
bool preCheck(); virtual bool preCheck();
/*! /*!
* @brief Snapshots characters affected by a cast. * @brief Snapshots characters affected by a cast.

View file

@ -91,6 +91,13 @@ void EffectBuilder::applyStatusEffect( Entity::CharaPtr& target, uint16_t status
moveToResultList( target, nextResult ); moveToResultList( target, nextResult );
} }
void EffectBuilder::mount( Entity::CharaPtr& target, uint16_t mountId )
{
EffectResultPtr nextResult = make_EffectResult( target, getResultDelayMs() );
nextResult->mount( mountId );
moveToResultList( target, nextResult );
}
void EffectBuilder::buildAndSendPackets() void EffectBuilder::buildAndSendPackets()
{ {
auto targetCount = m_resolvedEffects.size(); auto targetCount = m_resolvedEffects.size();

View file

@ -28,6 +28,8 @@ namespace Sapphire::World::Action
void applyStatusEffect( Entity::CharaPtr& target, uint16_t statusId, uint8_t param ); void applyStatusEffect( Entity::CharaPtr& target, uint16_t statusId, uint8_t param );
void mount( Entity::CharaPtr& target, uint16_t mountId );
void buildAndSendPackets(); void buildAndSendPackets();

View file

@ -3,6 +3,7 @@
#include <Util/Util.h> #include <Util/Util.h>
#include "Actor/Chara.h" #include "Actor/Chara.h"
#include "Actor/Player.h"
using namespace Sapphire; using namespace Sapphire;
using namespace Sapphire::World::Action; using namespace Sapphire::World::Action;
@ -84,6 +85,14 @@ void EffectResult::applyStatusEffect( uint16_t statusId, uint8_t param )
m_type = Common::ActionEffectType::ApplyStatusEffect; m_type = Common::ActionEffectType::ApplyStatusEffect;
} }
void EffectResult::mount( uint16_t moundId )
{
m_value = moundId;
m_param0 = 1;
m_type = Common::ActionEffectType::Mount;
}
Common::EffectEntry EffectResult::buildEffectEntry() const Common::EffectEntry EffectResult::buildEffectEntry() const
{ {
Common::EffectEntry entry{}; Common::EffectEntry entry{};
@ -121,6 +130,13 @@ void EffectResult::execute()
break; break;
} }
case Common::ActionEffectType::Mount:
{
auto pPlayer = m_target->getAsPlayer();
pPlayer->mount( m_value );
break;
}
default: default:
break; break;
} }

View file

@ -21,6 +21,7 @@ namespace Sapphire::World::Action
void startCombo( uint16_t actionId ); void startCombo( uint16_t actionId );
void comboSucceed(); void comboSucceed();
void applyStatusEffect( uint16_t statusId, uint8_t param ); void applyStatusEffect( uint16_t statusId, uint8_t param );
void mount( uint16_t moundId );
Entity::CharaPtr getTarget() const; Entity::CharaPtr getTarget() const;

View file

@ -0,0 +1,68 @@
#include "MountAction.h"
#include <Exd/ExdDataGenerated.h>
#include "Actor/Player.h"
#include <Network/CommonActorControl.h>
#include "Network/PacketWrappers/ActorControlSelfPacket.h"
#include <Util/UtilMath.h>
using namespace Sapphire;
using namespace Sapphire::Network::Packets;
using namespace Sapphire::Network::Packets::Server;
using namespace Sapphire::Network::ActorControl;
using namespace Sapphire::World::Action;
MountAction::MountAction( Sapphire::Entity::CharaPtr source, uint16_t mountId, uint16_t sequence, Data::ActionPtr actionData, Sapphire::FrameworkPtr fw ) :
Action::Action( source, 4, sequence, actionData, fw ),
m_mountId( mountId )
{
}
bool MountAction::preCheck()
{
// todo: check if mount is unlocked
return m_pSource->isPlayer();
}
void MountAction::start()
{
assert( m_pSource );
m_startTime = Common::Util::getTimeMs();
auto player = m_pSource->getAsPlayer();
auto castPacket = makeZonePacket< Server::FFXIVIpcActorCast >( getId() );
auto& data = castPacket->data();
data.action_id = static_cast< uint16_t >( m_id );
data.skillType = Common::SkillType::MountSkill;
data.unknown_1 = m_mountId;
data.cast_time = m_castTimeMs / 1000.f;
data.target_id = static_cast< uint32_t >( m_targetId );
data.unknown_2 = 0xE0000000;
auto pos = m_pSource->getPos();
data.posX = Common::Util::floatToUInt16( pos.x );
data.posY = Common::Util::floatToUInt16( pos.y );
data.posZ = Common::Util::floatToUInt16( pos.z );
data.rotation = Common::Util::floatToUInt16Rot( m_pSource->getRot() );
m_pSource->sendToInRangeSet( castPacket, true );
player->setStateFlag( Common::PlayerStateFlag::Casting );
auto actionStartPkt = makeActorControlSelf( m_pSource->getId(), ActorControlType::ActionStart, 1, getId(), m_recastTimeMs / 10 );
player->queuePacket( actionStartPkt );
}
void MountAction::execute()
{
assert( m_pSource );
m_effectBuilder->mount( m_pSource, m_mountId );
m_effectBuilder->buildAndSendPackets();
}

View file

@ -0,0 +1,25 @@
#ifndef SAPPHIRE_MOUNTACTION_H
#define SAPPHIRE_MOUNTACTION_H
#include "Action.h"
namespace Sapphire::World::Action
{
class MountAction : public Action
{
public:
MountAction( Entity::CharaPtr source, uint16_t mountId, uint16_t sequence, Data::ActionPtr actionData, FrameworkPtr fw );
virtual ~MountAction() = default;
bool preCheck() override;
void start() override;
void execute() override;
private:
uint16_t m_mountId;
};
}
#endif //SAPPHIRE_MOUNTACTION_H

View file

@ -1045,7 +1045,7 @@ namespace Sapphire::Entity
uint8_t m_titleList[48]; uint8_t m_titleList[48];
uint8_t m_howTo[34]; uint8_t m_howTo[34];
uint8_t m_minions[40]; uint8_t m_minions[40];
uint8_t m_mountGuide[19]; uint8_t m_mountGuide[22];
uint8_t m_homePoint; uint8_t m_homePoint;
uint8_t m_startTown; uint8_t m_startTown;
uint16_t m_townWarpFstFlags; uint16_t m_townWarpFstFlags;

View file

@ -87,6 +87,7 @@ namespace World::Action
TYPE_FORWARD( Action ); TYPE_FORWARD( Action );
TYPE_FORWARD( EventAction ); TYPE_FORWARD( EventAction );
TYPE_FORWARD( ItemAction ); TYPE_FORWARD( ItemAction );
TYPE_FORWARD( MountAction );
TYPE_FORWARD( EffectBuilder ); TYPE_FORWARD( EffectBuilder );
TYPE_FORWARD( EffectResult ); TYPE_FORWARD( EffectResult );

View file

@ -2,6 +2,7 @@
#include "Action/Action.h" #include "Action/Action.h"
#include "Action/ItemAction.h" #include "Action/ItemAction.h"
#include "Action/MountAction.h"
#include "Script/ScriptMgr.h" #include "Script/ScriptMgr.h"
#include "Actor/Player.h" #include "Actor/Player.h"
@ -78,6 +79,22 @@ void World::Manager::ActionMgr::handleItemAction( Sapphire::Entity::Player& play
action->start(); action->start();
} }
void World::Manager::ActionMgr::handleMountAction( Entity::Player& player, uint16_t mountId,
Data::ActionPtr actionData, uint64_t targetId,
uint16_t sequence )
{
player.sendDebug( "mount: {0}", mountId );
auto action = Action::make_MountAction( player.getAsPlayer(), mountId, sequence, actionData, framework() );
action->setTargetId( targetId );
if( !action->init() )
return;
bootstrapAction( player, action, *actionData );
}
void World::Manager::ActionMgr::bootstrapAction( Entity::Player& player, void World::Manager::ActionMgr::bootstrapAction( Entity::Player& player,
Action::ActionPtr currentAction, Action::ActionPtr currentAction,
Data::Action& actionData ) Data::Action& actionData )

View file

@ -29,6 +29,9 @@ namespace Sapphire::World::Manager
void handleItemAction( Entity::Player& player, uint32_t itemId, Data::ItemActionPtr itemActionData, void handleItemAction( Entity::Player& player, uint32_t itemId, Data::ItemActionPtr itemActionData,
uint16_t itemSourceSlot, uint16_t itemSourceContainer ); uint16_t itemSourceSlot, uint16_t itemSourceContainer );
void handleMountAction( Entity::Player& player, uint16_t mountId,
Data::ActionPtr actionData, uint64_t targetId, uint16_t sequence );
private: private:
void bootstrapAction( Entity::Player& player, Action::ActionPtr currentAction, Data::Action& actionData ); void bootstrapAction( Entity::Player& player, Action::ActionPtr currentAction, Data::Action& actionData );

View file

@ -72,7 +72,9 @@ void Sapphire::Network::GameConnection::actionHandler( FrameworkPtr pFw,
case Common::SkillType::MountSkill: case Common::SkillType::MountSkill:
{ {
auto action = exdData->get< Data::Action >( 4 );
assert( action );
actionMgr->handleMountAction( player, static_cast< uint16_t >( actionId ), action, targetId, sequence );
break; break;
} }
} }