Merge branch 'master' of github.com:EQEmu/Server

This commit is contained in:
Michael Cook (mackal) 2014-02-19 20:37:26 -05:00
commit 754d70d513
13 changed files with 89 additions and 31 deletions

View File

@ -1,5 +1,10 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50)
-------------------------------------------------------
== 02/18/2014 ==
Kayen: Implemented SE_TriggerOnReqCaster - triggers a spell which a certain criteria are met (below X amount of hp,mana,end, number of pets on hatelist)
Kayen: Implemented SE_ImprovedTaunt - Locks Aggro On Caster and Decrease other Players Aggro by X% on NPC targets below level Y
Kayen: Fixed an error where SE_ChangeAggro was adding its bonus x 2 for spell generated aggro. (this applies also to spell casting subtlety AA reduction)
== 02/14/2014 ==
Kayen: Fixes for buffs not fading under certain conditions in revised numhits system, and other fixes.
Kayen: Implemented support for spell_new field CastRestrictions (limits what type of targets spells can effect).

View File

@ -949,7 +949,7 @@ bool IsDebuffSpell(uint16 spell_id)
if (IsBeneficialSpell(spell_id) || IsEffectHitpointsSpell(spell_id) || IsStunSpell(spell_id) ||
IsMezSpell(spell_id) || IsCharmSpell(spell_id) || IsSlowSpell(spell_id) ||
IsEffectInSpell(spell_id, SE_Root) || IsEffectInSpell(spell_id, SE_CancelMagic) ||
IsEffectInSpell(spell_id, SE_MovementSpeed) || IsFearSpell(spell_id) || IsEffectInSpell(spell_id, SE_Calm))
IsEffectInSpell(spell_id, SE_MovementSpeed) || IsFearSpell(spell_id) || IsEffectInSpell(spell_id, SE_InstantHate))
return false;
else
return true;

View File

