mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-05-03 17:27:47 +00:00
fix WHM Divine Benison, Temperance, Assize
This commit is contained in:
parent
0a4bd0dee4
commit
ddbb6b8403
3 changed files with 164 additions and 115 deletions
46
src/scripts/action/whm/ActionDivineBenison7432.cpp
Normal file
46
src/scripts/action/whm/ActionDivineBenison7432.cpp
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#include <Script/NativeScriptApi.h>
|
||||||
|
#include <ScriptObject.h>
|
||||||
|
#include <Actor/Player.h>
|
||||||
|
#include <Action/Action.h>
|
||||||
|
#include <Math/CalcStats.h>
|
||||||
|
|
||||||
|
#include "StatusEffect/StatusEffect.h"
|
||||||
|
|
||||||
|
using namespace Sapphire;
|
||||||
|
using namespace Sapphire::StatusEffect;
|
||||||
|
|
||||||
|
const uint16_t STATUS_ID_DEVINE_BENISON = 1218;
|
||||||
|
|
||||||
|
class ActionDivineBenison7432 :
|
||||||
|
public ScriptAPI::ActionScript
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ActionDivineBenison7432() :
|
||||||
|
ScriptAPI::ActionScript( 7432 )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void onExecute( Sapphire::World::Action::Action& action ) override
|
||||||
|
{
|
||||||
|
auto pTarget = action.getHitChara();
|
||||||
|
if( pTarget )
|
||||||
|
{
|
||||||
|
float shieldValue = action.calcHealing( 500 ).first; // 500 ptc worth of shield
|
||||||
|
shieldValue = Math::CalcStats::applyHealingReceiveMultiplier( *pTarget, shieldValue );
|
||||||
|
|
||||||
|
auto oldEffect = pTarget->getStatusEffectById( STATUS_ID_DEVINE_BENISON );
|
||||||
|
if( !oldEffect.second || oldEffect.second->getEffectEntry().getRemainingShield() <= shieldValue )
|
||||||
|
{
|
||||||
|
World::Action::StatusEffectEntry effectEntry;
|
||||||
|
effectEntry.init( Common::StatusEffectType::Shield, shieldValue, 0, 0, 0 );
|
||||||
|
auto pNewEffect = Sapphire::StatusEffect::make_StatusEffect( STATUS_ID_DEVINE_BENISON, action.getSourceChara(), pTarget, 15000, 3000 );
|
||||||
|
pNewEffect->replaceEffectEntry( effectEntry );
|
||||||
|
action.getEffectbuilder()->applyStatusEffect( pTarget, action.getSourceChara(), pNewEffect );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
action.getEffectbuilder()->statusNoEffect( pTarget, STATUS_ID_DEVINE_BENISON );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
EXPOSE_SCRIPT( ActionDivineBenison7432 );
|
|
@ -512,8 +512,8 @@ void Action::Action::buildEffects()
|
||||||
if( !shouldHitThisTarget )
|
if( !shouldHitThisTarget )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
bool shouldTriggerActionBonus = true;
|
bool isValidVictim = false;
|
||||||
if( m_lutEntry.damagePotency > 0 )
|
if( m_lutEntry.damagePotency > 0 && actor->getObjKind() != m_pSource->getObjKind() /* is NOT friendly target, this will do for now */ )
|
||||||
{
|
{
|
||||||
Common::AttackType attackType = static_cast< Common::AttackType >( m_actionData->attackType );
|
Common::AttackType attackType = static_cast< Common::AttackType >( m_actionData->attackType );
|
||||||
actor->onActionHostile( m_pSource );
|
actor->onActionHostile( m_pSource );
|
||||||
|
@ -539,7 +539,6 @@ void Action::Action::buildEffects()
|
||||||
if( actor->hasInvulnerableEffect() )
|
if( actor->hasInvulnerableEffect() )
|
||||||
{
|
{
|
||||||
dmg.first = 0;
|
dmg.first = 0;
|
||||||
shouldTriggerActionBonus = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( dmg.first > 0 )
|
if( dmg.first > 0 )
|
||||||
|
@ -563,7 +562,6 @@ void Action::Action::buildEffects()
|
||||||
if( dodged )
|
if( dodged )
|
||||||
{
|
{
|
||||||
dmg.first = 0;
|
dmg.first = 0;
|
||||||
shouldTriggerActionBonus = false;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -573,6 +571,7 @@ void Action::Action::buildEffects()
|
||||||
|
|
||||||
if( dmg.first > 0 )
|
if( dmg.first > 0 )
|
||||||
{
|
{
|
||||||
|
isValidVictim = true;
|
||||||
auto attackTypeEffect = m_actionData->attackType;
|
auto attackTypeEffect = m_actionData->attackType;
|
||||||
if( attackTypeEffect == -1 )
|
if( attackTypeEffect == -1 )
|
||||||
{
|
{
|
||||||
|
@ -612,113 +611,114 @@ void Action::Action::buildEffects()
|
||||||
m_effectBuilder->invulnerable( actor );
|
m_effectBuilder->invulnerable( actor );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( shouldTriggerActionBonus )
|
|
||||||
{
|
|
||||||
if( ( !isComboAction() || isCorrectCombo() ) )
|
|
||||||
{
|
|
||||||
if ( !m_actionData->preservesCombo ) // this matches retail packet, on all standalone actions even casts.
|
|
||||||
{
|
|
||||||
m_effectBuilder->startCombo( actor, getId() ); // this is on all targets hit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( m_lutEntry.bonusEffect & Common::ActionBonusEffect::SelfHeal )
|
|
||||||
{
|
|
||||||
if( checkActionBonusRequirement() )
|
|
||||||
{
|
|
||||||
auto heal = calcHealing( m_lutEntry.getSelfHealPotency() );
|
|
||||||
heal.first = Math::CalcStats::applyHealingReceiveMultiplier( *m_pSource, heal.first );
|
|
||||||
m_effectBuilder->heal( actor, m_pSource, heal.first, heal.second, Common::ActionEffectResultFlag::EffectOnSource );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( validVictimCounter == 0 ) // effects only apply once if aoe, on first valid target (can be single target action as well)
|
|
||||||
{
|
|
||||||
if( isCorrectCombo() )
|
|
||||||
m_effectBuilder->comboSucceed( actor );
|
|
||||||
|
|
||||||
if( m_isAutoAttack && player )
|
|
||||||
{
|
|
||||||
if( player->getClass() == Common::ClassJob::Paladin )
|
|
||||||
{
|
|
||||||
player->gaugePldSetOath( std::min( 100, player->gaugePldGetOath() + 5 ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( m_lutEntry.bonusEffect & Common::ActionBonusEffect::GainMPPercentage )
|
|
||||||
{
|
|
||||||
if( checkActionBonusRequirement() )
|
|
||||||
m_effectBuilder->restoreMP( actor, m_pSource, m_pSource->getMaxMp() * m_lutEntry.getMPGainPercentage() / 100, Common::ActionEffectResultFlag::EffectOnSource );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ( m_lutEntry.bonusEffect & Common::ActionBonusEffect::GainJobResource ) && player )
|
|
||||||
{
|
|
||||||
if( checkActionBonusRequirement() )
|
|
||||||
{
|
|
||||||
switch( m_lutEntry.getAffectedJob() )
|
|
||||||
{
|
|
||||||
case Common::ClassJob::Marauder:
|
|
||||||
case Common::ClassJob::Warrior:
|
|
||||||
{
|
|
||||||
player->gaugeWarSetIb( std::min( 100, player->gaugeWarGetIb() + m_lutEntry.getJobResourceGain() ) );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Common::ClassJob::Darkknight:
|
|
||||||
{
|
|
||||||
player->gaugeDrkSetBlood( std::min( 100, player->gaugeDrkGetBlood() + m_lutEntry.getJobResourceGain() ) );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Common::ClassJob::Gunbreaker:
|
|
||||||
{
|
|
||||||
player->gaugeGnbSetAmmo( std::min( 2, player->gaugeGnbGetAmmo() + m_lutEntry.getJobResourceGain() ) );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Common::ClassJob::Samurai:
|
|
||||||
{
|
|
||||||
player->gaugeSamSetKenki( std::min( 100, player->gaugeSamGetKenki() + m_lutEntry.getJobResourceGain() ) );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ( m_lutEntry.bonusEffect & Common::ActionBonusEffect::GainJobTimer ) && player )
|
|
||||||
{
|
|
||||||
if( checkActionBonusRequirement() )
|
|
||||||
{
|
|
||||||
switch( m_lutEntry.getAffectedJob() )
|
|
||||||
{
|
|
||||||
case Common::ClassJob::Darkknight:
|
|
||||||
{
|
|
||||||
player->gaugeDrkSetDarkSideTimer( std::min( 60000, player->gaugeDrkGetDarkSideTimer() + m_lutEntry.getJobTimerGain() ), true );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Common::ClassJob::Dragoon:
|
|
||||||
{
|
|
||||||
player->gaugeDrgSetDragonTimer( std::min( 30000, player->gaugeDrgGetDragonTimer() + m_lutEntry.getJobTimerGain() ), true );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if( validVictimCounter == 0 )
|
|
||||||
firstValidVictim = actor;
|
|
||||||
validVictimCounter++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( m_lutEntry.healPotency > 0 && actor->getObjKind() == m_pSource->getObjKind() /* is friendly target, this will do for now */)
|
if( m_lutEntry.healPotency > 0 && actor->getObjKind() == m_pSource->getObjKind() /* is friendly target, this will do for now */)
|
||||||
{
|
{
|
||||||
|
isValidVictim = true;
|
||||||
auto heal = calcHealing( m_lutEntry.healPotency );
|
auto heal = calcHealing( m_lutEntry.healPotency );
|
||||||
heal.first = Math::CalcStats::applyHealingReceiveMultiplier( *actor, heal.first );
|
heal.first = Math::CalcStats::applyHealingReceiveMultiplier( *actor, heal.first );
|
||||||
m_effectBuilder->heal( actor, actor, heal.first, heal.second, Common::ActionEffectResultFlag::None, getExecutionDelay() + victimCounter * 100 );
|
m_effectBuilder->heal( actor, actor, heal.first, heal.second, Common::ActionEffectResultFlag::None, getExecutionDelay() + victimCounter * 100 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( isValidVictim )
|
||||||
|
{
|
||||||
|
if( ( !isComboAction() || isCorrectCombo() ) )
|
||||||
|
{
|
||||||
|
if ( !m_actionData->preservesCombo ) // this matches retail packet, on all standalone actions even casts.
|
||||||
|
{
|
||||||
|
m_effectBuilder->startCombo( actor, getId() ); // this is on all targets hit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_lutEntry.bonusEffect & Common::ActionBonusEffect::SelfHeal )
|
||||||
|
{
|
||||||
|
if( checkActionBonusRequirement() )
|
||||||
|
{
|
||||||
|
auto heal = calcHealing( m_lutEntry.getSelfHealPotency() );
|
||||||
|
heal.first = Math::CalcStats::applyHealingReceiveMultiplier( *m_pSource, heal.first );
|
||||||
|
m_effectBuilder->heal( actor, m_pSource, heal.first, heal.second, Common::ActionEffectResultFlag::EffectOnSource );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( validVictimCounter == 0 ) // effects only apply once if aoe, on first valid target (can be single target action as well)
|
||||||
|
{
|
||||||
|
if( isCorrectCombo() )
|
||||||
|
m_effectBuilder->comboSucceed( actor );
|
||||||
|
|
||||||
|
if( m_isAutoAttack && player )
|
||||||
|
{
|
||||||
|
if( player->getClass() == Common::ClassJob::Paladin )
|
||||||
|
{
|
||||||
|
player->gaugePldSetOath( std::min( 100, player->gaugePldGetOath() + 5 ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_lutEntry.bonusEffect & Common::ActionBonusEffect::GainMPPercentage )
|
||||||
|
{
|
||||||
|
if( checkActionBonusRequirement() )
|
||||||
|
m_effectBuilder->restoreMP( actor, m_pSource, m_pSource->getMaxMp() * m_lutEntry.getMPGainPercentage() / 100, Common::ActionEffectResultFlag::EffectOnSource );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ( m_lutEntry.bonusEffect & Common::ActionBonusEffect::GainJobResource ) && player )
|
||||||
|
{
|
||||||
|
if( checkActionBonusRequirement() )
|
||||||
|
{
|
||||||
|
switch( m_lutEntry.getAffectedJob() )
|
||||||
|
{
|
||||||
|
case Common::ClassJob::Marauder:
|
||||||
|
case Common::ClassJob::Warrior:
|
||||||
|
{
|
||||||
|
player->gaugeWarSetIb( std::min( 100, player->gaugeWarGetIb() + m_lutEntry.getJobResourceGain() ) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Common::ClassJob::Darkknight:
|
||||||
|
{
|
||||||
|
player->gaugeDrkSetBlood( std::min( 100, player->gaugeDrkGetBlood() + m_lutEntry.getJobResourceGain() ) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Common::ClassJob::Gunbreaker:
|
||||||
|
{
|
||||||
|
player->gaugeGnbSetAmmo( std::min( 2, player->gaugeGnbGetAmmo() + m_lutEntry.getJobResourceGain() ) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Common::ClassJob::Samurai:
|
||||||
|
{
|
||||||
|
player->gaugeSamSetKenki( std::min( 100, player->gaugeSamGetKenki() + m_lutEntry.getJobResourceGain() ) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ( m_lutEntry.bonusEffect & Common::ActionBonusEffect::GainJobTimer ) && player )
|
||||||
|
{
|
||||||
|
if( checkActionBonusRequirement() )
|
||||||
|
{
|
||||||
|
switch( m_lutEntry.getAffectedJob() )
|
||||||
|
{
|
||||||
|
case Common::ClassJob::Darkknight:
|
||||||
|
{
|
||||||
|
player->gaugeDrkSetDarkSideTimer( std::min( 60000, player->gaugeDrkGetDarkSideTimer() + m_lutEntry.getJobTimerGain() ), true );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Common::ClassJob::Dragoon:
|
||||||
|
{
|
||||||
|
player->gaugeDrgSetDragonTimer( std::min( 30000, player->gaugeDrgGetDragonTimer() + m_lutEntry.getJobTimerGain() ), true );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( validVictimCounter == 0 )
|
||||||
|
firstValidVictim = actor;
|
||||||
|
validVictimCounter++;
|
||||||
|
}
|
||||||
|
|
||||||
if( m_lutEntry.targetStatus != 0 )
|
if( m_lutEntry.targetStatus != 0 )
|
||||||
{
|
{
|
||||||
if( shouldTriggerActionBonus || actor->getObjKind() == m_pSource->getObjKind() /* is friendly target, this will do for now */ )
|
if( isValidVictim || actor->getObjKind() == m_pSource->getObjKind() /* is friendly target, this will do for now */ )
|
||||||
{
|
{
|
||||||
if( !isComboAction() || isCorrectCombo() )
|
if( !isComboAction() || isCorrectCombo() )
|
||||||
applyStatusEffect( false, 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 );
|
||||||
|
@ -1168,6 +1168,9 @@ void Action::Action::addDefaultActorFilters()
|
||||||
|
|
||||||
bool Action::Action::preFilterActor( Sapphire::Entity::Actor& actor ) const
|
bool Action::Action::preFilterActor( Sapphire::Entity::Actor& actor ) const
|
||||||
{
|
{
|
||||||
|
if( m_castType == Common::CastType::SingleTarget ) // trust the target sent by client is valid
|
||||||
|
return true;
|
||||||
|
|
||||||
auto kind = actor.getObjKind();
|
auto kind = actor.getObjKind();
|
||||||
auto chara = actor.getAsChara();
|
auto chara = actor.getAsChara();
|
||||||
|
|
||||||
|
@ -1175,19 +1178,16 @@ bool Action::Action::preFilterActor( Sapphire::Entity::Actor& actor ) const
|
||||||
if( kind != ObjKind::BattleNpc && kind != ObjKind::Player )
|
if( kind != ObjKind::BattleNpc && kind != ObjKind::Player )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if( m_lutEntry.damagePotency > 0 && chara->getId() == m_pSource->getId() ) // !m_canTargetSelf
|
if( chara->isAlive() && m_lutEntry.healPotency > 0 && m_pSource->getObjKind() == chara->getObjKind() )
|
||||||
return false;
|
return true;
|
||||||
|
|
||||||
if( ( m_lutEntry.damagePotency > 0 || m_lutEntry.healPotency > 0 ) && !chara->isAlive() ) // !m_canTargetDead not working for aoe
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if( m_lutEntry.damagePotency > 0 && m_pSource->getObjKind() == chara->getObjKind() ) // !m_canTargetFriendly not working for aoe
|
if( chara->isAlive() && m_lutEntry.damagePotency > 0 && m_pSource->getObjKind() != chara->getObjKind() )
|
||||||
return false;
|
return true;
|
||||||
|
|
||||||
if( ( m_lutEntry.damagePotency == 0 && m_lutEntry.healPotency > 0 ) && m_pSource->getObjKind() != chara->getObjKind() ) // !m_canTargetHostile not working for aoe
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
if( !chara->isAlive() && m_lutEntry.damagePotency == 0 && m_lutEntry.healPotency == 0 )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector< Sapphire::Entity::CharaPtr >& Action::Action::getHitCharas()
|
std::vector< Sapphire::Entity::CharaPtr >& Action::Action::getHitCharas()
|
||||||
|
|
|
@ -1837,8 +1837,8 @@ ActionLut::Lut ActionLut::m_actionLut =
|
||||||
{ 7431, { 280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
|
{ 7431, { 280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
|
||||||
|
|
||||||
//Divine Benison, ディヴァインベニゾン
|
//Divine Benison, ディヴァインベニゾン
|
||||||
//applies to targets: Divine Benison, ディヴァインベニゾン, duration 15000, param 0
|
//applies to targets: Divine Benison, ディヴァインベニゾン, duration 15000, param 0 >> moved to script
|
||||||
{ 7432, { 0, 0, 0, 0, 0, 0, 0, 1218, 15000, 0, 0, 0, 0 } },
|
{ 7432, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
|
||||||
|
|
||||||
//Plenary Indulgence, インドゥルゲンティア
|
//Plenary Indulgence, インドゥルゲンティア
|
||||||
//applies to targets: Confession, インドゥルゲンティア, duration 10000, param 0
|
//applies to targets: Confession, インドゥルゲンティア, duration 10000, param 0
|
||||||
|
@ -1863,8 +1863,8 @@ ActionLut::Lut ActionLut::m_actionLut =
|
||||||
{ 16534, { 0, 0, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
|
{ 16534, { 0, 0, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
|
||||||
|
|
||||||
//Temperance, テンパランス
|
//Temperance, テンパランス
|
||||||
//applies to targets: Temperance, テンパランス:効果, duration 20000, param 0
|
//applies to targets: Temperance, テンパランス, duration 20000, param 0
|
||||||
{ 16536, { 0, 0, 0, 0, 0, 0, 0, 1873, 20000, 0, 0, 0, 0 } },
|
{ 16536, { 0, 0, 0, 0, 0, 0, 0, 1872, 20000, 0, 0, 0, 0 } },
|
||||||
|
|
||||||
//Ruin, ルイン
|
//Ruin, ルイン
|
||||||
//has damage: potency 160, combo potency 0, directional potency 0
|
//has damage: potency 160, combo potency 0, directional potency 0
|
||||||
|
@ -3560,4 +3560,7 @@ ActionLut::StatusEffectTable ActionLut::m_statusEffectTable =
|
||||||
|
|
||||||
//Walking Dead, ウォーキングデッド: CannotDie
|
//Walking Dead, ウォーキングデッド: CannotDie
|
||||||
{ 811, { 19, 0, 0, 0, 0 } },
|
{ 811, { 19, 0, 0, 0, 0 } },
|
||||||
|
|
||||||
|
//Divine Benison, ディヴァインベニゾン (scripted)
|
||||||
|
{ 1218, { 0, 0, 0, 0, 0 } },
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue