1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-05-03 17:27:47 +00:00

update WAR to 5.58

This commit is contained in:
collett 2023-07-19 03:52:16 +09:00
parent 6ddc959498
commit e8ab350ad2
12 changed files with 195 additions and 44 deletions

View file

@ -1195,6 +1195,16 @@ namespace Sapphire::Common
RequireCorrectPositional = 2,
};
enum class StatusRefreshPolicy : uint8_t
{
Stack = 0,
ReplaceOrApply = 1,
Extend = 2,
ExtendOrApply = 3,
Reject = 4,
Custom = 15, // script handled
};
enum class AstCardType : uint8_t
{
None = 0,

View file

@ -721,7 +721,7 @@ void Action::Action::buildEffects()
if( shouldTriggerActionBonus || actor->getObjKind() == m_pSource->getObjKind() /* is friendly target, this will do for now */ )
{
if( !isComboAction() || isCorrectCombo() )
m_effectBuilder->applyStatusEffect( actor, m_pSource, m_lutEntry.targetStatus, m_lutEntry.targetStatusDuration, m_lutEntry.targetStatusParam, getExecutionDelay() + victimCounter * 100 );
applyStatusEffect( false, actor, m_pSource, m_lutEntry.targetStatus, m_lutEntry.targetStatusDuration, m_lutEntry.targetStatusParam, getExecutionDelay() + victimCounter * 100 );
}
else if( actor->hasInvulnerableEffect() )
{
@ -735,9 +735,9 @@ void Action::Action::buildEffects()
if( !isComboAction() || isCorrectCombo() )
{
if( firstValidVictim )
m_effectBuilder->applyStatusEffect( firstValidVictim, m_pSource, m_lutEntry.selfStatus, m_lutEntry.selfStatusDuration, m_lutEntry.selfStatusParam, getExecutionDelay(), true );
applyStatusEffect( true, firstValidVictim, m_pSource, m_lutEntry.selfStatus, m_lutEntry.selfStatusDuration, m_lutEntry.selfStatusParam, getExecutionDelay(), true );
else if ( m_lutEntry.damagePotency == 0 ) // only non-offensive actions can apply self status without a valid victim
m_effectBuilder->applyStatusEffect( m_pSource, m_pSource, m_lutEntry.selfStatus, m_lutEntry.selfStatusDuration, m_lutEntry.selfStatusParam, getExecutionDelay() );
applyStatusEffect( true, m_pSource, m_pSource, m_lutEntry.selfStatus, m_lutEntry.selfStatusDuration, m_lutEntry.selfStatusParam, getExecutionDelay() );
}
}
@ -1334,4 +1334,75 @@ uint64_t Action::Action::getExecutionDelay() const
{
// let's see how 3.x is going to do it
return 600;
}
void Sapphire::World::Action::Action::applyStatusEffect( bool selfStatus, Entity::CharaPtr& target, Entity::CharaPtr& source, uint16_t statusId, uint32_t duration, uint16_t param, uint64_t resultDelayMs, bool statusToSource )
{
auto hasSameStatus = false;
auto hasSameStatusFromSameCaster = false;
StatusEffect::StatusEffectPtr referenceStatus = nullptr;
for( auto const& entry : statusToSource ? source->getStatusEffectMap() : target->getStatusEffectMap() )
{
auto statusEffect = entry.second;
if( statusEffect->getId() == statusId )
{
hasSameStatus = true;
if( !referenceStatus )
referenceStatus = statusEffect;
if( statusEffect->getSrcActorId() == source->getId() )
{
hasSameStatusFromSameCaster = true;
referenceStatus = statusEffect;
break;;
}
}
}
auto policy = selfStatus ? m_lutEntry.getSelfStatusRefreshPolicy( hasSameStatusFromSameCaster ) : m_lutEntry.getTargetStatusRefreshPolicy( hasSameStatusFromSameCaster );
int64_t policyValue = selfStatus ? m_lutEntry.getSelfStatusRefreshValue() : m_lutEntry.getTargetStatusRefreshValue();
switch( policy )
{
case Common::StatusRefreshPolicy::Stack:
{
m_effectBuilder->applyStatusEffect( target, source, statusId, duration, param, resultDelayMs, statusToSource, false );
break;
}
case Common::StatusRefreshPolicy::ReplaceOrApply:
{
m_effectBuilder->applyStatusEffect( target, source, statusId, duration, param, resultDelayMs, statusToSource, true );
break;
}
case Common::StatusRefreshPolicy::Extend:
case Common::StatusRefreshPolicy::ExtendOrApply:
{
int64_t remainingDuration = 0;
if( hasSameStatus )
{
remainingDuration = static_cast< int64_t >( referenceStatus->getDuration() ) - ( Common::Util::getTimeMs() - referenceStatus->getStartTimeMs() ) - resultDelayMs;
if( remainingDuration < 0 )
remainingDuration = 0;
}
if( hasSameStatus || policy == Common::StatusRefreshPolicy::ExtendOrApply )
{
m_effectBuilder->applyStatusEffect( target, source, statusId, std::min( duration + remainingDuration, policyValue ), param, resultDelayMs, statusToSource, true );
}
break;
}
case Common::StatusRefreshPolicy::Reject:
{
if( !hasSameStatus )
{
m_effectBuilder->applyStatusEffect( target, source, statusId, duration, param, resultDelayMs, statusToSource, true );
}
else
{
m_effectBuilder->statusNoEffect( target, statusId );
}
break;
}
case Common::StatusRefreshPolicy::Custom:
{
// expect script to handle it
break;
}
}
}

View file

@ -176,6 +176,8 @@ namespace Sapphire::World::Action
bool hasValidLutEntry() const;
void applyStatusEffect( bool selfStatus, Entity::CharaPtr& target, Entity::CharaPtr& source, uint16_t statusId, uint32_t duration, uint16_t param, uint64_t resultDelayMs = 500, bool statusToSource = false );
uint32_t m_id;
uint16_t m_sequence;

View file

@ -351,21 +351,46 @@ bool Sapphire::World::Action::StatusEffectEntry::canApplyToAction( uint32_t acti
}
}
Sapphire::World::Action::ActionEntry::ActionEntry( uint16_t dp, uint16_t dcp, uint16_t ddp, uint16_t hp, uint16_t ss, uint32_t ssd, uint16_t ssp, uint16_t ts, uint32_t tsd, uint16_t tsp, uint8_t be, uint8_t br, uint32_t bdu32 )
Sapphire::World::Action::ActionEntry::ActionEntry( uint16_t dp, uint16_t dcp, uint16_t ddp, uint16_t hp, uint16_t ss, uint32_t ssd, uint16_t ssp, uint16_t ts, uint32_t tsd, uint16_t tsp, uint8_t be, uint8_t br, uint32_t bdu32 ) :
damagePotency( dp ),
damageComboPotency( dcp ),
damageDirectionalPotency( ddp ),
healPotency( hp ),
selfStatus( ss ),
selfStatusDuration( ssd ),
selfStatusParam( ssp ),
targetStatus( ts ),
targetStatusDuration( tsd ),
targetStatusParam ( tsp ),
bonusEffect( be ),
bonusRequirement( br ),
bonusDataUInt32 ( bdu32 ),
selfStatusRefreshPolicy( 1 ),
selfStatusRefreshValue( 0 ),
targetStatusRefreshPolicy( 1 ),
targetStatusRefreshValue( 0 )
{
}
Sapphire::World::Action::ActionEntry::ActionEntry( uint16_t dp, uint16_t dcp, uint16_t ddp, uint16_t hp, uint16_t ss, uint32_t ssd, uint16_t ssp, uint16_t ts, uint32_t tsd, uint16_t tsp, uint8_t be, uint8_t br, uint32_t bdu32, int ssrp, int32_t ssrv, int tsrp, int32_t tsrv ) :
damagePotency( dp ),
damageComboPotency( dcp ),
damageDirectionalPotency( ddp ),
healPotency( hp ),
selfStatus( ss ),
selfStatusDuration( ssd ),
selfStatusParam( ssp ),
targetStatus( ts ),
targetStatusDuration( tsd ),
targetStatusParam ( tsp ),
bonusEffect( be ),
bonusRequirement( br ),
bonusDataUInt32 ( bdu32 ),
selfStatusRefreshPolicy( static_cast< uint8_t >( ssrp ) ),
selfStatusRefreshValue( ssrv ),
targetStatusRefreshPolicy( static_cast< uint8_t >( tsrp ) ),
targetStatusRefreshValue( tsrv )
{
damagePotency = dp;
damageComboPotency = dcp;
damageDirectionalPotency = ddp;
healPotency = hp;
selfStatus = ss;
selfStatusDuration = ssd;
selfStatusParam = ssp;
targetStatus = ts;
targetStatusDuration = tsd;
targetStatusParam = tsp;
bonusEffect = be;
bonusRequirement = br;
bonusDataUInt32 = bdu32;
}
uint32_t Sapphire::World::Action::ActionEntry::getRawBonusData() const
@ -429,3 +454,25 @@ uint16_t Sapphire::World::Action::ActionEntry::getDirectHitRateBonus() const
return bonusDataUInt16L;
return 0;
}
Sapphire::Common::StatusRefreshPolicy Sapphire::World::Action::ActionEntry::getSelfStatusRefreshPolicy( bool sameSource )
{
uint8_t policy = sameSource ? selfStatusRefreshPolicy >> 4 : selfStatusRefreshPolicy & 0x0F;
return static_cast< Sapphire::Common::StatusRefreshPolicy >( policy );
}
Sapphire::Common::StatusRefreshPolicy Sapphire::World::Action::ActionEntry::getTargetStatusRefreshPolicy( bool sameSource )
{
uint8_t policy = sameSource ? targetStatusRefreshPolicy >> 4 : targetStatusRefreshPolicy & 0x0F;
return static_cast< Sapphire::Common::StatusRefreshPolicy >( policy );
}
int32_t Sapphire::World::Action::ActionEntry::getSelfStatusRefreshValue()
{
return selfStatusRefreshValue;
}
int32_t Sapphire::World::Action::ActionEntry::getTargetStatusRefreshValue()
{
return targetStatusRefreshValue;
}

