mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-05-01 16:37:45 +00:00
Merge pull request #915 from Skyliegirl33/actions
[3.x] Some initial action work (mostly statuses)
This commit is contained in:
commit
801fc9da8a
17 changed files with 314 additions and 48 deletions
|
@ -398,7 +398,18 @@
|
|||
"restorePercentage": 0,
|
||||
"nextCombo": [],
|
||||
"statuses": {
|
||||
"caster": [],
|
||||
"caster": [
|
||||
{
|
||||
"id": 83,
|
||||
"duration": 20000,
|
||||
"modifiers": [
|
||||
{
|
||||
"modifier": "DefensePercent",
|
||||
"value": 20
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"target": []
|
||||
}
|
||||
},
|
||||
|
@ -414,7 +425,18 @@
|
|||
"nextCombo": [],
|
||||
"statuses": {
|
||||
"caster": [],
|
||||
"target": []
|
||||
"target": [
|
||||
{
|
||||
"id": 244,
|
||||
"duration": 30000,
|
||||
"modifiers": [
|
||||
{
|
||||
"modifier": "TickDamage",
|
||||
"value": 20
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"34": {
|
||||
|
@ -478,7 +500,18 @@
|
|||
45
|
||||
],
|
||||
"statuses": {
|
||||
"caster": [],
|
||||
"caster": [
|
||||
{
|
||||
"id": 85,
|
||||
"duration": 24000,
|
||||
"modifiers": [
|
||||
{
|
||||
"modifier": "AttackPowerPercent",
|
||||
"value": 20
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"target": []
|
||||
}
|
||||
},
|
||||
|
@ -493,7 +526,18 @@
|
|||
"restorePercentage": 0,
|
||||
"nextCombo": [],
|
||||
"statuses": {
|
||||
"caster": [],
|
||||
"caster": [
|
||||
{
|
||||
"id": 86,
|
||||
"duration": 20000,
|
||||
"modifiers": [
|
||||
{
|
||||
"modifier": "AttackPowerPercent",
|
||||
"value": 50
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"target": []
|
||||
}
|
||||
},
|
||||
|
@ -523,7 +567,18 @@
|
|||
"restorePercentage": 0,
|
||||
"nextCombo": [],
|
||||
"statuses": {
|
||||
"caster": [],
|
||||
"caster": [
|
||||
{
|
||||
"id": 87,
|
||||
"duration": 20000,
|
||||
"modifiers": [
|
||||
{
|
||||
"modifier": "HPPercent",
|
||||
"value": 20
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"target": []
|
||||
}
|
||||
},
|
||||
|
@ -2454,7 +2509,38 @@
|
|||
"nextCombo": [],
|
||||
"statuses": {
|
||||
"caster": [],
|
||||
"target": []
|
||||
"target": [
|
||||
{
|
||||
"id": 180,
|
||||
"duration": 24000,
|
||||
"modifiers": [
|
||||
{
|
||||
"modifier": "TickDamage",
|
||||
"value": 35
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 191,
|
||||
"duration": 24000,
|
||||
"modifiers": [
|
||||
{
|
||||
"modifier": "HealingRecoveryPercent",
|
||||
"value": -20
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 240,
|
||||
"duration": 24000,
|
||||
"modifiers": [
|
||||
{
|
||||
"modifier": "HeavyPercent",
|
||||
"value": 40
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"169": {
|
||||
|
|
|
@ -887,22 +887,30 @@ namespace Sapphire::Common
|
|||
Perception = 73,
|
||||
|
||||
// Unique modifiers
|
||||
HPPercent = 1000,
|
||||
MPPercent = 1001,
|
||||
TPPercent = 1002,
|
||||
GPPercent = 1003,
|
||||
CPPercent = 1004,
|
||||
PhysicalDamagePercent = 1005,
|
||||
MagicDamagePercent = 1006,
|
||||
AttackPowerPercent = 1007,
|
||||
DefensePercent = 1008,
|
||||
AccuracyPercent = 1009,
|
||||
EvasionPercent = 1010,
|
||||
MagicDefensePercent = 1011,
|
||||
CriticalHitPowerPercent = 1012,
|
||||
CriticalHitResiliencePercent = 1013,
|
||||
CriticalHitPercent = 1014,
|
||||
EnmityPercent = 1015
|
||||
TickHeal = 1000,
|
||||
TickDamage = 1001,
|
||||
StrengthPercent = 1002,
|
||||
DexterityPercent = 1003,
|
||||
VitalityPercent = 1004,
|
||||
IntelligencePercent = 1005,
|
||||
MindPercent = 1006,
|
||||
PietyPercent = 1007,
|
||||
HPPercent = 1008,
|
||||
MPPercent = 1009,
|
||||
TPPercent = 1010,
|
||||
GPPercent = 1011,
|
||||
CPPercent = 1012,
|
||||
PhysicalDamagePercent = 1013,
|
||||
MagicDamagePercent = 1014,
|
||||
AttackPowerPercent = 1015,
|
||||
DefensePercent = 1016,
|
||||
AccuracyPercent = 1017,
|
||||
EvasionPercent = 1018,
|
||||
MagicDefensePercent = 1019,
|
||||
CriticalHitPowerPercent = 1020,
|
||||
CriticalHitResiliencePercent = 1021,
|
||||
CriticalHitPercent = 1022,
|
||||
EnmityPercent = 1023
|
||||
};
|
||||
|
||||
enum struct ActionAspect : uint8_t
|
||||
|
|
|
@ -40,6 +40,7 @@ struct StatusModifier
|
|||
struct StatusEntry
|
||||
{
|
||||
uint16_t id;
|
||||
int32_t duration;
|
||||
std::vector< StatusModifier > modifiers;
|
||||
};
|
||||
|
||||
|
@ -76,6 +77,7 @@ void to_json( nlohmann::ordered_json& j, const StatusEntry& statusEntry )
|
|||
{
|
||||
j = nlohmann::ordered_json{
|
||||
{ "id", statusEntry.id },
|
||||
{ "duration", statusEntry.duration },
|
||||
{ "modifiers", statusEntry.modifiers }
|
||||
};
|
||||
}
|
||||
|
|
|
@ -431,7 +431,7 @@ void Action::Action::execute()
|
|||
|
||||
if( !hasClientsideTarget() )
|
||||
{
|
||||
buildEffects();
|
||||
handleAction();
|
||||
}
|
||||
else if( auto player = m_pSource->getAsPlayer() )
|
||||
{
|
||||
|
@ -501,7 +501,15 @@ std::pair< uint32_t, Common::ActionHitSeverityType > Action::Action::calcHealing
|
|||
return Math::CalcStats::calcActionHealing( *m_pSource, potency, wepDmg );
|
||||
}
|
||||
|
||||
void Action::Action::buildEffects()
|
||||
void Action::Action::applyStatusEffectSelf( uint16_t statusId, uint8_t param )
|
||||
{
|
||||
if( m_hitActors.size() > 0 )
|
||||
getEffectbuilder()->applyStatusEffect( m_hitActors[ 0 ], statusId, param, true );
|
||||
else
|
||||
getEffectbuilder()->applyStatusEffect( m_pSource, statusId, param );
|
||||
}
|
||||
|
||||
void Action::Action::handleAction()
|
||||
{
|
||||
snapshotAffectedActors( m_hitActors );
|
||||
|
||||
|
@ -593,6 +601,9 @@ void Action::Action::buildEffects()
|
|||
}
|
||||
}
|
||||
|
||||
if( m_lutEntry.statuses.caster.size() > 0 || m_lutEntry.statuses.target.size() > 0 )
|
||||
handleStatusEffects();
|
||||
|
||||
m_effectBuilder->buildAndSendPackets( m_hitActors );
|
||||
|
||||
// TODO: disabled, reset kills our queued actions
|
||||
|
@ -600,6 +611,38 @@ void Action::Action::buildEffects()
|
|||
// m_effectBuilder.reset();
|
||||
}
|
||||
|
||||
void Action::Action::handleStatusEffects()
|
||||
{
|
||||
if( isComboAction() && !isCorrectCombo() )
|
||||
return;
|
||||
|
||||
// handle caster statuses
|
||||
if( m_lutEntry.statuses.caster.size() > 0 )
|
||||
{
|
||||
for( auto& status : m_lutEntry.statuses.caster )
|
||||
{
|
||||
applyStatusEffectSelf( status.id );
|
||||
m_pSource->addStatusEffectByIdIfNotExist( status.id, status.duration, *m_pSource, status.modifiers );
|
||||
}
|
||||
}
|
||||
|
||||
// handle hit actor statuses
|
||||
if( m_lutEntry.statuses.target.size() > 0 && m_hitActors.size() > 0 )
|
||||
{
|
||||
for( auto& actor : m_hitActors )
|
||||
{
|
||||
for( auto& status : m_lutEntry.statuses.target )
|
||||
{
|
||||
getEffectbuilder()->applyStatusEffect( actor, status.id, 0 );
|
||||
actor->addStatusEffectByIdIfNotExist( status.id, status.duration, *m_pSource, status.modifiers );
|
||||
}
|
||||
|
||||
if( actor->getStatusEffectMap().size() > 0 )
|
||||
actor->onActionHostile( m_pSource );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Action::Action::preCheck()
|
||||
{
|
||||
if( auto player = m_pSource->getAsPlayer() )
|
||||
|
@ -864,7 +907,8 @@ Entity::CharaPtr Action::Action::getHitChara()
|
|||
bool Action::Action::hasValidLutEntry() const
|
||||
{
|
||||
return m_lutEntry.potency != 0 || m_lutEntry.comboPotency != 0 || m_lutEntry.flankPotency != 0 || m_lutEntry.frontPotency != 0 ||
|
||||
m_lutEntry.rearPotency != 0 || m_lutEntry.curePotency != 0 || m_lutEntry.restoreMPPercentage != 0;
|
||||
m_lutEntry.rearPotency != 0 || m_lutEntry.curePotency != 0 || m_lutEntry.restoreMPPercentage != 0 ||
|
||||
m_lutEntry.statuses.caster.size() > 0 || m_lutEntry.statuses.target.size() > 0;
|
||||
}
|
||||
|
||||
Action::EffectBuilderPtr Action::Action::getEffectbuilder()
|
||||
|
|
|
@ -105,7 +105,11 @@ namespace Sapphire::World::Action
|
|||
|
||||
EffectBuilderPtr getEffectbuilder();
|
||||
|
||||
void buildEffects();
|
||||
void applyStatusEffectSelf( uint16_t statusId, uint8_t param = 0 );
|
||||
|
||||
void handleAction();
|
||||
|
||||
void handleStatusEffects();
|
||||
|
||||
/*!
|
||||
* @brief Adds an actor filter to this action.
|
||||
|
|
|
@ -15,7 +15,8 @@ bool ActionLut::validEntryExists( uint16_t actionId )
|
|||
|
||||
// if all of the fields are 0, it's not 'valid' due to parse error or no useful data in the tooltip
|
||||
return entry.potency != 0 || entry.comboPotency != 0 || entry.flankPotency != 0 || entry.frontPotency != 0 ||
|
||||
entry.rearPotency != 0 || entry.curePotency != 0;
|
||||
entry.rearPotency != 0 || entry.curePotency != 0 ||
|
||||
entry.statuses.caster.size() > 0 || entry.statuses.target.size() > 0;
|
||||
}
|
||||
|
||||
const ActionEntry& ActionLut::getEntry( uint16_t actionId )
|
||||
|
|
|
@ -17,6 +17,7 @@ namespace Sapphire::World::Action
|
|||
struct StatusEntry
|
||||
{
|
||||
uint16_t id;
|
||||
int32_t duration;
|
||||
std::vector< StatusModifier > modifiers;
|
||||
};
|
||||
|
||||
|
|
|
@ -85,6 +85,14 @@ std::unordered_map< std::string, Common::ParamModifier > ActionLutData::m_modifi
|
|||
{ "Control", Common::ParamModifier::Control },
|
||||
{ "Gathering", Common::ParamModifier::Gathering },
|
||||
{ "Perception", Common::ParamModifier::Perception },
|
||||
{ "TickHeal", Common::ParamModifier::TickHeal },
|
||||
{ "TickDamage", Common::ParamModifier::TickDamage },
|
||||
{ "StrengthPercent", Common::ParamModifier::StrengthPercent },
|
||||
{ "DexterityPercent", Common::ParamModifier::DexterityPercent },
|
||||
{ "VitalityPercent", Common::ParamModifier::VitalityPercent },
|
||||
{ "IntelligencePercent", Common::ParamModifier::IntelligencePercent },
|
||||
{ "MindPercent", Common::ParamModifier::MindPercent },
|
||||
{ "PietyPercent", Common::ParamModifier::PietyPercent },
|
||||
{ "HPPercent", Common::ParamModifier::HPPercent },
|
||||
{ "MPPercent", Common::ParamModifier::MPPercent },
|
||||
{ "TPPercent", Common::ParamModifier::TPPercent },
|
||||
|
|
|
@ -32,6 +32,7 @@ namespace Sapphire::World::Action
|
|||
inline void from_json( const nlohmann::json& j, StatusEntry& statusEntry )
|
||||
{
|
||||
j.at( "id" ).get_to( statusEntry.id );
|
||||
j.at( "duration" ).get_to( statusEntry.duration );
|
||||
if( j.contains( "modifiers" ) )
|
||||
j.at( "modifiers" ).get_to( statusEntry.modifiers );
|
||||
}
|
||||
|
|
|
@ -93,10 +93,10 @@ void EffectBuilder::comboSucceed( Entity::CharaPtr& target )
|
|||
addResultToActor( target, nextResult );
|
||||
}
|
||||
|
||||
void EffectBuilder::applyStatusEffect( Entity::CharaPtr& target, uint16_t statusId, uint8_t param )
|
||||
void EffectBuilder::applyStatusEffect( Entity::CharaPtr& target, uint16_t statusId, uint8_t param, bool forSelf )
|
||||
{
|
||||
EffectResultPtr nextResult = make_EffectResult( target, 0 );
|
||||
nextResult->applyStatusEffect( statusId, param );
|
||||
nextResult->applyStatusEffect( statusId, param, forSelf );
|
||||
addResultToActor( target, nextResult );
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace Sapphire::World::Action
|
|||
|
||||
void comboSucceed( Entity::CharaPtr& target );
|
||||
|
||||
void applyStatusEffect( Entity::CharaPtr& target, uint16_t statusId, uint8_t param );
|
||||
void applyStatusEffect( Entity::CharaPtr& target, uint16_t statusId, uint8_t param, bool forSelf = false );
|
||||
|
||||
void mount( Entity::CharaPtr& target, uint16_t mountId );
|
||||
|
||||
|
|
|
@ -70,11 +70,13 @@ void EffectResult::comboSucceed()
|
|||
m_result.Type = Common::ActionEffectType::CALC_RESULT_TYPE_COMBO_HIT;
|
||||
}
|
||||
|
||||
void EffectResult::applyStatusEffect( uint16_t statusId, uint8_t param )
|
||||
void EffectResult::applyStatusEffect( uint16_t statusId, uint8_t param, bool forSelf )
|
||||
{
|
||||
m_result.Value = static_cast< int16_t >( statusId );
|
||||
m_result.Arg2 = param;
|
||||
m_result.Type = Common::ActionEffectType::CALC_RESULT_TYPE_SET_STATUS;
|
||||
if( forSelf )
|
||||
m_result.Flag = static_cast< uint8_t >( Common::ActionEffectResultFlag::EffectOnSource );
|
||||
m_result.Type = forSelf ? Common::ActionEffectType::CALC_RESULT_TYPE_SET_STATUS_ME : Common::ActionEffectType::CALC_RESULT_TYPE_SET_STATUS;
|
||||
}
|
||||
|
||||
void EffectResult::mount( uint16_t mountId )
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace Sapphire::World::Action
|
|||
void restoreMP( uint32_t amount, Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None );
|
||||
void startCombo( uint16_t actionId );
|
||||
void comboSucceed();
|
||||
void applyStatusEffect( uint16_t statusId, uint8_t param );
|
||||
void applyStatusEffect( uint16_t statusId, uint8_t param, bool forSelf );
|
||||
void mount( uint16_t mountId );
|
||||
|
||||
Entity::CharaPtr getTarget() const;
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include <Network/CommonActorControl.h>
|
||||
#include <Service.h>
|
||||
|
||||
|
||||
#include "Forwards.h"
|
||||
|
||||
#include "Territory/Territory.h"
|
||||
|
@ -26,6 +25,7 @@
|
|||
#include "Player.h"
|
||||
#include "Manager/TerritoryMgr.h"
|
||||
#include "Manager/MgrUtil.h"
|
||||
#include "Manager/PlayerMgr.h"
|
||||
#include "Common.h"
|
||||
|
||||
using namespace Sapphire::Common;
|
||||
|
@ -559,7 +559,17 @@ void Sapphire::Entity::Chara::addStatusEffectByIdIfNotExist( uint32_t id, int32_
|
|||
auto effect = StatusEffect::make_StatusEffect( id, source.getAsChara(), getAsChara(), duration, 3000 );
|
||||
effect->setParam( param );
|
||||
addStatusEffect( effect );
|
||||
}
|
||||
|
||||
void Sapphire::Entity::Chara::addStatusEffectByIdIfNotExist( uint32_t id, int32_t duration, Entity::Chara& source,
|
||||
std::vector< World::Action::StatusModifier >& modifiers, uint16_t param )
|
||||
{
|
||||
if( hasStatusEffect( id ) )
|
||||
return;
|
||||
|
||||
auto effect = StatusEffect::make_StatusEffect( id, source.getAsChara(), getAsChara(), duration, modifiers, 3000 );
|
||||
effect->setParam( param );
|
||||
addStatusEffect( effect );
|
||||
}
|
||||
|
||||
int8_t Sapphire::Entity::Chara::getStatusEffectFreeSlot()
|
||||
|
@ -644,7 +654,6 @@ void Sapphire::Entity::Chara::sendStatusEffectUpdate()
|
|||
{
|
||||
uint64_t currentTimeMs = Util::getTimeMs();
|
||||
|
||||
|
||||
auto statusEffectList = makeZonePacket< FFXIVIpcStatus >( getId() );
|
||||
uint8_t slot = 0;
|
||||
for( const auto& effectIt : m_statusEffectMap )
|
||||
|
@ -689,7 +698,13 @@ void Sapphire::Entity::Chara::updateStatusEffects()
|
|||
|
||||
bool Sapphire::Entity::Chara::hasStatusEffect( uint32_t id )
|
||||
{
|
||||
return m_statusEffectMap.find( id ) != m_statusEffectMap.end();
|
||||
for( const auto& [ key, val ] : m_statusEffectMap )
|
||||
{
|
||||
if( val->getId() == id )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int64_t Sapphire::Entity::Chara::getLastUpdateTime() const
|
||||
|
@ -785,6 +800,47 @@ void Sapphire::Entity::Chara::setStatValue( Common::BaseParam baseParam, uint32_
|
|||
m_baseStats[ index ] = value;
|
||||
}
|
||||
|
||||
float Sapphire::Entity::Chara::getModifier( Common::ParamModifier paramModifier ) const
|
||||
{
|
||||
if( m_modifiers.find( paramModifier ) == m_modifiers.end() )
|
||||
return paramModifier >= Common::ParamModifier::StrengthPercent ? 1.0f : 0;
|
||||
|
||||
auto& mod = m_modifiers.at( paramModifier );
|
||||
if( paramModifier >= Common::ParamModifier::StrengthPercent )
|
||||
{
|
||||
auto valPercent = 1.0f;
|
||||
for( const auto val : mod )
|
||||
valPercent *= 1.0f + ( val / 100.0f );
|
||||
return valPercent;
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::accumulate( mod.begin(), mod.end(), 0 );
|
||||
}
|
||||
}
|
||||
|
||||
void Sapphire::Entity::Chara::addModifier( Common::ParamModifier paramModifier, int32_t value )
|
||||
{
|
||||
m_modifiers[ paramModifier ].push_back( value );
|
||||
|
||||
if( auto pPlayer = this->getAsPlayer(); pPlayer )
|
||||
Common::Service< World::Manager::PlayerMgr >::ref().sendDebug( *pPlayer, "Modifier: {}, value: {}", static_cast< int32_t >( paramModifier ), getModifier( paramModifier ) );
|
||||
}
|
||||
|
||||
void Sapphire::Entity::Chara::delModifier( Common::ParamModifier paramModifier, int32_t value )
|
||||
{
|
||||
assert( m_modifiers.count( paramModifier ) != 0 );
|
||||
auto& mod = m_modifiers.at( paramModifier );
|
||||
|
||||
mod.erase( std::remove( mod.begin(), mod.end(), value ), mod.end() );
|
||||
|
||||
if( mod.size() == 0 )
|
||||
m_modifiers.erase( paramModifier );
|
||||
|
||||
if( auto pPlayer = this->getAsPlayer(); pPlayer )
|
||||
Common::Service< World::Manager::PlayerMgr >::ref().sendDebug( *pPlayer, "Modifier: {}, value: {}", static_cast< int32_t >( paramModifier ), getModifier( paramModifier ) );
|
||||
}
|
||||
|
||||
void Sapphire::Entity::Chara::onTick()
|
||||
{
|
||||
uint32_t thisTickDmg = 0;
|
||||
|
@ -795,13 +851,13 @@ void Sapphire::Entity::Chara::onTick()
|
|||
auto thisEffect = effectIt.second->getTickEffect();
|
||||
switch( thisEffect.first )
|
||||
{
|
||||
case 1:
|
||||
case Common::ParamModifier::TickDamage:
|
||||
{
|
||||
thisTickDmg += thisEffect.second;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
case Common::ParamModifier::TickHeal:
|
||||
{
|
||||
thisTickHeal += thisEffect.second;
|
||||
break;
|
||||
|
@ -809,12 +865,18 @@ void Sapphire::Entity::Chara::onTick()
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: don't really like how this is handled
|
||||
// TODO: calculate actual damage from potency
|
||||
if( thisTickDmg != 0 )
|
||||
{
|
||||
takeDamage( thisTickDmg );
|
||||
server().queueForPlayers( getInRangePlayerIds( isPlayer() ), makeActorControl( getId(), HPFloatingText, 0,
|
||||
static_cast< uint8_t >( ActionEffectType::CALC_RESULT_TYPE_DAMAGE_HP ),
|
||||
thisTickDmg ) );
|
||||
if( isPlayer() )
|
||||
server().queueForPlayers( getInRangePlayerIds( isPlayer() ), makeHudParam( *getAsPlayer() ) );
|
||||
else if( isBattleNpc() )
|
||||
server().queueForPlayers( getInRangePlayerIds( isPlayer() ), makeHudParam( *getAsBNpc() ) );
|
||||
}
|
||||
|
||||
if( thisTickHeal != 0 )
|
||||
|
@ -823,5 +885,9 @@ void Sapphire::Entity::Chara::onTick()
|
|||
server().queueForPlayers( getInRangePlayerIds( isPlayer() ), makeActorControl( getId(), HPFloatingText, 0,
|
||||
static_cast< uint8_t >( ActionEffectType::CALC_RESULT_TYPE_RECOVER_HP ),
|
||||
thisTickHeal ) );
|
||||
if( isPlayer() )
|
||||
server().queueForPlayers( getInRangePlayerIds( isPlayer() ), makeHudParam( *getAsPlayer() ) );
|
||||
else if( isBattleNpc() )
|
||||
server().queueForPlayers( getInRangePlayerIds( isPlayer() ), makeHudParam( *getAsBNpc() ) );
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <Common.h>
|
||||
#include "Action/ActionLut.h"
|
||||
|
||||
#include "Forwards.h"
|
||||
#include "GameObject.h"
|
||||
|
@ -8,6 +9,7 @@
|
|||
#include <map>
|
||||
#include <queue>
|
||||
#include <array>
|
||||
#include <numeric>
|
||||
|
||||
namespace Sapphire::Entity
|
||||
{
|
||||
|
@ -26,10 +28,13 @@ namespace Sapphire::Entity
|
|||
public:
|
||||
|
||||
using ActorStatsArray = std::array< uint32_t, STAT_ARRAY_SIZE >;
|
||||
using ActorModifiersMap = std::unordered_map< Common::ParamModifier, std::vector< int32_t > >;
|
||||
|
||||
ActorStatsArray m_baseStats{ 0 };
|
||||
ActorStatsArray m_bonusStats{ 0 };
|
||||
|
||||
ActorModifiersMap m_modifiers{ 0 };
|
||||
|
||||
protected:
|
||||
char m_name[34];
|
||||
/*! Last tick time for the actor ( in ms ) */
|
||||
|
@ -133,9 +138,9 @@ namespace Sapphire::Entity
|
|||
|
||||
// add a status effect by id
|
||||
void addStatusEffectById( uint32_t id, int32_t duration, Entity::Chara& source, uint16_t param = 0 );
|
||||
|
||||
// add a status effect by id if it doesn't exist
|
||||
void addStatusEffectByIdIfNotExist( uint32_t id, int32_t duration, Entity::Chara& source, uint16_t param = 0 );
|
||||
void addStatusEffectByIdIfNotExist( uint32_t id, int32_t duration, Entity::Chara& source, std::vector< World::Action::StatusModifier >& modifiers, uint16_t param = 0 );
|
||||
|
||||
// remove a status effect by id
|
||||
void removeSingleStatusEffectFromId( uint32_t id );
|
||||
|
@ -159,6 +164,12 @@ namespace Sapphire::Entity
|
|||
|
||||
void setStatValue( Common::BaseParam baseParam, uint32_t value );
|
||||
|
||||
float getModifier( Common::ParamModifier paramModifier ) const;
|
||||
|
||||
void addModifier( Common::ParamModifier paramModifier, int32_t value );
|
||||
|
||||
void delModifier( Common::ParamModifier paramModifier, int32_t value );
|
||||
|
||||
uint32_t getHp() const;
|
||||
|
||||
uint32_t getHpPercent() const;
|
||||
|
|
|
@ -17,12 +17,20 @@ using namespace Sapphire::Common;
|
|||
using namespace Sapphire::Network::Packets;
|
||||
//using namespace Sapphire::Network::Packets::WorldPackets::Server;
|
||||
|
||||
Sapphire::StatusEffect::StatusEffect::StatusEffect( uint32_t id, Entity::CharaPtr sourceActor, Entity::CharaPtr targetActor,
|
||||
uint32_t duration, std::vector< World::Action::StatusModifier >& modifiers, uint32_t tickRate ) :
|
||||
StatusEffect( id, sourceActor, targetActor, duration, tickRate )
|
||||
{
|
||||
m_modifiers = std::move( modifiers );
|
||||
}
|
||||
|
||||
Sapphire::StatusEffect::StatusEffect::StatusEffect( uint32_t id, Entity::CharaPtr sourceActor, Entity::CharaPtr targetActor,
|
||||
uint32_t duration, uint32_t tickRate ) :
|
||||
m_id( id ),
|
||||
m_sourceActor( sourceActor ),
|
||||
m_targetActor( targetActor ),
|
||||
m_duration( duration ),
|
||||
m_modifiers( 0 ),
|
||||
m_startTime( 0 ),
|
||||
m_tickRate( tickRate ),
|
||||
m_lastTick( 0 )
|
||||
|
@ -47,16 +55,14 @@ Sapphire::StatusEffect::StatusEffect::~StatusEffect()
|
|||
{
|
||||
}
|
||||
|
||||
void Sapphire::StatusEffect::StatusEffect::registerTickEffect( uint8_t type, uint32_t param )
|
||||
void Sapphire::StatusEffect::StatusEffect::registerTickEffect( ParamModifier type, uint32_t param )
|
||||
{
|
||||
m_currTickEffect = std::make_pair( type, param );
|
||||
}
|
||||
|
||||
std::pair< uint8_t, uint32_t > Sapphire::StatusEffect::StatusEffect::getTickEffect()
|
||||
std::pair< ParamModifier, uint32_t > Sapphire::StatusEffect::StatusEffect::getTickEffect()
|
||||
{
|
||||
auto thisTick = m_currTickEffect;
|
||||
m_currTickEffect = std::make_pair( 0, 0 );
|
||||
return thisTick;
|
||||
return m_currTickEffect;
|
||||
}
|
||||
|
||||
void Sapphire::StatusEffect::StatusEffect::onTick()
|
||||
|
@ -87,6 +93,19 @@ void Sapphire::StatusEffect::StatusEffect::applyStatus()
|
|||
m_startTime = Util::getTimeMs();
|
||||
auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref();
|
||||
|
||||
for( const auto& mod : m_modifiers )
|
||||
{
|
||||
// TODO: ticks
|
||||
if( mod.modifier != Common::ParamModifier::TickDamage && mod.modifier != Common::ParamModifier::TickHeal )
|
||||
m_targetActor->addModifier( mod.modifier, mod.value );
|
||||
else if( mod.modifier == Common::ParamModifier::TickDamage )
|
||||
registerTickEffect( mod.modifier, mod.value );
|
||||
else if( mod.modifier == Common::ParamModifier::TickHeal )
|
||||
registerTickEffect( mod.modifier, mod.value );
|
||||
}
|
||||
|
||||
m_targetActor->calculateStats();
|
||||
|
||||
// this is only right when an action is being used by the player
|
||||
// else you probably need to use an actorcontrol
|
||||
|
||||
|
@ -111,6 +130,15 @@ void Sapphire::StatusEffect::StatusEffect::applyStatus()
|
|||
void Sapphire::StatusEffect::StatusEffect::removeStatus()
|
||||
{
|
||||
auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref();
|
||||
|
||||
for( const auto& mod : m_modifiers )
|
||||
{
|
||||
if( mod.modifier != Common::ParamModifier::TickDamage && mod.modifier != Common::ParamModifier::TickHeal )
|
||||
m_targetActor->delModifier( mod.modifier, mod.value );
|
||||
}
|
||||
|
||||
m_targetActor->calculateStats();
|
||||
|
||||
scriptMgr.onStatusTimeOut( m_targetActor, m_id );
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define _STATUSEFFECT_H_
|
||||
|
||||
#include "Forwards.h"
|
||||
#include "Action/ActionLut.h"
|
||||
|
||||
namespace Sapphire {
|
||||
namespace StatusEffect {
|
||||
|
@ -10,6 +11,9 @@ namespace StatusEffect {
|
|||
class StatusEffect
|
||||
{
|
||||
public:
|
||||
StatusEffect( uint32_t id, Entity::CharaPtr sourceActor, Entity::CharaPtr targetActor,
|
||||
uint32_t duration, std::vector< World::Action::StatusModifier >& modifiers, uint32_t tickRate );
|
||||
|
||||
StatusEffect( uint32_t id, Entity::CharaPtr sourceActor, Entity::CharaPtr targetActor,
|
||||
uint32_t duration, uint32_t tickRate );
|
||||
|
||||
|
@ -41,9 +45,9 @@ public:
|
|||
|
||||
void setParam( uint16_t param );
|
||||
|
||||
void registerTickEffect( uint8_t type, uint32_t param );
|
||||
void registerTickEffect( Common::ParamModifier type, uint32_t param );
|
||||
|
||||
std::pair< uint8_t, uint32_t > getTickEffect();
|
||||
std::pair< Common::ParamModifier, uint32_t > getTickEffect();
|
||||
|
||||
const std::string& getName() const;
|
||||
|
||||
|
@ -57,8 +61,8 @@ private:
|
|||
uint64_t m_lastTick;
|
||||
uint16_t m_param;
|
||||
std::string m_name;
|
||||
std::pair< uint8_t, uint32_t > m_currTickEffect;
|
||||
|
||||
std::pair< Common::ParamModifier, uint32_t > m_currTickEffect;
|
||||
std::vector< World::Action::StatusModifier > m_modifiers;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue