1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-28 15:17:46 +00:00

Add flags to StatusEffects

This commit is contained in:
Lucy 2023-03-12 16:37:33 +01:00
parent f4a3c9493b
commit 5bb8f11881
8 changed files with 121 additions and 11 deletions

View file

@ -629,7 +629,7 @@
},
"44": {
"name": "Vengeance",
"potency": 50,
"potency": 0,
"comboPotency": 0,
"flankPotency": 0,
"frontPotency": 0,
@ -638,7 +638,18 @@
"restorePercentage": 0,
"nextCombo": [],
"statuses": {
"caster": [],
"caster": [
{
"id": 89,
"duration": 20000,
"modifiers": [
{
"modifier": "ReflectPhysical",
"value": 50
}
]
}
],
"target": []
}
},
@ -1263,7 +1274,19 @@
"restorePercentage": 0,
"nextCombo": [],
"statuses": {
"caster": [],
"caster": [
{
"id": 116,
"duration": 10000,
"flag": 4096,
"modifiers": [
{
"modifier": "CriticalHitPercent",
"value": 100
}
]
}
],
"target": []
}
},

View file

@ -922,6 +922,23 @@ namespace Sapphire::Common
ParryPercent = 1031
};
enum class StatusEffectFlag : uint32_t
{
BuffCategory = 1,
DebuffCategory = 2,
Permanent = 4,
IsGaze = 8,
Transfiguration = 16,
CanDispel = 32,
LockActions = 64,
LockControl = 128,
LockMovement = 256,
Invisibilty = 512,
CanStatusOff = 1024,
FcBuff = 2048,
RemoveOnSuccessfulHit = 4096
};
enum struct ActionAspect : uint8_t
{
None = 0, // Doesn't imply unaspected

View file

@ -41,6 +41,7 @@ struct StatusEntry
{
uint16_t id;
int32_t duration;
uint32_t flag;
std::vector< StatusModifier > modifiers;
};
@ -78,6 +79,7 @@ void to_json( nlohmann::ordered_json& j, const StatusEntry& statusEntry )
j = nlohmann::ordered_json{
{ "id", statusEntry.id },
{ "duration", statusEntry.duration },
{ "flag", statusEntry.flag },
{ "modifiers", statusEntry.modifiers }
};
}

View file

