mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-13 10:31:29 +00:00
commit
5121cc25a4
@ -5,6 +5,7 @@ cavedude: Live-Like weather system (Thanks to robregen for figuring it out!)
|
||||
demonstar55: Implemented not_extendable spell flag
|
||||
demonstar55: Moved Spell Casting Reinforcement to DB
|
||||
demonstar55: Moved Mez Mastery to DB
|
||||
Kayen: Complete revision of the numhits systems to utilize 'numhits type' field in spell file.
|
||||
|
||||
== 01/18/2014 ==
|
||||
sorvani: Implemented for Lua eq.get_characters_in_instance(uint16 instance_id), return a Lua HashTable
|
||||
|
||||
@ -182,9 +182,6 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c
|
||||
//The old code basically meant that any in high level (50+) combat,
|
||||
//both parties always had 95% chance to hit the other one.
|
||||
/*/
|
||||
//If chance bonus set in spell data for Skill Attacks is 10k allow to hit without calculations.
|
||||
if (chance_mod == 10000)
|
||||
return true;
|
||||
|
||||
Mob *attacker=other;
|
||||
Mob *defender=this;
|
||||
@ -281,8 +278,6 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c
|
||||
if(bonus > 0) {
|
||||
chancetohit -= ((bonus * chancetohit) / 1000);
|
||||
mlog(COMBAT__TOHIT, "Applied avoidance chance %.2f/10, yeilding %.2f", bonus, chancetohit);
|
||||
if (defender->spellbonuses.AvoidMeleeChance)
|
||||
defender->CheckHitsRemaining(0, false, false,SE_AvoidMeleeChance);
|
||||
}
|
||||
|
||||
if(attacker->IsNPC())
|
||||
@ -330,6 +325,11 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c
|
||||
chancetohit = 5;
|
||||
}
|
||||
|
||||
CheckNumHitsRemaining(1);
|
||||
|
||||
if (attacker)
|
||||
attacker->CheckNumHitsRemaining(2);
|
||||
|
||||
//I dont know the best way to handle a garunteed hit discipline being used
|
||||
//agains a garunteed riposte (for example) discipline... for now, garunteed hit wins
|
||||
|
||||
@ -1117,6 +1117,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
|
||||
mlog(COMBAT__ATTACKS, "Attack canceled, invalid circumstances.");
|
||||
return false; // Only bards can attack while casting
|
||||
}
|
||||
|
||||
if(DivineAura() && !GetGM()) {//cant attack while invulnerable unless your a gm
|
||||
mlog(COMBAT__ATTACKS, "Attack canceled, Divine Aura is in effect.");
|
||||
Message_StringID(MT_DefaultText, DIVINE_AURA_NO_ATK); //You can't attack while invulnerable!
|
||||
@ -1247,7 +1248,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
|
||||
hate *= opts->hate_percent;
|
||||
hate += opts->hate_flat;
|
||||
}
|
||||
|
||||
|
||||
//check to see if we hit..
|
||||
if(!other->CheckHitChance(this, skillinuse, Hand)) {
|
||||
mlog(COMBAT__ATTACKS, "Attack missed. Damage set to 0.");
|
||||
@ -1326,8 +1327,6 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
|
||||
//heal self for damage done..
|
||||
HealDamage(lifetap_amt);
|
||||
|
||||
if (spellbonuses.MeleeLifetap)
|
||||
CheckHitsRemaining(0, false,false, SE_MeleeLifetap);
|
||||
}
|
||||
|
||||
//break invis when you attack
|
||||
@ -2058,6 +2057,7 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
|
||||
killerMob->GetCleanName(), GetCleanName(), ConvertArray(damage, val1));
|
||||
}
|
||||
} else {
|
||||
|
||||
char buffer[48] = { 0 };
|
||||
snprintf(buffer, 47, "%d %d %d %d", killerMob ? killerMob->GetID() : 0, damage, spell, static_cast<int>(attack_skill));
|
||||
if(parse->EventNPC(EVENT_DEATH, this, nullptr, buffer, 0) != 0)
|
||||
@ -3128,8 +3128,12 @@ int32 Mob::ReduceDamage(int32 damage)
|
||||
if (spellbonuses.NegateAttacks[0]){
|
||||
slot = spellbonuses.NegateAttacks[1];
|
||||
if(slot >= 0) {
|
||||
if(CheckHitsRemaining(slot, false, true))
|
||||
return -6;
|
||||
if(--buffs[slot].numhits == 0) {
|
||||
|
||||
if(!TryFadeEffect(slot))
|
||||
BuffFadeBySlot(slot , true);
|
||||
}
|
||||
return -6;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3156,7 +3160,6 @@ int32 Mob::ReduceDamage(int32 damage)
|
||||
" damage remaining.", damage_to_reduce, buffs[slot].melee_rune);
|
||||
buffs[slot].melee_rune = (buffs[slot].melee_rune - damage_to_reduce);
|
||||
damage -= damage_to_reduce;
|
||||
CheckHitsRemaining(slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3182,8 +3185,7 @@ int32 Mob::ReduceDamage(int32 damage)
|
||||
" damage remaining.", damage_to_reduce, buffs[slot].melee_rune);
|
||||
buffs[slot].melee_rune = (buffs[slot].melee_rune - damage_to_reduce);
|
||||
damage -= damage_to_reduce;
|
||||
if (!CheckHitsRemaining(slot))
|
||||
UpdateRuneFlags();
|
||||
UpdateRuneFlags();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3198,7 +3200,6 @@ int32 Mob::ReduceDamage(int32 damage)
|
||||
}
|
||||
else{
|
||||
buffs[slot].melee_rune = (buffs[slot].melee_rune - damage);
|
||||
CheckHitsRemaining(slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3212,16 +3213,6 @@ int32 Mob::ReduceDamage(int32 damage)
|
||||
if(damage < 1)
|
||||
return -6;
|
||||
|
||||
if (spellbonuses.ManaAbsorbPercentDamage[0]){
|
||||
slot = spellbonuses.ManaAbsorbPercentDamage[1];
|
||||
if(GetMana() > damage * spellbonuses.ManaAbsorbPercentDamage[0] / 100) {
|
||||
damage -= (damage * spellbonuses.ManaAbsorbPercentDamage[0] / 100);
|
||||
SetMana(GetMana() - damage);
|
||||
TryTriggerOnValueAmount(false, true);
|
||||
CheckHitsRemaining(slot);
|
||||
}
|
||||
}
|
||||
|
||||
return(damage);
|
||||
}
|
||||
|
||||
@ -3237,8 +3228,12 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
|
||||
if (spellbonuses.NegateAttacks[0]){
|
||||
slot = spellbonuses.NegateAttacks[1];
|
||||
if(slot >= 0) {
|
||||
if(CheckHitsRemaining(slot, false, true))
|
||||
return 0;
|
||||
if(--buffs[slot].numhits == 0) {
|
||||
|
||||
if(!TryFadeEffect(slot))
|
||||
BuffFadeBySlot(slot , true);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3272,7 +3267,6 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
|
||||
{
|
||||
buffs[slot].melee_rune = (buffs[slot].magic_rune - damage_to_reduce);
|
||||
damage -= damage_to_reduce;
|
||||
CheckHitsRemaining(slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3299,8 +3293,7 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
|
||||
" damage remaining.", damage_to_reduce, buffs[slot].magic_rune);
|
||||
buffs[slot].magic_rune = (buffs[slot].magic_rune - damage_to_reduce);
|
||||
damage -= damage_to_reduce;
|
||||
if (!CheckHitsRemaining(slot))
|
||||
UpdateRuneFlags();
|
||||
UpdateRuneFlags();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3315,7 +3308,6 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
|
||||
}
|
||||
else{
|
||||
buffs[slot].melee_rune = (buffs[slot].magic_rune - damage);
|
||||
CheckHitsRemaining(slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3329,20 +3321,26 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
|
||||
|
||||
if(damage < 1)
|
||||
return 0;
|
||||
|
||||
if (spellbonuses.ManaAbsorbPercentDamage[0]){
|
||||
slot = spellbonuses.ManaAbsorbPercentDamage[1];
|
||||
if(GetMana() > damage * spellbonuses.ManaAbsorbPercentDamage[0] / 100) {
|
||||
damage -= (damage * spellbonuses.ManaAbsorbPercentDamage[0] / 100);
|
||||
SetMana(GetMana() - damage);
|
||||
TryTriggerOnValueAmount(false, true);
|
||||
CheckHitsRemaining(slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
return damage;
|
||||
}
|
||||
|
||||
int32 Mob::ReduceAllDamage(int32 damage)
|
||||
{
|
||||
if(damage <= 0)
|
||||
return damage;
|
||||
|
||||
if(spellbonuses.ManaAbsorbPercentDamage[0] && (GetMana() > damage * spellbonuses.ManaAbsorbPercentDamage[0] / 100)) {
|
||||
damage -= (damage * spellbonuses.ManaAbsorbPercentDamage[0] / 100);
|
||||
SetMana(GetMana() - damage);
|
||||
TryTriggerOnValueAmount(false, true);
|
||||
}
|
||||
|
||||
CheckNumHitsRemaining(8);
|
||||
|
||||
return(damage);
|
||||
}
|
||||
|
||||
bool Mob::HasProcs() const
|
||||
{
|
||||
for (int i = 0; i < MAX_PROCS; i++)
|
||||
@ -3441,9 +3439,6 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
|
||||
// damage shield calls this function with spell_id set, so its unavoidable
|
||||
if (attacker && damage > 0 && spell_id == SPELL_UNKNOWN && skill_used != SkillArchery && skill_used != SkillThrowing) {
|
||||
DamageShield(attacker);
|
||||
|
||||
if (spellbonuses.DamageShield)
|
||||
CheckHitsRemaining(0, false, false, SE_DamageShield);
|
||||
}
|
||||
|
||||
if(attacker){
|
||||
@ -3511,11 +3506,12 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
|
||||
}
|
||||
if (damage == 0 && attacker && origdmg != damage && IsClient()) {
|
||||
//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());
|
||||
Message(263, "%s tries to cast on YOU, but YOUR magical skin absorbs the spell.",attacker->GetCleanName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ReduceAllDamage(damage);
|
||||
|
||||
if(IsClient() && CastToClient()->sneaking){
|
||||
CastToClient()->sneaking = false;
|
||||
@ -3919,7 +3915,7 @@ void Mob::TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand, int dam
|
||||
int chance = ProcChance * (DefensiveProcs[i].chance);
|
||||
if ((MakeRandomInt(0, 100) < chance)) {
|
||||
ExecWeaponProc(nullptr, DefensiveProcs[i].spellID, on);
|
||||
CheckHitsRemaining(0, false, false, 0, DefensiveProcs[i].base_spellID);
|
||||
CheckNumHitsRemaining(10,0,DefensiveProcs[i].base_spellID);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4087,6 +4083,7 @@ void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct* weapon, Mob *on
|
||||
if(MakeRandomInt(0, 100) < chance) {
|
||||
mlog(COMBAT__PROCS, "Spell proc %d procing spell %d (%d percent chance)", i, SpellProcs[i].spellID, chance);
|
||||
ExecWeaponProc(nullptr, SpellProcs[i].spellID, on);
|
||||
CheckNumHitsRemaining(11, 0, SpellProcs[i].base_spellID);
|
||||
} else {
|
||||
mlog(COMBAT__PROCS, "Spell proc %d failed to proc %d (%d percent chance)", i, SpellProcs[i].spellID, chance);
|
||||
}
|
||||
@ -4097,7 +4094,7 @@ void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct* weapon, Mob *on
|
||||
if(MakeRandomInt(0, 100) < chance) {
|
||||
mlog(COMBAT__PROCS, "Ranged proc %d procing spell %d", i, RangedProcs[i].spellID, RangedProcs[i].chance);
|
||||
ExecWeaponProc(nullptr, RangedProcs[i].spellID, on);
|
||||
CheckHitsRemaining(0, false, false, 0, RangedProcs[i].base_spellID);
|
||||
CheckNumHitsRemaining(11, 0, RangedProcs[i].base_spellID);
|
||||
} else {
|
||||
mlog(COMBAT__PROCS, "Ranged proc %d failed to proc %d", i, RangedProcs[i].spellID, RangedProcs[i].chance);
|
||||
}
|
||||
@ -4358,10 +4355,6 @@ void Mob::ApplyMeleeDamageBonus(uint16 skill, int32 &damage){
|
||||
}
|
||||
|
||||
damage += damage * GetMeleeDamageMod_SE(skill) / 100;
|
||||
|
||||
//Rogue sneak attack disciplines make use of this, they are active for one hit
|
||||
if (spellbonuses.HitChanceEffect[HIGHEST_SKILL+1] || spellbonuses.HitChanceEffect[skill])
|
||||
CheckHitsRemaining(0, false, false, SE_HitChance,0,true,skill);
|
||||
}
|
||||
|
||||
bool Mob::HasDied() {
|
||||
@ -4435,7 +4428,7 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, float chance)
|
||||
int ProcChance = chance * (float)SkillProcs[i].chance;
|
||||
if ((MakeRandomInt(0, 100) < ProcChance)) {
|
||||
ExecWeaponProc(nullptr, SkillProcs[i].spellID, on);
|
||||
CheckHitsRemaining(0, false, false, 0, SkillProcs[i].base_spellID);
|
||||
CheckNumHitsRemaining(11,0, SkillProcs[i].base_spellID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1148,7 +1148,6 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case SE_DivineSave:
|
||||
{
|
||||
if(newbon->DivineSaveChance[0] < base1)
|
||||
@ -2460,6 +2459,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
newbon->TriggerOnValueAmount = true;
|
||||
break;
|
||||
|
||||
case SE_DivineAura:
|
||||
newbon->DivineAura = true;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3768,6 +3771,10 @@ void Mob::NegateSpellsBonuses(uint16 spell_id)
|
||||
spellbonuses.TriggerSpellThreshold[1] = effect_value;
|
||||
spellbonuses.TriggerSpellThreshold[2] = effect_value;
|
||||
break;
|
||||
|
||||
case SE_DivineAura:
|
||||
spellbonuses.DivineAura = false;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -6604,9 +6604,6 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b
|
||||
mlog(COMBAT__DAMAGE, "Melee lifetap healing for %d damage.", damage);
|
||||
//heal self for damage done..
|
||||
HealDamage(lifetap_amt);
|
||||
|
||||
if (spellbonuses.MeleeLifetap)
|
||||
CheckHitsRemaining(0, false,false, SE_MeleeLifetap);
|
||||
}
|
||||
|
||||
//break invis when you attack
|
||||
|
||||
@ -323,6 +323,7 @@ struct StatBonuses {
|
||||
bool CriticalRegenDecay; // increase critical regen chance, decays based on spell level cast
|
||||
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
|
||||
//bool AbsorbMagicAtt; // Magic Rune *Need to be implemented for NegateEffect
|
||||
//bool MeleeRune; // Melee Rune *Need to be implemented for NegateEffect
|
||||
|
||||
|
||||
54
zone/mob.cpp
54
zone/mob.cpp
@ -178,6 +178,7 @@ Mob::Mob(const char* in_name,
|
||||
findable = false;
|
||||
trackable = true;
|
||||
has_shieldequiped = false;
|
||||
has_numhits = false;
|
||||
|
||||
if(in_aa_title>0)
|
||||
aa_title = in_aa_title;
|
||||
@ -2732,21 +2733,9 @@ void Mob::Warp( float x, float y, float z )
|
||||
|
||||
bool Mob::DivineAura() const
|
||||
{
|
||||
uint32 l;
|
||||
uint32 buff_count = GetMaxTotalSlots();
|
||||
for (l = 0; l < buff_count; l++)
|
||||
{
|
||||
if (buffs[l].spellid != SPELL_UNKNOWN)
|
||||
{
|
||||
for (int k = 0; k < EFFECT_COUNT; k++)
|
||||
{
|
||||
if (spells[buffs[l].spellid].effectid[k] == SE_DivineAura)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (spellbonuses.DivineAura)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3156,7 +3145,7 @@ void Mob::TriggerOnCast(uint32 focus_spell, uint32 spell_id, bool aa_trigger)
|
||||
|
||||
if(IsValidSpell(trigger_spell_id) && GetTarget()){
|
||||
SpellFinished(trigger_spell_id, GetTarget(),10, 0, -1, spells[trigger_spell_id].ResistDiff);
|
||||
CheckHitsRemaining(0, false,false, 0, focus_spell);
|
||||
CheckNumHitsRemaining(7,0, focus_spell);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3361,7 +3350,7 @@ int32 Mob::GetVulnerability(int32 damage, Mob *caster, uint32 spell_id, uint32 t
|
||||
|
||||
//Apply spell derived vulnerabilities
|
||||
if (spellbonuses.FocusEffects[focusSpellVulnerability]){
|
||||
|
||||
|
||||
int32 tmp_focus = 0;
|
||||
int tmp_buffslot = -1;
|
||||
|
||||
@ -3394,7 +3383,7 @@ int32 Mob::GetVulnerability(int32 damage, Mob *caster, uint32 spell_id, uint32 t
|
||||
damage += damage * tmp_focus / 100;
|
||||
|
||||
if (tmp_buffslot >= 0)
|
||||
CheckHitsRemaining(tmp_buffslot);
|
||||
CheckNumHitsRemaining(7, tmp_buffslot);
|
||||
}
|
||||
return damage;
|
||||
}
|
||||
@ -3402,7 +3391,7 @@ int32 Mob::GetVulnerability(int32 damage, Mob *caster, uint32 spell_id, uint32 t
|
||||
int16 Mob::GetSkillDmgTaken(const SkillUseTypes skill_used)
|
||||
{
|
||||
int skilldmg_mod = 0;
|
||||
|
||||
|
||||
// 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];
|
||||
@ -3414,8 +3403,7 @@ int16 Mob::GetSkillDmgTaken(const SkillUseTypes skill_used)
|
||||
if(skilldmg_mod < -100)
|
||||
skilldmg_mod = -100;
|
||||
|
||||
if (spellbonuses.SkillDmgTaken[HIGHEST_SKILL+1] || spellbonuses.SkillDmgTaken[skill_used])
|
||||
CheckHitsRemaining(0, false,false, SE_SkillDamageTaken,0,true,skill_used);
|
||||
CheckNumHitsRemaining(6);
|
||||
|
||||
return skilldmg_mod;
|
||||
}
|
||||
@ -3458,7 +3446,7 @@ 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_TriggerMeleeThreshold || spells[buffs[slot].spellid].effectid[i] == SE_TriggerSpellThreshold)
|
||||
{
|
||||
uint16 spell_id = spells[buffs[slot].spellid].base[i];
|
||||
BuffFadeBySlot(slot);
|
||||
@ -3515,7 +3503,8 @@ void Mob::TrySympatheticProc(Mob *target, uint32 spell_id)
|
||||
else
|
||||
SpellFinished(focus_trigger, target, 10, 0, -1, spells[focus_trigger].ResistDiff);
|
||||
}
|
||||
CheckHitsRemaining(0, false,false, 0, focus_spell);
|
||||
|
||||
CheckNumHitsRemaining(7, 0, focus_spell);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4289,9 +4278,6 @@ int16 Mob::GetMeleeDamageMod_SE(uint16 skill)
|
||||
if(dmg_mod < -100)
|
||||
dmg_mod = -100;
|
||||
|
||||
if (spellbonuses.DamageModifier[HIGHEST_SKILL+1] || spellbonuses.DamageModifier[skill])
|
||||
CheckHitsRemaining(0, false, false, SE_DamageModifier,0,true,skill);
|
||||
|
||||
return dmg_mod;
|
||||
}
|
||||
|
||||
@ -4338,13 +4324,8 @@ int16 Mob::GetSkillDmgAmt(uint16 skill)
|
||||
skill_dmg += spellbonuses.SkillDamageAmount2[HIGHEST_SKILL+1] + itembonuses.SkillDamageAmount2[HIGHEST_SKILL+1]
|
||||
+ itembonuses.SkillDamageAmount2[skill] + spellbonuses.SkillDamageAmount2[skill];
|
||||
|
||||
// Deplete the buff if needed
|
||||
if (spellbonuses.SkillDamageAmount[HIGHEST_SKILL+1] || spellbonuses.SkillDamageAmount[skill])
|
||||
CheckHitsRemaining(0, false,false, SE_SkillDamageAmount,0,true,skill);
|
||||
|
||||
if (spellbonuses.SkillDamageAmount2[HIGHEST_SKILL+1] || spellbonuses.SkillDamageAmount2[skill])
|
||||
CheckHitsRemaining(0, false,false, SE_SkillDamageAmount2,0,true,skill);
|
||||
|
||||
CheckNumHitsRemaining(5);
|
||||
|
||||
return skill_dmg;
|
||||
}
|
||||
|
||||
@ -4352,10 +4333,7 @@ bool Mob::TryReflectSpell(uint32 spell_id)
|
||||
{
|
||||
if(!GetTarget())
|
||||
return false;
|
||||
|
||||
if(GetTarget()->spellbonuses.reflect_chance)
|
||||
CheckHitsRemaining(0, false, false, SE_Reflect);
|
||||
|
||||
|
||||
if(MakeRandomInt(0, 99) < (GetTarget()->itembonuses.reflect_chance + GetTarget()->spellbonuses.reflect_chance))
|
||||
return true;
|
||||
|
||||
@ -4583,8 +4561,6 @@ void Mob::CastOnNumHitFade(uint32 spell_id)
|
||||
if(!IsValidSpell(spell_id))
|
||||
return;
|
||||
|
||||
uint32 buff_max = GetMaxTotalSlots();
|
||||
|
||||
for(int i = 0; i < EFFECT_COUNT; i++)
|
||||
{
|
||||
if (spells[spell_id].effectid[i] == SE_CastonNumHitFade)
|
||||
|
||||
@ -251,8 +251,9 @@ public:
|
||||
int16 GetBuffSlotFromType(uint16 type);
|
||||
uint16 GetSpellIDFromSlot(uint8 slot);
|
||||
int CountDispellableBuffs();
|
||||
bool CheckHitsRemaining(uint32 buff_slot, bool when_spell_done=false, bool negate=false,uint16 type=0,
|
||||
uint16 spell_id=0, bool use_skill=false,uint16 skill=0);
|
||||
void CheckNumHitsRemaining(uint8 type, uint32 buff_slot=0, uint16 spell_id=SPELL_UNKNOWN);
|
||||
bool HasNumhits() const { return has_numhits; }
|
||||
inline void Numhits(bool val) { has_numhits = val; }
|
||||
void SpreadVirus(uint16 spell_id, uint16 casterID);
|
||||
bool IsNimbusEffectActive(uint32 nimbus_effect);
|
||||
void SetNimbusEffect(uint32 nimbus_effect);
|
||||
@ -656,6 +657,7 @@ public:
|
||||
|
||||
int32 ReduceDamage(int32 damage);
|
||||
int32 AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTic, Mob* attacker);
|
||||
int32 ReduceAllDamage(int32 damage);
|
||||
|
||||
virtual void DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool HitChance=false);
|
||||
virtual void DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const Item_Struct* item=nullptr, uint16 weapon_damage=0, int16 chance_mod=0,int16 focus=0);
|
||||
@ -1055,6 +1057,7 @@ protected:
|
||||
int16 rooted_mod; //Modifier to root break chance, defined when root is cast on a target.
|
||||
bool offhand;
|
||||
bool has_shieldequiped;
|
||||
bool has_numhits;
|
||||
|
||||
// Bind wound
|
||||
Timer bindwound_timer;
|
||||
|
||||
@ -183,6 +183,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
numhit += caster->CastToClient()->GetFocusEffect(focusIncreaseNumHits, spell_id);
|
||||
}
|
||||
|
||||
Numhits(true);
|
||||
buffs[buffslot].numhits = numhit;
|
||||
}
|
||||
|
||||
@ -3881,6 +3882,25 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses)
|
||||
}
|
||||
}
|
||||
|
||||
if (HasNumhits()){
|
||||
|
||||
uint32 buff_max = GetMaxTotalSlots();
|
||||
bool found_numhits = false;
|
||||
|
||||
for(uint32 d = 0; d < buff_max; d++) {
|
||||
|
||||
if(IsValidSpell(buffs[d].spellid) && (buffs[d].numhits > 0)) {
|
||||
Numhits(true);
|
||||
found_numhits = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_numhits)
|
||||
Numhits(false);
|
||||
}
|
||||
|
||||
Numhits(false);
|
||||
|
||||
buffs[slot].spellid = SPELL_UNKNOWN;
|
||||
if(IsPet() && GetOwner() && GetOwner()->IsClient()) {
|
||||
SendPetBuffsToClient();
|
||||
@ -5274,123 +5294,91 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) {
|
||||
return realTotal + realTotal2 + realTotal3;
|
||||
}
|
||||
|
||||
bool Mob::CheckHitsRemaining(uint32 buff_slot, bool when_spell_done, bool negate, uint16 type, uint16 spell_id,bool use_skill,uint16 skill)
|
||||
void Mob::CheckNumHitsRemaining(uint8 type, uint32 buff_slot, uint16 spell_id)
|
||||
{
|
||||
|
||||
/*
|
||||
TO DO: Rewrite code so it checks for numhits by type not after each specified spell effect is triggered...
|
||||
Field 175 = numhits type
|
||||
1: [Incoming Hit Attempts] (323=SE_DefensiveProc, 172=SE_AvoidMeleeChance, 1=SE_ArmorClass, 40=SE_DivineAura)
|
||||
2: [Outgoing Hit Attempts] (184=SE_DamageModifer, 185=SE_HitChance)
|
||||
3: [Incoming Spells] (180=SE_ResistSpellChance, 296=SE_SpellVulnerability)
|
||||
2: [Outgoing Hit Attempts] (185=SE_DamageModifer, 184=SE_HitChance)
|
||||
3: [Incoming Spells] (180=SE_ResistSpellChance, 296=SE_SpellVulnerability) //Note: Determinetal spells only unless proven otherwise
|
||||
4: NONE
|
||||
5: [Outgoing Hit Successes] (196=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_CastOnWearoff)
|
||||
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)
|
||||
9: [Reflected Spells]
|
||||
10: [Defensive Procs]
|
||||
11: [Melee Procs]
|
||||
9: [Reflected Spells] If successful
|
||||
10: [Defensive Procs] Only count down buff of the proc that executed
|
||||
11: [Melee Procs] Only count down the buff of the proc that executed
|
||||
*/
|
||||
|
||||
if (!HasNumhits())
|
||||
return;
|
||||
|
||||
bool bDepleted = false;
|
||||
//Effects: Cast: SE_ResistSpellChance, SE_Reflect, SE_SpellDamageShield
|
||||
//Effects: Attack: SE_MeleeLifetap : SE_DamageShield, SE_AvoidMeleeChance, SE_SkillProc
|
||||
//Effects: Skill: SE_DamageModifier, SE_SkillDamageTaken, SE_SkillDamageAmount, SE_HitChance
|
||||
//For spell buffs that are limited typically when you are attacked or are subject to an attack/cast and we do not know the buff slot.
|
||||
if (type){
|
||||
uint32 buff_max = GetMaxTotalSlots();
|
||||
uint32 buff_max = GetMaxTotalSlots();
|
||||
|
||||
//Spell specific procs [Type 7,10,11]
|
||||
if (IsValidSpell(spell_id)){
|
||||
|
||||
for(uint32 d = 0; d < buff_max; d++) {
|
||||
if((buffs[d].spellid != SPELL_UNKNOWN) && (buffs[d].numhits > 0) && IsEffectInSpell(buffs[d].spellid, type)){
|
||||
if (!use_skill){
|
||||
if(--buffs[d].numhits == 0) {
|
||||
if(!TryFadeEffect(d)){
|
||||
CastOnNumHitFade(buffs[d].spellid);
|
||||
BuffFadeBySlot(d, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
bDepleted = false;
|
||||
for (int j = 0; j < EFFECT_COUNT; j++) {
|
||||
if (bDepleted)
|
||||
continue;
|
||||
if ((buffs[d].spellid != SPELL_UNKNOWN) && (spells[buffs[d].spellid].effectid[j] == type)) {
|
||||
if(spells[buffs[d].spellid].base2[j] == -1 || spells[buffs[d].spellid].base2[j] == skill) {
|
||||
bDepleted = true;
|
||||
if(--buffs[d].numhits == 0) {
|
||||
if(!TryFadeEffect(d)){
|
||||
CastOnNumHitFade(buffs[d].spellid);
|
||||
BuffFadeBySlot(d, true);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if((buffs[d].spellid == spell_id) && (buffs[d].numhits > 0) && (spells[buffs[d].spellid].numhitstype == type)){
|
||||
|
||||
// For spell buffs that are limited by the number of times it can successfully trigger a spell.
|
||||
// Effects: SE_TriggerOnCast, SE_SympatheticProc,SE_DefensiveProc, SE_SkillProc, SE_RangedProc
|
||||
if(spell_id){
|
||||
uint32 buff_count = GetMaxTotalSlots();
|
||||
for(uint32 d = 0; d < buff_count; d++){
|
||||
if((buffs[d].spellid != SPELL_UNKNOWN) && (buffs[d].numhits > 0) && buffs[d].spellid == spell_id){
|
||||
if(--buffs[d].numhits == 0) {
|
||||
if(!TryFadeEffect(d)){
|
||||
CastOnNumHitFade(buffs[d].spellid);
|
||||
BuffFadeBySlot(d, true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// For focusTypes that limit the number of spell casts it will effect.
|
||||
// Effect: Focus effects ie SE_ImprovedDamage ect
|
||||
if(when_spell_done) {
|
||||
uint32 buff_max = GetMaxTotalSlots();
|
||||
// Go through all possible saved spells with limited hits, the place in the array is the same as the buff slot
|
||||
for(int d = 0; d < buff_max; d++) {
|
||||
if(!m_spellHitsLeft[d])
|
||||
continue;
|
||||
// Double check to make sure the saved spell matches the buff in that slot
|
||||
if (m_spellHitsLeft[d] == buffs[d].spellid) {
|
||||
if(buffs[d].numhits > 1) {
|
||||
buffs[d].numhits--;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
CastOnNumHitFade(buffs[d].spellid);
|
||||
if(!TryFadeEffect(d))
|
||||
BuffFadeBySlot(d, true);
|
||||
CastOnNumHitFade(m_spellHitsLeft[d]);
|
||||
m_spellHitsLeft[d] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// For lowering numhits when we already know the effects buff_slot
|
||||
// Effects: SE_SpellVulnerability,SE_MitigateMeleeDamage,SE_MitigateMeleeDamage2,SE_NegateAttacks,SE_MitigateSpellDamage,SE_ManaAbsorbPercentDamage
|
||||
if(spells[buffs[buff_slot].spellid].numhits > 0 || negate) {
|
||||
if(buffs[buff_slot].numhits > 1) {
|
||||
buffs[buff_slot].numhits--;
|
||||
return true;
|
||||
}
|
||||
else if(!TryFadeEffect(buff_slot)) {
|
||||
CastOnNumHitFade(buffs[buff_slot].spellid);
|
||||
BuffFadeBySlot(buff_slot, true);
|
||||
return false;
|
||||
else if (type == 7){
|
||||
if (buff_slot > 0){
|
||||
|
||||
if(--buffs[buff_slot].numhits == 0) {
|
||||
CastOnNumHitFade(buffs[buff_slot].spellid);
|
||||
if(!TryFadeEffect(buff_slot))
|
||||
BuffFadeBySlot(buff_slot , true);
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
|
||||
for(int d = 0; d < buff_max; d++) {
|
||||
|
||||
if(!m_spellHitsLeft[d])
|
||||
continue;
|
||||
|
||||
if ((IsValidSpell(buffs[d].spellid)) && (m_spellHitsLeft[d] == buffs[d].spellid)) {
|
||||
if(--buffs[d].numhits == 0) {
|
||||
CastOnNumHitFade(buffs[d].spellid);
|
||||
m_spellHitsLeft[d] = 0;
|
||||
if(!TryFadeEffect(d))
|
||||
BuffFadeBySlot(d, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
else{
|
||||
|
||||
for(uint32 d = 0; d < buff_max; d++) {
|
||||
|
||||
if((IsValidSpell(buffs[d].spellid)) && (buffs[d].numhits > 0) && (spells[buffs[d].spellid].numhitstype == type)){
|
||||
|
||||
if(--buffs[d].numhits == 0) {
|
||||
CastOnNumHitFade(buffs[d].spellid);
|
||||
if(!TryFadeEffect(d)){
|
||||
BuffFadeBySlot(d, true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//for some stupid reason SK procs return theirs one base off...
|
||||
@ -5627,7 +5615,7 @@ int32 Mob::GetAdditionalDamage(Mob *caster, uint32 spell_id, bool use_skill, uin
|
||||
}
|
||||
if ((!limit_exists) || (limit_exists && skill_found)){
|
||||
dmg += temp_dmg;
|
||||
CheckHitsRemaining(i);
|
||||
CheckNumHitsRemaining(7,i);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5635,7 +5623,7 @@ int32 Mob::GetAdditionalDamage(Mob *caster, uint32 spell_id, bool use_skill, uin
|
||||
int32 focus = caster->CalcFocusEffect(focusAdditionalDamage, buffs[i].spellid, spell_id);
|
||||
if(focus){
|
||||
dmg += focus;
|
||||
CheckHitsRemaining(i);
|
||||
CheckNumHitsRemaining(7,i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1234,16 +1234,9 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot,
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(IsClient()) {
|
||||
uint32 buff_max = GetMaxTotalSlots();
|
||||
for (int buffSlot = 0; buffSlot < buff_max; buffSlot++) {
|
||||
if (buffs[buffSlot].spellid == 0 || buffs[buffSlot].spellid >= SPDAT_RECORDS)
|
||||
continue;
|
||||
|
||||
if(spells[buffs[buffSlot].spellid].numhits > 0)
|
||||
CheckHitsRemaining(buffSlot, true);
|
||||
}
|
||||
|
||||
if(IsClient()) {
|
||||
CheckNumHitsRemaining(7);
|
||||
TrySympatheticProc(target, spell_id);
|
||||
}
|
||||
|
||||
@ -3369,7 +3362,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r
|
||||
if(IsEffectInSpell(buffs[b].spellid, SE_BlockNextSpellFocus)) {
|
||||
focus = CalcFocusEffect(focusBlockNextSpell, buffs[b].spellid, spell_id);
|
||||
if(focus) {
|
||||
CheckHitsRemaining(b);
|
||||
CheckNumHitsRemaining(7,b);
|
||||
Message_StringID(MT_SpellFailure, SPELL_WOULDNT_HOLD);
|
||||
safe_delete(action_packet);
|
||||
return false;
|
||||
@ -3418,12 +3411,16 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r
|
||||
}
|
||||
if(reflect_chance) {
|
||||
Message_StringID(MT_Spells, SPELL_REFLECT, GetCleanName(), spelltar->GetCleanName());
|
||||
CheckNumHitsRemaining(9);
|
||||
SpellOnTarget(spell_id, this, true, use_resist_adjust, resist_adjust);
|
||||
safe_delete(action_packet);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (spelltar && IsDetrimentalSpell(spell_id))
|
||||
spelltar->CheckNumHitsRemaining(3);
|
||||
|
||||
// resist check - every spell can be resisted, beneficial or not
|
||||
// add: ok this isn't true, eqlive's spell data is fucked up, buffs are
|
||||
// not all unresistable, so changing this to only check certain spells
|
||||
@ -3563,14 +3560,12 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r
|
||||
}
|
||||
}
|
||||
|
||||
if(spelltar->spellbonuses.SpellDamageShield && IsDetrimentalSpell(spell_id)){
|
||||
spelltar->DamageShield(this, true);
|
||||
spelltar->CheckHitsRemaining(0, false, false, SE_DamageShield);
|
||||
}
|
||||
if(spelltar->spellbonuses.SpellDamageShield && IsDetrimentalSpell(spell_id))
|
||||
spelltar->DamageShield(this, true);
|
||||
|
||||
TrySpellTrigger(spelltar, spell_id);
|
||||
TryApplyEffect(spelltar, spell_id);
|
||||
|
||||
|
||||
if (spelltar->IsAIControlled() && IsDetrimentalSpell(spell_id) && !IsHarmonySpell(spell_id)) {
|
||||
int32 aggro_amount = CheckAggroAmount(spell_id, isproc);
|
||||
mlog(SPELLS__CASTING, "Spell %d cast on %s generated %d hate", spell_id, spelltar->GetName(), aggro_amount);
|
||||
@ -4343,9 +4338,6 @@ int16 Mob::CalcResistChanceBonus()
|
||||
if(IsClient())
|
||||
resistchance += aabonuses.ResistSpellChance;
|
||||
|
||||
if (spellbonuses.ResistSpellChance)
|
||||
CheckHitsRemaining(0, false, false, SE_ResistSpellChance);
|
||||
|
||||
return resistchance;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user