@ -148,7 +148,7 @@ typedef enum {
// full listing: https://forums.station.sony.com/eq/index.php?threads/enumerated-spa-list.206288/
// mirror: http://pastebin.com/MYeQqGwe
#define SE_CurrentHP 0 // implemented - Heals and nukes, repeates every tic if in a buff
#define SE_ArmorClass 1 // implemented
#define SE_ArmorClass 1 // implemented
#define SE_ATK 2 // implemented
#define SE_MovementSpeed 3 // implemented - SoW, SoC, etc
#define SE_STR 4 // implemented
@ -239,7 +239,7 @@ typedef enum {
#define SE_ModelSize 89 // implemented - Shrink, Growth
#define SE_Cloak 90 // *not implemented - Used in only 2 spells
#define SE_SummonCorpse 91 // implemented
#define SE_Calm 92 // implemented - Hate modifier stuff(poorly named)
#define SE_InstantHate 92 // implemented - add hate
#define SE_StopRain 93 // implemented - Wake of Karana
#define SE_NegateIfCombat 94 // *not implemented? - Works client side but there is comment todo in spell effects...Component of Spirit of Scale
#define SE_Sacrifice 95 // implemented
@ -572,7 +572,7 @@ typedef enum {
#define SE_LimitUseMin 422 // implemented - limit a focus to require a min amount of numhits value (used with above)
#define SE_LimitUseType 423 // implemented - limit a focus to require a certain numhits type
#define SE_GravityEffect 424 // implemented - Pulls/pushes you toward/away the mob at a set pace
#define SE_Display 425 // *not implemented - Illusion: Flying Dragon(21626)
//#define SE_Display 425 // *not implemented - Illusion: Flying Dragon(21626)
#define SE_IncreaseExtTargetWindow 426 // *not implmented[AA] - increases the capacity of your extended target window
#define SE_SkillProc 427 // implemented - chance to proc when using a skill(ie taunt)
#define SE_LimitToSkill 428 // implemented - limits what skills will effect a skill proc
@ -589,9 +589,9 @@ typedef enum {
#define SE_IncreaseAssassinationLvl 439 // *not implemented[AA] - increases the maximum level of humanoid that can be affected by assassination
#define SE_FinishingBlowLvl 440 // implemented[AA] - Sets the level Finishing blow can be triggered on an NPC
#define SE_CancleIfMoved 441 // *not implemented - Buff is removed from target when target moves X amount of distance away from where initially hit.
#define SE_TriggerOnValueAmount 442 // implemented - triggers a spell which a certain criteria are met (below X amount of hp,mana,end, number of pets on hatelist)
#define SE_TriggerIfMovement 443 // *not implemented - Trigger a spell if you move (37846 | Chopping Block)
#define SE_ImprovedTaunt 444 // *not implemented - Locks Aggro On Caster and Decrease other Players Aggro by X% up to level Z
#define SE_TriggerOnReqTarget 442 // implemented - triggers a spell which a certain criteria are met (below X amount of hp,mana,end, number of pets on hatelist)
#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

View File

@ -1054,7 +1054,8 @@ void Mob::AI_Process() {
SetTarget(hate_list.GetTop(this));
}
} else {
SetTarget(hate_list.GetTop(this));
if (!ImprovedTaunt())
SetTarget(hate_list.GetTop(this));
}
}

View File

@ -1257,7 +1257,7 @@ int32 Mob::CheckAggroAmount(uint16 spell_id, bool isproc)
break;
}
case SE_ReduceHate:
case SE_Calm: {
case SE_InstantHate: {
nonModifiedAggro = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base[o], spells[spell_id].max[o], slevel, spell_id);
break;
}
@ -1282,9 +1282,6 @@ int32 Mob::CheckAggroAmount(uint16 spell_id, bool isproc)
if (IsClient())
HateMod += CastToClient()->GetFocusEffect(focusSpellHateMod, spell_id);
//Live AA - Spell casting subtlety
HateMod += aabonuses.hatemod + spellbonuses.hatemod + itembonuses.hatemod;
AggroAmount = (AggroAmount * HateMod) / 100;
//made up number probably scales a bit differently on live but it seems like it will be close enough
@ -1405,7 +1402,7 @@ bool Mob::PassCharismaCheck(Mob* caster, Mob* spellTarget, uint16 spell_id) {
return true;
//1: The mob has a default 25% chance of being allowed a resistance check against the charm.
if (MakeRandomInt(0, 100) > RuleI(Spells, CharmBreakCheckChance))
if (MakeRandomInt(0, 99) > RuleI(Spells, CharmBreakCheckChance))
return true;
//2: The mob makes a resistance check against the charm
@ -1419,7 +1416,7 @@ bool Mob::PassCharismaCheck(Mob* caster, Mob* spellTarget, uint16 spell_id) {
//3: At maxed ability, Total Domination has a 50% chance of preventing the charm break that otherwise would have occurred.
uint16 TotalDominationBonus = caster->aabonuses.CharmBreakChance + caster->spellbonuses.CharmBreakChance + caster->itembonuses.CharmBreakChance;
if (MakeRandomInt(0, 100) < TotalDominationBonus)
if (MakeRandomInt(0, 99) < TotalDominationBonus)
return true;
}

View File

@ -1336,6 +1336,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
// Hate Generation is on a per swing basis, regardless of a hit, miss, or block, its always the same.
// If we are this far, this means we are atleast making a swing.
if (!bRiposte) // Ripostes never generate any aggro.
other->AddToHateList(this, hate);
@ -1901,6 +1902,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
mlog(COMBAT__HITS, "Generating hate %d towards %s", hate, GetName());
// now add done damage to the hate list
other->AddToHateList(this, hate);
} else {
if(opts) {
damage *= opts->damage_percent;
@ -2435,7 +2437,9 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
}
void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp, bool bFrenzy, bool iBuffTic) {
assert(other != nullptr);
if (other == this)
return;
@ -2516,6 +2520,10 @@ void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp,
if(damage > GetHP())
damage = GetHP();
if (spellbonuses.ImprovedTaunt[1] && (GetLevel() < spellbonuses.ImprovedTaunt[0])
&& other && (buffs[spellbonuses.ImprovedTaunt[2]].casterid != other->GetID()))
hate = (hate*spellbonuses.ImprovedTaunt[1])/100;
hate_list.Add(other, hate, damage, bFrenzy, !iBuffTic);
if(other->IsClient())

View File

@ -2496,7 +2496,8 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
break;
}
case SE_TriggerOnValueAmount:
case SE_TriggerOnReqTarget:
case SE_TriggerOnReqCaster:
newbon->TriggerOnValueAmount = true;
break;
@ -2504,6 +2505,14 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
newbon->DivineAura = true;
break;
case SE_ImprovedTaunt:
if (newbon->ImprovedTaunt[0] < effect_value) {
newbon->ImprovedTaunt[0] = effect_value;
newbon->ImprovedTaunt[1] = spells[spell_id].base2[i];
newbon->ImprovedTaunt[2] = buffslot;
}
break;
}
}
}

