From 7e0108aea54121c0d7fac688e4d83daa711e1c33 Mon Sep 17 00:00:00 2001 From: NotAdam Date: Thu, 25 Jul 2019 22:46:10 +1000 Subject: [PATCH] some effects/action wip crap --- src/world/Action/Action.cpp | 71 +++++++++++++++++------- src/world/Action/Action.h | 4 ++ src/world/Action/EffectBuilder.cpp | 87 ++++++++++++++++++++++++++++++ src/world/Action/EffectBuilder.h | 47 ++++++++++++++++ src/world/Action/EffectResult.cpp | 55 +++++++++++++++++++ src/world/Action/EffectResult.h | 39 ++++++++++++++ src/world/ForwardsZone.h | 2 + 7 files changed, 285 insertions(+), 20 deletions(-) create mode 100644 src/world/Action/EffectBuilder.cpp create mode 100644 src/world/Action/EffectBuilder.h create mode 100644 src/world/Action/EffectResult.cpp create mode 100644 src/world/Action/EffectResult.h diff --git a/src/world/Action/Action.cpp b/src/world/Action/Action.cpp index 2eb44e2b..8f9bfcab 100644 --- a/src/world/Action/Action.cpp +++ b/src/world/Action/Action.cpp @@ -1,5 +1,6 @@ #include "Action.h" #include "ActionLut.h" +#include "EffectBuilder.h" #include #include @@ -17,8 +18,9 @@ #include "Network/PacketWrappers/ActorControlPacket142.h" #include "Network/PacketWrappers/ActorControlPacket143.h" #include "Network/PacketWrappers/ActorControlPacket144.h" -#include + #include + #include 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() ) diff --git a/src/world/Action/Action.h b/src/world/Action/Action.h index 6f3fccca..debaaea0 100644 --- a/src/world/Action/Action.h +++ b/src/world/Action/Action.h @@ -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; }; diff --git a/src/world/Action/EffectBuilder.cpp b/src/world/Action/EffectBuilder.cpp new file mode 100644 index 00000000..6535604b --- /dev/null +++ b/src/world/Action/EffectBuilder.cpp @@ -0,0 +1,87 @@ +#include "EffectBuilder.h" +#include "EffectResult.h" + +#include + +#include + +#include + +#include +#include + +#include + +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 ); + } + +} \ No newline at end of file diff --git a/src/world/Action/EffectBuilder.h b/src/world/Action/EffectBuilder.h new file mode 100644 index 00000000..386bf080 --- /dev/null +++ b/src/world/Action/EffectBuilder.h @@ -0,0 +1,47 @@ +#ifndef SAPPHIRE_EFFECTBUILDER_H +#define SAPPHIRE_EFFECTBUILDER_H + +#include +#include + +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 diff --git a/src/world/Action/EffectResult.cpp b/src/world/Action/EffectResult.cpp new file mode 100644 index 00000000..fd7cc0e1 --- /dev/null +++ b/src/world/Action/EffectResult.cpp @@ -0,0 +1,55 @@ +#include "EffectResult.h" + +#include + +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; +} \ No newline at end of file diff --git a/src/world/Action/EffectResult.h b/src/world/Action/EffectResult.h new file mode 100644 index 00000000..65026802 --- /dev/null +++ b/src/world/Action/EffectResult.h @@ -0,0 +1,39 @@ +#ifndef SAPPHIRE_EFFECTRESULT_H +#define SAPPHIRE_EFFECTRESULT_H + +#include +#include + +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 diff --git a/src/world/ForwardsZone.h b/src/world/ForwardsZone.h index 95ac658f..4ff4af79 100644 --- a/src/world/ForwardsZone.h +++ b/src/world/ForwardsZone.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 ) >; }