@ -88,6 +88,7 @@ bool Action::Action::init()
m_cooldownGroup = m_actionData->data().RecastGroup;
m_range = m_actionData->data().SelectRange;
m_effectRange = m_actionData->data().EffectRange;
m_effectWidth = m_actionData->data().EffectWidth;
m_category = static_cast< Common::ActionCategory >( m_actionData->data().Category );
m_castType = static_cast< Common::CastType >( m_actionData->data().EffectType );
m_aspect = static_cast< Common::ActionAspect >( m_actionData->data().AttackType );
@ -119,7 +120,7 @@ bool Action::Action::init()
m_primaryCostType = static_cast< Common::ActionPrimaryCostType >( m_actionData->data().CostType );
m_primaryCost = m_actionData->data().CostValue;
/*if( !m_actionData->targetArea )
if( !m_actionData->data().SelectGround )
{
// override pos to target position
// todo: this is kinda dirty
@ -131,7 +132,7 @@ bool Action::Action::init()
break;
}
}
}*/
}
// todo: add missing rows for secondaryCostType/secondaryCostType and rename the current rows to primaryCostX
@ -607,11 +608,17 @@ void Action::Action::handleAction()
}
}
if( m_lutEntry.statuses.caster.size() > 0 || m_lutEntry.statuses.target.size() > 0 )
handleStatusEffects();
// If we hit an enemy
if( m_hitActors.size() > 0 && getHitChara()->getObjKind() != m_pSource->getObjKind() )
{
m_pSource->removeStatusEffectByFlag( Common::StatusEffectFlag::RemoveOnSuccessfulHit );
}
handleJobAction();
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
@ -630,7 +637,7 @@ void Action::Action::handleStatusEffects()
for( auto& status : m_lutEntry.statuses.caster )
{
applyStatusEffectSelf( status.id );
m_pSource->addStatusEffectByIdIfNotExist( status.id, status.duration, *m_pSource, status.modifiers );
m_pSource->addStatusEffectByIdIfNotExist( status.id, status.duration, *m_pSource, status );
}
}
@ -642,7 +649,7 @@ void Action::Action::handleStatusEffects()
for( auto& status : m_lutEntry.statuses.target )
{
getEffectbuilder()->applyStatusEffect( actor, status.id, 0 );
actor->addStatusEffectByIdIfNotExist( status.id, status.duration, *m_pSource, status.modifiers );
actor->addStatusEffectByIdIfNotExist( status.id, status.duration, *m_pSource, status );
}
if( actor->getStatusEffectMap().size() > 0 )
@ -866,7 +873,6 @@ void Action::Action::addDefaultActorFilters()
switch( m_castType )
{
case Common::CastType::SingleTarget:
case Common::CastType::Type3:
{
auto filter = std::make_shared< World::Util::ActorFilterSingleTarget >( static_cast< uint32_t >( m_targetId ) );
addActorFilter( filter );

View file

@ -572,6 +572,17 @@ void Sapphire::Entity::Chara::addStatusEffectByIdIfNotExist( uint32_t id, int32_
addStatusEffect( effect );
}
void Sapphire::Entity::Chara::addStatusEffectByIdIfNotExist( uint32_t id, int32_t duration, Entity::Chara& source,
World::Action::StatusEntry& statusEntry, uint16_t param )
{
if( hasStatusEffect( id ) )
return;
auto effect = StatusEffect::make_StatusEffect( id, source.getAsChara(), getAsChara(), duration, statusEntry, 3000 );
effect->setParam( param );
addStatusEffect( effect );
}
int8_t Sapphire::Entity::Chara::getStatusEffectFreeSlot()
{
int8_t freeEffectSlot = -1;
@ -614,6 +625,17 @@ void Sapphire::Entity::Chara::removeSingleStatusEffectById( uint32_t id )
}
}
void Sapphire::Entity::Chara::removeStatusEffectByFlag( Common::StatusEffectFlag flag )
{
for( auto effectIt = m_statusEffectMap.begin(); effectIt != m_statusEffectMap.end(); )
{
if( effectIt->second->getFlag() & static_cast< uint32_t >( flag ) )
effectIt = removeStatusEffect( effectIt->first );
else
++effectIt;
}
}
std::map< uint8_t, Sapphire::StatusEffect::StatusEffectPtr >::iterator Sapphire::Entity::Chara::removeStatusEffect( uint8_t effectSlotId, bool sendOrder )
{
auto pEffectIt = m_statusEffectMap.find( effectSlotId );

View file

@ -114,6 +114,8 @@ namespace Sapphire::Entity
void removeSingleStatusEffectById( uint32_t id );
void removeStatusEffectByFlag( Common::StatusEffectFlag flag );
void updateStatusEffects();
bool hasStatusEffect( uint32_t id );
@ -143,6 +145,8 @@ namespace Sapphire::Entity
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 );
void addStatusEffectByIdIfNotExist( uint32_t id, int32_t duration, Entity::Chara& source, World::Action::StatusEntry& statusEntry,
uint16_t param = 0 );
// remove a status effect by id
void removeSingleStatusEffectFromId( uint32_t id );

View file

@ -28,6 +28,14 @@ Sapphire::StatusEffect::StatusEffect::StatusEffect( uint32_t id, Entity::CharaPt
m_statusModifiers = std::move( modifiers );
}
Sapphire::StatusEffect::StatusEffect::StatusEffect( uint32_t id, Entity::CharaPtr sourceActor, Entity::CharaPtr targetActor,
uint32_t duration, World::Action::StatusEntry& statusEntry, uint32_t tickRate ) :
StatusEffect( id, sourceActor, targetActor, duration, tickRate )
{
m_statusModifiers = statusEntry.modifiers;
m_flag |= statusEntry.flag;
}
Sapphire::StatusEffect::StatusEffect::StatusEffect( uint32_t id, Entity::CharaPtr sourceActor, Entity::CharaPtr targetActor,
uint32_t duration, uint32_t tickRate ) :
m_id( id ),
@ -37,7 +45,8 @@ Sapphire::StatusEffect::StatusEffect::StatusEffect( uint32_t id, Entity::CharaPt
m_modifiers( 0 ),
m_startTime( 0 ),
m_tickRate( tickRate ),
m_lastTick( 0 )
m_lastTick( 0 ),
m_flag( 0 )
{
auto& exdData = Common::Service< Data::ExdData >::ref();
auto entry = exdData.getRow< Excel::Status >( id );
@ -52,6 +61,15 @@ Sapphire::StatusEffect::StatusEffect::StatusEffect( uint32_t id, Entity::CharaPt
Util::eraseAll( m_name, '-' );
Util::eraseAll( m_name, '(' );
Util::eraseAll( m_name, ')' );
m_flag |= entry->data().Category;
m_flag |= static_cast< uint32_t >( entry->data().Forever ) << static_cast< uint32_t >( Common::StatusEffectFlag::Permanent );
m_flag |= static_cast< uint32_t >( entry->data().CanOff ) << static_cast< uint32_t >( Common::StatusEffectFlag::CanStatusOff );
m_flag |= static_cast< uint32_t >( entry->data().NotAction ) << static_cast< uint32_t >( Common::StatusEffectFlag::LockActions );
m_flag |= static_cast< uint32_t >( entry->data().NotControl ) << static_cast< uint32_t >( Common::StatusEffectFlag::LockControl );
m_flag |= static_cast< uint32_t >( entry->data().NotMove ) << static_cast< uint32_t >( Common::StatusEffectFlag::LockMovement );
m_flag |= static_cast< uint32_t >( entry->data().NotLookAt ) << static_cast< uint32_t >( Common::StatusEffectFlag::IsGaze );
m_flag |= static_cast< uint32_t >( entry->data().FcAction ) << static_cast< uint32_t >( Common::StatusEffectFlag::FcBuff );
}
@ -192,6 +210,16 @@ uint64_t Sapphire::StatusEffect::StatusEffect::getStartTimeMs() const
return m_startTime;
}
uint32_t Sapphire::StatusEffect::StatusEffect::getFlag() const
{
return m_flag;
}
void Sapphire::StatusEffect::StatusEffect::setFlag( uint32_t flag )
{
m_flag = flag;
}
void Sapphire::StatusEffect::StatusEffect::setLastTick( uint64_t lastTick )
{
m_lastTick = lastTick;

View file

@ -14,6 +14,9 @@ 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, World::Action::StatusEntry& statusEntry, uint32_t tickRate );
StatusEffect( uint32_t id, Entity::CharaPtr sourceActor, Entity::CharaPtr targetActor,
uint32_t duration, uint32_t tickRate );
@ -47,10 +50,14 @@ public:
uint16_t getParam() const;
uint32_t getFlag() const;
void setLastTick( uint64_t lastTick );
void setParam( uint16_t param );
void setFlag( uint32_t flag );
void registerTickEffect( Common::ParamModifier type, uint32_t param );
std::pair< Common::ParamModifier, uint32_t > getTickEffect();
@ -66,6 +73,7 @@ private:
uint32_t m_tickRate;
uint64_t m_lastTick;
uint16_t m_param;
uint32_t m_flag;
std::string m_name;
std::pair< Common::ParamModifier, uint32_t > m_currTickEffect;
std::vector< World::Action::StatusModifier > m_statusModifiers;