View file

@ -40,9 +40,14 @@ namespace Sapphire::World::Action
uint8_t bonusDataByte4;
};
};
uint8_t selfStatusRefreshPolicy;
int32_t selfStatusRefreshValue;
uint8_t targetStatusRefreshPolicy;
int32_t targetStatusRefreshValue;
public:
ActionEntry() = default;
ActionEntry( uint16_t dp, uint16_t dcp, uint16_t ddp, uint16_t hp, uint16_t ss, uint32_t ssd, uint16_t ssp, uint16_t ts, uint32_t tsd, uint16_t tsp, uint8_t be, uint8_t br, uint32_t bdu32 );
ActionEntry( uint16_t dp, uint16_t dcp, uint16_t ddp, uint16_t hp, uint16_t ss, uint32_t ssd, uint16_t ssp, uint16_t ts, uint32_t tsd, uint16_t tsp, uint8_t be, uint8_t br, uint32_t bdu32, int ssrp, int32_t ssrv, int tsrp, int32_t tsrv );
uint32_t getRawBonusData() const;
uint8_t getDamageFallOffPercentage() const; // as the result percentage for 2nd (or more) victims, not the percentage to subtract from 100%
uint16_t getSelfHealPotency() const;
@ -52,6 +57,10 @@ namespace Sapphire::World::Action
uint16_t getJobTimerGain() const;
uint16_t getCritRateBonus() const;
uint16_t getDirectHitRateBonus() const;
Common::StatusRefreshPolicy getSelfStatusRefreshPolicy( bool sameSource );
Common::StatusRefreshPolicy getTargetStatusRefreshPolicy( bool sameSource );
int32_t getSelfStatusRefreshValue();
int32_t getTargetStatusRefreshValue();
};
struct StatusEffectEntry

