mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-05-08 03:37:45 +00:00
some effects/action wip crap
This commit is contained in:
parent
a5b9923b66
commit
7e0108aea5
7 changed files with 285 additions and 20 deletions
|
@ -1,5 +1,6 @@
|
||||||
#include "Action.h"
|
#include "Action.h"
|
||||||
#include "ActionLut.h"
|
#include "ActionLut.h"
|
||||||
|
#include "EffectBuilder.h"
|
||||||
|
|
||||||
#include <Exd/ExdDataGenerated.h>
|
#include <Exd/ExdDataGenerated.h>
|
||||||
#include <Util/Util.h>
|
#include <Util/Util.h>
|
||||||
|
@ -17,8 +18,9 @@
|
||||||
#include "Network/PacketWrappers/ActorControlPacket142.h"
|
#include "Network/PacketWrappers/ActorControlPacket142.h"
|
||||||
#include "Network/PacketWrappers/ActorControlPacket143.h"
|
#include "Network/PacketWrappers/ActorControlPacket143.h"
|
||||||
#include "Network/PacketWrappers/ActorControlPacket144.h"
|
#include "Network/PacketWrappers/ActorControlPacket144.h"
|
||||||
#include <Network/PacketWrappers/EffectPacket.h>
|
|
||||||
#include <Logging/Logger.h>
|
#include <Logging/Logger.h>
|
||||||
|
|
||||||
#include <Util/ActorFilter.h>
|
#include <Util/ActorFilter.h>
|
||||||
|
|
||||||
using namespace Sapphire;
|
using namespace Sapphire;
|
||||||
|
@ -68,6 +70,8 @@ bool Action::Action::init()
|
||||||
m_actionData = actionData;
|
m_actionData = actionData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_effectBuilder = make_EffectBuilder( m_pSource, getId() );
|
||||||
|
|
||||||
m_castTimeMs = static_cast< uint32_t >( m_actionData->cast100ms * 100 );
|
m_castTimeMs = static_cast< uint32_t >( m_actionData->cast100ms * 100 );
|
||||||
m_recastTimeMs = static_cast< uint32_t >( m_actionData->recast100ms * 100 );
|
m_recastTimeMs = static_cast< uint32_t >( m_actionData->recast100ms * 100 );
|
||||||
m_cooldownGroup = m_actionData->cooldownGroup;
|
m_cooldownGroup = m_actionData->cooldownGroup;
|
||||||
|
@ -326,30 +330,13 @@ void Action::Action::execute()
|
||||||
player->sendDebug( "action combo success from action#{0}", player->getLastComboActionId() );
|
player->sendDebug( "action combo success from action#{0}", player->getLastComboActionId() );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !hasClientsideTarget() )
|
if( !hasClientsideTarget() )
|
||||||
{
|
{
|
||||||
snapshotAffectedActors( m_hitActors );
|
buildEffects();
|
||||||
|
|
||||||
if( !m_hitActors.empty() )
|
|
||||||
{
|
|
||||||
// only call script if actors are hit
|
|
||||||
if( !pScriptMgr->onExecute( *this ) && ActionLut::validEntryExists( getId() ) )
|
|
||||||
{
|
|
||||||
auto lutEntry = ActionLut::getEntry( getId() );
|
|
||||||
|
|
||||||
// no script exists but we have a valid lut entry
|
|
||||||
if( auto player = getSourceChara()->getAsPlayer() )
|
|
||||||
{
|
|
||||||
player->sendDebug( "Hit target: pot: {} (f: {}, r: {}), heal pot: {}",
|
|
||||||
lutEntry.potency, lutEntry.flankPotency, lutEntry.rearPotency, lutEntry.curePotency );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if( auto player = m_pSource->getAsPlayer() )
|
else if( auto player = m_pSource->getAsPlayer() )
|
||||||
{
|
{
|
||||||
pScriptMgr->onEObjHit( *player, m_targetId, getId() );
|
pScriptMgr->onEObjHit( *player, m_targetId, getId() );
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// set currently casted action as the combo action if it interrupts a combo
|
// set currently casted action as the combo action if it interrupts a combo
|
||||||
|
@ -360,6 +347,50 @@ void Action::Action::execute()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Action::Action::buildEffects()
|
||||||
|
{
|
||||||
|
snapshotAffectedActors( m_hitActors );
|
||||||
|
|
||||||
|
auto pScriptMgr = m_pFw->get< Scripting::ScriptMgr >();
|
||||||
|
|
||||||
|
if( !pScriptMgr->onExecute( *this ) && !ActionLut::validEntryExists( getId() ) )
|
||||||
|
{
|
||||||
|
if( auto player = m_pSource->getAsPlayer() )
|
||||||
|
{
|
||||||
|
player->sendUrgent( "missing lut entry for action#{}", getId() );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_hitActors.empty() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto lutEntry = ActionLut::getEntry( getId() );
|
||||||
|
|
||||||
|
// no script exists but we have a valid lut entry
|
||||||
|
if( auto player = getSourceChara()->getAsPlayer() )
|
||||||
|
{
|
||||||
|
player->sendDebug( "Hit target: pot: {} (f: {}, r: {}), heal pot: {}",
|
||||||
|
lutEntry.potency, lutEntry.flankPotency, lutEntry.rearPotency, lutEntry.curePotency );
|
||||||
|
}
|
||||||
|
|
||||||
|
for( auto& actor : m_hitActors )
|
||||||
|
{
|
||||||
|
// todo: this is shit
|
||||||
|
if( actor->getObjKind() == m_pSource->getObjKind() && lutEntry.curePotency > 0 )
|
||||||
|
m_effectBuilder->healTarget( actor, lutEntry.curePotency );
|
||||||
|
|
||||||
|
else if( lutEntry.potency > 0 )
|
||||||
|
m_effectBuilder->damageTarget( actor, lutEntry.potency );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_effectBuilder->buildAndSendPackets();
|
||||||
|
|
||||||
|
// at this point we're done with it and no longer need it
|
||||||
|
m_effectBuilder.reset();
|
||||||
|
}
|
||||||
|
|
||||||
bool Action::Action::preCheck()
|
bool Action::Action::preCheck()
|
||||||
{
|
{
|
||||||
if( auto player = m_pSource->getAsPlayer() )
|
if( auto player = m_pSource->getAsPlayer() )
|
||||||
|
|
|
@ -85,6 +85,8 @@ namespace Sapphire::World::Action
|
||||||
*/
|
*/
|
||||||
bool snapshotAffectedActors( std::vector< Entity::CharaPtr >& actors );
|
bool snapshotAffectedActors( std::vector< Entity::CharaPtr >& actors );
|
||||||
|
|
||||||
|
void buildEffects();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Adds an actor filter to this action.
|
* @brief Adds an actor filter to this action.
|
||||||
* @param filter The ptr to the ActorFilter to add
|
* @param filter The ptr to the ActorFilter to add
|
||||||
|
@ -171,6 +173,8 @@ namespace Sapphire::World::Action
|
||||||
|
|
||||||
Common::FFXIVARR_POSITION3 m_pos;
|
Common::FFXIVARR_POSITION3 m_pos;
|
||||||
|
|
||||||
|
EffectBuilderPtr m_effectBuilder;
|
||||||
|
|
||||||
std::vector< World::Util::ActorFilterPtr > m_actorFilters;
|
std::vector< World::Util::ActorFilterPtr > m_actorFilters;
|
||||||
std::vector< Entity::CharaPtr > m_hitActors;
|
std::vector< Entity::CharaPtr > m_hitActors;
|
||||||
};
|
};
|
||||||
|
|
87
src/world/Action/EffectBuilder.cpp
Normal file
87
src/world/Action/EffectBuilder.cpp
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
#include "EffectBuilder.h"
|
||||||
|
#include "EffectResult.h"
|
||||||
|
|
||||||
|
#include <Actor/Chara.h>
|
||||||
|
|
||||||
|
#include <Network/PacketWrappers/EffectPacket.h>
|
||||||
|
|
||||||
|
#include <Territory/Territory.h>
|
||||||
|
|
||||||
|
#include <Util/Util.h>
|
||||||
|
#include <Util/UtilMath.h>
|
||||||
|
|
||||||
|
#include <Logging/Logger.h>
|
||||||
|
|
||||||
|
using namespace Sapphire;
|
||||||
|
using namespace Sapphire::World::Action;
|
||||||
|
using namespace Sapphire::Network::Packets;
|
||||||
|
|
||||||
|
EffectBuilder::EffectBuilder( Entity::CharaPtr source, uint32_t actionId ) :
|
||||||
|
m_sourceChara( std::move( source ) ),
|
||||||
|
m_actionId( actionId )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t EffectBuilder::getResultDelayMs()
|
||||||
|
{
|
||||||
|
// todo: actually figure this retarded shit out
|
||||||
|
|
||||||
|
return Common::Util::getTimeMs() + 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
EffectResultPtr EffectBuilder::getResult( Entity::CharaPtr& chara )
|
||||||
|
{
|
||||||
|
auto it = m_resolvedEffects.find( chara->getId() );
|
||||||
|
if( it == m_resolvedEffects.end() )
|
||||||
|
{
|
||||||
|
// create a new one and return it
|
||||||
|
// todo: this feels kinda dirty but makes for easy work
|
||||||
|
auto result = make_EffectResult( chara, getResultDelayMs() );
|
||||||
|
|
||||||
|
m_resolvedEffects[ chara->getId() ] = result;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EffectBuilder::healTarget( Entity::CharaPtr& target, uint32_t amount, Common::ActionHitSeverityType severity )
|
||||||
|
{
|
||||||
|
auto result = getResult( target );
|
||||||
|
assert( result );
|
||||||
|
|
||||||
|
result->heal( amount, severity );
|
||||||
|
}
|
||||||
|
|
||||||
|
void EffectBuilder::damageTarget( Entity::CharaPtr& target, uint32_t amount, Common::ActionHitSeverityType severity )
|
||||||
|
{
|
||||||
|
auto result = getResult( target );
|
||||||
|
assert( result );
|
||||||
|
|
||||||
|
result->damage( amount, severity );
|
||||||
|
}
|
||||||
|
|
||||||
|
void EffectBuilder::buildAndSendPackets()
|
||||||
|
{
|
||||||
|
Logger::info( "EffectBuilder result: " );
|
||||||
|
Logger::info( "Targets afflicted: {}", m_resolvedEffects.size() );
|
||||||
|
|
||||||
|
// test shit
|
||||||
|
for( auto& effect : m_resolvedEffects )
|
||||||
|
{
|
||||||
|
auto& result = effect.second;
|
||||||
|
|
||||||
|
auto effectPacket = std::make_shared< Server::EffectPacket >( m_sourceChara->getId(), result->getTarget()->getId(), m_actionId );
|
||||||
|
effectPacket->setRotation( Common::Util::floatToUInt16Rot( m_sourceChara->getRot() ) );
|
||||||
|
|
||||||
|
effectPacket->addEffect( result->buildEffectEntry() );
|
||||||
|
|
||||||
|
auto sequence = m_sourceChara->getCurrentTerritory()->getNextEffectSequence();
|
||||||
|
effectPacket->setSequence( sequence );
|
||||||
|
|
||||||
|
m_sourceChara->sendToInRangeSet( effectPacket, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
47
src/world/Action/EffectBuilder.h
Normal file
47
src/world/Action/EffectBuilder.h
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#ifndef SAPPHIRE_EFFECTBUILDER_H
|
||||||
|
#define SAPPHIRE_EFFECTBUILDER_H
|
||||||
|
|
||||||
|
#include <ForwardsZone.h>
|
||||||
|
#include <Common.h>
|
||||||
|
|
||||||
|
namespace Sapphire::World::Action
|
||||||
|
{
|
||||||
|
class EffectBuilder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum HitSeverity
|
||||||
|
{
|
||||||
|
Normal,
|
||||||
|
Critical,
|
||||||
|
DirectHit,
|
||||||
|
CriticalDirectHit
|
||||||
|
};
|
||||||
|
|
||||||
|
EffectBuilder( Entity::CharaPtr source, uint32_t actionId );
|
||||||
|
|
||||||
|
|
||||||
|
void healTarget( Entity::CharaPtr& target, uint32_t amount,
|
||||||
|
Common::ActionHitSeverityType severity = Common::ActionHitSeverityType::NormalHeal );
|
||||||
|
|
||||||
|
void damageTarget( Entity::CharaPtr& target, uint32_t amount,
|
||||||
|
Common::ActionHitSeverityType severity = Common::ActionHitSeverityType::NormalDamage );
|
||||||
|
|
||||||
|
void buildAndSendPackets();
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
EffectResultPtr getResult( Entity::CharaPtr& chara );
|
||||||
|
|
||||||
|
uint32_t getResultDelayMs();
|
||||||
|
|
||||||
|
|
||||||
|
Entity::CharaPtr m_sourceChara;
|
||||||
|
|
||||||
|
uint32_t m_actionId;
|
||||||
|
|
||||||
|
std::unordered_map< uint32_t, EffectResultPtr > m_resolvedEffects;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //SAPPHIRE_EFFECTBUILDER_H
|
55
src/world/Action/EffectResult.cpp
Normal file
55
src/world/Action/EffectResult.cpp
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
#include "EffectResult.h"
|
||||||
|
|
||||||
|
#include <Util/Util.h>
|
||||||
|
|
||||||
|
using namespace Sapphire;
|
||||||
|
using namespace Sapphire::World::Action;
|
||||||
|
|
||||||
|
|
||||||
|
EffectResult::EffectResult( Entity::CharaPtr target, uint32_t runAfter ) :
|
||||||
|
m_target( std::move( target ) ),
|
||||||
|
m_runAfter( runAfter ),
|
||||||
|
m_value( 0 ),
|
||||||
|
m_severity( Common::ActionHitSeverityType::NormalDamage )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity::CharaPtr EffectResult::getTarget() const
|
||||||
|
{
|
||||||
|
return m_target;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t EffectResult::getValue() const
|
||||||
|
{
|
||||||
|
return m_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EffectResult::damage( uint32_t amount, Common::ActionHitSeverityType severity )
|
||||||
|
{
|
||||||
|
m_severity = severity;
|
||||||
|
m_value = amount;
|
||||||
|
|
||||||
|
m_type = Common::ActionEffectType::Damage;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EffectResult::heal( uint32_t amount, Sapphire::Common::ActionHitSeverityType severity )
|
||||||
|
{
|
||||||
|
m_severity = severity;
|
||||||
|
m_value = amount;
|
||||||
|
|
||||||
|
m_type = Common::ActionEffectType::Heal;
|
||||||
|
}
|
||||||
|
|
||||||
|
Common::EffectEntry EffectResult::buildEffectEntry() const
|
||||||
|
{
|
||||||
|
Common::EffectEntry entry{};
|
||||||
|
|
||||||
|
// todo: that retarded shit so > u16 max numbers work
|
||||||
|
entry.value = getValue();
|
||||||
|
entry.hitSeverity = m_severity;
|
||||||
|
entry.effectType = m_type;
|
||||||
|
|
||||||
|
|
||||||
|
return entry;
|
||||||
|
}
|
39
src/world/Action/EffectResult.h
Normal file
39
src/world/Action/EffectResult.h
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#ifndef SAPPHIRE_EFFECTRESULT_H
|
||||||
|
#define SAPPHIRE_EFFECTRESULT_H
|
||||||
|
|
||||||
|
#include <ForwardsZone.h>
|
||||||
|
#include <Common.h>
|
||||||
|
|
||||||
|
namespace Sapphire::World::Action
|
||||||
|
{
|
||||||
|
/*!
|
||||||
|
* @brief A container for the computed result of an effect on a single actor. Used to apply damage/healing dealt
|
||||||
|
* at a later point in time.
|
||||||
|
*/
|
||||||
|
class EffectResult
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit EffectResult( Entity::CharaPtr target, uint32_t delayMs );
|
||||||
|
|
||||||
|
void damage( uint32_t amount, Common::ActionHitSeverityType severity );
|
||||||
|
void heal( uint32_t amount, Common::ActionHitSeverityType severity );
|
||||||
|
|
||||||
|
Entity::CharaPtr getTarget() const;
|
||||||
|
|
||||||
|
uint32_t getValue() const;
|
||||||
|
|
||||||
|
Common::EffectEntry buildEffectEntry() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint64_t m_runAfter;
|
||||||
|
|
||||||
|
Entity::CharaPtr m_target;
|
||||||
|
|
||||||
|
Common::ActionHitSeverityType m_severity;
|
||||||
|
Common::ActionEffectType m_type;
|
||||||
|
|
||||||
|
uint32_t m_value;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //SAPPHIRE_EFFECTRESULT_H
|
|
@ -87,6 +87,8 @@ namespace World::Action
|
||||||
TYPE_FORWARD( Action );
|
TYPE_FORWARD( Action );
|
||||||
TYPE_FORWARD( EventAction );
|
TYPE_FORWARD( EventAction );
|
||||||
TYPE_FORWARD( ItemAction );
|
TYPE_FORWARD( ItemAction );
|
||||||
|
TYPE_FORWARD( EffectBuilder );
|
||||||
|
TYPE_FORWARD( EffectResult );
|
||||||
|
|
||||||
using ActionCallback = std::function< void( Entity::Player&, uint32_t, uint64_t ) >;
|
using ActionCallback = std::function< void( Entity::Player&, uint32_t, uint64_t ) >;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue