mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-29 07:37:45 +00:00
commit
3aafea9edf
16 changed files with 156 additions and 12 deletions
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 ) );
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
68
src/world/Action/MountAction.cpp
Normal file
68
src/world/Action/MountAction.cpp
Normal 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();
|
||||||
|
}
|
25
src/world/Action/MountAction.h
Normal file
25
src/world/Action/MountAction.h
Normal 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
|
|
@ -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;
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
||||||
|
|
|
@ -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 )
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue