mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 17:51:28 +00:00
Merge pull request #165 from KayenEQ/Development
Implemented SE_Sanctuary - Places caster at bottom hate list,
This commit is contained in:
commit
9a76df62dd
@ -1,5 +1,16 @@
|
||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||
-------------------------------------------------------
|
||||
== 07/2/2014 ==
|
||||
Kayen: Implemented SE_Sanctuary - Places caster at bottom hate list, effect fades if caster cast spell on targets other than self.
|
||||
Kayen: Implemented SE_ResourceTap - Coverts a percent of dmg from dmg spells(DD/DoT) to hp/mana/end.
|
||||
Kayen: Implemented SE_FactionModPct - Modifies faction gains and losses by percent.
|
||||
Kayen: Re-Implemented SE_TriggerMeleeThreshold and SE_TriggerSpellThreshold correctly - Trigger spell if owner of buff
|
||||
takes more than the specified damage amount in a SINGLE hit, then fade the buff.
|
||||
Kayen: Implemented SE_LimitSpellClass - Focus Limits spell to pre defined categories. (3=Cures,3=Offensive, 6=Lifetap)
|
||||
Kayen: Changed SE_LimitMaxMana to SE_MeleeVulnerability - Weakness/Mitigation verse melee damage
|
||||
(Despite lives SPA lable as the former it clearly is not what the effect does from all spell examples)
|
||||
Kayen: Updated SE_BardAEDot to no longer damage target while target is moving (consistent with live)
|
||||
Kayen: Update SE_InterruptCasting: Will now work for instant spells (as well as over time).
|
||||
|
||||
== 06/25/2014 ==
|
||||
Kayen: Updated SE_Hate (Renamed from SE_Hate2) to now properly work for instant +/- hate spells.
|
||||
|
||||
@ -157,6 +157,24 @@ bool IsFearSpell(uint16 spell_id)
|
||||
return IsEffectInSpell(spell_id, SE_Fear);
|
||||
}
|
||||
|
||||
bool IsCureSpell(uint16 spell_id)
|
||||
{
|
||||
const SPDat_Spell_Struct &sp = spells[spell_id];
|
||||
|
||||
bool CureEffect = false;
|
||||
|
||||
for(int i = 0; i < EFFECT_COUNT; i++){
|
||||
if (sp.effectid[i] == SE_DiseaseCounter || sp.effectid[i] == SE_PoisonCounter
|
||||
|| sp.effectid[i] == SE_CurseCounter || sp.effectid[i] == SE_CorruptionCounter)
|
||||
CureEffect = true;
|
||||
}
|
||||
|
||||
if (CureEffect && IsBeneficialSpell(spell_id))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsSlowSpell(uint16 spell_id)
|
||||
{
|
||||
const SPDat_Spell_Struct &sp = spells[spell_id];
|
||||
@ -1003,7 +1021,7 @@ bool IsSuspendableSpell(uint16 spell_id)
|
||||
uint32 GetMorphTrigger(uint32 spell_id)
|
||||
{
|
||||
for (int i = 0; i < EFFECT_COUNT; ++i)
|
||||
if (spells[spell_id].effectid[i] == SE_ImprovedSpellEffect)
|
||||
if (spells[spell_id].effectid[i] == SE_CastOnFadeEffect)
|
||||
return spells[spell_id].base[i];
|
||||
|
||||
return 0;
|
||||
@ -1012,9 +1030,9 @@ uint32 GetMorphTrigger(uint32 spell_id)
|
||||
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){
|
||||
if (spells[spell_id].effectid[i] == SE_CastOnFadeEffect
|
||||
|| spells[spell_id].effectid[i] == SE_CastOnFadeEffectNPC
|
||||
|| spells[spell_id].effectid[i] == SE_CastOnFadeEffectAlways){
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
#define EFFECT_COUNT 12
|
||||
#define MAX_SPELL_TRIGGER 12 // One for each slot(only 6 for AA since AA use 2)
|
||||
#define MAX_RESISTABLE_EFFECTS 12 // Number of effects that are typcially checked agianst resists.
|
||||
#define MaxLimitInclude 12 //Number(x 0.5) of focus Limiters that have inclusive checksm used when calcing focus effects
|
||||
#define MaxLimitInclude 16 //Number(x 0.5) of focus Limiters that have inclusive checks used when calcing focus effects
|
||||
|
||||
const int Z_AGGRO=10;
|
||||
|
||||
@ -436,7 +436,7 @@ typedef enum {
|
||||
#define SE_FcDamageAmt 286 // implemented - adds direct spell damage
|
||||
#define SE_SpellDurationIncByTic 287 // implemented
|
||||
#define SE_SpecialAttackKBProc 288 // implemented[AA] - Chance to to do a knockback from special attacks [AA Dragon Punch].
|
||||
#define SE_ImprovedSpellEffect 289 // implemented - Triggers only if fades after natural duration.
|
||||
#define SE_CastOnFadeEffect 289 // implemented - Triggers only if fades after natural duration.
|
||||
#define SE_IncreaseRunSpeedCap 290 // implemented[AA] - increases run speed over the hard cap
|
||||
#define SE_Purify 291 // implemented - Removes determental effects
|
||||
#define SE_StrikeThrough2 292 // implemented[AA] - increasing chance of bypassing an opponent's special defenses, such as dodge, block, parry, and riposte.
|
||||
@ -455,11 +455,11 @@ typedef enum {
|
||||
#define SE_MitigateDamageShield 305 // implemented - off hand attacks only (Shielding Resistance)
|
||||
//#define SE_ArmyOfTheDead 306 // *not implemented NecroAA - This ability calls up to five shades of nearby corpses back to life to serve the necromancer. The soulless abominations will mindlessly fight the target until called back to the afterlife some time later. The first rank summons up to three shades that serve for 60 seconds, and each additional rank adds one more possible shade and increases their duration by 15 seconds
|
||||
//#define SE_Appraisal 307 // *not implemented Rogue AA - This ability allows you to estimate the selling price of an item you are holding on your cursor.
|
||||
#define SE_SuspendMinion 308 // not implemented as bonus
|
||||
#define SE_SuspendMinion 308 // implemented
|
||||
#define SE_GateCastersBindpoint 309 // implemented - Gate to casters bind point
|
||||
#define SE_ReduceReuseTimer 310 // implemented
|
||||
#define SE_LimitCombatSkills 311 // implemented - Excludes focus from procs (except if proc is a memorizable spell)
|
||||
//#define SE_Sanctuary 312 // *not implemented
|
||||
#define SE_Sanctuary 312 // implemented - Places caster at bottom hate list, effect fades if cast cast spell on targets other than self.
|
||||
#define SE_ForageAdditionalItems 313 // implemented[AA] - chance to forage additional items
|
||||
#define SE_Invisibility2 314 // implemented - fixed duration invisible
|
||||
#define SE_InvisVsUndead2 315 // implemented - fixed duration ITU
|
||||
@ -480,7 +480,7 @@ typedef enum {
|
||||
#define SE_CriticalDamageMob 330 // implemented
|
||||
#define SE_Salvage 331 // implemented - chance to recover items that would be destroyed in failed tradeskill combine
|
||||
//#define SE_SummonToCorpse 332 // *not implemented AA - Call of the Wild (Druid/Shaman Res spell with no exp)
|
||||
#define SE_EffectOnFade 333 // implemented
|
||||
#define SE_CastOnRuneFadeEffect 333 // implemented
|
||||
#define SE_BardAEDot 334 // implemented
|
||||
#define SE_BlockNextSpellFocus 335 // implemented - base1 chance to block next spell ie Puratus (8494)
|
||||
//#define SE_IllusionaryTarget 336 // not used
|
||||
@ -520,11 +520,11 @@ typedef enum {
|
||||
#define SE_ResistCorruption 370 // implemented
|
||||
#define SE_AttackSpeed4 371 // implemented - stackable slow effect 'Inhibit Melee'
|
||||
//#define SE_ForageSkill 372 // *not implemented[AA] Will increase the skill cap for those that have the Forage skill and grant the skill and raise the cap to those that do not.
|
||||
#define SE_CastOnWearoff 373 // implemented - Triggers only if fades after natural duration.
|
||||
#define SE_CastOnFadeEffectAlways 373 // implemented - Triggers if fades after natural duration OR from rune/numhits fades.
|
||||
#define SE_ApplyEffect 374 // implemented
|
||||
#define SE_DotCritDmgIncrease 375 // implemented - Increase damage of DoT critical amount
|
||||
//#define SE_Fling 376 // *not implemented - used in 2 test spells (12945 | Movement Test Spell 1)
|
||||
#define SE_BossSpellTrigger 377 // implemented - Triggers only if fades after natural duration.
|
||||
#define SE_CastOnFadeEffectNPC 377 // implemented - Triggers only if fades after natural duration (On live these are usually players spells that effect an NPC).
|
||||
#define SE_SpellEffectResistChance 378 // implemented - Increase chance to resist specific spell effect (base1=value, base2=spell effect id)
|
||||
#define SE_ShadowStepDirectional 379 // implemented - handled by client
|
||||
#define SE_Knockdown 380 // implemented - small knock back(handled by client)
|
||||
@ -538,7 +538,7 @@ typedef enum {
|
||||
//#define SE_SummonCorpseZone 388 // *not implemented - summons a corpse from any zone(nec AA)
|
||||
#define SE_FcTimerRefresh 389 // implemented - Refresh spell icons
|
||||
//#define SE_FcTimerLockout 390 // *not implemented - Sets recast timers to specific value, focus limited.
|
||||
#define SE_LimitManaMax 391 // implemented
|
||||
#define SE_MeleeVulnerability 391 // implemented [Live SPA has this as LimitManaMax however that is clearly not the effect used]
|
||||
#define SE_FcHealAmt 392 // implemented - Adds or removes healing from spells
|
||||
#define SE_FcHealPctIncoming 393 // implemented - HealRate with focus restrictions.
|
||||
#define SE_FcHealAmtIncoming 394 // implemented - Adds/Removes amount of healing on target by X value with foucs restrictions.
|
||||
@ -550,8 +550,8 @@ typedef enum {
|
||||
#define SE_HealGroupFromMana 400 // implemented - Drains mana and heals for each point of mana drained
|
||||
#define SE_ManaDrainWithDmg 401 // implemented - Deals damage based on the amount of mana drained
|
||||
#define SE_EndDrainWithDmg 402 // implemented - Deals damage for the amount of endurance drained
|
||||
//#define SE_LimitSpellClass 403 // *not implemented - unclear what this refers too (not 'right click' spell bar)
|
||||
//#define SE_LimitSpellSubclass 404 // *not implemented - unclear what this refers too (not 'right click' spell bar)
|
||||
#define SE_LimitSpellClass 403 // implemented - Limits to specific types of spells (see CheckSpellCategory)
|
||||
#define SE_LimitSpellSubclass 404 // *not implemented - Limits to specific types of spells (see CheckSpellCategory) [Categories NOT defined yet]
|
||||
#define SE_TwoHandBluntBlock 405 // implemented - chance to block attacks when using two hand blunt weapons (similiar to shield block)
|
||||
#define SE_CastonNumHitFade 406 // implemented - casts a spell when a buff fades due to its numhits being depleted
|
||||
#define SE_CastonFocusEffect 407 // implemented - casts a spell if focus limits are met (ie triggers when a focus effects is applied)
|
||||
@ -600,12 +600,12 @@ typedef enum {
|
||||
#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
|
||||
#define SE_TriggerMeleeThreshold 453 // implemented Trigger effect on X amount of melee damage taken
|
||||
#define SE_TriggerSpellThreshold 454 // implemented Trigger effect on X amount of spell damage taken
|
||||
#define SE_TriggerMeleeThreshold 453 // implemented Trigger effect on X amount of melee damage taken in a single hit
|
||||
#define SE_TriggerSpellThreshold 454 // implemented Trigger effect on X amount of spell damage taken in a single hit
|
||||
#define SE_AddHatePct 455 // implemented Modify total hate by %
|
||||
#define SE_AddHateOverTimePct 456 // implemented Modify total hate by % over time.
|
||||
//#define SE_ResourceTap 457 // not used
|
||||
//#define SE_FactionModPct 458 // not used
|
||||
#define SE_ResourceTap 457 // implemented Coverts a percent of dmg from dmg spells(DD/DoT) to hp/mana/end.
|
||||
#define SE_FactionModPct 458 // implemented Modifies faction gains and losses by percent.
|
||||
#define SE_DamageModifier2 459 // implemented - Modifies melee damage by skill type
|
||||
|
||||
// LAST
|
||||
@ -787,6 +787,7 @@ bool IsSummonSpell(uint16 spellid);
|
||||
bool IsEvacSpell(uint16 spellid);
|
||||
bool IsDamageSpell(uint16 spellid);
|
||||
bool IsFearSpell(uint16 spellid);
|
||||
bool IsCureSpell(uint16 spellid);
|
||||
bool BeneficialSpell(uint16 spell_id);
|
||||
bool GroupOnlySpell(uint16 spell_id);
|
||||
int GetSpellEffectIndex(uint16 spell_id, int effect);
|
||||
|
||||
@ -3251,20 +3251,6 @@ int32 Mob::ReduceDamage(int32 damage)
|
||||
}
|
||||
}
|
||||
|
||||
if (spellbonuses.TriggerMeleeThreshold[2]){
|
||||
slot = spellbonuses.TriggerMeleeThreshold[1];
|
||||
|
||||
if (slot >= 0) {
|
||||
if(damage > buffs[slot].melee_rune) {
|
||||
if(!TryFadeEffect(slot))
|
||||
BuffFadeBySlot(slot);
|
||||
}
|
||||
else{
|
||||
buffs[slot].melee_rune = (buffs[slot].melee_rune - damage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(damage < 1)
|
||||
return -6;
|
||||
|
||||
@ -3393,20 +3379,6 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
|
||||
}
|
||||
}
|
||||
|
||||
if (spellbonuses.TriggerSpellThreshold[2]){
|
||||
slot = spellbonuses.TriggerSpellThreshold[1];
|
||||
|
||||
if (slot >= 0) {
|
||||
if(damage > buffs[slot].magic_rune) {
|
||||
if(!TryFadeEffect(slot))
|
||||
BuffFadeBySlot(slot);
|
||||
}
|
||||
else{
|
||||
buffs[slot].magic_rune = (buffs[slot].magic_rune - damage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(damage < 1)
|
||||
return 0;
|
||||
|
||||
@ -3599,6 +3571,8 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
|
||||
if(spell_id == SPELL_UNKNOWN) {
|
||||
damage = ReduceDamage(damage);
|
||||
mlog(COMBAT__HITS, "Melee Damage reduced to %d", damage);
|
||||
ReduceAllDamage(damage);
|
||||
TryTriggerThreshHold(damage, SE_TriggerMeleeThreshold, attacker);
|
||||
} else {
|
||||
int32 origdmg = damage;
|
||||
damage = AffectMagicalDamage(damage, spell_id, iBuffTic, attacker);
|
||||
@ -3610,14 +3584,13 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
|
||||
//Kayen: Probably need to add a filter for this - Not sure if this msg is correct but there should be a message for spell negate/runes.
|
||||
Message(263, "%s tries to cast on YOU, but YOUR magical skin absorbs the spell.",attacker->GetCleanName());
|
||||
}
|
||||
|
||||
ReduceAllDamage(damage);
|
||||
TryTriggerThreshHold(damage, SE_TriggerSpellThreshold, attacker);
|
||||
}
|
||||
|
||||
if (skill_used)
|
||||
CheckNumHitsRemaining(NUMHIT_IncomingHitSuccess);
|
||||
|
||||
ReduceAllDamage(damage);
|
||||
|
||||
if(IsClient() && CastToClient()->sneaking){
|
||||
CastToClient()->sneaking = false;
|
||||
SendAppearancePacket(AT_Sneak, 0);
|
||||
|
||||
@ -1315,6 +1315,20 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon)
|
||||
newbon->PetMeleeMitigation += base1;
|
||||
break;
|
||||
|
||||
case SE_MeleeVulnerability:
|
||||
newbon->MeleeVulnerability += base1;
|
||||
break;
|
||||
|
||||
case SE_FactionModPct:
|
||||
{
|
||||
if((base1 < 0) && (newbon->FactionModPct > base1))
|
||||
newbon->FactionModPct = base1;
|
||||
|
||||
else if(newbon->FactionModPct < base1)
|
||||
newbon->FactionModPct = base1;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2415,24 +2429,12 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
}
|
||||
|
||||
case SE_TriggerMeleeThreshold:
|
||||
{
|
||||
if (newbon->TriggerMeleeThreshold[2] < base2){
|
||||
newbon->TriggerMeleeThreshold[0] = effect_value;
|
||||
newbon->TriggerMeleeThreshold[1] = buffslot;
|
||||
newbon->TriggerMeleeThreshold[2] = base2;
|
||||
}
|
||||
newbon->TriggerMeleeThreshold = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_TriggerSpellThreshold:
|
||||
{
|
||||
if (newbon->TriggerSpellThreshold[2] < base2){
|
||||
newbon->TriggerSpellThreshold[0] = effect_value;
|
||||
newbon->TriggerSpellThreshold[1] = buffslot;
|
||||
newbon->TriggerSpellThreshold[2] = base2;
|
||||
}
|
||||
newbon->TriggerSpellThreshold = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_ShieldBlock:
|
||||
newbon->ShieldBlock += effect_value;
|
||||
@ -2856,6 +2858,24 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
newbon->PetMeleeMitigation += effect_value;
|
||||
break;
|
||||
|
||||
case SE_MeleeVulnerability:
|
||||
newbon->MeleeVulnerability += effect_value;
|
||||
break;
|
||||
|
||||
case SE_Sanctuary:
|
||||
newbon->Sanctuary = true;
|
||||
break;
|
||||
|
||||
case SE_FactionModPct:
|
||||
{
|
||||
if((effect_value < 0) && (newbon->FactionModPct > effect_value))
|
||||
newbon->FactionModPct = effect_value;
|
||||
|
||||
else if(newbon->FactionModPct < effect_value)
|
||||
newbon->FactionModPct = effect_value;
|
||||
break;
|
||||
}
|
||||
|
||||
//Special custom cases for loading effects on to NPC from 'npc_spels_effects' table
|
||||
if (IsAISpellEffect) {
|
||||
|
||||
@ -4194,15 +4214,11 @@ void Mob::NegateSpellsBonuses(uint16 spell_id)
|
||||
break;
|
||||
|
||||
case SE_TriggerMeleeThreshold:
|
||||
spellbonuses.TriggerMeleeThreshold[0] = effect_value;
|
||||
spellbonuses.TriggerMeleeThreshold[1] = effect_value;
|
||||
spellbonuses.TriggerMeleeThreshold[2] = effect_value;
|
||||
spellbonuses.TriggerMeleeThreshold = effect_value;
|
||||
break;
|
||||
|
||||
case SE_TriggerSpellThreshold:
|
||||
spellbonuses.TriggerSpellThreshold[0] = effect_value;
|
||||
spellbonuses.TriggerSpellThreshold[1] = effect_value;
|
||||
spellbonuses.TriggerSpellThreshold[2] = effect_value;
|
||||
spellbonuses.TriggerSpellThreshold = effect_value;
|
||||
break;
|
||||
|
||||
case SE_DivineAura:
|
||||
@ -4330,6 +4346,16 @@ void Mob::NegateSpellsBonuses(uint16 spell_id)
|
||||
itembonuses.FinishingBlowLvl[1] = effect_value;
|
||||
break;
|
||||
|
||||
case SE_Sanctuary:
|
||||
spellbonuses.Sanctuary = effect_value;
|
||||
break;
|
||||
|
||||
case SE_FactionModPct:
|
||||
spellbonuses.FactionModPct = effect_value;
|
||||
itembonuses.FactionModPct = effect_value;
|
||||
aabonuses.FactionModPct = effect_value;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -7629,6 +7629,9 @@ void Client::SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, ui
|
||||
if(npc_value[i] != 0) {
|
||||
tmpValue = current_value + mod + npc_value[i];
|
||||
|
||||
int16 FactionModPct = spellbonuses.FactionModPct + itembonuses.FactionModPct + aabonuses.FactionModPct;
|
||||
tmpValue += (tmpValue * FactionModPct) / 100;
|
||||
|
||||
// Make sure faction hits don't go to GMs...
|
||||
if (m_pp.gm==1 && (tmpValue < current_value)) {
|
||||
tmpValue = current_value;
|
||||
|
||||
@ -348,8 +348,8 @@ struct StatBonuses {
|
||||
uint16 SpellThresholdGuard[3]; // 0 = Mitigation value 1 = Buff Slot 2 = Min damage to trigger.
|
||||
uint16 MitigateSpellRune[4]; // 0 = Mitigation value 1 = Buff Slot 2 = Max mitigation per spell 3 = Rune Amt
|
||||
uint16 MitigateDotRune[4]; // 0 = Mitigation value 1 = Buff Slot 2 = Max mitigation per tick 3 = Rune Amt
|
||||
uint32 TriggerMeleeThreshold[3]; // 0 = Spell Effect ID 1 = Buff slot 2 = Damage Amount to Trigger
|
||||
uint32 TriggerSpellThreshold[3]; // 0 = Spell Effect ID 1 = Buff slot 2 = Damage Amount to Trigger
|
||||
bool TriggerMeleeThreshold; // Has Melee Threshhold
|
||||
bool TriggerSpellThreshold; // Has Spell Threshhold
|
||||
uint16 ManaAbsorbPercentDamage[2]; // 0 = Mitigation value 1 = Buff Slot
|
||||
int16 ShieldBlock; // Chance to Shield Block
|
||||
int16 BlockBehind; // Chance to Block Behind (with our without shield)
|
||||
@ -372,6 +372,9 @@ struct StatBonuses {
|
||||
int16 DStacker[1]; // For buff stack blocking 0=Exists 1=Effect_value
|
||||
bool BerserkSPA; // berserk effect
|
||||
int16 Metabolism; // Food/drink consumption rates.
|
||||
bool Sanctuary; // Sanctuary effect, lowers place on hate list until cast on others.
|
||||
int16 FactionModPct; // Modifies amount of faction gained.
|
||||
int16 MeleeVulnerability; // Weakness/mitigation to melee damage
|
||||
|
||||
// AAs
|
||||
int8 Packrat; //weight reduction for items, 1 point = 10%
|
||||
|
||||
@ -3419,6 +3419,8 @@ int16 Mob::GetSkillDmgTaken(const SkillUseTypes skill_used)
|
||||
{
|
||||
int skilldmg_mod = 0;
|
||||
|
||||
int16 MeleeVuln = spellbonuses.MeleeVulnerability + itembonuses.MeleeVulnerability + aabonuses.MeleeVulnerability;
|
||||
|
||||
// All skill dmg mod + Skill specific
|
||||
skilldmg_mod += itembonuses.SkillDmgTaken[HIGHEST_SKILL+1] + spellbonuses.SkillDmgTaken[HIGHEST_SKILL+1] +
|
||||
itembonuses.SkillDmgTaken[skill_used] + spellbonuses.SkillDmgTaken[skill_used];
|
||||
@ -3427,6 +3429,8 @@ int16 Mob::GetSkillDmgTaken(const SkillUseTypes skill_used)
|
||||
if ((SkillDmgTaken_Mod[skill_used]) || (SkillDmgTaken_Mod[HIGHEST_SKILL+1]))
|
||||
skilldmg_mod += SkillDmgTaken_Mod[skill_used] + SkillDmgTaken_Mod[HIGHEST_SKILL+1];
|
||||
|
||||
skilldmg_mod += MeleeVuln;
|
||||
|
||||
if(skilldmg_mod < -100)
|
||||
skilldmg_mod = -100;
|
||||
|
||||
@ -3452,8 +3456,8 @@ bool Mob::TryFadeEffect(int slot)
|
||||
{
|
||||
for(int i = 0; i < EFFECT_COUNT; i++)
|
||||
{
|
||||
if (spells[buffs[slot].spellid].effectid[i] == SE_CastOnWearoff || spells[buffs[slot].spellid].effectid[i] == SE_EffectOnFade
|
||||
|| spells[buffs[slot].spellid].effectid[i] == SE_TriggerMeleeThreshold || spells[buffs[slot].spellid].effectid[i] == SE_TriggerSpellThreshold)
|
||||
if (spells[buffs[slot].spellid].effectid[i] == SE_CastOnFadeEffectAlways ||
|
||||
spells[buffs[slot].spellid].effectid[i] == SE_CastOnRuneFadeEffect)
|
||||
{
|
||||
uint16 spell_id = spells[buffs[slot].spellid].base[i];
|
||||
BuffFadeBySlot(slot);
|
||||
|
||||
@ -229,6 +229,10 @@ public:
|
||||
bool TryDispel(uint8 caster_level, uint8 buff_level, int level_modifier);
|
||||
void SpellProjectileEffect();
|
||||
bool TrySpellProjectile(Mob* spell_target, uint16 spell_id);
|
||||
void ResourceTap(int32 damage, uint16 spell_id);
|
||||
void TryTriggerThreshHold(int32 damage, int effect_id, Mob* attacker);
|
||||
bool CheckSpellCategory(uint16 spell_id, int category_id, int effect_id);
|
||||
|
||||
|
||||
//Buff
|
||||
void BuffProcess();
|
||||
|
||||
@ -224,8 +224,10 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
dmg = (int32) (dmg * partial / 100);
|
||||
|
||||
//handles AAs and what not...
|
||||
if(caster)
|
||||
if(caster) {
|
||||
dmg = caster->GetActSpellDamage(spell_id, dmg, this);
|
||||
caster->ResourceTap(-dmg, spell_id);
|
||||
}
|
||||
|
||||
dmg = -dmg;
|
||||
Damage(caster, dmg, spell_id, spell.skill, false, buffslot, false);
|
||||
@ -1315,18 +1317,6 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_TriggerMeleeThreshold:
|
||||
{
|
||||
buffs[buffslot].melee_rune = spells[spell_id].base2[i];
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_TriggerSpellThreshold:
|
||||
{
|
||||
buffs[buffslot].magic_rune = spells[spell_id].base2[i];
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_DistanceRemoval:
|
||||
{
|
||||
buffs[buffslot].caston_x = int(GetX());
|
||||
@ -2338,6 +2328,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
// SE_CurrentHP is calculated at first tick if its a dot/buff
|
||||
if (buffslot >= 0)
|
||||
break;
|
||||
//This effect does no damage if target is moving.
|
||||
if (IsMoving())
|
||||
break;
|
||||
|
||||
// for offensive spells check if we have a spell rune on
|
||||
int32 dmg = effect_value;
|
||||
@ -2719,6 +2712,16 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_InterruptCasting:{
|
||||
if (buffslot >= 0)
|
||||
break;
|
||||
|
||||
if(IsCasting() && MakeRandomInt(0, 100) <= spells[spell_id].base[i])
|
||||
InterruptSpell();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_MassGroupBuff:{
|
||||
|
||||
SetMGB(true);
|
||||
@ -2732,6 +2735,22 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_Sanctuary:
|
||||
{
|
||||
std::list<NPC*> npc_list;
|
||||
entity_list.GetNPCList(npc_list);
|
||||
|
||||
for(std::list<NPC*>::iterator itr = npc_list.begin(); itr != npc_list.end(); ++itr) {
|
||||
|
||||
NPC* npc = *itr;
|
||||
|
||||
if (npc && npc->CheckAggro(this))
|
||||
npc->SetHate(caster, 1);
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Handled Elsewhere
|
||||
case SE_ImmuneFleeing:
|
||||
case SE_NegateSpellEffect:
|
||||
@ -2845,11 +2864,10 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
case SE_ApplyEffect:
|
||||
case SE_FcTwincast:
|
||||
case SE_DelayDeath:
|
||||
case SE_InterruptCasting:
|
||||
case SE_ImprovedSpellEffect:
|
||||
case SE_BossSpellTrigger:
|
||||
case SE_CastOnWearoff:
|
||||
case SE_EffectOnFade:
|
||||
case SE_CastOnFadeEffect:
|
||||
case SE_CastOnFadeEffectNPC:
|
||||
case SE_CastOnFadeEffectAlways:
|
||||
case SE_CastOnRuneFadeEffect:
|
||||
case SE_MaxHPChange:
|
||||
case SE_SympatheticProc:
|
||||
case SE_FcDamageAmt:
|
||||
@ -2936,7 +2954,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
case SE_FcIncreaseNumHits:
|
||||
case SE_CastonFocusEffect:
|
||||
case SE_FcHealAmtIncoming:
|
||||
case SE_LimitManaMax:
|
||||
case SE_MeleeVulnerability:
|
||||
case SE_DoubleRangedAttack:
|
||||
case SE_ShieldEquipHateMod:
|
||||
case SE_ShieldEquipDmgMod:
|
||||
@ -2960,6 +2978,12 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
case SE_Berserk:
|
||||
case SE_Vampirism:
|
||||
case SE_Metabolism:
|
||||
case SE_FinishingBlow:
|
||||
case SE_FinishingBlowLvl:
|
||||
case SE_Assassinate:
|
||||
case SE_AssassinateLevel:
|
||||
case SE_FactionModPct:
|
||||
case SE_LimitSpellClass:
|
||||
{
|
||||
break;
|
||||
}
|
||||
@ -3347,6 +3371,8 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste
|
||||
|
||||
if(caster->IsNPC())
|
||||
effect_value = caster->CastToNPC()->GetActSpellDamage(spell_id, effect_value, this);
|
||||
|
||||
caster->ResourceTap(-effect_value, spell_id);
|
||||
}
|
||||
|
||||
effect_value = -effect_value;
|
||||
@ -3377,7 +3403,7 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste
|
||||
{
|
||||
effect_value = CalcSpellEffectValue(spell_id, i, caster_level, caster);
|
||||
|
||||
if (invulnerable || /*effect_value > 0 ||*/ DivineAura())
|
||||
if (IsMoving() || invulnerable || /*effect_value > 0 ||*/ DivineAura())
|
||||
break;
|
||||
|
||||
if(effect_value < 0) {
|
||||
@ -3545,9 +3571,9 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste
|
||||
break;
|
||||
}
|
||||
// These effects always trigger when they fade.
|
||||
case SE_ImprovedSpellEffect:
|
||||
case SE_BossSpellTrigger:
|
||||
case SE_CastOnWearoff:
|
||||
case SE_CastOnFadeEffect:
|
||||
case SE_CastOnFadeEffectNPC:
|
||||
case SE_CastOnFadeEffectAlways:
|
||||
{
|
||||
if (ticsremaining == 1)
|
||||
{
|
||||
@ -3604,6 +3630,22 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_Sanctuary:
|
||||
{
|
||||
std::list<NPC*> npc_list;
|
||||
entity_list.GetNPCList(npc_list);
|
||||
|
||||
for(std::list<NPC*>::iterator itr = npc_list.begin(); itr != npc_list.end(); ++itr) {
|
||||
|
||||
NPC* npc = *itr;
|
||||
|
||||
if (npc && npc->CheckAggro(this))
|
||||
npc->SetHate(caster, 1);
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
// do we need to do anyting here?
|
||||
@ -4099,6 +4141,8 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id)
|
||||
6/7 SE_LimitTarget
|
||||
8/9 SE_LimitSpellGroup:
|
||||
10/11 SE_LimitCastingSkill:
|
||||
12/13 SE_LimitSpellClass:
|
||||
14/15 SE_LimitSpellSubClass:
|
||||
Remember: Update MaxLimitInclude in spdat.h if adding new limits that require Includes
|
||||
*/
|
||||
int FocusCount = 0;
|
||||
@ -4255,11 +4299,6 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id)
|
||||
LimitFailure = true;
|
||||
break;
|
||||
|
||||
case SE_LimitManaMax:
|
||||
if(spell.mana > base1)
|
||||
LimitFailure = true;
|
||||
break;
|
||||
|
||||
case SE_LimitTarget:
|
||||
if (base1 < 0) {
|
||||
if (-base1 == spell.targettype) //Exclude
|
||||
@ -4304,6 +4343,30 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id)
|
||||
}
|
||||
break;
|
||||
|
||||
case SE_LimitSpellClass:
|
||||
if(base1 < 0) { //Exclude
|
||||
if (CheckSpellCategory(spell_id, base1, SE_LimitSpellClass));
|
||||
return(0);
|
||||
}
|
||||
else {
|
||||
LimitInclude[12] = true;
|
||||
if (CheckSpellCategory(spell_id, base1, SE_LimitSpellClass)); //Include
|
||||
LimitInclude[13] = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case SE_LimitSpellSubclass:
|
||||
if(base1 < 0) { //Exclude
|
||||
if (CheckSpellCategory(spell_id, base1, SE_LimitSpellSubclass));
|
||||
return(0);
|
||||
}
|
||||
else {
|
||||
LimitInclude[14] = true;
|
||||
if (CheckSpellCategory(spell_id, base1, SE_LimitSpellSubclass)); //Include
|
||||
LimitInclude[15] = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case SE_LimitClass:
|
||||
//Do not use this limit more then once per spell. If multiple class, treat value like items would.
|
||||
if (!PassLimitClass(base1, GetClass()))
|
||||
@ -4546,6 +4609,8 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
|
||||
6/7 SE_LimitTarget
|
||||
8/9 SE_LimitSpellGroup:
|
||||
10/11 SE_LimitCastingSkill:
|
||||
12/13 SE_LimitSpellClass:
|
||||
14/15 SE_LimitSpellSubClass:
|
||||
Remember: Update MaxLimitInclude in spdat.h if adding new limits that require Includes
|
||||
*/
|
||||
|
||||
@ -4660,11 +4725,6 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case SE_LimitManaMax:
|
||||
if(spell.mana > focus_spell.base[i])
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case SE_LimitTarget:
|
||||
if (focus_spell.base[i] < 0) {
|
||||
if (-focus_spell.base[i] == spell.targettype) //Exclude
|
||||
@ -4735,6 +4795,30 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
|
||||
Caston_spell_id = focus_spell.base[i];
|
||||
break;
|
||||
|
||||
case SE_LimitSpellClass:
|
||||
if(focus_spell.base[i] < 0) { //Exclude
|
||||
if (CheckSpellCategory(spell_id, focus_spell.base[i], SE_LimitSpellClass));
|
||||
return(0);
|
||||
}
|
||||
else {
|
||||
LimitInclude[12] = true;
|
||||
if (CheckSpellCategory(spell_id, focus_spell.base[i], SE_LimitSpellClass)); //Include
|
||||
LimitInclude[13] = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case SE_LimitSpellSubclass:
|
||||
if(focus_spell.base[i] < 0) { //Exclude
|
||||
if (CheckSpellCategory(spell_id, focus_spell.base[i], SE_LimitSpellSubclass));
|
||||
return(0);
|
||||
}
|
||||
else {
|
||||
LimitInclude[14] = true;
|
||||
if (CheckSpellCategory(spell_id, focus_spell.base[i], SE_LimitSpellSubclass)); //Include
|
||||
LimitInclude[15] = true;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
//handle effects
|
||||
case SE_ImprovedDamage:
|
||||
@ -5338,7 +5422,7 @@ void Mob::CheckNumHitsRemaining(uint8 type, uint32 buff_slot, uint16 spell_id)
|
||||
2: [Outgoing Hit Attempts] (185=SE_DamageModifer, 184=SE_HitChance)
|
||||
3: [Incoming Spells] (180=SE_ResistSpellChance, 296=SE_FcSpellVulnerability) //Note: Determinetal spells only unless proven otherwise
|
||||
4: [Outgoing Spells]
|
||||
5: [Outgoing Hit Successes] (220=SE_SkillDamageAmount, 178=SE_MeleeLifetap, 121=SE_ReverseDS, ?373=SE_CastOnWearoff)
|
||||
5: [Outgoing Hit Successes] (220=SE_SkillDamageAmount, 178=SE_MeleeLifetap, 121=SE_ReverseDS, ?373=SE_CastOnFadeEffectAlways)
|
||||
6: [Incoming Hit Successes] (59=SE_DamageShield, 197=SE_SkillDamageTaken, 162=define SE_MitigateMeleeDamage)
|
||||
7: [Matching Spells] *When focus is triggered (focus effects)
|
||||
8: [Incoming Hits or Spells] (329=SE_ManaAbsorbPercentDamage)
|
||||
@ -6247,4 +6331,121 @@ bool Mob::TrySpellProjectile(Mob* spell_target, uint16 spell_id){
|
||||
return true;
|
||||
}
|
||||
|
||||
void Mob::ResourceTap(int32 damage, uint16 spellid){
|
||||
//'this' = caster
|
||||
if (!IsValidSpell(spellid))
|
||||
return;
|
||||
|
||||
for (int i = 0; i <= EFFECT_COUNT; i++)
|
||||
{
|
||||
if (spells[spellid].effectid[i] == SE_ResourceTap){
|
||||
|
||||
damage += (damage * spells[spellid].base[i])/100;
|
||||
|
||||
if (spells[spellid].max[i] && (damage > spells[spellid].max[i]))
|
||||
damage = spells[spellid].max[i];
|
||||
|
||||
if (spells[spellid].base2[i] == 0) //HP Tap
|
||||
SetHP((GetHP()+ damage));
|
||||
|
||||
if (spells[spellid].base2[i] == 1) //Mana Tap
|
||||
SetMana(GetMana() + damage);
|
||||
|
||||
if (spells[spellid].base2[i] == 2 && IsClient()) //Endurance Tap
|
||||
CastToClient()->SetEndurance(CastToClient()->GetEndurance() + damage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Mob::TryTriggerThreshHold(int32 damage, int effect_id, Mob* attacker){
|
||||
|
||||
if (damage <= 0)
|
||||
return;
|
||||
|
||||
if ((SE_TriggerMeleeThreshold == effect_id) && !spellbonuses.TriggerMeleeThreshold )
|
||||
return;
|
||||
else if ((SE_TriggerSpellThreshold == effect_id) && !spellbonuses.TriggerSpellThreshold)
|
||||
return;
|
||||
|
||||
int buff_count = GetMaxTotalSlots();
|
||||
|
||||
for(int slot = 0; slot < buff_count; slot++) {
|
||||
|
||||
if(IsValidSpell(buffs[slot].spellid)){
|
||||
|
||||
for(int i = 0; i < EFFECT_COUNT; i++){
|
||||
|
||||
if (spells[buffs[slot].spellid].effectid[i] == effect_id){
|
||||
|
||||
uint16 spell_id = spells[buffs[slot].spellid].base[i];
|
||||
|
||||
if (damage > spells[buffs[slot].spellid].base2[i]){
|
||||
|
||||
BuffFadeBySlot(slot);
|
||||
|
||||
if (IsValidSpell(spell_id)) {
|
||||
|
||||
if (IsBeneficialSpell(spell_id))
|
||||
SpellFinished(spell_id, this, 10, 0, -1, spells[spell_id].ResistDiff);
|
||||
|
||||
else if(attacker)
|
||||
SpellFinished(spell_id, attacker, 10, 0, -1, spells[spell_id].ResistDiff);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Mob::CheckSpellCategory(uint16 spell_id, int category_id, int effect_id){
|
||||
|
||||
if (!IsValidSpell(spell_id) || !category_id)
|
||||
return false;
|
||||
|
||||
int effectid = 0;
|
||||
int category = 0;
|
||||
|
||||
/*Category ID SE_LimitSpellClass [(+) Include (-) Exclude]
|
||||
1 = UNK
|
||||
2 = Cures
|
||||
3 = Offensive Spells
|
||||
4 = UNK
|
||||
5 = UNK
|
||||
6 = Lifetap
|
||||
*/
|
||||
|
||||
/*Category ID SE_LimitSpellSubClass [(+) Include (-) Exclude]
|
||||
5 = UNK
|
||||
8 = UNK
|
||||
*/
|
||||
|
||||
if (effect_id == SE_LimitSpellClass) {
|
||||
|
||||
switch(category_id)
|
||||
{
|
||||
case 2:
|
||||
if (IsCureSpell(spell_id))
|
||||
return true;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (IsDetrimentalSpell(spell_id))
|
||||
return true;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
if (spells[spell_id].targettype == ST_Tap || spells[spell_id].targettype == ST_TargetAETap)
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
else if (effect_id == SE_LimitSpellSubclass) {
|
||||
//Pending Implementation when category types are figured out.
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -183,6 +183,9 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot,
|
||||
CastToNPC()->AI_Event_SpellCastFinished(false, casting_spell_slot);
|
||||
return(false);
|
||||
}
|
||||
//It appears that the Sanctuary effect is removed by a check on the client side (keep this however for redundancy)
|
||||
if (spellbonuses.Sanctuary && (spells[spell_id].targettype != ST_Self && GetTarget() != this) || IsDetrimentalSpell(spell_id))
|
||||
BuffFadeByEffect(SE_Sanctuary);
|
||||
|
||||
if(IsClient()){
|
||||
int chance = CastToClient()->GetFocusEffect(focusFcMute, spell_id);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user