mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-05-07 11:17:46 +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 "ActionLut.h"
|
||||
#include "EffectBuilder.h"
|
||||
|
||||
#include <Exd/ExdDataGenerated.h>
|
||||
#include <Util/Util.h>
|
||||
|
@ -17,8 +18,9 @@
|
|||
#include "Network/PacketWrappers/ActorControlPacket142.h"
|
||||
#include "Network/PacketWrappers/ActorControlPacket143.h"
|
||||
#include "Network/PacketWrappers/ActorControlPacket144.h"
|
||||
#include <Network/PacketWrappers/EffectPacket.h>
|
||||
|
||||
#include <Logging/Logger.h>
|
||||
|
||||
#include <Util/ActorFilter.h>
|
||||
|
||||
using namespace Sapphire;
|
||||
|
@ -68,6 +70,8 @@ bool Action::Action::init()
|
|||
m_actionData = actionData;
|
||||
}
|
||||
|
||||
m_effectBuilder = make_EffectBuilder( m_pSource, getId() );
|
||||
|
||||
m_castTimeMs = static_cast< uint32_t >( m_actionData->cast100ms * 100 );
|
||||
m_recastTimeMs = static_cast< uint32_t >( m_actionData->recast100ms * 100 );
|
||||
m_cooldownGroup = m_actionData->cooldownGroup;
|
||||
|
@ -326,30 +330,13 @@ void Action::Action::execute()
|
|||
player->sendDebug( "action combo success from action#{0}", player->getLastComboActionId() );
|
||||
}
|
||||
|
||||
if( !hasClientsideTarget() )
|
||||
if( !hasClientsideTarget() )
|
||||
{
|
||||
snapshotAffectedActors( m_hitActors );
|
||||
|
||||
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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
buildEffects();
|
||||
}
|
||||
else if( auto player = m_pSource->getAsPlayer() )
|
||||
{
|
||||
pScriptMgr->onEObjHit( *player, m_targetId, getId() );
|
||||
return;
|
||||
}
|
||||
|
||||
// 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()
|
||||
{
|
||||
if( auto player = m_pSource->getAsPlayer() )
|
||||
|
|
|
@ -85,6 +85,8 @@ namespace Sapphire::World::Action
|
|||
*/
|
||||
bool snapshotAffectedActors( std::vector< Entity::CharaPtr >& actors );
|
||||
|
||||
void buildEffects();
|
||||
|
||||
/*!
|
||||
* @brief Adds an actor filter to this action.
|
||||
* @param filter The ptr to the ActorFilter to add
|
||||
|
@ -171,6 +173,8 @@ namespace Sapphire::World::Action
|
|||
|
||||
Common::FFXIVARR_POSITION3 m_pos;
|
||||
|
||||
EffectBuilderPtr m_effectBuilder;
|
||||
|
||||
std::vector< World::Util::ActorFilterPtr > m_actorFilters;
|
||||
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( EventAction );
|
||||
TYPE_FORWARD( ItemAction );
|
||||
TYPE_FORWARD( EffectBuilder );
|
||||
TYPE_FORWARD( EffectResult );
|
||||
|
||||
using ActionCallback = std::function< void( Entity::Player&, uint32_t, uint64_t ) >;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue