mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 16:51:29 +00:00
[Spells] Implemented SPA 463 SE_SHIELD_TARGET (#4224)
SPA 463 SE_SHIELD_TARGET Live description: "Shields your target, taking a percentage of their damage". Only example spell on live is an NPC who uses it during a raid event "Laurion's Song" expansion. SPA 54492 'Guardian Stance' Described as 100% Melee Shielding Example of mechanic. Base value = 70. Caster puts buff on target. Each melee hit Buff Target takes 70% less damage, Buff Caster receives 30% of the melee damage. Added mechanic to cause buff to fade if target or caster are separated by a distance greater than the casting range of the spell. This allows similar mechanics to the /shield ability, without a range removal mechanic it would be too easy to abuse if put on a player spell. *can not confirm live does this currently Can not be cast on self.
This commit is contained in:
parent
cd89926435
commit
9e3bf91374
@ -1257,7 +1257,7 @@ typedef enum {
|
||||
#define SE_Ff_Override_NotFocusable 460 // implemented, @Fc, Allow spell to be focused event if flagged with 'not_focusable' in spell table, base: 1
|
||||
#define SE_ImprovedDamage2 461 // implemented, @Fc, On Caster, spell damage mod pct, base: min pct, limit: max pct
|
||||
#define SE_FcDamageAmt2 462 // implemented, @Fc, On Caster, spell damage mod flat amt, base: amt
|
||||
//#define SE_Shield_Target 463 //
|
||||
#define SE_Shield_Target 463 // implemented, Base1 % damage shielded on target
|
||||
#define SE_PC_Pet_Rampage 464 // implemented - Base1 % chance to do rampage for base2 % of damage each melee round
|
||||
#define SE_PC_Pet_AE_Rampage 465 // implemented - Base1 % chance to do AE rampage for base2 % of damage each melee round
|
||||
#define SE_PC_Pet_Flurry_Chance 466 // implemented - Base1 % chance to do flurry from double attack hit.
|
||||
|
||||
@ -6285,9 +6285,24 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraAttac
|
||||
|
||||
hit.damage_done += (hit.damage_done * pct_damage_reduction / 100) + defender->GetPositionalDmgTakenAmt(this);
|
||||
|
||||
if (defender->GetShielderID()) {
|
||||
DoShieldDamageOnShielder(defender, hit.damage_done, hit.skill);
|
||||
hit.damage_done -= hit.damage_done * defender->GetShieldTargetMitigation() / 100; //Default shielded takes 50 pct damage
|
||||
if (defender->GetShielderID() || defender->spellbonuses.ShieldTargetSpa[SBIndex::SHIELD_TARGET_MITIGATION_PERCENT]) {
|
||||
bool use_shield_ability = true;
|
||||
//If defender is being shielded by an ability AND has a shield spell effect buff use highest mitigation value.
|
||||
if ((defender->GetShieldTargetMitigation() && defender->spellbonuses.ShieldTargetSpa[SBIndex::SHIELD_TARGET_MITIGATION_PERCENT]) &&
|
||||
(defender->spellbonuses.ShieldTargetSpa[SBIndex::SHIELD_TARGET_MITIGATION_PERCENT] >= defender->GetShieldTargetMitigation())){
|
||||
bool use_shield_ability = false;
|
||||
}
|
||||
|
||||
//use targeted /shield ability values
|
||||
if (defender->GetShielderID() && use_shield_ability) {
|
||||
DoShieldDamageOnShielder(defender, hit.damage_done, hit.skill);
|
||||
hit.damage_done -= hit.damage_done * defender->GetShieldTargetMitigation() / 100; //Default shielded takes 50 pct damage
|
||||
}
|
||||
//use spell effect SPA 463 values
|
||||
else if (defender->spellbonuses.ShieldTargetSpa[SBIndex::SHIELD_TARGET_MITIGATION_PERCENT]){
|
||||
DoShieldDamageOnShielderSpellEffect(defender, hit.damage_done, hit.skill);
|
||||
hit.damage_done -= hit.damage_done * defender->spellbonuses.ShieldTargetSpa[SBIndex::SHIELD_TARGET_MITIGATION_PERCENT] / 100;
|
||||
}
|
||||
}
|
||||
|
||||
CheckNumHitsRemaining(NumHit::OutgoingHitSuccess);
|
||||
@ -6330,7 +6345,57 @@ void Mob::DoShieldDamageOnShielder(Mob *shield_target, int64 hit_damage_done, EQ
|
||||
|
||||
hit_damage_done -= hit_damage_done * mitigation / 100;
|
||||
shielder->Damage(this, hit_damage_done, SPELL_UNKNOWN, skillInUse, true, -1, false, m_specialattacks);
|
||||
shielder->CheckNumHitsRemaining(NumHit::OutgoingHitSuccess);
|
||||
}
|
||||
|
||||
void Mob::DoShieldDamageOnShielderSpellEffect(Mob* shield_target, int64 hit_damage_done, EQ::skills::SkillType skillInUse)
|
||||
{
|
||||
if (!shield_target) {
|
||||
return;
|
||||
}
|
||||
/*
|
||||
SPA 463 SE_SHIELD_TARGET
|
||||
|
||||
Live description: "Shields your target, taking a percentage of their damage".
|
||||
Only example spell on live is an NPC who uses it during a raid event "Laurion's Song" expansion. SPA 54492 'Guardian Stance' Described as 100% Melee Shielding
|
||||
|
||||
Example of mechanic. Base value = 70. Caster puts buff on target. Each melee hit Buff Target takes 70% less damage, Buff Caster receives 30% of the melee damage.
|
||||
Added mechanic to cause buff to fade if target or caster are seperated by a distance greater than the casting range of the spell. This allows similiar mechanics
|
||||
to the /shield ability, without a range removal mechanic it would be too easy to abuse if put on a player spell. *can not confirm live does this currently
|
||||
|
||||
Can not be cast on self.
|
||||
*/
|
||||
|
||||
if (shield_target->spellbonuses.ShieldTargetSpa[SBIndex::SHIELD_TARGET_MITIGATION_PERCENT])
|
||||
{
|
||||
if (shield_target->spellbonuses.ShieldTargetSpa[SBIndex::SHIELD_TARGET_BUFFSLOT] >= 0)
|
||||
{
|
||||
Mob *shielder = entity_list.GetMob(shield_target->buffs[shield_target->spellbonuses.ShieldTargetSpa[SBIndex::SHIELD_TARGET_BUFFSLOT]].casterid);
|
||||
if (!shielder) {
|
||||
shield_target->BuffFadeBySlot(shield_target->spellbonuses.ShieldTargetSpa[SBIndex::SHIELD_TARGET_BUFFSLOT]);
|
||||
return;
|
||||
}
|
||||
|
||||
int shield_spell_id = shield_target->buffs[shield_target->spellbonuses.ShieldTargetSpa[SBIndex::SHIELD_TARGET_BUFFSLOT]].spellid;
|
||||
if (!IsValidSpell(shield_spell_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
float max_range = spells[shield_spell_id].range;
|
||||
if (spells[shield_spell_id].aoe_range > max_range) {
|
||||
max_range = spells[shield_spell_id].aoe_range;
|
||||
}
|
||||
max_range += 5.0f; //small buffer in case casted at exactly max range.
|
||||
|
||||
if (shield_target->CalculateDistance(shielder->GetX(), shielder->GetY(), shielder->GetZ()) > max_range) {
|
||||
shield_target->BuffFadeBySlot(shield_target->spellbonuses.ShieldTargetSpa[SBIndex::SHIELD_TARGET_BUFFSLOT]);
|
||||
return;
|
||||
}
|
||||
|
||||
int mitigation = 100 - shield_target->spellbonuses.ShieldTargetSpa[SBIndex::SHIELD_TARGET_MITIGATION_PERCENT];
|
||||
hit_damage_done -= hit_damage_done * mitigation / 100;
|
||||
shielder->Damage(this, hit_damage_done, SPELL_UNKNOWN, skillInUse, true, -1, false, m_specialattacks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Mob::CommonBreakInvisibleFromCombat()
|
||||
|
||||
@ -3301,6 +3301,15 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_Shield_Target:
|
||||
{
|
||||
if (new_bonus->ShieldTargetSpa[SBIndex::SHIELD_TARGET_MITIGATION_PERCENT] < effect_value) {
|
||||
new_bonus->ShieldTargetSpa[SBIndex::SHIELD_TARGET_MITIGATION_PERCENT] = effect_value;
|
||||
new_bonus->ShieldTargetSpa[SBIndex::SHIELD_TARGET_BUFFSLOT] = buffslot;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_TriggerMeleeThreshold:
|
||||
new_bonus->TriggerMeleeThreshold = true;
|
||||
break;
|
||||
@ -5919,6 +5928,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id)
|
||||
if (negate_itembonus) { itembonuses.SkillProcSuccess[e] = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.SkillProcSuccess[e] = effect_value; }
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_SkillProcAttempt: {
|
||||
@ -5928,6 +5938,15 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id)
|
||||
if (negate_itembonus) { itembonuses.SkillProc[e] = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.SkillProc[e] = effect_value; }
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_Shield_Target: {
|
||||
if (negate_spellbonus) {
|
||||
spellbonuses.ShieldTargetSpa[SBIndex::SHIELD_TARGET_MITIGATION_PERCENT] = effect_value;
|
||||
spellbonuses.ShieldTargetSpa[SBIndex::SHIELD_TARGET_BUFFSLOT] = effect_value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -512,6 +512,7 @@ struct StatBonuses {
|
||||
uint8 invisibility; // invisibility level
|
||||
uint8 invisibility_verse_undead; // IVU level
|
||||
uint8 invisibility_verse_animal; // IVA level
|
||||
int32 ShieldTargetSpa[2]; // [0] base = % mitigation amount, [1] buff slot
|
||||
|
||||
// AAs
|
||||
int32 TrapCircumvention; // reduce chance to trigger a trap.
|
||||
@ -657,6 +658,8 @@ namespace SBIndex {
|
||||
constexpr uint16 COMBAT_PROC_SPELL_ID = 1; // SPA
|
||||
constexpr uint16 COMBAT_PROC_RATE_MOD = 2; // SPA
|
||||
constexpr uint16 COMBAT_PROC_REUSE_TIMER = 3; // SPA
|
||||
constexpr uint16 SHIELD_TARGET_MITIGATION_PERCENT = 0; // SPA 463
|
||||
constexpr uint16 SHIELD_TARGET_BUFFSLOT = 1; // SPA 463
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -995,6 +995,7 @@ public:
|
||||
inline void SetDualWieldingSameDelayWeapons(int32 val) { dw_same_delay = val; }
|
||||
bool IsTargetedFocusEffect(int focus_type);
|
||||
bool HasPersistDeathIllusion(int32 spell_id);
|
||||
void DoShieldDamageOnShielderSpellEffect(Mob* shield_target, int64 hit_damage_done, EQ::skills::SkillType skillInUse);
|
||||
|
||||
|
||||
bool TryDoubleMeleeRoundEffect();
|
||||
|
||||
@ -863,6 +863,14 @@ bool Mob::DoCastingChecksOnTarget(bool check_on_casting, int32 spell_id, Mob *sp
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
Cannot cast shield target on self
|
||||
*/
|
||||
if (this == spell_target && IsEffectInSpell(spell_id, SE_Shield_Target)) {
|
||||
LogSpells("You cannot shield yourself");
|
||||
Message(Chat::SpellFailure, "You cannot shield yourself.");
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
Cannot cast life tap on self
|
||||
*/
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user