Implemented SE_AStacker, BStacker, CStacker, DStacker

Effects are buff stacking blockers.
This commit is contained in:
KayenEQ 2014-06-17 09:45:12 -04:00
parent 308562f939
commit 57a216cb44
8 changed files with 69 additions and 8 deletions

View File

@ -1,5 +1,10 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50)
-------------------------------------------------------
== 06/17/2014 ==
Kayen: Implemented SE_AStacker, SE_BStacker, SE_CStacker, SE_DStacker.
These effects when present in buffs prevent each other from stacking,
Any effect with B prevents A, C prevents B, D prevents C.
== 06/13/2014 ==
Kayen: For table 'npc_spell_effects_entries' setting se_max for damage shield effects (59) will now determine the DS Type (ie burning)
Setting se_max to 1 for SkillDamageTaken effects (127) will allow for stackable mitigation/weakness same as quest function ModSkillDmgTaken.

View File

@ -1009,6 +1009,19 @@ uint32 GetMorphTrigger(uint32 spell_id)
return 0;
}
bool IsCastonFadeDurationSpell(uint16 spell_id)
{
for (int i = 0; i < EFFECT_COUNT; ++i) {
if (spells[spell_id].effectid[i] == SE_ImprovedSpellEffect
|| spells[spell_id].effectid[i] == SE_BossSpellTrigger
|| spells[spell_id].effectid[i] == SE_CastOnWearoff){
return true;
}
}
return false;
}
uint32 GetPartialMeleeRuneReduction(uint32 spell_id)
{
for (int i = 0; i < EFFECT_COUNT; ++i)

View File

@ -593,10 +593,10 @@ typedef enum {
#define SE_TriggerOnReqCaster 443 // implemented - triggers a spell which a certain criteria are met (below X amount of hp,mana,end, number of pets on hatelist)
#define SE_ImprovedTaunt 444 // implemented - Locks Aggro On Caster and Decrease other Players Aggro by X% on NPC targets below level Y
//#define SE_AddMercSlot 445 // *not implemented[AA] - [Hero's Barracks] Allows you to conscript additional mercs.
//#define SE_AStacker 446 // *not implementet - bufff stacking blocker ? (26219 | Qirik's Watch)
//#define SE_BStacker 447 // *not implemented
//#define SE_CStacker 448 // *not implemented
//#define SE_DStacker 449 // *not implemented
#define SE_AStacker 446 // implementet - bufff stacking blocker (26219 | Qirik's Watch)
#define SE_BStacker 447 // implemented
#define SE_CStacker 448 // implemented
#define SE_DStacker 449 // implemented
#define SE_MitigateDotDamage 450 // implemented DOT spell mitigation rune with max value
#define SE_MeleeThresholdGuard 451 // implemented Partial Melee Rune that only is lowered if melee hits are over X amount of damage
#define SE_SpellThresholdGuard 452 // implemented Partial Spell Rune that only is lowered if spell hits are over X amount of damage
@ -833,6 +833,7 @@ bool IsBuffSpell(uint16 spell_id);
bool IsPersistDeathSpell(uint16 spell_id);
bool IsSuspendableSpell(uint16 spell_id);
uint32 GetMorphTrigger(uint32 spell_id);
bool IsCastonFadeDurationSpell(uint16 spell_id);
uint32 GetPartialMeleeRuneReduction(uint32 spell_id);
uint32 GetPartialMagicRuneReduction(uint32 spell_id);
uint32 GetPartialMeleeRuneAmount(uint32 spell_id);

View File

@ -2661,6 +2661,22 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
}
break;
case SE_AStacker:
newbon->AStacker = true;
break;
case SE_BStacker:
newbon->BStacker = true;
break;
case SE_CStacker:
newbon->CStacker = true;
break;
case SE_DStacker:
newbon->DStacker = true;
break;
//Special custom cases for loading effects on to NPC from 'npc_spels_effects' table
if (IsAISpellEffect) {

View File

@ -350,6 +350,10 @@ struct StatBonuses {
bool NegateIfCombat; // Bool Drop buff if cast or melee
int8 Screech; // -1 = Will be blocked if another Screech is +(1)
int16 AlterNPCLevel; // amount of lvls +/-
bool AStacker; // For buff stack blocking
bool BStacker; // For buff stack blocking
bool CStacker; // For buff stack blocking
bool DStacker; // For buff stack blocking
// AAs
int8 Packrat; //weight reduction for items, 1 point = 10%

View File

@ -800,7 +800,7 @@ public:
uint16 GetInstrumentMod(uint16 spell_id) const;
int CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level = 1, Mob *caster = nullptr, int ticsremaining = 0);
int CalcSpellEffectValue_formula(int formula, int base, int max, int caster_level, uint16 spell_id, int ticsremaining = 0);
virtual int CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, int caster_level2, Mob* caster1 = nullptr, Mob* caster2 = nullptr);
virtual int CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, int caster_level2, Mob* caster1 = nullptr, Mob* caster2 = nullptr, int buffslot = -1);
uint32 GetCastedSpellInvSlot() const { return casting_spell_inventory_slot; }
// HP Event

