diff --git a/src/common/Common.h b/src/common/Common.h index e258b3aa..0135c030 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -1039,6 +1039,7 @@ namespace Sapphire::Common Shield = 10, MPRestore = 11, Haste = 12, + InstantCast = 13, }; enum class ActionTypeFilter : int32_t diff --git a/src/world/Action/ActionLutData.cpp b/src/world/Action/ActionLutData.cpp index 4b44b5e3..96313c15 100644 --- a/src/world/Action/ActionLutData.cpp +++ b/src/world/Action/ActionLutData.cpp @@ -3511,4 +3511,7 @@ ActionLut::StatusEffectTable ActionLut::m_statusEffectTable = //Presence of Mind, 神速魔: Haste, 20% { 157, { 12, 20, 0, 0, 0 } }, + //Swiftcast, 迅速魔: InstantCast, 1 casts + { 167, { 13, 1, 0, 0, 0 } }, + }; diff --git a/src/world/Actor/Chara.cpp b/src/world/Actor/Chara.cpp index da3bff35..6bd8c039 100644 --- a/src/world/Actor/Chara.cpp +++ b/src/world/Actor/Chara.cpp @@ -722,7 +722,7 @@ void Sapphire::Entity::Chara::updateStatusEffects() uint32_t duration = effect->getDuration(); uint32_t tickRate = effect->getTickRate(); - if( duration > 0 && ( currentTimeMs - startTime ) > duration ) + if( effect->isMarkedToRemove() || ( duration > 0 && ( currentTimeMs - startTime ) > duration ) ) { // remove status effect removeStatusEffect( effectIndex, true, true ); diff --git a/src/world/Manager/ActionMgr.cpp b/src/world/Manager/ActionMgr.cpp index 2356d7b3..f5a7303e 100644 --- a/src/world/Manager/ActionMgr.cpp +++ b/src/world/Manager/ActionMgr.cpp @@ -5,6 +5,8 @@ #include "Script/ScriptMgr.h" #include "Actor/Player.h" +#include "StatusEffect/StatusEffect.h" + #include #include "Framework.h" @@ -89,6 +91,11 @@ void World::Manager::ActionMgr::bootstrapAction( Entity::Player& player, return; } + for( const auto& statusIt : player.getStatusEffectMap() ) + { + statusIt.second->onBeforeActionStart( currentAction ); + } + if( player.getCurrentAction() ) { player.sendDebug( "Skill queued: {0}", currentAction->getId() ); diff --git a/src/world/StatusEffect/StatusEffect.cpp b/src/world/StatusEffect/StatusEffect.cpp index 30ae2125..3392c331 100644 --- a/src/world/StatusEffect/StatusEffect.cpp +++ b/src/world/StatusEffect/StatusEffect.cpp @@ -9,6 +9,8 @@ #include "Actor/Chara.h" #include "Actor/Actor.h" +#include "Action/Action.h" + #include "Script/ScriptMgr.h" #include "Math/CalcStats.h" @@ -32,7 +34,8 @@ Sapphire::StatusEffect::StatusEffect::StatusEffect( uint32_t id, Entity::CharaPt m_pFw( pFw ), m_value( 0 ), m_cachedSourceCrit( 0 ), - m_cachedSourceCritBonus( 0 ) + m_cachedSourceCritBonus( 0 ), + m_markToRemove( false ) { auto pExdData = m_pFw->get< Data::ExdDataGenerated >(); auto entry = pExdData->get< Sapphire::Data::Status >( id ); @@ -262,4 +265,44 @@ const Sapphire::World::Action::StatusEffectEntry& Sapphire::StatusEffect::Status void Sapphire::StatusEffect::StatusEffect::replaceEffectEntry( Sapphire::World::Action::StatusEffectEntry entryOverride ) { m_effectEntry = entryOverride; +} + +void Sapphire::StatusEffect::StatusEffect::onBeforeActionStart( Sapphire::World::Action::ActionPtr action ) +{ + // todo: add script function for this if needed + //auto pScriptMgr = m_pFw->get< Scripting::ScriptMgr >(); + //pScriptMgr->onBeforeActionStart( m_targetActor, *this ); + + 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->getId() != m_effectEntry.effectValue2 && + action->getId() != m_effectEntry.effectValue3 && + action->getId() != m_effectEntry.effectValue4 ) + return; + } + if( m_effectEntry.effectValue1 > 0 ) + { + m_effectEntry.effectValue1--; + if( m_effectEntry.effectValue1 == 0 ) + { + m_markToRemove = true; + } + action->setCastTime( 0 ); + } + break; + } + } +} + +bool Sapphire::StatusEffect::StatusEffect::isMarkedToRemove() +{ + return m_markToRemove; } \ No newline at end of file diff --git a/src/world/StatusEffect/StatusEffect.h b/src/world/StatusEffect/StatusEffect.h index 70a9cd0d..a297094e 100644 --- a/src/world/StatusEffect/StatusEffect.h +++ b/src/world/StatusEffect/StatusEffect.h @@ -19,6 +19,8 @@ public: void onTick(); + void onBeforeActionStart( World::Action::ActionPtr action ); + void applyStatus(); void removeStatus(); @@ -53,6 +55,8 @@ public: void replaceEffectEntry( Sapphire::World::Action::StatusEffectEntry entryOverride ); + bool isMarkedToRemove(); + private: uint32_t m_id; Entity::CharaPtr m_sourceActor; @@ -69,6 +73,7 @@ private: uint32_t m_value; float m_cachedSourceCrit; float m_cachedSourceCritBonus; + bool m_markToRemove; }; }