1
Fork 0
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:
NotAdam 2019-07-25 22:46:10 +10:00
parent a5b9923b66
commit 7e0108aea5
7 changed files with 285 additions and 20 deletions

View file

@ -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() )

View file

@ -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;
};

View 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 );
}
}

View 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

View 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;
}

View 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

View file

@ -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 ) >;
}