diff --git a/src/world/Action/Action.cpp b/src/world/Action/Action.cpp index 1c134990..646759bf 100644 --- a/src/world/Action/Action.cpp +++ b/src/world/Action/Action.cpp @@ -1196,6 +1196,12 @@ bool Action::Action::isGCD() const return actionCategory == Common::ActionCategory::Weaponskill || actionCategory == Common::ActionCategory::Spell; } +bool Action::Action::isWeaponSkill() const +{ + auto actionCategory = static_cast< Common::ActionCategory >( m_actionData->actionCategory ); + return actionCategory == Common::ActionCategory::Weaponskill; +} + bool Action::Action::isAttackTypePhysical( Common::AttackType attackType ) { return attackType == Common::AttackType::Physical; diff --git a/src/world/Action/Action.h b/src/world/Action/Action.h index c77c730f..3c215684 100644 --- a/src/world/Action/Action.h +++ b/src/world/Action/Action.h @@ -135,6 +135,7 @@ namespace Sapphire::World::Action bool isPhysical() const; bool isMagical() const; bool isGCD() const; + bool isWeaponSkill() const; static bool isAttackTypePhysical( Common::AttackType attackType ); static bool isAttackTypeMagical( Common::AttackType attackType ); diff --git a/src/world/Action/ActionLutData.cpp b/src/world/Action/ActionLutData.cpp index 1f6791c2..4d4eeb93 100644 --- a/src/world/Action/ActionLutData.cpp +++ b/src/world/Action/ActionLutData.cpp @@ -3541,7 +3541,7 @@ ActionLut::StatusEffectTable ActionLut::m_statusEffectTable = { 1972, { 15, 2, 7392, 7391, 0 } }, //Meikyo Shisui, 明鏡止水: AlwaysCombo, 3 uses - { 1233, { 16, 3, 0, 0, 0 } }, + { 1233, { 16, 3, 0, 3, 0 } }, //Shifu, 士風: Haste, 13% { 1299, { 12, 13, 0, 0, 0 } }, diff --git a/src/world/StatusEffect/StatusEffect.cpp b/src/world/StatusEffect/StatusEffect.cpp index 74f95bcc..8432331c 100644 --- a/src/world/StatusEffect/StatusEffect.cpp +++ b/src/world/StatusEffect/StatusEffect.cpp @@ -297,64 +297,83 @@ void Sapphire::StatusEffect::StatusEffect::onBeforeActionStart( Sapphire::World: //auto pScriptMgr = m_pFw->get< Scripting::ScriptMgr >(); //pScriptMgr->onBeforeActionStart( m_targetActor, *this ); + auto checkAction1 = []( Sapphire::World::Action::Action* action, Sapphire::World::Action::StatusEffectEntry& effectEntry ) + { + // value1: remaining uses if >= 0 + // value2-4: affected action ids if value2 > 0, otherwise value3 is actionCategory filter (4 bytes for 4 categories) + if( effectEntry.effectValue1 == 0 ) + return false; + + if( effectEntry.effectValue2 != 0 ) + { + if( action->getId() != effectEntry.effectValue2 && + action->getId() != effectEntry.effectValue3 && + action->getId() != effectEntry.effectValue4 ) + return false; + } + else + { + if( effectEntry.effectValue3 != 0 ) + { + auto ac = action->getActionData()->actionCategory; + uint8_t f1 = static_cast< uint8_t >( effectEntry.effectValue3 ); + uint8_t f2 = static_cast< uint8_t >( effectEntry.effectValue3 >> 8 ); + uint8_t f3 = static_cast< uint8_t >( effectEntry.effectValue3 >> 16 ); + uint8_t f4 = static_cast< uint8_t >( effectEntry.effectValue3 >> 24 ); + bool passed = false; + if( f1 != 0 && ac == f1 ) + passed = true; + else if ( f2 != 0 && ac == f2 ) + passed = true; + else if ( f3 != 0 && ac == f3 ) + passed = true; + else if ( f4 != 0 && ac == f4 ) + passed = true; + if( !passed ) + return false; + } + } + + return true; + }; + switch( static_cast< Common::StatusEffectType >( m_effectEntry.effectType ) ) { case Common::StatusEffectType::InstantCast: { - if( !action->hasCastTime() ) - return; - // value1: remaining uses - // value2-4: affected action ids, or all actions if value2 is 0 - if( m_effectEntry.effectValue2 != 0 ) + if( action->hasCastTime() && checkAction1( action, m_effectEntry ) ) { - if( action->getId() != m_effectEntry.effectValue2 && - action->getId() != m_effectEntry.effectValue3 && - action->getId() != m_effectEntry.effectValue4 ) - break; - } - if( m_effectEntry.effectValue1 > 0 ) - { - // if stacks equal to remaining uses, assume it is synced - if( m_effectEntry.effectValue1 == getStacks() ) + if( m_effectEntry.effectValue1 > 0 ) { + if( m_effectEntry.effectValue1 == getStacks() ) + { + // if stacks equal to remaining uses, assume it is synced + setStacks( getStacks() - 1 ); + m_targetActor->sendStatusEffectUpdate(); + } m_effectEntry.effectValue1--; - setStacks( m_effectEntry.effectValue1 ); - m_targetActor->sendStatusEffectUpdate(); + if( m_effectEntry.effectValue1 == 0 ) + { + markToRemove(); + } + action->setCastTime( 0 ); } - else - m_effectEntry.effectValue1--; - if( m_effectEntry.effectValue1 == 0 ) - { - markToRemove(); - } - action->setCastTime( 0 ); } break; } case Common::StatusEffectType::AlwaysCombo: { - if( action->isGCD() ) + if( checkAction1( action, m_effectEntry ) ) { - // value1: remaining uses - // value2-4: affected action ids, or all actions if value2 is 0 - if( m_effectEntry.effectValue2 != 0 ) - { - if( action->getId() != m_effectEntry.effectValue2 && - action->getId() != m_effectEntry.effectValue3 && - action->getId() != m_effectEntry.effectValue4 ) - break; - } if( m_effectEntry.effectValue1 > 0 ) { - // if stacks equal to remaining uses, assume it is synced if( m_effectEntry.effectValue1 == getStacks() ) { - m_effectEntry.effectValue1--; - setStacks( m_effectEntry.effectValue1 ); + // if stacks equal to remaining uses, assume it is synced + setStacks( getStacks() - 1 ); m_targetActor->sendStatusEffectUpdate(); } - else - m_effectEntry.effectValue1--; + m_effectEntry.effectValue1--; if( m_effectEntry.effectValue1 == 0 ) { markToRemove();