View File

@ -2886,6 +2886,10 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
case SE_LimitCastTimeMax:
case SE_TriggerOnReqCaster:
case SE_FrenziedDevastation:
case SE_AStacker:
case SE_BStacker:
case SE_CStacker:
case SE_DStacker:
{
break;
}

View File

@ -2542,7 +2542,7 @@ int CalcBuffDuration_formula(int level, int formula, int duration)
// -1 if they can't stack and spellid2 should be stopped
//currently, a spell will not land if it would overwrite a better spell on any effect
//if all effects are better or the same, we overwrite, else we do nothing
int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, int caster_level2, Mob* caster1, Mob* caster2)
int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, int caster_level2, Mob* caster1, Mob* caster2, int buffslot)
{
const SPDat_Spell_Struct &sp1 = spells[spellid1];
const SPDat_Spell_Struct &sp2 = spells[spellid2];
@ -2621,6 +2621,24 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2,
}
}
/*Buff stacking prevention spell effects (446 - 449) works as follows... If B prevent A, if C prevent B, if D prevent C.
Special check is added to make sure the buffs stack properly when applied from fade on duration effect, since the buff
is not fully removed at the time of the trgger*/
if (spellbonuses.BStacker) {
if ((effect2 == SE_AStacker) && (!IsCastonFadeDurationSpell(spellid1) && buffs[buffslot].ticsremaining != 1 && IsEffectInSpell(spellid1, SE_BStacker)))
return -1;
}
if (spellbonuses.CStacker) {
if ((effect2 == SE_BStacker) && (!IsCastonFadeDurationSpell(spellid1) && buffs[buffslot].ticsremaining != 1 && IsEffectInSpell(spellid1, SE_CStacker)))
return -1;
}
if (spellbonuses.DStacker) {
if ((effect2 == SE_CStacker) && (!IsCastonFadeDurationSpell(spellid1) && buffs[buffslot].ticsremaining != 1 && IsEffectInSpell(spellid1, SE_DStacker)))
return -1;
}
if(effect2 == SE_StackingCommand_Overwrite)
{
overwrite_effect = sp2.base[i];
@ -2901,7 +2919,7 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid
if (curbuf.spellid != SPELL_UNKNOWN) {
// there's a buff in this slot
ret = CheckStackConflict(curbuf.spellid, curbuf.casterlevel, spell_id,
caster_level, entity_list.GetMobID(curbuf.casterid), caster);
caster_level, entity_list.GetMobID(curbuf.casterid), caster, buffslot);
if (ret == -1) { // stop the spell
mlog(SPELLS__BUFFS, "Adding buff %d failed: stacking prevented by spell %d in slot %d with caster level %d",
spell_id, curbuf.spellid, buffslot, curbuf.casterlevel);
@ -3047,7 +3065,7 @@ int Mob::CanBuffStack(uint16 spellid, uint8 caster_level, bool iFailIfOverwrite)
return(-1); //do not recast a buff we already have on, we recast fast enough that we dont need to refresh our buffs
// there's a buff in this slot
ret = CheckStackConflict(curbuf.spellid, curbuf.casterlevel, spellid, caster_level);
ret = CheckStackConflict(curbuf.spellid, curbuf.casterlevel, spellid, caster_level, nullptr, nullptr, i);
if(ret == 1) {
// should overwrite current slot
if(iFailIfOverwrite) {