View File

@ -12973,7 +12973,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) {
pacer->Say("Trying to pacify %s \n", target->GetCleanName());
if(pacer->Bot_Command_CalmTarget(target)) {
if(target->FindType(SE_Lull) || target->FindType(SE_Harmony) || target->FindType(SE_Calm))
if(target->FindType(SE_Lull) || target->FindType(SE_Harmony) || target->FindType(SE_InstantHate))
//if(pacer->IsPacified(target))
c->Message(0, "I have successfully pacified %s.", target->GetCleanName());
return;
@ -12989,7 +12989,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) {
pacer->Say("Trying to pacify %s \n", target->GetCleanName());
if(pacer->Bot_Command_CalmTarget(target)) {
if(target->FindType(SE_Lull) || target->FindType(SE_Harmony) || target->FindType(SE_Calm))
if(target->FindType(SE_Lull) || target->FindType(SE_Harmony) || target->FindType(SE_InstantHate))
//if(pacer->IsPacified(target))
c->Message(0, "I have successfully pacified %s.", target->GetCleanName());
return;

View File

@ -328,6 +328,7 @@ struct StatBonuses {
bool CriticalHealDecay; // increase critical heal chance, decays based on spell level cast
bool CriticalDotDecay; // increase critical dot chance, decays based on spell level cast
bool DivineAura; // invulnerability
int16 ImprovedTaunt[3]; // 0 = Max Level 1 = Aggro modifier 2 = buffid
//bool AbsorbMagicAtt; // Magic Rune *Need to be implemented for NegateEffect
//bool MeleeRune; // Melee Rune *Need to be implemented for NegateEffect

View File

@ -3670,7 +3670,7 @@ MercSpell Merc::GetBestMercSpellForHate(Merc* caster) {
result.time_cancast = 0;
if(caster) {
std::list<MercSpell> mercSpellList = GetMercSpellsForSpellEffect(caster, SE_Calm);
std::list<MercSpell> mercSpellList = GetMercSpellsForSpellEffect(caster, SE_InstantHate);
for(std::list<MercSpell>::iterator mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) {
// Assuming all the spells have been loaded into this list by level and in descending order

View File

@ -3228,11 +3228,20 @@ void Mob::TryApplyEffect(Mob *target, uint32 spell_id)
void Mob::TryTriggerOnValueAmount(bool IsHP, bool IsMana, bool IsEndur, bool IsPet)
{
/*
At present time there is no obvious difference between ReqTarget and ReqCaster
ReqTarget is typically used in spells cast on a target where the trigger occurs on that target.
ReqCaster is typically self only spells where the triggers on self.
Regardless both trigger on the owner of the buff.
*/
/*
Base2 Range: 1004 = Below < 80% HP
Base2 Range: 500-520 = Below (base2 - 500)*5 HP
Base2 Range: 521 = Below (?) Mana UKNOWN - Will assume its 20% unless proven otherwise
Base2 Range: 522 = Below (40%) Endurance
Base2 Range: 523 = Below (40%) Mana
Base2 Range: 220-? = Number of pets on hatelist to trigger (base2 - 220) (Set at 30 pets max for now)
38311 = < 10% mana;
*/
if (!spellbonuses.TriggerOnValueAmount)
@ -3250,21 +3259,25 @@ void Mob::TryTriggerOnValueAmount(bool IsHP, bool IsMana, bool IsEndur, bool IsP
for(int i = 0; i < EFFECT_COUNT; i++){
if (spells[spell_id].effectid[i] == SE_TriggerOnValueAmount){
if ((spells[spell_id].effectid[i] == SE_TriggerOnReqTarget) || (spells[spell_id].effectid[i] == SE_TriggerOnReqCaster)) {
int base2 = spells[spell_id].base2[i];
bool use_spell = false;
if (IsHP){
if ((base2 >= 500 && base2 <= 520) && GetHPRatio() < (base2 - 500)*5){
if ((base2 >= 500 && base2 <= 520) && GetHPRatio() < (base2 - 500)*5)
use_spell = true;
else if (base2 = 1004 && GetHPRatio() < 80)
use_spell = true;
}
}
else if (IsMana){
if ( (base2 = 521 && GetManaRatio() < 20) || (base2 = 523 && GetManaRatio() < 40)) {
if ( (base2 = 521 && GetManaRatio() < 20) || (base2 = 523 && GetManaRatio() < 40))
use_spell = true;
else if (base2 = 38311 && GetManaRatio() < 10)
use_spell = true;
}
}
else if (IsEndur){
@ -3283,10 +3296,6 @@ void Mob::TryTriggerOnValueAmount(bool IsHP, bool IsMana, bool IsEndur, bool IsP
if (use_spell){
SpellFinished(spells[spell_id].base[i], this, 10, 0, -1, spells[spell_id].ResistDiff);
/*Note, spell data shows numhits values of 0 or 1, however many descriptions of these spells indicate they should
be fading when consumed even with numhits of 0 (It makes sense they should fade...).
Unless proven otherwise, they should fade when triggered. */
if(!TryFadeEffect(e))
BuffFadeBySlot(e);
}

View File

@ -592,6 +592,7 @@ public:
int32 GetExtraSpellAmt(uint16 spell_id, int32 extra_spell_amt, int32 base_spell_dmg);
void MeleeLifeTap(int32 damage);
bool PassCastRestriction(bool UseCastRestriction = true, int16 value = 0, bool IsDamage = true);
bool ImprovedTaunt();
void ModSkillDmgTaken(SkillUseTypes skill_num, int value);
int16 GetModSkillDmgTaken(const SkillUseTypes skill_num);

View File

@ -2667,7 +2667,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
case SE_ChangeAggro:
case SE_Hate2:
case SE_Identify:
case SE_Calm:
case SE_InstantHate:
case SE_ReduceHate:
case SE_SpellDamageShield:
case SE_ReverseDS:
@ -2806,7 +2806,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
case SE_DoubleRangedAttack:
case SE_ShieldEquipHateMod:
case SE_ShieldEquipDmgMod:
case SE_TriggerOnValueAmount:
case SE_TriggerOnReqTarget:
case SE_LimitRace:
case SE_FcLimitUse:
case SE_FcMute:
@ -5577,6 +5577,28 @@ bool Mob::TryDispel(uint8 caster_level, uint8 buff_level, int level_modifier){
return false;
}
bool Mob::ImprovedTaunt(){
if (spellbonuses.ImprovedTaunt[2]){
if (GetLevel() > spellbonuses.ImprovedTaunt[0])
return false;
target = entity_list.GetMob(buffs[spellbonuses.ImprovedTaunt[2]].casterid);
if (target){
SetTarget(target);
return true;
}
else
BuffFadeBySlot(spellbonuses.ImprovedTaunt[2]); //If caster killed removed effect.
}
return false;
}
bool Mob::PassCastRestriction(bool UseCastRestriction, int16 value, bool IsDamage)
{
/*If return TRUE spell met all restrictions and can continue (this = target).
@ -5633,7 +5655,7 @@ bool Mob::PassCastRestriction(bool UseCastRestriction, int16 value, bool IsDama
Range 839 : Unknown *not implemented
Range 842 - 844 : Humaniod lv MAX ((842 - 800) * 2)
Range 845 - 847 : UNKNOWN
Range 10000+ : Limit to Race [base2 - 10000 = Race] (*Not on live: Too useful a function to not implement)
Range 10000 - 11000 : Limit to Race [base2 - 10000 = Race] (*Not on live: Too useful a function to not implement)
THIS IS A WORK IN PROGRESS
*/
@ -5650,7 +5672,7 @@ bool Mob::PassCastRestriction(bool UseCastRestriction, int16 value, bool IsDama
break;
case 101:
if (GetBodyType() == BT_Dragon)
if (GetBodyType() == BT_Dragon || GetBodyType() == BT_VeliousDragon || GetBodyType() == BT_Dragon3)
return true;
break;
@ -5786,6 +5808,11 @@ bool Mob::PassCastRestriction(bool UseCastRestriction, int16 value, bool IsDama
return true;
break;
case 701:
if (!IsPet())
return true;
break;
case 818:
if (GetBodyType() == BT_Undead)
return true;