View file

@ -135,14 +135,15 @@ ActionLut::Lut ActionLut::m_actionLut =
{ 31, { 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
//Maim, メイム
//has damage: potency 100, combo potency 300, directional potency 0
//has damage: potency 100, combo potency 320, directional potency 0
//has bonus effect: GainJobResource, 169148416
//bonus effect requirement: RequireCorrectCombo
{ 37, { 100, 300, 0, 0, 0, 0, 0, 0, 0, 0, 8, 1, 169148416 } },
{ 37, { 100, 320, 0, 0, 0, 0, 0, 0, 0, 0, 8, 1, 169148416 } },
//Berserk, バーサク
//applies to self: Berserk, バーサク, duration 10000, param 0
{ 38, { 0, 0, 0, 0, 86, 10000, 0, 0, 0, 0, 0, 0, 0 } },
//applies to target: Storm's Eye, シュトルムブレハ, duration 15000, param 0, Extend, Extend, 60000
{ 38, { 0, 0, 0, 0, 86, 10000, 0, 90, 15000, 0, 0, 0, 0, 0, 0, ( 2 << 4 ) + 2, 60000 } },
//Overpower, オーバーパワー
//has damage: potency 130, combo potency 0, directional potency 0
@ -158,10 +159,10 @@ ActionLut::Lut ActionLut::m_actionLut =
{ 46, { 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
//Storm's Path, シュトルムヴィント
//has damage: potency 100, combo potency 380, directional potency 0
//has damage: potency 100, combo potency 420, directional potency 0
//has bonus effect: 24, 336920826
//bonus effect requirement: RequireCorrectCombo
{ 42, { 100, 380, 0, 0, 0, 0, 0, 0, 0, 0, 24, 1, 336920826 } },
{ 42, { 100, 420, 0, 0, 0, 0, 0, 0, 0, 0, 24, 1, 336920826 } },
//Thrill of Battle, スリル・オブ・バトル
//applies to targets: Thrill of Battle, スリル・オブ・バトル, duration 20000, param 0
@ -179,11 +180,11 @@ ActionLut::Lut ActionLut::m_actionLut =
{ 43, { 0, 0, 0, 0, 409, 8000, 0, 88, 8000, 0, 0, 0, 0 } },
//Storm's Eye, シュトルムブレハ
//has damage: potency 100, combo potency 380, directional potency 0
//applies to self: Storm's Eye, シュトルムブレハ, duration 30000, param 0
//has damage: potency 100, combo potency 420, directional potency 0
//applies to self: Storm's Eye, シュトルムブレハ, duration 30000, param 0, ExtendOrApply, ExtendOrApply, 60000
//has bonus effect: GainJobResource, 169148416
//bonus effect requirement: RequireCorrectCombo
{ 45, { 100, 380, 0, 0, 90, 30000, 0, 0, 0, 0, 8, 1, 169148416 } },
{ 45, { 100, 420, 0, 0, 90, 30000, 0, 0, 0, 0, 8, 1, 169148416, ( 3 << 4 ) + 3, 60000, 0, 0 } },
//Inner Beast, 原初の魂
//has damage: potency 350, combo potency 0, directional potency 0
@ -191,7 +192,8 @@ ActionLut::Lut ActionLut::m_actionLut =
//Mythril Tempest, ミスリルテンペスト
//has damage: potency 100, combo potency 200, directional potency 0
{ 16462, { 100, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
//applies to self: Storm's Eye, シュトルムブレハ, duration 30000, param 0, Extend, Extend, 60000
{ 16462, { 100, 200, 0, 0, 90, 30000, 0, 0, 0, 0, 0, 0, 0, ( 2 << 4 ) + 2, 60000, 0, 0 } },
//Steel Cyclone, スチールサイクロン
//has damage: potency 220, combo potency 0, directional potency 0
@ -231,7 +233,8 @@ ActionLut::Lut ActionLut::m_actionLut =
//Inner Release, 原初の解放
//applies to self: Inner Release, 原初の解放, duration 10000, param 65436
{ 7389, { 0, 0, 0, 0, 1177, 10000, 65436, 0, 0, 0, 0, 0, 0 } },
//applies to target: Storm's Eye, シュトルムブレハ, duration 15000, param 0, Extend, Extend, 60000
{ 7389, { 0, 0, 0, 0, 1177, 10000, 65436, 90, 15000, 0, 0, 0, 0, 0, 0, ( 2 << 4 ) + 2, 60000 } },
//Chaotic Cyclone, カオティックサイクロン
//has damage: potency 400, combo potency 0, directional potency 0
@ -239,8 +242,8 @@ ActionLut::Lut ActionLut::m_actionLut =
{ 16463, { 400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 100 } },
//Nascent Flash, 原初の猛り
//applies to targets: Sleep, 睡眠, duration 30000, param 0
{ 16464, { 0, 0, 0, 0, 0, 0, 0, 3, 30000, 0, 0, 0, 0 } },
//applies to targets: Nascent Flash, 原初の猛り, duration 6000, param 0
{ 16464, { 0, 0, 0, 0, 0, 0, 0, 1857, 6000, 0, 0, 0, 0 } },
//Inner Chaos, インナーカオス
//has damage: potency 920, combo potency 0, directional potency 0

View file

@ -99,17 +99,17 @@ void EffectBuilder::comboSucceed( Entity::CharaPtr& target )
moveToResultList( target, nextResult );
}
void EffectBuilder::applyStatusEffect( Entity::CharaPtr& target, Entity::CharaPtr& source, uint16_t statusId, uint32_t duration, uint16_t param, uint64_t resultDelayMs, bool statusToSource )
void EffectBuilder::applyStatusEffect( Entity::CharaPtr& target, Entity::CharaPtr& source, uint16_t statusId, uint32_t duration, uint16_t param, uint64_t resultDelayMs, bool statusToSource, bool shouldReuse )
{
EffectResultPtr nextResult = make_EffectResult( target, source, Common::Util::getTimeMs() + resultDelayMs );
nextResult->applyStatusEffect( statusId, duration, param, statusToSource );
nextResult->applyStatusEffect( statusId, duration, param, statusToSource, shouldReuse );
moveToResultList( target, nextResult );
}
void EffectBuilder::applyStatusEffect( Entity::CharaPtr& target, Entity::CharaPtr& source, StatusEffect::StatusEffectPtr pStatusEffect, uint64_t resultDelayMs, bool statusToSource )
void EffectBuilder::applyStatusEffect( Entity::CharaPtr& target, Entity::CharaPtr& source, StatusEffect::StatusEffectPtr pStatusEffect, uint64_t resultDelayMs, bool statusToSource, bool shouldReuse )
{
EffectResultPtr nextResult = make_EffectResult( target, source, Common::Util::getTimeMs() + resultDelayMs );
nextResult->applyStatusEffect( pStatusEffect, statusToSource );
nextResult->applyStatusEffect( pStatusEffect, statusToSource, shouldReuse );
moveToResultList( target, nextResult );
}

View file

@ -36,8 +36,8 @@ namespace Sapphire::World::Action
void comboSucceed( Entity::CharaPtr& target );
void applyStatusEffect( Entity::CharaPtr& target, Entity::CharaPtr& source, uint16_t statusId, uint32_t duration, uint16_t param, uint64_t resultDelayMs = 500, bool statusToSource = false );
void applyStatusEffect( Entity::CharaPtr& target, Entity::CharaPtr& source, StatusEffect::StatusEffectPtr pStatusEffect, uint64_t resultDelayMs = 500, bool statusToSource = false );
void applyStatusEffect( Entity::CharaPtr& target, Entity::CharaPtr& source, uint16_t statusId, uint32_t duration, uint16_t param, uint64_t resultDelayMs = 500, bool statusToSource = false, bool shouldReuse = true );
void applyStatusEffect( Entity::CharaPtr& target, Entity::CharaPtr& source, StatusEffect::StatusEffectPtr pStatusEffect, uint64_t resultDelayMs = 500, bool statusToSource = false, bool shouldReuse = true );
void statusNoEffect( Entity::CharaPtr& target, uint16_t statusId );

View file

@ -20,7 +20,8 @@ EffectResult::EffectResult( Entity::CharaPtr target, Entity::CharaPtr source, ui
m_param1( 0 ),
m_param2( 0 ),
m_flag( Common::ActionEffectResultFlag::None ),
m_pPreBuiltStatusEffect( nullptr )
m_pPreBuiltStatusEffect( nullptr ),
m_statusShouldReuse( true )
{
}
@ -123,23 +124,23 @@ void EffectResult::comboSucceed()
m_type = Common::ActionEffectType::ComboSucceed;
}
void EffectResult::applyStatusEffect( uint16_t statusId, uint32_t duration, uint16_t param, bool statusToSource )
void EffectResult::applyStatusEffect( uint16_t statusId, uint32_t duration, uint16_t param, bool statusToSource, bool shouldReuse )
{
m_value = statusId;
m_statusDuration = duration;
m_param2 = param;
m_flag = statusToSource ? Common::ActionEffectResultFlag::EffectOnSource : Common::ActionEffectResultFlag::None;
m_statusShouldReuse = shouldReuse;
m_type = statusToSource ? Common::ActionEffectType::ApplyStatusEffectSource : Common::ActionEffectType::ApplyStatusEffectTarget;
}
void EffectResult::applyStatusEffect( StatusEffect::StatusEffectPtr pStatusEffect, bool statusToSource )
void EffectResult::applyStatusEffect( StatusEffect::StatusEffectPtr pStatusEffect, bool statusToSource, bool shouldReuse )
{
m_value = pStatusEffect->getId();
m_param2 = pStatusEffect->getParam();
m_pPreBuiltStatusEffect = std::move( pStatusEffect );
m_flag = statusToSource ? Common::ActionEffectResultFlag::EffectOnSource : Common::ActionEffectResultFlag::None;
m_statusShouldReuse = shouldReuse;
m_type = statusToSource ? Common::ActionEffectType::ApplyStatusEffectSource : Common::ActionEffectType::ApplyStatusEffectTarget;
}
@ -224,7 +225,7 @@ void EffectResult::execute()
for( auto const& entry : applyTarget->getStatusEffectMap() )
{
auto statusEffect = entry.second;
if( statusEffect->getId() == m_value && statusEffect->getSrcActorId() == m_source->getId() )
if( statusEffect->getId() == m_value && m_statusShouldReuse )
{
if( m_pPreBuiltStatusEffect )
{
@ -232,7 +233,7 @@ void EffectResult::execute()
}
else
{
statusEffect->refresh();
statusEffect->refresh( m_statusDuration );
}
applyTarget->sendStatusEffectUpdate();
return;

View file

@ -26,8 +26,8 @@ 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, uint32_t duration, uint16_t param, bool statusToSource = false );
void applyStatusEffect( StatusEffect::StatusEffectPtr pStatusEffect, bool statusToSource = false );
void applyStatusEffect( uint16_t statusId, uint32_t duration, uint16_t param, bool statusToSource = false, bool shouldReuse = true );
void applyStatusEffect( StatusEffect::StatusEffectPtr pStatusEffect, bool statusToSource = false, bool shouldReuse = true );
void statusNoEffect( uint16_t statusId );
void mount( uint16_t mountId );
void provoke();
@ -61,6 +61,7 @@ namespace Sapphire::World::Action
Common::ActionEffectResultFlag m_flag;
StatusEffect::StatusEffectPtr m_pPreBuiltStatusEffect;
bool m_statusShouldReuse;
};
}

View file

@ -341,6 +341,12 @@ void Sapphire::StatusEffect::StatusEffect::refresh()
applyStatus();
}
void Sapphire::StatusEffect::StatusEffect::refresh( uint32_t newDuration )
{
m_duration = newDuration;
refresh();
}
void Sapphire::StatusEffect::StatusEffect::refresh( Sapphire::World::Action::StatusEffectEntry newEntry )
{
m_effectEntry = newEntry;

View file

@ -68,6 +68,7 @@ public:
void markToRemove();
void refresh();
void refresh( uint32_t newDuration );
void refresh( Sapphire::World::Action::StatusEffectEntry newEntry );
private: