From 1deef77f07954b449f75094a00a5a3d926ec7791 Mon Sep 17 00:00:00 2001 From: Leere Date: Sat, 9 Nov 2013 04:56:57 +0100 Subject: [PATCH 01/25] Fix for bard mana regen --- changelog.txt | 2 ++ zone/bonuses.cpp | 1 + zone/spell_effects.cpp | 6 ++++++ 3 files changed, 9 insertions(+) diff --git a/changelog.txt b/changelog.txt index f72280c13..a99bec7d0 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 11/09/2013 == +Leere: Fixed Bard mana regen, they now only are affected by items and AA. == 11/07/2013 == KLS: Added a system to use the BaseData system in the client. diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 18ad2dc8f..3c3788a74 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1188,6 +1188,7 @@ void Mob::CalcSpellBonuses(StatBonuses* newbon) } //this prolly suffer from roundoff error slightly... newbon->AC = newbon->AC * 10 / 34; //ratio determined impirically from client. + if (GetClass() == BARD) newbon->ManaRegen = 0; // Bards do not get mana regen from spells. } void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* newbon, uint16 casterId, bool item_bonus, uint32 ticsremaining, int buffslot) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index acd041f05..2f0ffe1a0 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -325,6 +325,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) case SE_CurrentMana: { + // Bards don't get mana from effects, good or bad. + if(GetClass() == BARD) + break; if(IsManaTapSpell(spell_id)) { if(GetCasterClass() != 'N') { #ifdef SPELL_EFFECT_SPAM @@ -352,6 +355,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) case SE_CurrentManaOnce: { + // Bards don't get mana from effects, good or bad. + if(GetClass() == BARD) + break; #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Current Mana Once: %+i", effect_value); #endif From 2be71fc2ec6dece1da8d38a0cac04b8d78533c56 Mon Sep 17 00:00:00 2001 From: Michael Cook Date: Sun, 10 Nov 2013 21:37:01 -0500 Subject: [PATCH 02/25] Cleaned up common/spdat.cpp There was a lot of stuff that I found that the level of readability. I cleaned up a lot of the stuff, no functionality should be changed unless where noted below. * IsPartialDeathSaveSpell is now generic and no longer uses a hardcoded spell id * IsFullDeathSaveSpell is now generic and no longer uses a hardcoded spell id If these functions were actually used in the spell effects it would probably fix issues with newer spells (which there are on live) --- common/spdat.cpp | 897 ++++++++++++++++++++++------------------------- 1 file changed, 420 insertions(+), 477 deletions(-) diff --git a/common/spdat.cpp b/common/spdat.cpp index 437fd88c7..f43b77a9b 100644 --- a/common/spdat.cpp +++ b/common/spdat.cpp @@ -70,8 +70,6 @@ */ - - #include "debug.h" #include "spdat.h" #include "packet_dump.h" @@ -89,14 +87,12 @@ /////////////////////////////////////////////////////////////////////////////// // spell property testing functions -bool IsTargetableAESpell(uint16 spell_id) { - bool bResult = false; +bool IsTargetableAESpell(uint16 spell_id) +{ + if (IsValidSpell(spell_id) && spells[spell_id].targettype == ST_AETarget) + return true; - if (IsValidSpell(spell_id) && spells[spell_id].targettype == ST_AETarget) { - bResult = true; - } - - return bResult; + return false; } bool IsSacrificeSpell(uint16 spell_id) @@ -106,16 +102,12 @@ bool IsSacrificeSpell(uint16 spell_id) bool IsLifetapSpell(uint16 spell_id) { - return - ( - IsValidSpell(spell_id) && - ( - spells[spell_id].targettype == ST_Tap || - ( - spell_id == 2115 // Ancient: Lifebane - ) - ) - ); + // Ancient Lifebane: 2115 + if (IsValidSpell(spell_id) && + (spells[spell_id].targettype == ST_Tap || spell_id == 2115)) + return true; + + return false; } bool IsMezSpell(uint16 spell_id) @@ -128,63 +120,60 @@ bool IsStunSpell(uint16 spell_id) return IsEffectInSpell(spell_id, SE_Stun); } -bool IsSummonSpell(uint16 spellid) { - for (int o = 0; o < EFFECT_COUNT; o++) - { +bool IsSummonSpell(uint16 spellid) +{ + for (int o = 0; o < EFFECT_COUNT; o++) { uint32 tid = spells[spellid].effectid[o]; - if(tid == SE_SummonPet || tid == SE_SummonItem || tid == SE_SummonPC) - { + if (tid == SE_SummonPet || tid == SE_SummonItem || tid == SE_SummonPC) return true; - } } + return false; } -bool IsEvacSpell(uint16 spellid) { +bool IsEvacSpell(uint16 spellid) +{ return IsEffectInSpell(spellid, SE_Succor); } -bool IsDamageSpell(uint16 spellid) { - for (int o = 0; o < EFFECT_COUNT; o++) - { +bool IsDamageSpell(uint16 spellid) +{ + for (int o = 0; o < EFFECT_COUNT; o++) { uint32 tid = spells[spellid].effectid[o]; - if((tid == SE_CurrentHPOnce || tid == SE_CurrentHP) && spells[spellid].targettype != ST_Tap && spells[spellid].buffduration < 1 && spells[spellid].base[o] < 0) - { + if ((tid == SE_CurrentHPOnce || tid == SE_CurrentHP) && + spells[spellid].targettype != ST_Tap && spells[spellid].buffduration < 1 && + spells[spellid].base[o] < 0) return true; - } } + return false; } -bool IsFearSpell(uint16 spell_id) { +bool IsFearSpell(uint16 spell_id) +{ return IsEffectInSpell(spell_id, SE_Fear); } bool IsSlowSpell(uint16 spell_id) { - int i; const SPDat_Spell_Struct &sp = spells[spell_id]; - for(i = 0; i < EFFECT_COUNT; i++) - { - if ((sp.effectid[i] == SE_AttackSpeed && sp.base[i] < 100) || (sp.effectid[i] == SE_AttackSpeed4)) - return true; - } + for(int i = 0; i < EFFECT_COUNT; i++) + if ((sp.effectid[i] == SE_AttackSpeed && sp.base[i] < 100) || + (sp.effectid[i] == SE_AttackSpeed4)) + return true; return false; } bool IsHasteSpell(uint16 spell_id) { - int i; const SPDat_Spell_Struct &sp = spells[spell_id]; - for(i = 0; i < EFFECT_COUNT; i++) - { + for(int i = 0; i < EFFECT_COUNT; i++) if(sp.effectid[i] == SE_AttackSpeed) - return(sp.base[i] < 100); - } + return (sp.base[i] < 100); return false; } @@ -207,27 +196,41 @@ bool IsGroupOnlySpell(uint16 spell_id) bool IsBeneficialSpell(uint16 spell_id) { - if(!IsValidSpell(spell_id)) + if (!IsValidSpell(spell_id)) return false; - if(spells[spell_id].goodEffect == 1){ + // You'd think just checking goodEffect flag would be enough? + if (spells[spell_id].goodEffect == 1) { + // If the target type is ST_Self or ST_Pet and is a SE_CancleMagic spell + // it is not Beneficial SpellTargetType tt = spells[spell_id].targettype; - if(tt != ST_Self && tt != ST_Pet){ - if(IsEffectInSpell(spell_id, SE_CancelMagic)) - return false; - } - if(tt == ST_Target || tt == ST_AETarget || tt == ST_Animal || tt == ST_Undead || tt == ST_Pet) { + if (tt != ST_Self && tt != ST_Pet && + IsEffectInSpell(spell_id, SE_CancelMagic)) + return false; + + // When our targettype is ST_Target, ST_AETarget, ST_Aniaml, ST_Undead, or ST_Pet + // We need to check more things! + if (tt == ST_Target || tt == ST_AETarget || tt == ST_Animal || + tt == ST_Undead || tt == ST_Pet) { uint16 sai = spells[spell_id].SpellAffectIndex; - if(spells[spell_id].resisttype == RESIST_MAGIC){ - if(sai == SAI_Calm || sai == SAI_Dispell_Sight || sai == SAI_Memory_Blur || sai == SAI_Calm_Song) + + // If the resisttype is magic and SpellAffectIndex is Calm/memblur/dispell sight + // it's not beneficial + if (spells[spell_id].resisttype == RESIST_MAGIC) { + if (sai == SAI_Calm || sai == SAI_Dispell_Sight || + sai == SAI_Memory_Blur || sai == SAI_Calm_Song) return false; - }else{ - // Bind Sight and Cast Sight - if(sai == SAI_Dispell_Sight && spells[spell_id].skill == 18 && !IsEffectInSpell(spell_id, SE_VoiceGraft)) + } else { + // If the resisttype is not magic and spell is Bind Sight or Cast Sight + // It's not beneficial + if (sai == SAI_Dispell_Sight && spells[spell_id].skill == 18 && + !IsEffectInSpell(spell_id, SE_VoiceGraft)) return false; } } } + + // And finally, if goodEffect is not 0 or if it's a group spell it's beneficial return spells[spell_id].goodEffect != 0 || IsGroupSpell(spell_id); } @@ -268,11 +271,11 @@ bool IsSummonSkeletonSpell(uint16 spell_id) bool IsSummonPetSpell(uint16 spell_id) { - return - ( - IsEffectInSpell(spell_id, SE_SummonPet) || - IsEffectInSpell(spell_id, SE_SummonBSTPet) - ); + if (IsEffectInSpell(spell_id, SE_SummonPet) || + IsEffectInSpell(spell_id, SE_SummonBSTPet)) + return true; + + return false; } bool IsSummonPCSpell(uint16 spell_id) @@ -327,125 +330,125 @@ bool IsImprovedDamageSpell(uint16 spell_id) bool IsAEDurationSpell(uint16 spell_id) { - return IsValidSpell(spell_id) && - (spells[spell_id].targettype == ST_AETarget || spells[spell_id].targettype == ST_UndeadAE ) - && spells[spell_id].AEDuration !=0; + if (IsValidSpell(spell_id) && + (spells[spell_id].targettype == ST_AETarget || spells[spell_id].targettype == ST_UndeadAE) && + spells[spell_id].AEDuration != 0) + return true; + + return false; } bool IsPureNukeSpell(uint16 spell_id) { int i, effect_count = 0; - if(!IsValidSpell(spell_id)) + if (!IsValidSpell(spell_id)) return false; - for(i = 0; i < EFFECT_COUNT; i++) - { - if(!IsBlankSpellEffect(spell_id, i)) + for (i = 0; i < EFFECT_COUNT; i++) + if (!IsBlankSpellEffect(spell_id, i)) effect_count++; - } - return - ( - effect_count == 1 && IsEffectInSpell(spell_id, SE_CurrentHP) && - spells[spell_id].buffduration == 0 && IsDamageSpell(spell_id) - ); + if (effect_count == 1 && IsEffectInSpell(spell_id, SE_CurrentHP) && + spells[spell_id].buffduration == 0 && IsDamageSpell(spell_id)) + return true; + + return false; } bool IsAENukeSpell(uint16 spell_id) { - return IsValidSpell(spell_id) && IsPureNukeSpell(spell_id) && spells[spell_id].aoerange > 0; + if (IsValidSpell(spell_id) && IsPureNukeSpell(spell_id) && + spells[spell_id].aoerange > 0) + return true; + + return false; } bool IsPBAENukeSpell(uint16 spell_id) { - return IsValidSpell(spell_id) && IsPureNukeSpell(spell_id) && spells[spell_id].aoerange > 0 && spells[spell_id].targettype == ST_AECaster; + if (IsValidSpell(spell_id) && IsPureNukeSpell(spell_id) && + spells[spell_id].aoerange > 0 && spells[spell_id].targettype == ST_AECaster) + return true; + + return false; } bool IsAERainNukeSpell(uint16 spell_id) { - return IsValidSpell(spell_id) && IsPureNukeSpell(spell_id) - && spells[spell_id].aoerange > 0 && spells[spell_id].AEDuration > 1000; + if (IsValidSpell(spell_id) && IsPureNukeSpell(spell_id) && + spells[spell_id].aoerange > 0 && spells[spell_id].AEDuration > 1000) + return true; + + return false; } bool IsPartialCapableSpell(uint16 spell_id) { - if(IsPureNukeSpell(spell_id) || - IsFearSpell(spell_id) || - IsEffectInSpell(spell_id, SE_Root) || - IsEffectInSpell(spell_id, SE_Charm)) - { + if (IsPureNukeSpell(spell_id) || IsFearSpell(spell_id) || + IsEffectInSpell(spell_id, SE_Root) || + IsEffectInSpell(spell_id, SE_Charm)) return true; - } return false; } bool IsResistableSpell(uint16 spell_id) { - // solar: for now only detrimental spells are resistable. later on i will + // for now only detrimental spells are resistable. later on i will // add specific exceptions for the beneficial spells that are resistable - if(IsDetrimentalSpell(spell_id)) - { + if (IsDetrimentalSpell(spell_id)) return true; - } return false; } -// solar: checks if this spell affects your group +// checks if this spell affects your group bool IsGroupSpell(uint16 spell_id) { - return - ( - IsValidSpell(spell_id) && - ( - spells[spell_id].targettype == ST_AEBard || - spells[spell_id].targettype == ST_Group || - spells[spell_id].targettype == ST_GroupTeleport - ) - ); + if (IsValidSpell(spell_id) && + (spells[spell_id].targettype == ST_AEBard || + spells[spell_id].targettype == ST_Group || + spells[spell_id].targettype == ST_GroupTeleport)) + return true; + + return false; } -// solar: checks if this spell can be targeted +// checks if this spell can be targeted bool IsTGBCompatibleSpell(uint16 spell_id) { - return - ( - IsValidSpell(spell_id) && - ( - !IsDetrimentalSpell(spell_id) && - spells[spell_id].buffduration != 0 && - !IsBardSong(spell_id) && - !IsEffectInSpell(spell_id, SE_Illusion) - ) - ); + if (IsValidSpell(spell_id) && + (!IsDetrimentalSpell(spell_id) && spells[spell_id].buffduration != 0 && + !IsBardSong(spell_id) && !IsEffectInSpell(spell_id, SE_Illusion))) + return true; + + return false; } bool IsBardSong(uint16 spell_id) { - return - ( - IsValidSpell(spell_id) && - spells[spell_id].classes[BARD - 1] < 255 - ); + if (IsValidSpell(spell_id) && spells[spell_id].classes[BARD - 1] < 255) + return true; + + return false; } bool IsEffectInSpell(uint16 spellid, int effect) { int j; - if(!IsValidSpell(spellid)) + if (!IsValidSpell(spellid)) return false; - for(j = 0; j < EFFECT_COUNT; j++) - if(spells[spellid].effectid[j] == effect) + for (j = 0; j < EFFECT_COUNT; j++) + if (spells[spellid].effectid[j] == effect) return true; return false; } -// solar: arguments are spell id and the index of the effect to check. +// arguments are spell id and the index of the effect to check. // this is used in loops that process effects inside a spell to skip // the blanks bool IsBlankSpellEffect(uint16 spellid, int effect_index) @@ -456,209 +459,187 @@ bool IsBlankSpellEffect(uint16 spellid, int effect_index) base = spells[spellid].base[effect_index]; formula = spells[spellid].formula[effect_index]; - return - ( - effect == SE_Blank || // blank marker - ( // spacer - effect == SE_CHA && - base == 0 && - formula == 100 - ) - || - effect == SE_StackingCommand_Block || // these are only used by stacking code - effect == SE_StackingCommand_Overwrite - ); + // SE_CHA is "spacer" + // SE_Stacking* are also considered blank where this is used + if (effect == SE_Blank || (effect == SE_CHA && base == 0 && formula == 100) || + effect == SE_StackingCommand_Block || effect == SE_StackingCommand_Overwrite) + return true; + + return false; } -// solar: checks some things about a spell id, to see if we can proceed +// checks some things about a spell id, to see if we can proceed bool IsValidSpell(uint32 spellid) { - return - ( - SPDAT_RECORDS > 0 && - spellid != 0 && - spellid != 1 && - spellid != 0xFFFFFFFF && - spellid < SPDAT_RECORDS && - spells[spellid].player_1[0] - ); + if (SPDAT_RECORDS > 0 && spellid != 0 && spellid != 1 && + spellid != 0xFFFFFFFF && spellid < SPDAT_RECORDS && spells[spellid].player_1[0]) + return true; + + return false; } -//returns the lowest level of any caster which can use the spell -int GetMinLevel(uint16 spell_id) { - int r; - int min = 255; +// returns the lowest level of any caster which can use the spell +int GetMinLevel(uint16 spell_id) +{ + int r, min = 255; const SPDat_Spell_Struct &spell = spells[spell_id]; - for(r = 0; r < PLAYER_CLASS_COUNT; r++) { - if(spell.classes[r] < min) + for (r = 0; r < PLAYER_CLASS_COUNT; r++) + if (spell.classes[r] < min) min = spell.classes[r]; - } - //if we can't cast the spell return 0 - //just so it wont screw up calculations used in other areas of the code - //seen 127, 254, 255 - if(min >= 127) + // if we can't cast the spell return 0 + // just so it wont screw up calculations used in other areas of the code + // seen 127, 254, 255 + if (min >= 127) return 0; else - return(min); + return min; } -int GetSpellLevel(uint16 spell_id, int classa) { - if(classa >= PLAYER_CLASS_COUNT) { +int GetSpellLevel(uint16 spell_id, int classa) +{ + if (classa >= PLAYER_CLASS_COUNT) return 255; - } const SPDat_Spell_Struct &spell = spells[spell_id]; return spell.classes[classa - 1]; } -// solar: this will find the first occurance of effect. this is handy +// this will find the first occurrence of effect. this is handy // for spells like mez and charm, but if the effect appears more than once // in a spell this will just give back the first one. int GetSpellEffectIndex(uint16 spell_id, int effect) { int i; - if(!IsValidSpell(spell_id)) + if (!IsValidSpell(spell_id)) return -1; - for(i = 0; i < EFFECT_COUNT; i++) - { - if(spells[spell_id].effectid[i] == effect) + for (i = 0; i < EFFECT_COUNT; i++) + if (spells[spell_id].effectid[i] == effect) return i; - } return -1; } -// solar: returns the level required to use the spell if that class/level +// returns the level required to use the spell if that class/level // can use it, 0 otherwise // note: this isn't used by anything right now int CanUseSpell(uint16 spellid, int classa, int level) { int level_to_use; - if(!IsValidSpell(spellid) || classa >= PLAYER_CLASS_COUNT) + if (!IsValidSpell(spellid) || classa >= PLAYER_CLASS_COUNT) return 0; level_to_use = spells[spellid].classes[classa - 1]; - if - ( - level_to_use && - level_to_use != 255 && - level >= level_to_use - ) + if (level_to_use && level_to_use != 255 && level >= level_to_use) return level_to_use; return 0; } - - bool BeneficialSpell(uint16 spell_id) { if (spell_id <= 0 || spell_id >= SPDAT_RECORDS - /*|| spells[spell_id].stacking == 27*/ ) - { + /*|| spells[spell_id].stacking == 27*/ ) return true; - } - switch (spells[spell_id].goodEffect) - { + + switch (spells[spell_id].goodEffect) { case 1: case 3: return true; } + return false; } bool GroupOnlySpell(uint16 spell_id) { - switch (spells[spell_id].goodEffect) - { + switch (spells[spell_id].goodEffect) { case 2: case 3: return true; } - switch (spell_id) - { + + switch (spell_id) { case 1771: return true; } + return false; } -int32 CalculatePoisonCounters(uint16 spell_id){ - if(!IsValidSpell(spell_id)) +int32 CalculatePoisonCounters(uint16 spell_id) +{ + if (!IsValidSpell(spell_id)) return 0; int32 Counters = 0; - for(int i = 0; i < EFFECT_COUNT; i++) - { - if(spells[spell_id].effectid[i] == SE_PoisonCounter && spells[spell_id].base[i] > 0){ + for (int i = 0; i < EFFECT_COUNT; i++) + if (spells[spell_id].effectid[i] == SE_PoisonCounter && + spells[spell_id].base[i] > 0) Counters += spells[spell_id].base[i]; - } - } + return Counters; } -int32 CalculateDiseaseCounters(uint16 spell_id){ - if(!IsValidSpell(spell_id)) +int32 CalculateDiseaseCounters(uint16 spell_id) +{ + if (!IsValidSpell(spell_id)) return 0; int32 Counters = 0; - for(int i = 0; i < EFFECT_COUNT; i++) - { - if(spells[spell_id].effectid[i] == SE_DiseaseCounter && spells[spell_id].base[i] > 0){ + for (int i = 0; i < EFFECT_COUNT; i++) + if(spells[spell_id].effectid[i] == SE_DiseaseCounter && + spells[spell_id].base[i] > 0) Counters += spells[spell_id].base[i]; - } - } + return Counters; } -int32 CalculateCurseCounters(uint16 spell_id){ - if(!IsValidSpell(spell_id)) +int32 CalculateCurseCounters(uint16 spell_id) +{ + if (!IsValidSpell(spell_id)) return 0; int32 Counters = 0; - for(int i = 0; i < EFFECT_COUNT; i++) - { - if(spells[spell_id].effectid[i] == SE_CurseCounter && spells[spell_id].base[i] > 0){ + for (int i = 0; i < EFFECT_COUNT; i++) + if(spells[spell_id].effectid[i] == SE_CurseCounter && + spells[spell_id].base[i] > 0) Counters += spells[spell_id].base[i]; - } - } + return Counters; } -int32 CalculateCorruptionCounters(uint16 spell_id){ - if(!IsValidSpell(spell_id)) +int32 CalculateCorruptionCounters(uint16 spell_id) +{ + if (!IsValidSpell(spell_id)) return 0; int32 Counters = 0; - for(int i = 0; i < EFFECT_COUNT; i++) - { - if(spells[spell_id].effectid[i] == SE_CorruptionCounter && spells[spell_id].base[i] > 0){ + for (int i = 0; i < EFFECT_COUNT; i++) + if (spells[spell_id].effectid[i] == SE_CorruptionCounter && + spells[spell_id].base[i] > 0) Counters += spells[spell_id].base[i]; - } - } + return Counters; } -int32 CalculateCounters(uint16 spell_id) { +int32 CalculateCounters(uint16 spell_id) +{ int32 counter = CalculatePoisonCounters(spell_id); - if(counter != 0) { + if (counter != 0) return counter; - } counter = CalculateDiseaseCounters(spell_id); - if(counter != 0) { + if (counter != 0) return counter; - } counter = CalculateCurseCounters(spell_id); - if(counter != 0) { + if (counter != 0) return counter; - } counter = CalculateCorruptionCounters(spell_id); return counter; @@ -666,192 +647,174 @@ int32 CalculateCounters(uint16 spell_id) { bool IsDisciplineBuff(uint16 spell_id) { - if(!IsValidSpell(spell_id)) + if (!IsValidSpell(spell_id)) return false; - if(spells[spell_id].mana == 0 - && spells[spell_id].short_buff_box == 0 - && (spells[spell_id].EndurCost || spells[spell_id].EndurUpkeep) - && spells[spell_id].targettype == ST_Self) - { + if (spells[spell_id].mana == 0 && spells[spell_id].short_buff_box == 0 && + (spells[spell_id].EndurCost || spells[spell_id].EndurUpkeep) && + spells[spell_id].targettype == ST_Self) return true; - } + return false; } bool IsDiscipline(uint16 spell_id) { - if(!IsValidSpell(spell_id)) + if (!IsValidSpell(spell_id)) return false; - if(spells[spell_id].mana == 0 && (spells[spell_id].EndurCost || spells[spell_id].EndurUpkeep)) - { + if (spells[spell_id].mana == 0 && + (spells[spell_id].EndurCost || spells[spell_id].EndurUpkeep)) return true; - } + return false; } -bool IsResurrectionEffects(uint16 spell_id) { - bool Result = false; +bool IsResurrectionEffects(uint16 spell_id) +{ + // spell id 756 is Resurrection Effects spell + if(IsValidSpell(spell_id) && spell_id == 756) + return true; - if(IsValidSpell(spell_id) && spell_id == 756) // spell id 756 is Resurrection Effects spell - Result = true; - - return Result; + return false; } -bool IsRuneSpell(uint16 spell_id) { - bool Result = false; +bool IsRuneSpell(uint16 spell_id) +{ + if (IsValidSpell(spell_id)) + for (int i = 0; i < EFFECT_COUNT; i++) + if (spells[spell_id].effectid[i] == SE_Rune) + return true; - if(IsValidSpell(spell_id)) { - for(int i = 0; i < EFFECT_COUNT; i++) { - if(spells[spell_id].effectid[i] == SE_Rune) { - Result = true; - break; - } - } - } - - return Result; + return false; } -bool IsMagicRuneSpell(uint16 spell_id) { - bool Result = false; - - if(IsValidSpell(spell_id)) { - for(int i = 0; i < EFFECT_COUNT; i++) { - if(spells[spell_id].effectid[i] == SE_AbsorbMagicAtt) { - Result = true; - break; - } - } - } - - return Result; -} - -bool IsManaTapSpell(uint16 spell_id) { - bool Result = false; - - if(IsValidSpell(spell_id)) { - for(int i = 0; i < EFFECT_COUNT; i++) { - if(spells[spell_id].effectid[i] == SE_CurrentMana && spells[spell_id].targettype == ST_Tap) { - Result = true; - break; - } - } - } - - return Result; -} - -bool IsAllianceSpellLine(uint16 spell_id) { - bool Result = false; - +bool IsMagicRuneSpell(uint16 spell_id) +{ if(IsValidSpell(spell_id)) - Result = IsEffectInSpell(spell_id, SE_AddFaction); + for(int i = 0; i < EFFECT_COUNT; i++) + if(spells[spell_id].effectid[i] == SE_AbsorbMagicAtt) + return true; - return Result; + return false; } -bool IsDeathSaveSpell(uint16 spell_id) { - bool Result = false; +bool IsManaTapSpell(uint16 spell_id) +{ + if (IsValidSpell(spell_id)) + for (int i = 0; i < EFFECT_COUNT; i++) + if (spells[spell_id].effectid[i] == SE_CurrentMana && + spells[spell_id].targettype == ST_Tap) + return true; - if(IsValidSpell(spell_id)) - Result = IsEffectInSpell(spell_id, SE_DeathSave); - - return Result; + return false; } -bool IsPartialDeathSaveSpell(uint16 spell_id) { - bool Result = false; - - // Death Pact - if(spell_id == 1547) - Result = true; - - return Result; -} - -bool IsFullDeathSaveSpell(uint16 spell_id) { - bool Result = false; - - // Divine Intervention - if(spell_id == 1546) - Result = true; - - return Result; -} - -bool IsShadowStepSpell(uint16 spell_id) { - if (IsEffectInSpell(spell_id, SE_ShadowStep)){ +bool IsAllianceSpellLine(uint16 spell_id) +{ + if (IsEffectInSpell(spell_id, SE_AddFaction)) return true; - } - else { - return false; - } + return false; } -bool IsSuccorSpell(uint16 spell_id) { - if (IsEffectInSpell(spell_id, SE_Succor)){ +bool IsDeathSaveSpell(uint16 spell_id) +{ + if (IsEffectInSpell(spell_id, SE_DeathSave)) return true; - } - else { - return false; - } + + return false; } -bool IsTeleportSpell(uint16 spell_id) { - if (IsEffectInSpell(spell_id, SE_Teleport)){ - return true; - } - else { - return false; - } -} - -bool IsGateSpell(uint16 spell_id) { - if (IsEffectInSpell(spell_id, SE_Gate)){ - return true; - } - else { - return false; - } -} -// seveian 2008-09-23 -bool IsPlayerIllusionSpell(uint16 spell_id) { - if(IsEffectInSpell(spell_id, SE_Illusion) && spells[spell_id].targettype == ST_Self) - return true; - else +// Deathsave spells with base of 1 are partial +bool IsPartialDeathSaveSpell(uint16 spell_id) +{ + if (!IsValidSpell(spell_id)) return false; + for (int i = 0; i < EFFECT_COUNT; i++) + if (spells[spell_id].effectid[i] == SE_DeathSave && + spells[spell_id].base[i] == 1) + return true; + + return false; +} + +// Deathsave spells with base 2 are "full" +bool IsFullDeathSaveSpell(uint16 spell_id) +{ + if (!IsValidSpell(spell_id)) + return false; + + for (int i = 0; i < EFFECT_COUNT; i++) + if (spells[spell_id].effectid[i] == SE_DeathSave && + spells[spell_id].base[i] == 2) + return true; + + return false; +} + +bool IsShadowStepSpell(uint16 spell_id) +{ + if (IsEffectInSpell(spell_id, SE_ShadowStep)) + return true; + + return false; +} + +bool IsSuccorSpell(uint16 spell_id) +{ + if (IsEffectInSpell(spell_id, SE_Succor)) + return true; + + return false; +} + +bool IsTeleportSpell(uint16 spell_id) +{ + if (IsEffectInSpell(spell_id, SE_Teleport)) + return true; + + return false; +} + +bool IsGateSpell(uint16 spell_id) +{ + if (IsEffectInSpell(spell_id, SE_Gate)) + return true; + + return false; +} + +bool IsPlayerIllusionSpell(uint16 spell_id) +{ + if (IsEffectInSpell(spell_id, SE_Illusion) && + spells[spell_id].targettype == ST_Self) + return true; + + return false; } int GetSpellEffectDescNum(uint16 spell_id) { - if( (spell_id > 0) && (spell_id < SPDAT_RECORDS) ){ + if (IsValidSpell(spell_id)) return spells[spell_id].effectdescnum; - } else { - return -1; - } + + return -1; } DmgShieldType GetDamageShieldType(uint16 spell_id) { - // If we have a DamageShieldType for this spell from the damageshieldtypes table, return that, // else, make a guess, based on the resist type. Default return value is DS_THORNS - // - if( (spell_id > 0) && (spell_id < SPDAT_RECORDS) ){ - + if (IsValidSpell(spell_id)) { _log(SPELLS__EFFECT_VALUES, "DamageShieldType for spell %i (%s) is %X\n", spell_id, spells[spell_id].name, spells[spell_id].DamageShieldType); - if(spells[spell_id].DamageShieldType) + if (spells[spell_id].DamageShieldType) return (DmgShieldType) spells[spell_id].DamageShieldType; - switch(spells[spell_id].resisttype) { + switch (spells[spell_id].resisttype) { case RESIST_COLD: return DS_TORMENT; case RESIST_FIRE: @@ -868,17 +831,12 @@ DmgShieldType GetDamageShieldType(uint16 spell_id) bool IsLDoNObjectSpell(uint16 spell_id) { - if(IsEffectInSpell(spell_id, SE_AppraiseLDonChest) || - IsEffectInSpell(spell_id, SE_DisarmLDoNTrap) || - IsEffectInSpell(spell_id, SE_UnlockLDoNChest)) - { + if (IsEffectInSpell(spell_id, SE_AppraiseLDonChest) || + IsEffectInSpell(spell_id, SE_DisarmLDoNTrap) || + IsEffectInSpell(spell_id, SE_UnlockLDoNChest)) return true; - } - else - { - return false; - } + return false; } int32 GetSpellResistType(uint16 spell_id) @@ -891,174 +849,172 @@ int32 GetSpellTargetType(uint16 spell_id) return (int32)spells[spell_id].targettype; } -bool IsHealOverTimeSpell(uint16 spell_id) { - if(IsEffectInSpell(spell_id, SE_HealOverTime) && !IsGroupSpell(spell_id)) +bool IsHealOverTimeSpell(uint16 spell_id) +{ + if (IsEffectInSpell(spell_id, SE_HealOverTime) && !IsGroupSpell(spell_id)) return true; - else - return false; + + return false; } -bool IsCompleteHealSpell(uint16 spell_id) { - - if(spell_id == 13 || IsEffectInSpell(spell_id, SE_CompleteHeal) || IsPercentalHealSpell(spell_id) && !IsGroupSpell(spell_id)) +bool IsCompleteHealSpell(uint16 spell_id) +{ + if (spell_id == 13 || IsEffectInSpell(spell_id, SE_CompleteHeal) || + IsPercentalHealSpell(spell_id) && !IsGroupSpell(spell_id)) return true; - else - return false; + + return false; } -bool IsFastHealSpell(uint16 spell_id) { +bool IsFastHealSpell(uint16 spell_id) +{ const int MaxFastHealCastingTime = 2000; - if(spells[spell_id].cast_time <= MaxFastHealCastingTime && spells[spell_id].effectid[0] == 0 && spells[spell_id].base[0] > 0 && !IsGroupSpell(spell_id)) + if (spells[spell_id].cast_time <= MaxFastHealCastingTime && + spells[spell_id].effectid[0] == 0 && spells[spell_id].base[0] > 0 && + !IsGroupSpell(spell_id)) return true; - else - return false; + + return false; } -bool IsVeryFastHealSpell(uint16 spell_id) { +bool IsVeryFastHealSpell(uint16 spell_id) +{ const int MaxFastHealCastingTime = 1000; - if(spells[spell_id].cast_time <= MaxFastHealCastingTime && spells[spell_id].effectid[0] == 0 && spells[spell_id].base[0] > 0 && !IsGroupSpell(spell_id)) + if (spells[spell_id].cast_time <= MaxFastHealCastingTime && + spells[spell_id].effectid[0] == 0 && spells[spell_id].base[0] > 0 && + !IsGroupSpell(spell_id)) return true; - else - return false; + + return false; } -bool IsRegularSingleTargetHealSpell(uint16 spell_id) { - bool result = false; - - if(spells[spell_id].effectid[0] == 0 && spells[spell_id].base[0] > 0 && spells[spell_id].targettype == ST_Target && spells[spell_id].buffduration == 0 - && !IsFastHealSpell(spell_id) && !IsCompleteHealSpell(spell_id) && !IsHealOverTimeSpell(spell_id) && !IsGroupSpell(spell_id)) { - result = true; - } - - return result; -} - -bool IsRegularGroupHealSpell(uint16 spell_id) { - - if(IsGroupSpell(spell_id) && !IsCompleteHealSpell(spell_id) && !IsHealOverTimeSpell(spell_id)) +bool IsRegularSingleTargetHealSpell(uint16 spell_id) +{ + if(spells[spell_id].effectid[0] == 0 && spells[spell_id].base[0] > 0 && + spells[spell_id].targettype == ST_Target && spells[spell_id].buffduration == 0 && + !IsFastHealSpell(spell_id) && !IsCompleteHealSpell(spell_id) && + !IsHealOverTimeSpell(spell_id) && !IsGroupSpell(spell_id)) return true; - else - return false; + + return false; } -bool IsGroupCompleteHealSpell(uint16 spell_id) { - - if(IsGroupSpell(spell_id) && IsCompleteHealSpell(spell_id)) +bool IsRegularGroupHealSpell(uint16 spell_id) +{ + if (IsGroupSpell(spell_id) && !IsCompleteHealSpell(spell_id) && !IsHealOverTimeSpell(spell_id)) return true; - else - return false; + + return false; } -bool IsGroupHealOverTimeSpell(uint16 spell_id) { - - if(IsGroupSpell(spell_id) && IsHealOverTimeSpell(spell_id) && spells[spell_id].buffduration < 10) +bool IsGroupCompleteHealSpell(uint16 spell_id) +{ + if (IsGroupSpell(spell_id) && IsCompleteHealSpell(spell_id)) return true; - else - return false; + + return false; } -bool IsDebuffSpell(uint16 spell_id) { +bool IsGroupHealOverTimeSpell(uint16 spell_id) +{ + if( IsGroupSpell(spell_id) && IsHealOverTimeSpell(spell_id) && spells[spell_id].buffduration < 10) + return true; - 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)) + return false; +} + +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)) return false; else return true; } -bool IsResistDebuffSpell(uint16 spell_id) { - - if((IsEffectInSpell(spell_id, SE_ResistFire) || IsEffectInSpell(spell_id, SE_ResistCold) || IsEffectInSpell(spell_id, SE_ResistPoison) - || IsEffectInSpell(spell_id, SE_ResistDisease) || IsEffectInSpell(spell_id, SE_ResistMagic) || IsEffectInSpell(spell_id, SE_ResistAll) - || IsEffectInSpell(spell_id, SE_ResistCorruption)) && !IsBeneficialSpell(spell_id)) +bool IsResistDebuffSpell(uint16 spell_id) +{ + if ((IsEffectInSpell(spell_id, SE_ResistFire) || IsEffectInSpell(spell_id, SE_ResistCold) || + IsEffectInSpell(spell_id, SE_ResistPoison) || IsEffectInSpell(spell_id, SE_ResistDisease) || + IsEffectInSpell(spell_id, SE_ResistMagic) || IsEffectInSpell(spell_id, SE_ResistAll) || + IsEffectInSpell(spell_id, SE_ResistCorruption)) && !IsBeneficialSpell(spell_id)) return true; else return false; } -bool IsSelfConversionSpell(uint16 spell_id) { - - if(GetSpellTargetType(spell_id) == ST_Self && IsEffectInSpell(spell_id, SE_CurrentMana) && IsEffectInSpell(spell_id, SE_CurrentHP) - && spells[spell_id].base[GetSpellEffectIndex(spell_id, SE_CurrentMana)] > 0 && spells[spell_id].base[GetSpellEffectIndex(spell_id, SE_CurrentHP)] < 0) +bool IsSelfConversionSpell(uint16 spell_id) +{ + if (GetSpellTargetType(spell_id) == ST_Self && IsEffectInSpell(spell_id, SE_CurrentMana) && + IsEffectInSpell(spell_id, SE_CurrentHP) && spells[spell_id].base[GetSpellEffectIndex(spell_id, SE_CurrentMana)] > 0 && + spells[spell_id].base[GetSpellEffectIndex(spell_id, SE_CurrentHP)] < 0) return true; else return false; } // returns true for both detrimental and beneficial buffs -bool IsBuffSpell(uint16 spell_id) { - if(IsValidSpell(spell_id) && (spells[spell_id].buffduration || spells[spell_id].buffdurationformula)) +bool IsBuffSpell(uint16 spell_id) +{ + if (IsValidSpell(spell_id) && (spells[spell_id].buffduration || spells[spell_id].buffdurationformula)) return true; + return false; } uint32 GetMorphTrigger(uint32 spell_id) { - for(int i = 0; i < EFFECT_COUNT; ++i) - { - if(spells[spell_id].effectid[i] == SE_ImprovedSpellEffect) - { + for (int i = 0; i < EFFECT_COUNT; ++i) + if (spells[spell_id].effectid[i] == SE_ImprovedSpellEffect) return spells[spell_id].base[i]; - } - } + return 0; } uint32 GetPartialMeleeRuneReduction(uint32 spell_id) { - for(int i = 0; i < EFFECT_COUNT; ++i) - { - if(spells[spell_id].effectid[i] == SE_MitigateMeleeDamage) - { + for (int i = 0; i < EFFECT_COUNT; ++i) + if (spells[spell_id].effectid[i] == SE_MitigateMeleeDamage) return spells[spell_id].base[i]; - } - } + return 0; } uint32 GetPartialMagicRuneReduction(uint32 spell_id) { - for(int i = 0; i < EFFECT_COUNT; ++i) - { - if(spells[spell_id].effectid[i] == SE_MitigateSpellDamage) - { + for (int i = 0; i < EFFECT_COUNT; ++i) + if (spells[spell_id].effectid[i] == SE_MitigateSpellDamage) return spells[spell_id].base[i]; - } - } + return 0; } uint32 GetPartialMeleeRuneAmount(uint32 spell_id) { - for(int i = 0; i < EFFECT_COUNT; ++i) - { - if(spells[spell_id].effectid[i] == SE_MitigateMeleeDamage) - { + for (int i = 0; i < EFFECT_COUNT; ++i) + if (spells[spell_id].effectid[i] == SE_MitigateMeleeDamage) return spells[spell_id].max[i]; - } - } + return 0; } uint32 GetPartialMagicRuneAmount(uint32 spell_id) { - for(int i = 0; i < EFFECT_COUNT; ++i) - { - if(spells[spell_id].effectid[i] == SE_MitigateSpellDamage) - { + for (int i = 0; i < EFFECT_COUNT; ++i) + if (spells[spell_id].effectid[i] == SE_MitigateSpellDamage) return spells[spell_id].max[i]; - } - } + return 0; } bool DetrimentalSpellAllowsRest(uint16 spell_id) { - if((spell_id > 0) && (spell_id < SPDAT_RECORDS)) + if (IsValidSpell(spell_id)) return spells[spell_id].AllowRest; return false; @@ -1066,7 +1022,7 @@ bool DetrimentalSpellAllowsRest(uint16 spell_id) uint32 GetNimbusEffect(uint16 spell_id) { - if((spell_id > 0) && (spell_id < SPDAT_RECORDS)) + if (IsValidSpell(spell_id)) return (int32)spells[spell_id].NimbusEffect; return 0; @@ -1074,28 +1030,19 @@ uint32 GetNimbusEffect(uint16 spell_id) int32 GetFuriousBash(uint16 spell_id) { - if(!IsValidSpell(spell_id)) + if (!IsValidSpell(spell_id)) return 0; bool found_effect_limit = false; int32 mod = 0; - for(int i = 0; i < EFFECT_COUNT; ++i) - { - if(spells[spell_id].effectid[i] == SE_SpellHateMod) - { + for (int i = 0; i < EFFECT_COUNT; ++i) + if (spells[spell_id].effectid[i] == SE_SpellHateMod) mod = spells[spell_id].base[i]; - } - else if(spells[spell_id].effectid[i] == SE_LimitEffect) - { - if(spells[spell_id].base[i] == 999) - { - found_effect_limit = true; - } - } - } + else if (spells[spell_id].effectid[i] == SE_LimitEffect && spells[spell_id].base[i] == 999) + found_effect_limit = true; - if(found_effect_limit) + if (found_effect_limit) return mod; else return 0; @@ -1103,29 +1050,25 @@ int32 GetFuriousBash(uint16 spell_id) bool IsShortDurationBuff(uint16 spell_id) { - if((spell_id > 0) && (spell_id < SPDAT_RECORDS)) { - if(spells[spell_id].short_buff_box != 0) - return true; - } + if (IsValidSpell(spell_id) && spells[spell_id].short_buff_box != 0) + return true; + return false; } bool IsSpellUsableThisZoneType(uint16 spell_id, uint8 zone_type) { - if((spell_id > 0) && (spell_id < SPDAT_RECORDS)) - { - //check if spell can be cast in any zone (-1 or 255), then if spell zonetype matches zone's zonetype - if(spells[spell_id].zonetype == -1 - || spells[spell_id].zonetype == 255 - || spells[spell_id].zonetype == zone_type) { - return true; - } - } + //check if spell can be cast in any zone (-1 or 255), then if spell zonetype matches zone's zonetype + // || spells[spell_id].zonetype == 255 comparing signed 8 bit int to 255 is always false + if (IsValidSpell(spell_id) && (spells[spell_id].zonetype == -1 || + spells[spell_id].zonetype == zone_type)) + return true; return false; } const char* GetSpellName(int16 spell_id) { - return( spells[spell_id].name ); + return spells[spell_id].name; } + From 925e19b15c60bc3349001eb2bb34103d951f2612 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 11 Nov 2013 15:37:20 -0500 Subject: [PATCH 03/25] Fix database scheme comments that got clobbered on nullptr conversion --- common/ptimer.cpp | 10 ++++----- common/rulesys.cpp | 10 ++++----- zone/forage.cpp | 26 ++++++++++----------- zone/guild_mgr.cpp | 56 +++++++++++++++++++++++----------------------- zone/spawn2.cpp | 34 ++++++++++++++-------------- zone/trap.cpp | 28 +++++++++++------------ 6 files changed, 82 insertions(+), 82 deletions(-) diff --git a/common/ptimer.cpp b/common/ptimer.cpp index 07533bc55..449b943c4 100644 --- a/common/ptimer.cpp +++ b/common/ptimer.cpp @@ -74,11 +74,11 @@ To use ptimers, you need to create the table below in your DB: Schema: CREATE TABLE timers ( - char_id INT(11) NOT nullptr, - type MEDIUMINT UNSIGNED NOT nullptr, - start INT UNSIGNED NOT nullptr, - duration INT UNSIGNED NOT nullptr, - enable TINYINT NOT nullptr, + char_id INT(11) NOT NULL, + type MEDIUMINT UNSIGNED NOT NULL, + start INT UNSIGNED NOT NULL, + duration INT UNSIGNED NOT NULL, + enable TINYINT NOT NULL, PRIMARY KEY(char_id, type) ); diff --git a/common/rulesys.cpp b/common/rulesys.cpp index 47ae94138..1f4ee8edf 100644 --- a/common/rulesys.cpp +++ b/common/rulesys.cpp @@ -35,17 +35,17 @@ Requred SQL: CREATE TABLE rule_sets ( - ruleset_id TINYINT UNSIGNED NOT nullptr auto_increment, - name VARCHAR(255) NOT nullptr, + ruleset_id TINYINT UNSIGNED NOT NULL auto_increment, + name VARCHAR(255) NOT NULL, PRIMARY KEY(ruleset_id) ); INSERT INTO rule_sets VALUES(0, "default"); UPDATE rule_sets SET ruleset_id=0; CREATE TABLE rule_values ( - ruleset_id TINYINT UNSIGNED NOT nullptr, - rule_name VARCHAR(64) NOT nullptr, - rule_value VARCHAR(10) NOT nullptr, + ruleset_id TINYINT UNSIGNED NOT NULL, + rule_name VARCHAR(64) NOT NULL, + rule_value VARCHAR(10) NOT NULL, INDEX(ruleset_id), PRIMARY KEY(ruleset_id,rule_name) ); diff --git a/zone/forage.cpp b/zone/forage.cpp index 7f9e145fb..ee0f45fb4 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -56,27 +56,27 @@ very low chance of dropping. Schema: CREATE TABLE forage ( - id int(11) NOT nullptr auto_increment, - zoneid int(4) NOT nullptr default '0', - Itemid int(11) NOT nullptr default '0', - level smallint(6) NOT nullptr default '0', - chance smallint(6) NOT nullptr default '0', + id int(11) NOT NULL auto_increment, + zoneid int(4) NOT NULL default '0', + Itemid int(11) NOT NULL default '0', + level smallint(6) NOT NULL default '0', + chance smallint(6) NOT NULL default '0', PRIMARY KEY (id) ) TYPE=MyISAM; old table upgrade: -alter table forage add chance smallint(6) NOT nullptr default '0'; +alter table forage add chance smallint(6) NOT NULL default '0'; update forage set chance=100; CREATE TABLE fishing ( - id int(11) NOT nullptr auto_increment, - zoneid int(4) NOT nullptr default '0', - Itemid int(11) NOT nullptr default '0', - skill_level smallint(6) NOT nullptr default '0', - chance smallint(6) NOT nullptr default '0', - npc_id int NOT nullptr default 0, - npc_chance int NOT nullptr default 0, + id int(11) NOT NULL auto_increment, + zoneid int(4) NOT NULL default '0', + Itemid int(11) NOT NULL default '0', + skill_level smallint(6) NOT NULL default '0', + chance smallint(6) NOT NULL default '0', + npc_id int NOT NULL default 0, + npc_chance int NOT NULL default 0, PRIMARY KEY (id) ) TYPE=MyISAM; diff --git a/zone/guild_mgr.cpp b/zone/guild_mgr.cpp index 0c7436514..7c1210ba8 100644 --- a/zone/guild_mgr.cpp +++ b/zone/guild_mgr.cpp @@ -27,49 +27,49 @@ /* CREATE TABLE guilds ( - id MEDIUMINT UNSIGNED NOT nullptr, - name VARCHAR(32) NOT nullptr, - leader int NOT nullptr, - minstatus SMALLINT NOT nullptr, - tribute INT UNSIGNED NOT nullptr, - motd TEXT NOT nullptr DEFAULT '', + id MEDIUMINT UNSIGNED NOT NULL, + name VARCHAR(32) NOT NULL, + leader int NOT NULL, + minstatus SMALLINT NOT NULL, + tribute INT UNSIGNED NOT NULL, + motd TEXT NOT NULL DEFAULT '', PRIMARY KEY(id), UNIQUE KEY(name), UNIQUE KEY(leader) ); CREATE TABLE guild_ranks ( - guild_id MEDIUMINT UNSIGNED NOT nullptr, - rank TINYINT UNSIGNED NOT nullptr, - title VARCHAR(128) NOT nullptr, - can_hear TINYINT UNSIGNED NOT nullptr, - can_speak TINYINT UNSIGNED NOT nullptr, - can_invite TINYINT UNSIGNED NOT nullptr, - can_remove TINYINT UNSIGNED NOT nullptr, - can_promote TINYINT UNSIGNED NOT nullptr, - can_demote TINYINT UNSIGNED NOT nullptr, - can_motd TINYINT UNSIGNED NOT nullptr, - can_warpeace TINYINT UNSIGNED NOT nullptr, + guild_id MEDIUMINT UNSIGNED NOT NULL, + rank TINYINT UNSIGNED NOT NULL, + title VARCHAR(128) NOT NULL, + can_hear TINYINT UNSIGNED NOT NULL, + can_speak TINYINT UNSIGNED NOT NULL, + can_invite TINYINT UNSIGNED NOT NULL, + can_remove TINYINT UNSIGNED NOT NULL, + can_promote TINYINT UNSIGNED NOT NULL, + can_demote TINYINT UNSIGNED NOT NULL, + can_motd TINYINT UNSIGNED NOT NULL, + can_warpeace TINYINT UNSIGNED NOT NULL, PRIMARY KEY(guild_id,rank) ); # guild1 < guild2 by definition. CREATE TABLE guild_relations ( - guild1 MEDIUMINT UNSIGNED NOT nullptr, - guild2 MEDIUMINT UNSIGNED NOT nullptr, - relation TINYINT NOT nullptr, + guild1 MEDIUMINT UNSIGNED NOT NULL, + guild2 MEDIUMINT UNSIGNED NOT NULL, + relation TINYINT NOT NULL, PRIMARY KEY(guild1, guild1) ); CREATE TABLE guild_members ( - char_id INT NOT nullptr, - guild_id MEDIUMINT UNSIGNED NOT nullptr, - rank TINYINT UNSIGNED NOT nullptr, - tribute_enable TINYINT UNSIGNED NOT nullptr DEFAULT 0, - total_tribute INT UNSIGNED NOT nullptr DEFAULT 0, - last_tribute INT UNSIGNED NOT nullptr DEFAULT 0, - banker TINYINT UNSIGNED NOT nullptr DEFAULT 0, - public_note TEXT NOT nullptr DEFAULT '', + char_id INT NOT NULL, + guild_id MEDIUMINT UNSIGNED NOT NULL, + rank TINYINT UNSIGNED NOT NULL, + tribute_enable TINYINT UNSIGNED NOT NULL DEFAULT 0, + total_tribute INT UNSIGNED NOT NULL DEFAULT 0, + last_tribute INT UNSIGNED NOT NULL DEFAULT 0, + banker TINYINT UNSIGNED NOT NULL DEFAULT 0, + public_note TEXT NOT NULL DEFAULT '', PRIMARY KEY(char_id) ); diff --git a/zone/spawn2.cpp b/zone/spawn2.cpp index a2426dd2c..cf02fa21b 100644 --- a/zone/spawn2.cpp +++ b/zone/spawn2.cpp @@ -34,33 +34,33 @@ extern WorldServer worldserver; /* CREATE TABLE spawn_conditions ( - zone VARCHAR(16) NOT nullptr, - id MEDIUMINT UNSIGNED NOT nullptr DEFAULT '1', - value MEDIUMINT NOT nullptr DEFAULT '0', - onchange TINYINT UNSIGNED NOT nullptr DEFAULT '0', - name VARCHAR(255) NOT nullptr DEFAULT '', + zone VARCHAR(16) NOT NULL, + id MEDIUMINT UNSIGNED NOT NULL DEFAULT '1', + value MEDIUMINT NOT NULL DEFAULT '0', + onchange TINYINT UNSIGNED NOT NULL DEFAULT '0', + name VARCHAR(255) NOT NULL DEFAULT '', PRIMARY KEY(zone,id) ); CREATE TABLE spawn_events ( #identifiers id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, - zone VARCHAR(16) NOT nullptr, - cond_id MEDIUMINT UNSIGNED NOT nullptr, - name VARCHAR(255) NOT nullptr DEFAULT '', + zone VARCHAR(16) NOT NULL, + cond_id MEDIUMINT UNSIGNED NOT NULL, + name VARCHAR(255) NOT NULL DEFAULT '', #timing information - period INT UNSIGNED NOT nullptr, - next_minute TINYINT UNSIGNED NOT nullptr, - next_hour TINYINT UNSIGNED NOT nullptr, - next_day TINYINT UNSIGNED NOT nullptr, - next_month TINYINT UNSIGNED NOT nullptr, - next_year INT UNSIGNED NOT nullptr, - enabled TINYINT NOT nullptr DEFAULT '1', + period INT UNSIGNED NOT NULL, + next_minute TINYINT UNSIGNED NOT NULL, + next_hour TINYINT UNSIGNED NOT NULL, + next_day TINYINT UNSIGNED NOT NULL, + next_month TINYINT UNSIGNED NOT NULL, + next_year INT UNSIGNED NOT NULL, + enabled TINYINT NOT NULL DEFAULT '1', #action: - action TINYINT UNSIGNED NOT nullptr DEFAULT '0', - argument MEDIUMINT NOT nullptr DEFAULT '0' + action TINYINT UNSIGNED NOT NULL DEFAULT '0', + argument MEDIUMINT NOT NULL DEFAULT '0' ); */ diff --git a/zone/trap.cpp b/zone/trap.cpp index 00ab31bd0..8d3b6010f 100644 --- a/zone/trap.cpp +++ b/zone/trap.cpp @@ -27,20 +27,20 @@ Schema: CREATE TABLE traps ( - id int(11) NOT nullptr auto_increment, - zone varchar(16) NOT nullptr default '', - x int(11) NOT nullptr default '0', - y int(11) NOT nullptr default '0', - z int(11) NOT nullptr default '0', - chance tinyint NOT nullptr default '0', - maxzdiff float NOT nullptr default '0', - radius float NOT nullptr default '0', - effect int(11) NOT nullptr default '0', - effectvalue int(11) NOT nullptr default '0', - effectvalue2 int(11) NOT nullptr default '0', - message varcahr(200) NOT nullptr; - skill int(11) NOT nullptr default '0', - spawnchance int(11) NOT nullptr default '0', + id int(11) NOT NULL auto_increment, + zone varchar(16) NOT NULL default '', + x int(11) NOT NULL default '0', + y int(11) NOT NULL default '0', + z int(11) NOT NULL default '0', + chance tinyint NOT NULL default '0', + maxzdiff float NOT NULL default '0', + radius float NOT NULL default '0', + effect int(11) NOT NULL default '0', + effectvalue int(11) NOT NULL default '0', + effectvalue2 int(11) NOT NULL default '0', + message varcahr(200) NOT NULL; + skill int(11) NOT NULL default '0', + spawnchance int(11) NOT NULL default '0', PRIMARY KEY (id) ) TYPE=MyISAM; From ed6c46f7ffa2a8155e0f22cc52730762df7aee35 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 11 Nov 2013 18:18:12 -0500 Subject: [PATCH 04/25] Fixed non-attacking related movement while mobs are snared On live a nec/shd normal splitting involved snaring the mob you want and FDing after they moved enough. The non-snared mobs would return home and the snared mob would just sit there until it was no longer snared. There is even a nice flash video! http://www.dzert.com/downloads/eq/fd02.swf This might need some tweaking, but I'm not sure of any instances where it would break things... --- changelog.txt | 3 +++ zone/MobAI.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index a99bec7d0..7f53de277 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 11/11/2013 == +demonstar55: Mobs shouldn't do any non-attacking related movement while snared. + == 11/09/2013 == Leere: Fixed Bard mana regen, they now only are affected by items and AA. diff --git a/zone/MobAI.cpp b/zone/MobAI.cpp index 7840444c0..e1a5eb2f1 100644 --- a/zone/MobAI.cpp +++ b/zone/MobAI.cpp @@ -1554,7 +1554,7 @@ void Mob::AI_Process() { return; } - if(IsNPC()) + if(IsNPC() && GetSnaredAmount() == -1) { if(RuleB(NPC, SmartLastFightingDelayMoving) && !feign_memory_list.empty()) { From d83b94d2319c7c754cff9c36682cae9791feee8d Mon Sep 17 00:00:00 2001 From: Michael Cook Date: Mon, 11 Nov 2013 21:06:48 -0500 Subject: [PATCH 05/25] Revert "Fixed non-attacking related movement while mobs are snared" Did some testing, this isn't exactly the case on live. This reverts commit ed6c46f7ffa2a8155e0f22cc52730762df7aee35. --- changelog.txt | 3 --- zone/MobAI.cpp | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/changelog.txt b/changelog.txt index 7f53de277..a99bec7d0 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,8 +1,5 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- -== 11/11/2013 == -demonstar55: Mobs shouldn't do any non-attacking related movement while snared. - == 11/09/2013 == Leere: Fixed Bard mana regen, they now only are affected by items and AA. diff --git a/zone/MobAI.cpp b/zone/MobAI.cpp index e1a5eb2f1..7840444c0 100644 --- a/zone/MobAI.cpp +++ b/zone/MobAI.cpp @@ -1554,7 +1554,7 @@ void Mob::AI_Process() { return; } - if(IsNPC() && GetSnaredAmount() == -1) + if(IsNPC()) { if(RuleB(NPC, SmartLastFightingDelayMoving) && !feign_memory_list.empty()) { From 78ab3471719283e2d8bd088394ffaeb90721b4f0 Mon Sep 17 00:00:00 2001 From: Michael Cook Date: Mon, 11 Nov 2013 23:55:43 -0500 Subject: [PATCH 06/25] Fix walk speed calculation Walk speed should be calculated as a movement speed reduction that stacks with snares so it's possible to snare a mob FD and have it not be able to walk back. --- changelog.txt | 3 +++ zone/mob.cpp | 10 +++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/changelog.txt b/changelog.txt index a99bec7d0..2acafcd16 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 11/11/2013 == +demonstar55: Changed the way walk speed is calculated to allow mobs to have their walk speed equal a 100% movement reduction + == 11/09/2013 == Leere: Fixed Bard mana regen, they now only are affected by items and AA. diff --git a/zone/mob.cpp b/zone/mob.cpp index 6780a1ca1..b6ec8e99d 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -561,16 +561,16 @@ float Mob::_GetMovementSpeed(int mod) const { movemod = static_cast(aa_mod); } - if(movemod < -85) //cap it at moving very very slow + if(mod != 0) + movemod += mod; + + if(IsClient() && movemod < -85) //cap it at moving very very slow movemod = -85; if (!has_horse && movemod != 0) speed_mod += (speed_mod * float(movemod) / 100.0f); - if(mod != 0) - speed_mod += (speed_mod * (float)mod / 100.0f); - - if(speed_mod <= 0.0f) + if(IsClient() && speed_mod <= 0.0f) return(0.0001f); //runspeed cap. From 65c0772d371bc56f80e1eb182ef929f6b401b19e Mon Sep 17 00:00:00 2001 From: httm Date: Tue, 12 Nov 2013 18:06:24 -0500 Subject: [PATCH 07/25] Update exp.cpp Replaced elseif statements in group experience calculation with single if statement for calculation when membercount between 2 and 5 --- zone/exp.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/zone/exp.cpp b/zone/exp.cpp index 95cbcb5e6..ec30aaab0 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -530,14 +530,8 @@ void Group::SplitExp(uint32 exp, Mob* other) { } float groupmod; - if (membercount == 2) - groupmod = 1.2; - else if (membercount == 3) - groupmod = 1.4; - else if (membercount == 4) - groupmod = 1.6; - else if (membercount == 5) - groupmod = 1.8; + if (membercount > 1 && membercount < 6) + groupmod = 1 + .2(membercount - 1); //2members=1.2exp, 3=1.4, 4=1.6, 5=1.8 else if (membercount == 6) groupmod = 2.16; else From 2ffa13c9935802340079bd14d2ed5c5c0650e84c Mon Sep 17 00:00:00 2001 From: cavedude00 Date: Tue, 12 Nov 2013 16:08:31 -0800 Subject: [PATCH 08/25] Compile fix. --- zone/exp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/exp.cpp b/zone/exp.cpp index ec30aaab0..cbf7f5f6d 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -531,7 +531,7 @@ void Group::SplitExp(uint32 exp, Mob* other) { float groupmod; if (membercount > 1 && membercount < 6) - groupmod = 1 + .2(membercount - 1); //2members=1.2exp, 3=1.4, 4=1.6, 5=1.8 + groupmod = 1 + .2*(membercount - 1); //2members=1.2exp, 3=1.4, 4=1.6, 5=1.8 else if (membercount == 6) groupmod = 2.16; else From 79c53a41a8daec087c7040fd5210abcb644965a6 Mon Sep 17 00:00:00 2001 From: Michael Cook Date: Tue, 12 Nov 2013 22:32:03 -0500 Subject: [PATCH 09/25] Add some sanity for bard songs in snares ... --- zone/mob.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index b6ec8e99d..d5afff3c2 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -561,17 +561,17 @@ float Mob::_GetMovementSpeed(int mod) const { movemod = static_cast(aa_mod); } - if(mod != 0) - movemod += mod; - - if(IsClient() && movemod < -85) //cap it at moving very very slow + if(movemod < -85) //cap it at moving very very slow movemod = -85; + if(mod != 0) // passing -47 for walking shouldn't be effected by cap above + movemod += mod; + if (!has_horse && movemod != 0) speed_mod += (speed_mod * float(movemod) / 100.0f); - if(IsClient() && speed_mod <= 0.0f) - return(0.0001f); + if(speed_mod <= 0.0f) + return (IsClient() ? 0.0001f : 0.0f); //runspeed cap. if(IsClient()) From 3f8ee533d3023aebf9fc245c3d4be463a58b109c Mon Sep 17 00:00:00 2001 From: Michael Cook Date: Wed, 13 Nov 2013 15:07:34 -0500 Subject: [PATCH 10/25] Implement bard song instrument mod caps The maximum bard songs can be effected by instrument mods is 3.6. This is set by the rule Character:BaseInstrumentSoftCap which defaults to 36 Also fix Echo of Taelosia and Ayonae's Tutelage to increase the mod cap. --- changelog.txt | 4 ++++ common/ruletypes.h | 1 + zone/client_mods.cpp | 14 +++++++++++--- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/changelog.txt b/changelog.txt index 2acafcd16..d1da71cac 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 11/13/2013 == +demonstar55: Implemented bard song effect cap. You can set the base cap with the rule Character:BaseInstrumentSoftCap, defaults to 36 or "3.6" as it is sometimes referred to. +demonstar55: Fix Echo of Taelosia and Ayonae's Tutelage to increase the mod cap instead of further improving the instrument mod + == 11/11/2013 == demonstar55: Changed the way walk speed is calculated to allow mobs to have their walk speed equal a 100% movement reduction diff --git a/common/ruletypes.h b/common/ruletypes.h index 9fbddd3ca..4b5608ae8 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -97,6 +97,7 @@ RULE_BOOL ( Character, EnableDiscoveredItems, true ) // If enabled, it enables E RULE_BOOL ( Character, EnableXTargetting, true) // Enable Extended Targetting Window, for users with UF and later clients. RULE_BOOL ( Character, KeepLevelOverMax, false) // Don't delevel a character that has somehow gone over the level cap RULE_INT ( Character, FoodLossPerUpdate, 35) // How much food/water you lose per stamina update +RULE_INT ( Character, BaseInstrumentSoftCap, 36) // Softcap for instrument mods, 36 commonly referred to as "3.6" as well. RULE_CATEGORY_END() RULE_CATEGORY( Mercs ) diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index 61580bc21..25724bd46 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -1796,6 +1796,7 @@ uint16 Mob::GetInstrumentMod(uint16 spell_id) const { return(10); uint16 effectmod = 10; + int effectmodcap = RuleI(Character, BaseInstrumentSoftCap); //this should never use spell modifiers... //if a spell grants better modifers, they are copied into the item mods @@ -1856,6 +1857,7 @@ uint16 Mob::GetInstrumentMod(uint16 spell_id) const { break; } + // TODO: These shouldn't be hardcoded. if(spells[spell_id].skill == SkillSinging) { effectmod += 2*GetAA(aaSingingMastery); @@ -1866,14 +1868,20 @@ uint16 Mob::GetInstrumentMod(uint16 spell_id) const { effectmod += 2*GetAA(aaInstrumentMastery); effectmod += 2*GetAA(aaImprovedInstrumentMastery); } - effectmod += 2*GetAA(aaAyonaesTutelage); //singing & instruments - effectmod += 2*GetAA(aaEchoofTaelosia); //singing & instruments + + // TODO: These shouldn't be hardcoded. + effectmodcap += GetAA(aaAyonaesTutelage); + effectmodcap += GetAA(aaEchoofTaelosia); if(effectmod < 10) effectmod = 10; - _log(SPELLS__BARDS, "%s::GetInstrumentMod() spell=%d mod=%d\n", GetName(), spell_id, effectmod); + if (effectmod > effectmodcap) + effectmod = effectmodcap; + + _log(SPELLS__BARDS, "%s::GetInstrumentMod() spell=%d mod=%d modcap=%d\n", + GetName(), spell_id, effectmod, effectmodcap); return(effectmod); } From d094a09ded1a0acb1515a6da8c533c137e46051e Mon Sep 17 00:00:00 2001 From: Michael Cook Date: Wed, 13 Nov 2013 18:03:08 -0500 Subject: [PATCH 11/25] Implemented Singing/Instrument Mastery as an AA bonus Don't forget to source the SQL file! --- .../2013_11_13_Instrument_Singing_Mastery.sql | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 utils/sql/git/required/2013_11_13_Instrument_Singing_Mastery.sql diff --git a/utils/sql/git/required/2013_11_13_Instrument_Singing_Mastery.sql b/utils/sql/git/required/2013_11_13_Instrument_Singing_Mastery.sql new file mode 100644 index 000000000..e4cdea18e --- /dev/null +++ b/utils/sql/git/required/2013_11_13_Instrument_Singing_Mastery.sql @@ -0,0 +1,30 @@ +-- Instrument Mastery +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (213, 1, 260, 2, 23); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (213, 2, 260, 2, 24); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (213, 3, 260, 2, 25); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (213, 4, 260, 2, 26); + +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (214, 1, 260, 4, 23); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (214, 2, 260, 4, 24); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (214, 3, 260, 4, 25); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (214, 4, 260, 4, 26); + +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (215, 1, 260, 6, 23); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (215, 2, 260, 6, 24); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (215, 3, 260, 6, 25); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (215, 4, 260, 6, 26); + +-- Improved Instrument Mastery +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (700, 1, 260, 2, 23); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (700, 2, 260, 2, 24); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (700, 3, 260, 2, 25); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (700, 4, 260, 2, 26); + +-- Singing Mastery +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (275, 1, 260, 2, 50); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (276, 1, 260, 4, 50); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (277, 1, 260, 6, 50); + +-- Improved Singing Mastery +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (701, 1, 260, 2, 50); + From 23ab896dfcbed710ab351a61cc66e5a5d7fe7972 Mon Sep 17 00:00:00 2001 From: Michael Cook Date: Wed, 13 Nov 2013 18:04:11 -0500 Subject: [PATCH 12/25] Fix last commit .... --- changelog.txt | 1 + common/spdat.h | 2 +- zone/bonuses.cpp | 41 +++++++++++++++++++++++++++++++++++++++++ zone/client_mods.cpp | 17 +++++------------ zone/spell_effects.cpp | 1 + 5 files changed, 49 insertions(+), 13 deletions(-) diff --git a/changelog.txt b/changelog.txt index d1da71cac..1a551977a 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,6 +3,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) == 11/13/2013 == demonstar55: Implemented bard song effect cap. You can set the base cap with the rule Character:BaseInstrumentSoftCap, defaults to 36 or "3.6" as it is sometimes referred to. demonstar55: Fix Echo of Taelosia and Ayonae's Tutelage to increase the mod cap instead of further improving the instrument mod +demonstar55: Implemented Singing/Instrument Mastery as an AA bonus. == 11/11/2013 == demonstar55: Changed the way walk speed is calculated to allow mobs to have their walk speed equal a 100% movement reduction diff --git a/common/spdat.h b/common/spdat.h index 225dbf0f1..743e79759 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -404,7 +404,7 @@ typedef enum { #define SE_PetDiscipline 257 // not implemented as bonus - /pet hold #define SE_TripleBackstab 258 // implemented[AA] - chance to perform a triple backstab #define SE_CombatStability 259 // implemented[AA] - damage mitigation -#define SE_AddSingingMod 260 // *not implemented +#define SE_AddSingingMod 260 // implemented[AA] - Instrument/Singing Mastery, base1 is the mod, base2 is the ItemType //#define SE_Unknown261 261 // not used #define SE_RaiseStatCap 262 // implemented #define SE_TradeSkillMastery 263 // implemented - lets you raise more than one tradeskill above master. diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 3c3788a74..a26517a35 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -874,6 +874,26 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) case SE_CombatStability: newbon->CombatStability += base1; break; + case SE_AddSingingMod: + switch (base2) + { + case ItemTypeWindInstrument: + newbon->windMod += base1; + break; + case ItemTypeStringedInstrument: + newbon->stringedMod += base1; + break; + case ItemTypeBrassInstrument: + newbon->brassMod += base1; + break; + case ItemTypePercussionInstrument: + newbon->percussionMod += base1; + break; + case ItemTypeSinging: + newbon->singingMod += base1; + break; + } + break; case SE_PetCriticalHit: newbon->PetCriticalHit += base1; break; @@ -2231,6 +2251,27 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne newbon->CombatStability += effect_value; break; + case SE_AddSingingMod: + switch (spells[spell_id].base2[i]) + { + case ItemTypeWindInstrument: + newbon->windMod += effect_value; + break; + case ItemTypeStringedInstrument: + newbon->stringedMod += effect_value; + break; + case ItemTypeBrassInstrument: + newbon->brassMod += effect_value; + break; + case ItemTypePercussionInstrument: + newbon->percussionMod += effect_value; + break; + case ItemTypeSinging: + newbon->singingMod += effect_value; + break; + } + break; + case SE_PetAvoidance: newbon->PetAvoidance += effect_value; break; diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index 25724bd46..2cc26c3f7 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -1813,6 +1813,7 @@ uint16 Mob::GetInstrumentMod(uint16 spell_id) const { effectmod = itembonuses.percussionMod; else effectmod = spellbonuses.percussionMod; + effectmod += aabonuses.percussionMod; break; case SkillStringedInstruments: if(itembonuses.stringedMod == 0 && spellbonuses.stringedMod == 0) @@ -1823,6 +1824,7 @@ uint16 Mob::GetInstrumentMod(uint16 spell_id) const { effectmod = itembonuses.stringedMod; else effectmod = spellbonuses.stringedMod; + effectmod += aabonuses.stringedMod; break; case SkillWindInstruments: if(itembonuses.windMod == 0 && spellbonuses.windMod == 0) @@ -1833,6 +1835,7 @@ uint16 Mob::GetInstrumentMod(uint16 spell_id) const { effectmod = itembonuses.windMod; else effectmod = spellbonuses.windMod; + effectmod += aabonuses.windMod; break; case SkillBrassInstruments: if(itembonuses.brassMod == 0 && spellbonuses.brassMod == 0) @@ -1843,6 +1846,7 @@ uint16 Mob::GetInstrumentMod(uint16 spell_id) const { effectmod = itembonuses.brassMod; else effectmod = spellbonuses.brassMod; + effectmod += aabonuses.brassMod; break; case SkillSinging: if(itembonuses.singingMod == 0 && spellbonuses.singingMod == 0) @@ -1851,24 +1855,13 @@ uint16 Mob::GetInstrumentMod(uint16 spell_id) const { effectmod = itembonuses.singingMod; else effectmod = spellbonuses.singingMod; + effectmod += aabonuses.singingMod; break; default: effectmod = 10; break; } - // TODO: These shouldn't be hardcoded. - if(spells[spell_id].skill == SkillSinging) - { - effectmod += 2*GetAA(aaSingingMastery); - effectmod += 2*GetAA(aaImprovedSingingMastery); - } - else - { - effectmod += 2*GetAA(aaInstrumentMastery); - effectmod += 2*GetAA(aaImprovedInstrumentMastery); - } - // TODO: These shouldn't be hardcoded. effectmodcap += GetAA(aaAyonaesTutelage); effectmodcap += GetAA(aaEchoofTaelosia); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 2f0ffe1a0..ba4200119 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2733,6 +2733,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) case SE_ImprovedBindWound: case SE_MaxBindWound: case SE_CombatStability: + case SE_AddSingingMod: case SE_PetAvoidance: case SE_GiveDoubleRiposte: case SE_Ambidexterity: From b99d476754c1b9cab0f4bcd772ef722af488dc39 Mon Sep 17 00:00:00 2001 From: JJ Date: Wed, 13 Nov 2013 21:59:38 -0500 Subject: [PATCH 13/25] Change INSERT to REPLACE --- .../2013_11_13_Instrument_Singing_Mastery.sql | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/utils/sql/git/required/2013_11_13_Instrument_Singing_Mastery.sql b/utils/sql/git/required/2013_11_13_Instrument_Singing_Mastery.sql index e4cdea18e..7c946184c 100644 --- a/utils/sql/git/required/2013_11_13_Instrument_Singing_Mastery.sql +++ b/utils/sql/git/required/2013_11_13_Instrument_Singing_Mastery.sql @@ -1,30 +1,30 @@ -- Instrument Mastery -INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (213, 1, 260, 2, 23); -INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (213, 2, 260, 2, 24); -INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (213, 3, 260, 2, 25); -INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (213, 4, 260, 2, 26); +REPLACE INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (213, 1, 260, 2, 23); +REPLACE INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (213, 2, 260, 2, 24); +REPLACE INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (213, 3, 260, 2, 25); +REPLACE INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (213, 4, 260, 2, 26); -INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (214, 1, 260, 4, 23); -INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (214, 2, 260, 4, 24); -INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (214, 3, 260, 4, 25); -INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (214, 4, 260, 4, 26); +REPLACE INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (214, 1, 260, 4, 23); +REPLACE INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (214, 2, 260, 4, 24); +REPLACE INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (214, 3, 260, 4, 25); +REPLACE INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (214, 4, 260, 4, 26); -INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (215, 1, 260, 6, 23); -INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (215, 2, 260, 6, 24); -INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (215, 3, 260, 6, 25); -INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (215, 4, 260, 6, 26); +REPLACE INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (215, 1, 260, 6, 23); +REPLACE INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (215, 2, 260, 6, 24); +REPLACE INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (215, 3, 260, 6, 25); +REPLACE INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (215, 4, 260, 6, 26); -- Improved Instrument Mastery -INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (700, 1, 260, 2, 23); -INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (700, 2, 260, 2, 24); -INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (700, 3, 260, 2, 25); -INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (700, 4, 260, 2, 26); +REPLACE INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (700, 1, 260, 2, 23); +REPLACE INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (700, 2, 260, 2, 24); +REPLACE INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (700, 3, 260, 2, 25); +REPLACE INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (700, 4, 260, 2, 26); -- Singing Mastery -INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (275, 1, 260, 2, 50); -INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (276, 1, 260, 4, 50); -INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (277, 1, 260, 6, 50); +REPLACE INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (275, 1, 260, 2, 50); +REPLACE INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (276, 1, 260, 4, 50); +REPLACE INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (277, 1, 260, 6, 50); -- Improved Singing Mastery -INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (701, 1, 260, 2, 50); +REPLACE INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (701, 1, 260, 2, 50); From e1255af708a9c3fb85bed3c3549265ac31ef0cb7 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 14 Nov 2013 20:26:58 -0500 Subject: [PATCH 14/25] Fix Spell level restrictions I made an incorrect assumption, fixed now --- zone/spells.cpp | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 68997eec3..ee9164df9 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2724,20 +2724,15 @@ bool Client::CheckSpellLevelRestriction(uint16 spell_id) { int SpellLevel = GetMinLevel(spell_id); - // Only check for beneficial buffs, if it's a bard song, only if it's short duration - if(IsBuffSpell(spell_id) && IsBeneficialSpell(spell_id) && - !(IsBardSong(spell_id) && !IsShortDurationBuff(spell_id))) - { - if(SpellLevel > 65) - { - if(IsGroupSpell(spell_id) && GetLevel() < 62) + // Only check for beneficial buffs + if (IsBuffSpell(spell_id) && IsBeneficialSpell(spell_id)) { + if (SpellLevel > 65) { + if (IsGroupSpell(spell_id) && GetLevel() < 62) return false; - else if(GetLevel() < 61) + else if (GetLevel() < 61) return false; - } - else if(SpellLevel > 50) // 51-65 - { - if(GetLevel() < (SpellLevel/2+15)) + } else if (SpellLevel > 50) { // 51-56 + if (GetLevel() < (SpellLevel/2+15)) return false; } } From a40a34d2e8197d07f1ab87856a0b88e99f09105a Mon Sep 17 00:00:00 2001 From: Michael Cook Date: Fri, 15 Nov 2013 01:17:27 -0500 Subject: [PATCH 15/25] Fixed Mob::CalcFocusEffect()'s SE_LimitEffect --- changelog.txt | 3 +++ zone/spell_effects.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index 1a551977a..b0ad2df81 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 11/15/2013 == +demonstar55: Fixed Mob::CalcFocusEffect()'s SE_LimitEffect + == 11/13/2013 == demonstar55: Implemented bard song effect cap. You can set the base cap with the rule Character:BaseInstrumentSoftCap, defaults to 36 or "3.6" as it is sometimes referred to. demonstar55: Fix Echo of Taelosia and Ayonae's Tutelage to increase the mod cap instead of further improving the instrument mod diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index ba4200119..18e08030b 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -4279,7 +4279,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo case SE_LimitEffect: if(focus_spell.base[i] < 0){ - if(IsEffectInSpell(spell_id,focus_spell.base[i])){ //we limit this effect, can't have + if(IsEffectInSpell(spell_id,(focus_spell.base[i] * -1))){ //we limit this effect, can't have return 0; } } From 765b5ee8262741c4efaf164ef1ab311d618c8f4a Mon Sep 17 00:00:00 2001 From: Leere Date: Fri, 15 Nov 2013 18:03:13 +0100 Subject: [PATCH 16/25] Fix for a stacking issue with SE_StackingCommand_Block for druid skins --- changelog.txt | 1 + zone/spells.cpp | 119 +++++++++++++++++++++++++++++------------------- 2 files changed, 73 insertions(+), 47 deletions(-) diff --git a/changelog.txt b/changelog.txt index b0ad2df81..3c19d577f 100644 --- a/changelog.txt +++ b/changelog.txt @@ -2,6 +2,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 11/15/2013 == demonstar55: Fixed Mob::CalcFocusEffect()'s SE_LimitEffect +Leere: Fixed a stacking issue for SE_StackingCommand_Block == 11/13/2013 == demonstar55: Implemented bard song effect cap. You can set the base cap with the rule Character:BaseInstrumentSoftCap, defaults to 36 or "3.6" as it is sometimes referred to. diff --git a/zone/spells.cpp b/zone/spells.cpp index ee9164df9..d66f2d1d4 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2509,43 +2509,6 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, } } - - // check for special stacking block command in spell1 against spell2 - for(i = 0; i < EFFECT_COUNT; i++) - { - effect1 = sp1.effectid[i]; - if(effect1 == SE_StackingCommand_Block) - { - /* - The logic here is if you're comparing the same spells they can't block each other - from refreshing - */ - if(spellid1 == spellid2) - continue; - - blocked_effect = sp1.base[i]; - blocked_slot = sp1.formula[i] - 201; //they use base 1 for slots, we use base 0 - blocked_below_value = sp1.max[i]; - - if(sp2.effectid[blocked_slot] == blocked_effect) - { - sp2_value = CalcSpellEffectValue(spellid2, blocked_slot, caster_level2); - - mlog(SPELLS__STACKING, "%s (%d) blocks effect %d on slot %d below %d. New spell has value %d on that slot/effect. %s.", - sp1.name, spellid1, blocked_effect, blocked_slot, blocked_below_value, sp2_value, (sp2_value < blocked_below_value)?"Blocked":"Not blocked"); - - if(sp2_value < blocked_below_value) - { - mlog(SPELLS__STACKING, "Blocking spell because sp2_value < blocked_below_value"); - return -1; // blocked - } - } else { - mlog(SPELLS__STACKING, "%s (%d) blocks effect %d on slot %d below %d, but we do not have that effect on that slot. Ignored.", - sp1.name, spellid1, blocked_effect, blocked_slot, blocked_below_value); - } - } - } - // check for special stacking overwrite in spell2 against effects in spell1 for(i = 0; i < EFFECT_COUNT; i++) { @@ -2588,14 +2551,41 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, // arbitration takes place if 2 spells have the same effect at the same // effect slot, otherwise they're stackable, even if it's the same effect bool will_overwrite = false; + bool effect_match = true; // Figure out if we're identical in effects on all slots. for(i = 0; i < EFFECT_COUNT; i++) { - if(IsBlankSpellEffect(spellid1, i) || IsBlankSpellEffect(spellid2, i)) - continue; - effect1 = sp1.effectid[i]; effect2 = sp2.effectid[i]; + /* + Quick check, are the effects the same, if so then + keep going else ignore it for stacking purposes. + */ + if(effect1 != effect2) { + effect_match = false; + continue; + } + + // If both spells have SE_StackingCommand_Block in the slot then we check if + // it applies to the same slot and effect type. + // This is handled here because IsBlankSpellEffect() would block it otherwise, + // but for stacking we need to handle it. + if (effect1 == SE_StackingCommand_Block) { + if (sp1.formula[i] == sp2.formula[i] && sp1.base[i] == sp2.base[i]) { + if(sp1.max[i] > sp2.max[i]) { + return(-1); + } else { + continue; + } + } else { + effect_match = false; + continue; + } + } + + if(IsBlankSpellEffect(spellid1, i) || IsBlankSpellEffect(spellid2, i)) + continue; + //Effects which really aren't going to affect stacking. if(effect1 == SE_CurrentHPOnce || effect1 == SE_CurseCounter || @@ -2604,12 +2594,6 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, continue; } - /* - Quick check, are the effects the same, if so then - keep going else ignore it for stacking purposes. - */ - if(effect1 != effect2) - continue; /* Skip check if effect is SE_Limit* @@ -2698,9 +2682,50 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, will_overwrite = true; } + // check for special stacking block command in spell1 against spell2 + // This has to happen last so that we don't mess ourselves up for effect identical + // spells. They should just overwrite each other without needing the stacking block + if (!effect_match) + { + for(i = 0; i < EFFECT_COUNT; i++) + { + effect1 = sp1.effectid[i]; + if(effect1 == SE_StackingCommand_Block) + { + /* + The logic here is if you're comparing the same spells they can't block each other + from refreshing + */ + if(spellid1 == spellid2) + continue; + + blocked_effect = sp1.base[i]; + blocked_slot = sp1.formula[i] - 201; //they use base 1 for slots, we use base 0 + blocked_below_value = sp1.max[i]; + + if(sp2.effectid[blocked_slot] == blocked_effect) + { + sp2_value = CalcSpellEffectValue(spellid2, blocked_slot, caster_level2); + + mlog(SPELLS__STACKING, "%s (%d) blocks effect %d on slot %d below %d. New spell has value %d on that slot/effect. %s.", + sp1.name, spellid1, blocked_effect, blocked_slot, blocked_below_value, sp2_value, (sp2_value < blocked_below_value)?"Blocked":"Not blocked"); + + if(sp2_value < blocked_below_value) + { + mlog(SPELLS__STACKING, "Blocking spell because sp2_value < blocked_below_value"); + return -1; // blocked + } + } else { + mlog(SPELLS__STACKING, "%s (%d) blocks effect %d on slot %d below %d, but we do not have that effect on that slot. Ignored.", + sp1.name, spellid1, blocked_effect, blocked_slot, blocked_below_value); + } + } + } + } + //if we get here, then none of the values on the new spell are "worse" //so now we see if this new spell is any better, or if its not related at all - if(will_overwrite) { + if(will_overwrite || effect_match) { mlog(SPELLS__STACKING, "Stacking code decided that %s should overwrite %s.", sp2.name, sp1.name); return(1); } From 4c6fce5d5c2c4c2e47f8b46642fee3eef0d012ff Mon Sep 17 00:00:00 2001 From: JJ Date: Fri, 15 Nov 2013 19:31:43 -0500 Subject: [PATCH 17/25] Add a little more debug info to MQGate hack detection. --- zone/client_packet.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index f28008ae3..97c7e1277 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -917,7 +917,7 @@ void Client::CheatDetected(CheatTypes CheatType, float x, float y, float z) Message(13, "Large warp detected."); char hString[250]; sprintf(hString, "/MQWarp with location %.2f, %.2f, %.2f", GetX(), GetY(), GetZ()); - database.SetMQDetectionFlag(this->account_name,this->name, hString, zone->GetShortName()); + database.SetMQDetectionFlag(this->account_name, this->name, hString, zone->GetShortName()); } break; case MQWarpShadowStep: @@ -927,7 +927,7 @@ void Client::CheatDetected(CheatTypes CheatType, float x, float y, float z) { char *hString = nullptr; MakeAnyLenString(&hString, "/MQWarp(SS) with location %.2f, %.2f, %.2f, the target was shadow step exempt but we still found this suspicious.", GetX(), GetY(), GetZ()); - database.SetMQDetectionFlag(this->account_name,this->name, hString, zone->GetShortName()); + database.SetMQDetectionFlag(this->account_name, this->name, hString, zone->GetShortName()); safe_delete_array(hString); } break; @@ -938,7 +938,7 @@ void Client::CheatDetected(CheatTypes CheatType, float x, float y, float z) { char *hString = nullptr; MakeAnyLenString(&hString, "/MQWarp(KB) with location %.2f, %.2f, %.2f, the target was Knock Back exempt but we still found this suspicious.", GetX(), GetY(), GetZ()); - database.SetMQDetectionFlag(this->account_name,this->name, hString, zone->GetShortName()); + database.SetMQDetectionFlag(this->account_name, this->name, hString, zone->GetShortName()); safe_delete_array(hString); } break; @@ -952,7 +952,7 @@ void Client::CheatDetected(CheatTypes CheatType, float x, float y, float z) { char *hString = nullptr; MakeAnyLenString(&hString, "/MQWarp(LT) with location %.2f, %.2f, %.2f, running fast but not fast enough to get killed, possibly: small warp, speed hack, excessive lag, marked as suspicious.", GetX(), GetY(), GetZ()); - database.SetMQDetectionFlag(this->account_name,this->name, hString, zone->GetShortName()); + database.SetMQDetectionFlag(this->account_name, this->name, hString, zone->GetShortName()); safe_delete_array(hString); } } @@ -963,7 +963,7 @@ void Client::CheatDetected(CheatTypes CheatType, float x, float y, float z) { char hString[250]; sprintf(hString, "/MQZone used at %.2f, %.2f, %.2f to %.2f %.2f %.2f", GetX(), GetY(), GetZ(), x, y, z); - database.SetMQDetectionFlag(this->account_name,this->name, hString, zone->GetShortName()); + database.SetMQDetectionFlag(this->account_name, this->name, hString, zone->GetShortName()); } break; case MQZoneUnknownDest: @@ -971,13 +971,15 @@ void Client::CheatDetected(CheatTypes CheatType, float x, float y, float z) { char hString[250]; sprintf(hString, "/MQZone used at %.2f, %.2f, %.2f", GetX(), GetY(), GetZ()); - database.SetMQDetectionFlag(this->account_name,this->name, hString, zone->GetShortName()); + database.SetMQDetectionFlag(this->account_name, this->name, hString, zone->GetShortName()); } break; case MQGate: if (RuleB(Zone, EnableMQGateDetector)&& ((this->Admin() < RuleI(Zone, MQGateExemptStatus) || (RuleI(Zone, MQGateExemptStatus)) == -1))) { Message(13, "Illegal gate request."); - database.SetMQDetectionFlag(this->account_name,this->name, "/MQGate", zone->GetShortName()); + char hString[250]; + sprintf(hString, "/MQGate used at %.2f, %.2f, %.2f", GetX(), GetY(), GetZ()); + database.SetMQDetectionFlag(this->account_name, this->name, hString, zone->GetShortName()); if(zone) { this->SetZone(this->GetZoneID(), zone->GetInstanceID()); //Prevent the player from zoning, place him back in the zone where he tried to originally /gate. @@ -991,13 +993,13 @@ void Client::CheatDetected(CheatTypes CheatType, float x, float y, float z) break; case MQGhost: //Not currently implemented, but the framework is in place - just needs detection scenarios identified if (RuleB(Zone, EnableMQGhostDetector) && ((this->Admin() < RuleI(Zone, MQGhostExemptStatus) || (RuleI(Zone, MQGhostExemptStatus)) == -1))) { - database.SetMQDetectionFlag(this->account_name,this->name, "/MQGhost", zone->GetShortName()); + database.SetMQDetectionFlag(this->account_name, this->name, "/MQGhost", zone->GetShortName()); } break; default: char *hString = nullptr; MakeAnyLenString(&hString, "Unhandled HackerDetection flag with location %.2f, %.2f, %.2f.", GetX(), GetY(), GetZ()); - database.SetMQDetectionFlag(this->account_name,this->name, hString, zone->GetShortName()); + database.SetMQDetectionFlag(this->account_name, this->name, hString, zone->GetShortName()); safe_delete_array(hString); break; } From 6a95abb01f23ed07d6da8cb9575ac9ee3b1e85a9 Mon Sep 17 00:00:00 2001 From: Leere Date: Sat, 16 Nov 2013 03:40:35 +0100 Subject: [PATCH 18/25] Fix for auto-consume drinking message --- changelog.txt | 3 +++ zone/client.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index 3c19d577f..739a627ec 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 11/16/2013 == +Leere: Fixed the drinking message for auto-consume, it will again correctly show up for forced consumption instead. + == 11/15/2013 == demonstar55: Fixed Mob::CalcFocusEffect()'s SE_LimitEffect Leere: Fixed a stacking issue for SE_StackingCommand_Block diff --git a/zone/client.cpp b/zone/client.cpp index b043536b3..a9ac4968c 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -8032,7 +8032,7 @@ void Client::Consume(const Item_Struct *item, uint8 type, int16 slot, bool auto_ m_pp.thirst_level += tchange; DeleteItemInInventory(slot, 1, false); - if(auto_consume) //no message if the client consumed for us + if(!auto_consume) //no message if the client consumed for us entity_list.MessageClose_StringID(this, true, 50, 0, DRINKING_MESSAGE, GetName(), item->Name); #if EQDEBUG >= 1 From 3d5b3d1e8c6e1b1ffd86e29f6e8d3f2674b8cdc5 Mon Sep 17 00:00:00 2001 From: Michael Cook Date: Sun, 17 Nov 2013 00:31:17 -0500 Subject: [PATCH 19/25] Added Mob::DoCastingChecks() which checks for various casting fail conditions while casting --- changelog.txt | 1 + zone/mob.h | 2 ++ zone/spells.cpp | 60 ++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index 739a627ec..b07ca5597 100644 --- a/changelog.txt +++ b/changelog.txt @@ -2,6 +2,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 11/16/2013 == Leere: Fixed the drinking message for auto-consume, it will again correctly show up for forced consumption instead. +demonstar55: Added Mob::DoCastingChecks() which will check for various fail conditions while the casting bar is up. This is called after Mob::DoCastSpell() starts the casting and before it returns. == 11/15/2013 == demonstar55: Fixed Mob::CalcFocusEffect()'s SE_LimitEffect diff --git a/zone/mob.h b/zone/mob.h index eec54e57c..962bef3c8 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -198,6 +198,7 @@ public: void InterruptSpell(uint16, uint16, uint16 spellid = SPELL_UNKNOWN); inline bool IsCasting() const { return((casting_spell_id != 0)); } uint16 CastingSpellID() const { return casting_spell_id; } + bool DoCastingChecks(); //Buff void BuffProcess(); @@ -998,6 +999,7 @@ protected: uint32 casting_spell_timer_duration; uint32 casting_spell_type; int16 casting_spell_resist_adjust; + bool casting_spell_checks; uint16 bardsong; uint8 bardsong_slot; uint32 bardsong_target_id; diff --git a/zone/spells.cpp b/zone/spells.cpp index d66f2d1d4..a9294c906 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -115,7 +115,7 @@ void Mob::SpellProcess() } // a timed spell is finished casting - if (casting_spell_id != 0 && spellend_timer.Check()) + if (casting_spell_id != 0 && casting_spell_checks && spellend_timer.Check()) { spellend_timer.Disable(); delaytimer = false; @@ -474,9 +474,66 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot, entity_list.QueueCloseClients(this, outapp, false, 200, 0, true); //IsClient() ? FILTER_PCSPELLS : FILTER_NPCSPELLS); safe_delete(outapp); outapp = nullptr; + + if (!DoCastingChecks()) { + InterruptSpell(); + return false; + } + return(true); } +/* + * Some failures should be caught before the spell finishes casting + * This is especially helpful to clients when they cast really long things + * If this passes it sets casting_spell_checks to true which is checked in + * SpellProcess(), if a situation ever arises where a spell is delayed by these + * it's probably doing something wrong. + */ + +bool Mob::DoCastingChecks() +{ + if (!IsClient() || (IsClient() && CastToClient()->GetGM())) { + casting_spell_checks = true; + return true; + } + + uint16 spell_id = casting_spell_id; + Mob *spell_target = entity_list.GetMob(casting_spell_targetid); + + if (RuleB(Spells, BuffLevelRestrictions) && + !spell_target->CheckSpellLevelRestriction(spell_id)) { + mlog(SPELLS__BUFFS, "Spell %d failed: recipient did not meet the level restrictions", spell_id); + if (!IsBardSong(spell_id)) + Message_StringID(MT_SpellFailure, SPELL_TOO_POWERFUL); + return false; + } + + if (spells[spell_id].zonetype == 1 && !zone->CanCastOutdoor()) { + Message_StringID(13, CAST_OUTDOORS); + return false; + } + + if (IsEffectInSpell(spell_id, SE_Levitate) && !zone->CanLevitate()) { + Message(13, "You can't levitate in this zone."); + return false; + } + + if (zone->IsSpellBlocked(spell_id, GetX(), GetY(), GetZ())) { + const char *msg = zone->GetSpellBlockedMessage(spell_id, GetX(), GetY(), GetZ()); + if (msg) { + Message(13, msg); + return false; + } else { + Message(13, "You can't cast this spell here."); + return false; + } + } + + casting_spell_checks = true; + return true; +} + uint16 Mob::GetSpecializeSkillValue(uint16 spell_id) const { switch(spells[spell_id].skill) { case SkillAbjuration: @@ -687,6 +744,7 @@ void Mob::ZeroCastingVars() casting_spell_timer_duration = 0; casting_spell_type = 0; casting_spell_resist_adjust = 0; + casting_spell_checks = false; delaytimer = false; } From 36233538fda1ff77af2d0ed14ac5ffba0fb3c5bf Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 17 Nov 2013 00:34:58 -0500 Subject: [PATCH 20/25] Some whitespace fixes in zone/spells.cpp --- zone/spells.cpp | 200 ++++++++++++++++++++++-------------------------- 1 file changed, 90 insertions(+), 110 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index a9294c906..6bd65f4f4 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -16,9 +16,7 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - /* - General outline of spell casting process 1. @@ -64,14 +62,10 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) If this was timed, CastedSpellFinished() will restore the client's spell bar gems. - Most user code should call CastSpell(), with a 0 casting time if needed, and not SpellFinished(). - */ - - #include "../common/debug.h" #include "../common/spdat.h" #include "masterentity.h" @@ -88,8 +82,8 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) #include #ifndef WIN32 - #include - #include "../common/unix.h" + #include + #include "../common/unix.h" #endif #ifdef _GOTFRAGS @@ -342,7 +336,6 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot, mlog(SPELLS__CASTING, "DoCastSpell called for spell %s (%d) on entity %d, slot %d, time %d, mana %d, from item %d", spell.name, spell_id, target_id, slot, cast_time, mana_cost, item_slot==0xFFFFFFFF?999:item_slot); - casting_spell_id = spell_id; casting_spell_slot = slot; casting_spell_inventory_slot = item_slot; @@ -1165,52 +1158,52 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, if(IsClient() && ((slot == USE_ITEM_SPELL_SLOT) || (slot == POTION_BELT_SPELL_SLOT)) && inventory_slot != 0xFFFFFFFF) // 10 is an item { - bool fromaug = false; - const ItemInst* inst = CastToClient()->GetInv()[inventory_slot]; - Item_Struct* augitem = 0; - uint32 recastdelay = 0; - uint32 recasttype = 0; + bool fromaug = false; + const ItemInst* inst = CastToClient()->GetInv()[inventory_slot]; + Item_Struct* augitem = 0; + uint32 recastdelay = 0; + uint32 recasttype = 0; - for(int r = 0; r < MAX_AUGMENT_SLOTS; r++) { - const ItemInst* aug_i = inst->GetAugment(r); + for(int r = 0; r < MAX_AUGMENT_SLOTS; r++) { + const ItemInst* aug_i = inst->GetAugment(r); - if(!aug_i) - continue; - const Item_Struct* aug = aug_i->GetItem(); - if(!aug) - continue; + if(!aug_i) + continue; + const Item_Struct* aug = aug_i->GetItem(); + if(!aug) + continue; - if ( aug->Click.Effect == spell_id ) - { - recastdelay = aug_i->GetItem()->RecastDelay; - recasttype = aug_i->GetItem()->RecastType; - fromaug = true; - break; - } - } + if ( aug->Click.Effect == spell_id ) + { + recastdelay = aug_i->GetItem()->RecastDelay; + recasttype = aug_i->GetItem()->RecastType; + fromaug = true; + break; + } + } - //Test the aug recast delay - if(IsClient() && fromaug && recastdelay > 0) - { - if(!CastToClient()->GetPTimers().Expired(&database, (pTimerItemStart + recasttype), false)) { - Message_StringID(13, SPELL_RECAST); - mlog(SPELLS__CASTING_ERR, "Casting of %d canceled: item spell reuse timer not expired", spell_id); - InterruptSpell(); - return; - } - else - { - //Can we start the timer here? I don't see why not. - CastToClient()->GetPTimers().Start((pTimerItemStart + recasttype), recastdelay); - } - } + //Test the aug recast delay + if(IsClient() && fromaug && recastdelay > 0) + { + if(!CastToClient()->GetPTimers().Expired(&database, (pTimerItemStart + recasttype), false)) { + Message_StringID(13, SPELL_RECAST); + mlog(SPELLS__CASTING_ERR, "Casting of %d canceled: item spell reuse timer not expired", spell_id); + InterruptSpell(); + return; + } + else + { + //Can we start the timer here? I don't see why not. + CastToClient()->GetPTimers().Start((pTimerItemStart + recasttype), recastdelay); + } + } if (inst && inst->IsType(ItemClassCommon) && (inst->GetItem()->Click.Effect == spell_id) && inst->GetCharges() || fromaug) { //const Item_Struct* item = inst->GetItem(); int16 charges = inst->GetItem()->MaxCharges; - if(fromaug) { charges = -1; } //Don't destroy the parent item + if(fromaug) { charges = -1; } //Don't destroy the parent item if(charges > -1) { // charged item, expend a charge mlog(SPELLS__CASTING, "Spell %d: Consuming a charge from item %s (%d) which had %d/%d charges.", spell_id, inst->GetItem()->Name, inst->GetItem()->ID, inst->GetCharges(), inst->GetItem()->MaxCharges); @@ -1787,7 +1780,6 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 } } - //determine the type of spell target we have CastAction_type CastAction; if(!DetermineSpellTargets(spell_id, spell_target, ae_center, CastAction)) @@ -1879,8 +1871,8 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 if(!SpellOnTarget(spell_id, spell_target, false, true, resist_adjust, false)) { if(IsBuffSpell(spell_id) && IsBeneficialSpell(spell_id)) { // Prevent mana usage/timers being set for beneficial buffs - if(casting_spell_type == 1) - InterruptSpell(); + if(casting_spell_type == 1) + InterruptSpell(); return false; } } @@ -2161,7 +2153,6 @@ bool Mob::ApplyNextBardPulse(uint16 spell_id, Mob *spell_target, uint16 slot) { SetMana(GetMana() - mana_used); } - // check line of sight to target if it's a detrimental spell if(spell_target && IsDetrimentalSpell(spell_id) && !CheckLosFN(spell_target)) { @@ -2429,7 +2420,7 @@ int Mob::CalcBuffDuration(Mob *caster, Mob *target, uint16 spell_id, int32 caste castlevel = caster_level_override; int res = CalcBuffDuration_formula(castlevel, formula, duration); - + res = mod_buff_duration(res, caster, target, spell_id); mlog(SPELLS__CASTING, "Spell %d: Casting level %d, formula %d, base_duration %d: result %d", @@ -2652,7 +2643,6 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, continue; } - /* Skip check if effect is SE_Limit* skip checking effect2 since we know they are equal @@ -2989,7 +2979,6 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid SendPetBuffsToClient(); } - if((IsClient() && !CastToClient()->GetPVP()) || (IsPet() && GetOwner() && GetOwner()->IsClient() && !GetOwner()->CastToClient()->GetPVP()) || (IsMerc() && GetOwner() && GetOwner()->IsClient() && !GetOwner()->CastToClient()->GetPVP())) { @@ -3181,7 +3170,6 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r // send to people in the area, ignoring caster and target entity_list.QueueCloseClients(spelltar, action_packet, true, 200, this, true, spelltar->IsClient() ? FilterPCSpells : FilterNPCSpells); - /* Send the EVENT_CAST_ON event */ if(spelltar->IsNPC()) { @@ -3312,7 +3300,6 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r } - if(!IsBeneficialAllowed(spelltar) || (IsGroupOnlySpell(spell_id) && !( @@ -3349,7 +3336,6 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r // ok at this point the spell is permitted to affect the target, // but we need to check special cases and resists - // check immunities if(spelltar->IsImmuneToSpell(spell_id, this)) { @@ -4092,7 +4078,6 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use } } - if (!CharismaCheck){ //Check for Spell Effect specific resistance chances (ie AA Mental Fortitude) @@ -4188,60 +4173,60 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use resist_chance = 0; } - //Adjust our resist chance based on level modifiers - int temp_level_diff = GetLevel() - caster->GetLevel(); - if(IsNPC() && GetLevel() >= RuleI(Casting,ResistFalloff)) - { - int a = (RuleI(Casting,ResistFalloff)-1) - caster->GetLevel(); - if(a > 0) - { - temp_level_diff = a; - } - else - { - temp_level_diff = 0; - } - } + //Adjust our resist chance based on level modifiers + int temp_level_diff = GetLevel() - caster->GetLevel(); + if(IsNPC() && GetLevel() >= RuleI(Casting,ResistFalloff)) + { + int a = (RuleI(Casting,ResistFalloff)-1) - caster->GetLevel(); + if(a > 0) + { + temp_level_diff = a; + } + else + { + temp_level_diff = 0; + } + } - if(IsClient() && GetLevel() >= 21 && temp_level_diff > 15) - { - temp_level_diff = 15; - } + if(IsClient() && GetLevel() >= 21 && temp_level_diff > 15) + { + temp_level_diff = 15; + } - if(IsNPC() && temp_level_diff < -9) - { - temp_level_diff = -9; - } + if(IsNPC() && temp_level_diff < -9) + { + temp_level_diff = -9; + } - int level_mod = temp_level_diff * temp_level_diff / 2; - if(temp_level_diff < 0) - { - level_mod = -level_mod; - } + int level_mod = temp_level_diff * temp_level_diff / 2; + if(temp_level_diff < 0) + { + level_mod = -level_mod; + } - if(IsNPC() && (caster->GetLevel() - GetLevel()) < -20) - { - level_mod = 1000; - } + if(IsNPC() && (caster->GetLevel() - GetLevel()) < -20) + { + level_mod = 1000; + } - //Even more level stuff this time dealing with damage spells - if(IsNPC() && IsDamageSpell(spell_id) && GetLevel() >= 17) - { - int level_diff; - if(GetLevel() >= RuleI(Casting,ResistFalloff)) - { - level_diff = (RuleI(Casting,ResistFalloff)-1) - caster->GetLevel(); - if(level_diff < 0) - { - level_diff = 0; - } - } - else - { - level_diff = GetLevel() - caster->GetLevel(); - } - level_mod += (2 * level_diff); - } + //Even more level stuff this time dealing with damage spells + if(IsNPC() && IsDamageSpell(spell_id) && GetLevel() >= 17) + { + int level_diff; + if(GetLevel() >= RuleI(Casting,ResistFalloff)) + { + level_diff = (RuleI(Casting,ResistFalloff)-1) - caster->GetLevel(); + if(level_diff < 0) + { + level_diff = 0; + } + } + else + { + level_diff = GetLevel() - caster->GetLevel(); + } + level_mod += (2 * level_diff); + } if (CharismaCheck) { @@ -4801,7 +4786,6 @@ uint16 Mob::GetSpellIDFromSlot(uint8 slot) return 0; } - bool Mob::FindType(uint16 type, bool bOffensive, uint16 threshold) { uint32 buff_count = GetMaxTotalSlots(); for (int i = 0; i < buff_count; i++) { @@ -5000,7 +4984,6 @@ int Mob::GetCasterLevel(uint16 spell_id) { return(level); } - //this method does NOT tell the client to stop singing the song. //this is NOT the right way to stop a mob from singing, use InterruptSpell //you should really know what your doing before you call this @@ -5043,7 +5026,6 @@ void Mob::SendPetBuffsToClient() int PetBuffCount = 0; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_PetBuffWindow,sizeof(PetBuff_Struct)); PetBuff_Struct* pbs=(PetBuff_Struct*)outapp->pBuffer; memset(outapp->pBuffer,0,outapp->size); @@ -5122,8 +5104,6 @@ EQApplicationPacket *Mob::MakeBuffsPacket(bool for_target) return outapp; } - - void Mob::BuffModifyDurationBySpellID(uint16 spell_id, int32 newDuration) { uint32 buff_count = GetMaxTotalSlots(); From 09dd3c1b3759d8cefe95060bc088460386f5c9b8 Mon Sep 17 00:00:00 2001 From: Michael Cook Date: Sun, 17 Nov 2013 19:37:49 -0500 Subject: [PATCH 21/25] Fixed an issue that arose from 78ab3471 Reworked how Mob::_GetMovementSpeed worked to fix an issue of walking with a sufficiently high movemod. Added a rule Character:BaseRunSpeedCap (default 158) to control the cap on runspeed from buffs. Hardcapped to 225 for sanity's sake. --- changelog.txt | 4 ++ common/ruletypes.h | 1 + zone/mob.cpp | 93 +++++++++++++++++++++++----------------------- 3 files changed, 51 insertions(+), 47 deletions(-) diff --git a/changelog.txt b/changelog.txt index b07ca5597..3ef9cdd30 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 11/17/2013 == +demonstar55: Rewrote the Mob::_GetMovementSpeed fix an issue that arose from the change on 11/11 + - Added the rule Character:BaseRunSpeedCap (default 158) so people can customize what their runspeed cap is. Hardcapped to 225 so stuff doesn't get too crazy. + == 11/16/2013 == Leere: Fixed the drinking message for auto-consume, it will again correctly show up for forced consumption instead. demonstar55: Added Mob::DoCastingChecks() which will check for various fail conditions while the casting bar is up. This is called after Mob::DoCastSpell() starts the casting and before it returns. diff --git a/common/ruletypes.h b/common/ruletypes.h index 4b5608ae8..bc10cbf9b 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -98,6 +98,7 @@ RULE_BOOL ( Character, EnableXTargetting, true) // Enable Extended Targetting Wi RULE_BOOL ( Character, KeepLevelOverMax, false) // Don't delevel a character that has somehow gone over the level cap RULE_INT ( Character, FoodLossPerUpdate, 35) // How much food/water you lose per stamina update RULE_INT ( Character, BaseInstrumentSoftCap, 36) // Softcap for instrument mods, 36 commonly referred to as "3.6" as well. +RULE_INT ( Character, BaseRunSpeedCap, 158) // Base Run Speed Cap, on live it's 158% which will give you a runspeed of 1.580 hard capped to 225. RULE_CATEGORY_END() RULE_CATEGORY( Mercs ) diff --git a/zone/mob.cpp b/zone/mob.cpp index d5afff3c2..820db7beb 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -517,76 +517,75 @@ bool Mob::IsInvisible(Mob* other) const return(false); } -float Mob::_GetMovementSpeed(int mod) const { +float Mob::_GetMovementSpeed(int mod) const +{ // List of movement speed modifiers, including AAs & spells: // http://everquest.allakhazam.com/db/item.html?item=1721;page=1;howmany=50#m10822246245352 if (IsRooted()) return 0.0f; - float aa_mod = 0.0f; float speed_mod = runspeed; - bool has_horse = false; - if (IsClient()) - { - if(CastToClient()->GetGMSpeed()) - { + + // These two cases ignore the cap, be wise in the DB for horses. + if (IsClient()) { + if (CastToClient()->GetGMSpeed()) { speed_mod = 3.125f; - } - else - { - Mob* horse = entity_list.GetMob(CastToClient()->GetHorseId()); - if(horse) - { + if (mod != 0) + speed_mod += speed_mod * static_cast(mod) / 100.0f; + return speed_mod; + } else { + Mob *horse = entity_list.GetMob(CastToClient()->GetHorseId()); + if (horse) { speed_mod = horse->GetBaseRunspeed(); - has_horse = true; + if (mod != 0) + speed_mod += speed_mod * static_cast(mod) / 100.0f; + return speed_mod; } } } - aa_mod += itembonuses.BaseMovementSpeed + spellbonuses.BaseMovementSpeed + aabonuses.BaseMovementSpeed; - - int spell_mod = spellbonuses.movementspeed + itembonuses.movementspeed; + int aa_mod = 0; + int spell_mod = 0; + int runspeedcap = RuleI(Character,BaseRunSpeedCap); int movemod = 0; + float frunspeedcap = 0.0f; - if(spell_mod < 0) - { + runspeedcap += itembonuses.IncreaseRunSpeedCap + spellbonuses.IncreaseRunSpeedCap + aabonuses.IncreaseRunSpeedCap; + aa_mod += itembonuses.BaseMovementSpeed + spellbonuses.BaseMovementSpeed + aabonuses.BaseMovementSpeed; + spell_mod += spellbonuses.movementspeed + itembonuses.movementspeed; + + // hard cap + if (runspeedcap > 225) + runspeedcap = 225; + + if (spell_mod < 0) movemod += spell_mod; - } - else if(spell_mod > (aa_mod)) - { + else if (spell_mod > aa_mod) movemod = spell_mod; - } else - { - movemod = static_cast(aa_mod); - } + movemod = aa_mod; - if(movemod < -85) //cap it at moving very very slow + // cap negative movemods from snares mostly + if (movemod < -85) movemod = -85; - if(mod != 0) // passing -47 for walking shouldn't be effected by cap above - movemod += mod; + if (movemod != 0) + speed_mod += speed_mod * static_cast(movemod) / 100.0f; - if (!has_horse && movemod != 0) - speed_mod += (speed_mod * float(movemod) / 100.0f); + // runspeed caps + frunspeedcap = static_cast(runspeedcap) / 100.0f; + if (IsClient() && speed_mod > frunspeedcap) + speed_mod = frunspeedcap; - if(speed_mod <= 0.0f) - return (IsClient() ? 0.0001f : 0.0f); + // apply final mod such as the -47 for walking + // use runspeed since it should stack with snares + // and if we get here, we know runspeed was the initial + // value before we applied movemod. + if (mod != 0) + speed_mod += runspeed * static_cast(mod) / 100.0f; - //runspeed cap. - if(IsClient()) - { - if (speed_mod > 1.58){ - uint8 bonus_IncreaseRunSpeedCap = itembonuses.IncreaseRunSpeedCap + spellbonuses.IncreaseRunSpeedCap + aabonuses.IncreaseRunSpeedCap; - if (bonus_IncreaseRunSpeedCap){ - speed_mod += float(bonus_IncreaseRunSpeedCap)/100.0f; - if(speed_mod > 1.74) - speed_mod = 1.74; - } - else - speed_mod = 1.58; - } - } + if (speed_mod <= 0.0f) + speed_mod = IsClient() ? 0.0001f : 0.0f; return speed_mod; } From 65e36e02fb80e820f989eaf94aadac47b49149d0 Mon Sep 17 00:00:00 2001 From: Sorvani Date: Sun, 17 Nov 2013 20:55:44 -0600 Subject: [PATCH 22/25] fixed leash and tether to correctly used specified range. --- changelog.txt | 1 + zone/MobAI.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/changelog.txt b/changelog.txt index 3ef9cdd30..e252cd1aa 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 11/17/2013 == +Sorvani: fixed leash and tether special abilities to use the specified range correctly. demonstar55: Rewrote the Mob::_GetMovementSpeed fix an issue that arose from the change on 11/11 - Added the rule Character:BaseRunSpeedCap (default 158) so people can customize what their runspeed cap is. Hardcapped to 225 so stuff doesn't get too crazy. diff --git a/zone/MobAI.cpp b/zone/MobAI.cpp index 7840444c0..4be72f7f9 100644 --- a/zone/MobAI.cpp +++ b/zone/MobAI.cpp @@ -1090,14 +1090,14 @@ void Mob::AI_Process() { if(GetSpecialAbility(TETHER)) { float aggro_range = static_cast(GetSpecialAbilityParam(TETHER, 0)); - aggro_range = aggro_range > 0.0f ? aggro_range : pAggroRange * pAggroRange; + aggro_range = aggro_range > 0.0f ? aggro_range * aggro_range : pAggroRange * pAggroRange; if(DistNoRootNoZ(CastToNPC()->GetSpawnPointX(), CastToNPC()->GetSpawnPointY()) > aggro_range) { GMMove(CastToNPC()->GetSpawnPointX(), CastToNPC()->GetSpawnPointY(), CastToNPC()->GetSpawnPointZ(), CastToNPC()->GetSpawnPointH()); } } else if(GetSpecialAbility(LEASH)) { float aggro_range = static_cast(GetSpecialAbilityParam(LEASH, 0)); - aggro_range = aggro_range > 0.0f ? aggro_range : pAggroRange * pAggroRange; + aggro_range = aggro_range > 0.0f ? aggro_range * aggro_range : pAggroRange * pAggroRange; if(DistNoRootNoZ(CastToNPC()->GetSpawnPointX(), CastToNPC()->GetSpawnPointY()) > aggro_range) { GMMove(CastToNPC()->GetSpawnPointX(), CastToNPC()->GetSpawnPointY(), CastToNPC()->GetSpawnPointZ(), CastToNPC()->GetSpawnPointH()); From 300799fdc8d0ff903752d185edb82173db536ecb Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 18 Nov 2013 12:44:39 -0500 Subject: [PATCH 23/25] Added npc_types.assistradius, defaults to npc_types.aggroradius if set to 0 --- changelog.txt | 3 +++ utils/sql/git/required/2013_11_18_AssistRadius.sql | 1 + zone/command.cpp | 10 ++++++++++ zone/npc.cpp | 2 +- zone/zonedb.cpp | 4 ++++ zone/zonedump.h | 1 + 6 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 utils/sql/git/required/2013_11_18_AssistRadius.sql diff --git a/changelog.txt b/changelog.txt index e252cd1aa..50c9373bd 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 11/18/2013 == +demonstar55: Added assistradius to npc_types, defaults to aggroradius if set to 0 (old behaviour) + == 11/17/2013 == Sorvani: fixed leash and tether special abilities to use the specified range correctly. demonstar55: Rewrote the Mob::_GetMovementSpeed fix an issue that arose from the change on 11/11 diff --git a/utils/sql/git/required/2013_11_18_AssistRadius.sql b/utils/sql/git/required/2013_11_18_AssistRadius.sql new file mode 100644 index 000000000..d42ba77fc --- /dev/null +++ b/utils/sql/git/required/2013_11_18_AssistRadius.sql @@ -0,0 +1 @@ +ALTER TABLE `npc_types` ADD `assistradius` INT( 10 ) UNSIGNED NOT NULL DEFAULT '0' AFTER `aggroradius`; diff --git a/zone/command.cpp b/zone/command.cpp index f9fc24832..0b562d6c8 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -6647,6 +6647,7 @@ void command_npcedit(Client *c, const Seperator *sep) c->Message(0, "#npcedit Mindmg - Sets an NPCs minimum damage"); c->Message(0, "#npcedit Maxdmg - Sets an NPCs maximum damage"); c->Message(0, "#npcedit Aggroradius - Sets an NPCs aggro radius"); + c->Message(0, "#npcedit Assistradius - Sets an NPCs assist radius"); c->Message(0, "#npcedit Social - Set to 1 if an NPC should assist others on its faction"); c->Message(0, "#npcedit Runspeed - Sets an NPCs run speed"); c->Message(0, "#npcedit MR - Sets an NPCs magic resistance"); @@ -6853,6 +6854,15 @@ void command_npcedit(Client *c, const Seperator *sep) c->LogSQL(query); safe_delete_array(query); } + else if ( strcasecmp( sep->arg[1], "assistradius" ) == 0 ) + { + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + c->Message(15,"NPCID %u now has an assist radius of %i",c->GetTarget()->CastToNPC()->GetNPCTypeID(),atoi(sep->arg[2])); + database.RunQuery(query, MakeAnyLenString(&query, "update npc_types set assistradius=%i where id=%i",atoi(sep->argplus[2]),c->GetTarget()->CastToNPC()->GetNPCTypeID()), errbuf); + c->LogSQL(query); + safe_delete_array(query); + } else if ( strcasecmp( sep->arg[1], "social" ) == 0 ) { char errbuf[MYSQL_ERRMSG_SIZE]; diff --git a/zone/npc.cpp b/zone/npc.cpp index ca10b7406..58d632d1a 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -148,7 +148,7 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, float x, float y, float z, float logging_enabled = NPC_DEFAULT_LOGGING_ENABLED; pAggroRange = d->aggroradius; - pAssistRange = GetAggroRange(); + pAssistRange = d->assistradius; findable = d->findable; trackable = d->trackable; diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 776ff9cfd..e1e5194df 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1046,6 +1046,7 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { "npc_types.hp_regen_rate," "npc_types.mana_regen_rate," "npc_types.aggroradius," + "npc_types.assistradius," "npc_types.bodytype," "npc_types.npc_faction_id," "npc_types.face," @@ -1145,6 +1146,9 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { // set defaultvalue for aggroradius if (tmpNPCType->aggroradius <= 0) tmpNPCType->aggroradius = 70; + tmpNPCType->assistradius = (int32)atoi(row[r++]); + if (tmpNPCType->assistradius <= 0) + tmpNPCType->assistradius = tmpNPCType->aggroradius; if (row[r] && strlen(row[r])) tmpNPCType->bodytype = (uint8)atoi(row[r]); diff --git a/zone/zonedump.h b/zone/zonedump.h index 65774d078..726041d5b 100644 --- a/zone/zonedump.h +++ b/zone/zonedump.h @@ -97,6 +97,7 @@ struct NPCType int32 hp_regen; int32 mana_regen; int32 aggroradius; // added for AI improvement - neotokyo + int32 assistradius; // assist radius, defaults to aggroradis if not set uint8 see_invis; // See Invis flag added bool see_invis_undead; // See Invis vs. Undead flag added bool see_hide; From 86bba4ff0e02f6cec222cfe8bc1d786168f9d644 Mon Sep 17 00:00:00 2001 From: Sorvani Date: Mon, 18 Nov 2013 13:53:21 -0600 Subject: [PATCH 24/25] changed aggro_range to leach_range and tether_range appropriately --- zone/MobAI.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/zone/MobAI.cpp b/zone/MobAI.cpp index 4be72f7f9..689854a17 100644 --- a/zone/MobAI.cpp +++ b/zone/MobAI.cpp @@ -1089,17 +1089,17 @@ void Mob::AI_Process() { return; if(GetSpecialAbility(TETHER)) { - float aggro_range = static_cast(GetSpecialAbilityParam(TETHER, 0)); - aggro_range = aggro_range > 0.0f ? aggro_range * aggro_range : pAggroRange * pAggroRange; + float tether_range = static_cast(GetSpecialAbilityParam(TETHER, 0)); + tether_range = tether_range > 0.0f ? tether_range * tether_range : pAggroRange * pAggroRange; - if(DistNoRootNoZ(CastToNPC()->GetSpawnPointX(), CastToNPC()->GetSpawnPointY()) > aggro_range) { + if(DistNoRootNoZ(CastToNPC()->GetSpawnPointX(), CastToNPC()->GetSpawnPointY()) > tether_range) { GMMove(CastToNPC()->GetSpawnPointX(), CastToNPC()->GetSpawnPointY(), CastToNPC()->GetSpawnPointZ(), CastToNPC()->GetSpawnPointH()); } } else if(GetSpecialAbility(LEASH)) { - float aggro_range = static_cast(GetSpecialAbilityParam(LEASH, 0)); - aggro_range = aggro_range > 0.0f ? aggro_range * aggro_range : pAggroRange * pAggroRange; + float leash_range = static_cast(GetSpecialAbilityParam(LEASH, 0)); + leash_range = leash_range > 0.0f ? leash_range * leash_range : pAggroRange * pAggroRange; - if(DistNoRootNoZ(CastToNPC()->GetSpawnPointX(), CastToNPC()->GetSpawnPointY()) > aggro_range) { + if(DistNoRootNoZ(CastToNPC()->GetSpawnPointX(), CastToNPC()->GetSpawnPointY()) > leash_range) { GMMove(CastToNPC()->GetSpawnPointX(), CastToNPC()->GetSpawnPointY(), CastToNPC()->GetSpawnPointZ(), CastToNPC()->GetSpawnPointH()); SetHP(GetMaxHP()); BuffFadeAll(); From 917a8ed389effba6df419aacce52c5ffb2e20421 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 18 Nov 2013 16:21:10 -0500 Subject: [PATCH 25/25] Fix some errors in comments --- zone/spells.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 6bd65f4f4..708347716 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2787,7 +2787,7 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, // derived from http://samanna.net/eq.general/buffs.shtml // spells 1-50: no restrictons // 51-65: SpellLevel/2+15 -// 66+L Group Spells 62, Single Target 61 +// 66+ Group Spells 62, Single Target 61 bool Mob::CheckSpellLevelRestriction(uint16 spell_id) { return true; @@ -2804,8 +2804,8 @@ bool Client::CheckSpellLevelRestriction(uint16 spell_id) return false; else if (GetLevel() < 61) return false; - } else if (SpellLevel > 50) { // 51-56 - if (GetLevel() < (SpellLevel/2+15)) + } else if (SpellLevel > 50) { // 51-65 + if (GetLevel() < (SpellLevel / 2 + 15)) return false; } }