From 8aadc3632002696a9feada53d582e2e61b517ed7 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 23 May 2015 02:20:36 -0400 Subject: [PATCH] Rework buff duration formulas These are derived from the client SE_IllusionPresistence will also set the duration to 10k tics like live --- common/eq_packet_structs.h | 18 +-- common/patches/rof2_structs.h | 10 +- common/patches/rof_structs.h | 10 +- common/patches/sod_structs.h | 4 +- common/patches/sof_structs.h | 4 +- common/patches/titanium_structs.h | 4 +- common/patches/uf_structs.h | 8 +- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + .../git/required/2015_05_23_BuffDurations.sql | 2 + zone/bonuses.cpp | 2 +- zone/effects.cpp | 24 ++-- zone/mob.h | 2 +- zone/spell_effects.cpp | 4 +- zone/spells.cpp | 129 +++++++++--------- zone/zonedb.cpp | 12 +- 16 files changed, 116 insertions(+), 120 deletions(-) create mode 100644 utils/sql/git/required/2015_05_23_BuffDurations.sql diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index f91107a14..e5ab88e57 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -553,7 +553,7 @@ struct SpellBuff_Struct /*002*/ uint8 bard_modifier; /*003*/ uint8 effect; //not real /*004*/ uint32 spellid; -/*008*/ uint32 duration; +/*008*/ int32 duration; /*012*/ uint32 counters; /*016*/ uint32 player_id; //'global' ID of the caster, for wearoff messages /*020*/ @@ -566,7 +566,7 @@ struct SpellBuffFade_Struct { /*006*/ uint8 effect; /*007*/ uint8 unknown7; /*008*/ uint32 spellid; -/*012*/ uint32 duration; +/*012*/ int32 duration; /*016*/ uint32 num_hits; /*020*/ uint32 unknown020; //prolly global player ID /*024*/ uint32 slotid; @@ -584,14 +584,8 @@ struct BuffRemoveRequest_Struct struct PetBuff_Struct { /*000*/ uint32 petid; -/*004*/ uint32 spellid[BUFF_COUNT]; -/*104*/ uint32 unknown700; -/*108*/ uint32 unknown701; -/*112*/ uint32 unknown702; -/*116*/ uint32 unknown703; -/*120*/ uint32 unknown704; -/*124*/ uint32 ticsremaining[BUFF_COUNT]; -/*224*/ uchar unknown705[20]; +/*004*/ uint32 spellid[BUFF_COUNT+5]; +/*124*/ int32 ticsremaining[BUFF_COUNT+5]; /*244*/ uint32 buffcount; }; @@ -4036,7 +4030,7 @@ struct MarkNPC_Struct struct InspectBuffs_Struct { /*000*/ uint32 spell_id[BUFF_COUNT]; -/*100*/ uint32 tics_remaining[BUFF_COUNT]; +/*100*/ int32 tics_remaining[BUFF_COUNT]; }; struct RaidGeneral_Struct { @@ -4737,7 +4731,7 @@ struct BuffIconEntry_Struct { uint32 buff_slot; uint32 spell_id; - uint32 tics_remaining; + int32 tics_remaining; uint32 num_hits; }; diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 4aac9e7de..a572a3834 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -687,7 +687,7 @@ struct SpellBuff_Struct /*005*/ uint32 player_id; // 'global' ID of the caster, for wearoff messages /*009*/ uint32 unknown016; /*013*/ uint8 bard_modifier; -/*014*/ uint32 duration; +/*014*/ int32 duration; /*018*/ uint8 level; /*019*/ uint32 spellid; /*023*/ uint32 counters; @@ -703,7 +703,7 @@ struct SpellBuff_Struct_Old /*003*/ uint8 effect; // not real /*004*/ float unknown004; // Seen 1 for no buff /*008*/ uint32 spellid; -/*012*/ uint32 duration; +/*012*/ int32 duration; /*016*/ uint32 unknown016; /*020*/ uint32 player_id; // 'global' ID of the caster, for wearoff messages /*024*/ uint32 counters; @@ -720,7 +720,7 @@ struct SpellBuffFade_Struct_Live { /*007*/ uint8 unknown007; /*008*/ float unknown008; /*012*/ uint32 spellid; -/*016*/ uint32 duration; +/*016*/ int32 duration; /*020*/ uint32 playerId; // Global player ID? /*024*/ uint32 num_hits; /*028*/ uint8 unknown0028[64]; @@ -736,7 +736,7 @@ struct SpellBuffFade_Struct { /*006*/ uint8 effect; /*007*/ uint8 unknown7; /*008*/ uint32 spellid; -/*012*/ uint32 duration; +/*012*/ int32 duration; /*016*/ uint32 num_hits; /*020*/ uint32 unknown020; // Global player ID? /*024*/ uint32 playerId; // Player id who cast the buff @@ -2473,7 +2473,7 @@ struct GroupFollow_Struct { // Live Follow Struct struct InspectBuffs_Struct { /*000*/ uint32 spell_id[BUFF_COUNT]; -/*168*/ uint32 tics_remaining[BUFF_COUNT]; +/*168*/ int32 tics_remaining[BUFF_COUNT]; }; struct LFG_Struct { diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 8fcfdb21d..7db21597c 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -676,7 +676,7 @@ struct SpellBuff_Struct /*005*/ uint32 player_id; // 'global' ID of the caster, for wearoff messages /*009*/ uint32 unknown016; /*013*/ uint8 bard_modifier; -/*014*/ uint32 duration; +/*014*/ int32 duration; /*018*/ uint8 level; /*019*/ uint32 spellid; /*023*/ uint32 counters; @@ -692,7 +692,7 @@ struct SpellBuff_Struct_Old /*003*/ uint8 effect; // not real /*004*/ float unknown004; // Seen 1 for no buff /*008*/ uint32 spellid; -/*012*/ uint32 duration; +/*012*/ int32 duration; /*016*/ uint32 unknown016; /*020*/ uint32 player_id; // 'global' ID of the caster, for wearoff messages /*024*/ uint32 counters; @@ -709,7 +709,7 @@ struct SpellBuffFade_Struct_Live { /*007*/ uint8 unknown007; /*008*/ float unknown008; /*012*/ uint32 spellid; -/*016*/ uint32 duration; +/*016*/ int32 duration; /*020*/ uint32 playerId; // Global player ID? /*024*/ uint32 num_hits; /*028*/ uint8 unknown0028[64]; @@ -725,7 +725,7 @@ struct SpellBuffFade_Struct { /*006*/ uint8 effect; /*007*/ uint8 unknown7; /*008*/ uint32 spellid; -/*012*/ uint32 duration; +/*012*/ int32 duration; /*016*/ uint32 num_hits; /*020*/ uint32 unknown020; // Global player ID? /*024*/ uint32 playerId; // Player id who cast the buff @@ -2501,7 +2501,7 @@ struct GroupFollow_Struct { // Live Follow Struct struct InspectBuffs_Struct { /*000*/ uint32 spell_id[BUFF_COUNT]; -/*168*/ uint32 tics_remaining[BUFF_COUNT]; +/*168*/ int32 tics_remaining[BUFF_COUNT]; }; struct LFG_Struct { diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 584318a71..2b7178daf 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -547,7 +547,7 @@ struct SpellBuff_Struct /*002*/ uint8 bard_modifier; /*003*/ uint8 effect; //not real /*004*/ uint32 spellid; -/*008*/ uint32 duration; +/*008*/ int32 duration; /*012*/ uint32 counters; /*016*/ uint32 unknown004; //Might need to be swapped with player_id /*020*/ uint32 player_id; //'global' ID of the caster, for wearoff messages @@ -564,7 +564,7 @@ struct SpellBuffFade_Struct { /*006*/ uint8 effect; /*007*/ uint8 unknown7; /*008*/ uint32 spellid; -/*012*/ uint32 duration; +/*012*/ int32 duration; /*016*/ uint32 unknown016; /*020*/ uint32 unknown020; //prolly global player ID /*024*/ uint32 playerId; // Player id who cast the buff diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 23404e051..f7ad59011 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -526,7 +526,7 @@ struct SpellBuff_Struct /*002*/ uint8 bard_modifier; /*003*/ uint8 effect; //not real /*004*/ uint32 spellid; -/*008*/ uint32 duration; +/*008*/ int32 duration; /*012*/ uint32 counters; /*016*/ uint32 unknown004; //Might need to be swapped with player_id /*020*/ uint32 player_id; //'global' ID of the caster, for wearoff messages @@ -543,7 +543,7 @@ struct SpellBuffFade_Struct { /*006*/ uint8 effect; /*007*/ uint8 unknown7; /*008*/ uint32 spellid; -/*012*/ uint32 duration; +/*012*/ int32 duration; /*016*/ uint32 unknown016; /*020*/ uint32 unknown020; //prolly global player ID /*024*/ uint32 playerId; // Player id who cast the buff diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index 89a3634fd..bdca057d0 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -445,7 +445,7 @@ struct SpellBuff_Struct /*002*/ uint8 bard_modifier; /*003*/ uint8 effect; //not real /*004*/ uint32 spellid; -/*008*/ uint32 duration; +/*008*/ int32 duration; /*012*/ uint32 counters; /*016*/ uint32 player_id; //'global' ID of the caster, for wearoff messages }; @@ -457,7 +457,7 @@ struct SpellBuffFade_Struct { /*006*/ uint8 effect; /*007*/ uint8 unknown7; /*008*/ uint32 spellid; -/*012*/ uint32 duration; +/*012*/ int32 duration; /*016*/ uint32 unknown016; /*020*/ uint32 unknown020; //prolly global player ID /*024*/ uint32 slotid; diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index 66cc58d1d..79363d68a 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -551,7 +551,7 @@ struct SpellBuff_Struct /*003*/ uint8 effect; // not real /*004*/ uint32 unknown004; // Seen 1 for no buff /*008*/ uint32 spellid; -/*012*/ uint32 duration; +/*012*/ int32 duration; /*016*/ uint32 unknown016; /*020*/ uint32 player_id; // 'global' ID of the caster, for wearoff messages /*024*/ uint32 counters; @@ -568,7 +568,7 @@ struct SpellBuffFade_Struct_Underfoot { /*007*/ uint8 unknown7; /*008*/ float unknown008; /*012*/ uint32 spellid; -/*016*/ uint32 duration; +/*016*/ int32 duration; /*020*/ uint32 num_hits; /*024*/ uint32 playerId; // Global player ID? /*028*/ uint32 unknown020; @@ -585,7 +585,7 @@ struct SpellBuffFade_Struct { /*006*/ uint8 effect; /*007*/ uint8 unknown7; /*008*/ uint32 spellid; -/*012*/ uint32 duration; +/*012*/ int32 duration; /*016*/ uint32 unknown016; /*020*/ uint32 unknown020; // Global player ID? /*024*/ uint32 playerId; // Player id who cast the buff @@ -2188,7 +2188,7 @@ struct GroupFollow_Struct { // Underfoot Follow Struct struct InspectBuffs_Struct { /*000*/ uint32 spell_id[BUFF_COUNT]; /*100*/ uint32 filler100[5]; // BUFF_COUNT is really 30... -/*120*/ uint32 tics_remaining[BUFF_COUNT]; +/*120*/ int32 tics_remaining[BUFF_COUNT]; /*220*/ uint32 filler220[5]; // BUFF_COUNT is really 30... }; diff --git a/common/version.h b/common/version.h index 9ce7b285c..fd0f433f4 100644 --- a/common/version.h +++ b/common/version.h @@ -30,7 +30,7 @@ Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9078 +#define CURRENT_BINARY_DATABASE_VERSION 9079 #define COMPILE_DATE __DATE__ #define COMPILE_TIME __TIME__ #ifndef WIN32 diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 537f8009b..00d7b9609 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -332,6 +332,7 @@ 9076|2015_02_04_average_coin.sql|SHOW COLUMNS FROM `loottable` WHERE Field = 'avgcoin'|contains|smallint 9077|2015_02_12_zone_gravity.sql|SHOW COLUMNS FROM `zone` LIKE 'gravity'|empty| 9078|2015_05_20_BuffInstrumentMod.sql|SHOW COLUMNS FROM `character_buffs` LIKE 'instrument_mod'|empty| +9079|2015_05_23_BuffDurations.sql|SHOW COLUMNS FROM `character_buffs` LIKE 'ticsremaining'|contains|unsigned| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2015_05_23_BuffDurations.sql b/utils/sql/git/required/2015_05_23_BuffDurations.sql new file mode 100644 index 000000000..5f03039a6 --- /dev/null +++ b/utils/sql/git/required/2015_05_23_BuffDurations.sql @@ -0,0 +1,2 @@ +ALTER TABLE `character_buffs` CHANGE COLUMN `ticsremaining` `ticsremaining` INT(11) SIGNED NOT NULL; +ALTER TABLE `merc_buffs` CHANGE COLUMN `TicsRemaining` `TicsRemaining` INT(11) SIGNED NOT NULL DEFAULT 0; diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index ab4afeab4..5dd7440f6 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1473,7 +1473,7 @@ void Mob::CalcSpellBonuses(StatBonuses* newbon) } void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *new_bonus, uint16 casterId, - uint8 WornType, uint32 ticsremaining, int buffslot, int instrument_mod, + uint8 WornType, int32 ticsremaining, int buffslot, int instrument_mod, bool IsAISpellEffect, uint16 effect_id, int32 se_base, int32 se_limit, int32 se_max) { int i, effect_value, base2, max, effectid; diff --git a/zone/effects.cpp b/zone/effects.cpp index 8a42b8e09..0f9dcfca1 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -89,7 +89,7 @@ int32 Mob::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { if (IsClient() && GetClass() == WIZARD) ratio += RuleI(Spells, WizCritRatio); //Default is zero - + if (Critical){ value = value_BaseEffect*ratio/100; @@ -172,7 +172,7 @@ int32 Mob::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) { value += int(value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100)*ratio/100; value += int(value_BaseEffect*GetFocusEffect(focusFcDamagePctCrit, spell_id)/100)*ratio/100; value += int(value_BaseEffect*target->GetVulnerability(this, spell_id, 0)/100)*ratio/100; - extra_dmg = target->GetFcDamageAmtIncoming(this, spell_id) + + extra_dmg = target->GetFcDamageAmtIncoming(this, spell_id) + int(GetFocusEffect(focusFcDamageAmtCrit, spell_id)*ratio/100) + GetFocusEffect(focusFcDamageAmt, spell_id); @@ -219,11 +219,11 @@ int32 Mob::GetExtraSpellAmt(uint16 spell_id, int32 extra_spell_amt, int32 base_s total_cast_time = spells[spell_id].recovery_time + spells[spell_id].cast_time; if (total_cast_time > 0 && total_cast_time <= 2500) - extra_spell_amt = extra_spell_amt*25/100; - else if (total_cast_time > 2500 && total_cast_time < 7000) - extra_spell_amt = extra_spell_amt*(167*((total_cast_time - 1000)/1000)) / 1000; - else - extra_spell_amt = extra_spell_amt * total_cast_time / 7000; + extra_spell_amt = extra_spell_amt*25/100; + else if (total_cast_time > 2500 && total_cast_time < 7000) + extra_spell_amt = extra_spell_amt*(167*((total_cast_time - 1000)/1000)) / 1000; + else + extra_spell_amt = extra_spell_amt * total_cast_time / 7000; if(extra_spell_amt*2 < base_spell_dmg) return 0; @@ -281,7 +281,7 @@ int32 Mob::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) { if (Critical) { entity_list.MessageClose_StringID(this, true, 100, MT_SpellCrits, OTHER_CRIT_HEAL, GetName(), itoa(value)); - + if (IsClient()) Message_StringID(MT_SpellCrits, YOU_CRIT_HEAL, itoa(value)); } @@ -413,6 +413,10 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost) int32 Mob::GetActSpellDuration(uint16 spell_id, int32 duration) { + if ((aabonuses.IllusionPersistence || spellbonuses.IllusionPersistence || itembonuses.IllusionPersistence) && + IsEffectInSpell(spell_id, SE_Illusion)) + return 10000; // ~16h + if (spells[spell_id].not_extendable) return duration; @@ -771,7 +775,7 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_ caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust); } } else { - if (spells[spell_id].aemaxtargets && iCounter < spells[spell_id].aemaxtargets) + if (spells[spell_id].aemaxtargets && iCounter < spells[spell_id].aemaxtargets) caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust); if (!spells[spell_id].aemaxtargets) caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust); @@ -859,7 +863,7 @@ void EntityList::AEBardPulse(Mob *caster, Mob *center, uint16 spell_id, bool aff if (!center->CheckLosFN(curmob)) continue; } else { // check to stop casting beneficial ae buffs (to wit: bard songs) on enemies... - // See notes in AESpell() above for more info. + // See notes in AESpell() above for more info. if (caster->IsAttackAllowed(curmob, true)) continue; if (caster->CheckAggro(curmob)) diff --git a/zone/mob.h b/zone/mob.h index 579ec75a8..bf7e2030a 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -200,7 +200,7 @@ public: bool IsBeneficialAllowed(Mob *target); virtual int GetCasterLevel(uint16 spell_id); void ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* newbon, uint16 casterID = 0, - uint8 WornType = 0, uint32 ticsremaining = 0, int buffslot = -1, int instrument_mod = 10, + uint8 WornType = 0, int32 ticsremaining = 0, int buffslot = -1, int instrument_mod = 10, bool IsAISpellEffect = false, uint16 effect_id = 0, int32 se_base = 0, int32 se_limit = 0, int32 se_max = 0); void NegateSpellsBonuses(uint16 spell_id); virtual float GetActSpellRange(uint16 spell_id, float range, bool IsBard = false); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 19e83c4df..59b154835 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -83,7 +83,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) if(c_override) { int durat = CalcBuffDuration(caster, this, spell_id, caster_level); - if(durat > 0) + if(durat) // negatives are perma buffs { buffslot = AddBuff(caster, spell_id, durat, caster_level); if(buffslot == -1) // stacking failure @@ -3366,7 +3366,7 @@ void Mob::BuffProcess() if(buffs[buffs_i].spellid == SPELL_UNKNOWN) continue; - if(spells[buffs[buffs_i].spellid].buffdurationformula != DF_Permanent) + if(buffs[buffs_i].ticsremaining > 0) // perma buffs will either be -1 or -4 { if(!zone->BuffTimersSuspended() || !IsSuspendableSpell(buffs[buffs_i].spellid)) { diff --git a/zone/spells.cpp b/zone/spells.cpp index 525470303..d0f60ea47 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2630,80 +2630,75 @@ int Mob::CalcBuffDuration(Mob *caster, Mob *target, uint16 spell_id, int32 caste Log.Out(Logs::Detail, Logs::Spells, "Spell %d: Casting level %d, formula %d, base_duration %d: result %d", spell_id, castlevel, formula, duration, res); - return(res); + return res; } // the generic formula calculations int CalcBuffDuration_formula(int level, int formula, int duration) { - int i; // temp variable + int temp; - switch(formula) - { - case 0: // not a buff - return 0; - - case 1: - i = (int)ceil(level / 2.0f); - return i < duration ? (i < 1 ? 1 : i) : duration; - - case 2: - i = (int)ceil(level / 5.0f * 3); - return i < duration ? (i < 1 ? 1 : i) : duration; - - case 3: - i = level * 30; - return i < duration ? (i < 1 ? 1 : i) : duration; - - case 4: // only used by 'LowerElement' - return ((duration != 0) ? duration : 50); - - case 5: - i = duration; - // 0 value results in a 3 tick spell, else its between 1-3 ticks. - return i < 3 ? (i < 1 ? 3 : i) : 3; - - case 6: - i = (int)ceil(level / 2.0f); - return i < duration ? (i < 1 ? 1 : i) : duration; - - case 7: - i = level; - return (duration == 0) ? (i < 1 ? 1 : i) : duration; - - case 8: - i = level + 10; - return i < duration ? (i < 1 ? 1 : i) : duration; - - case 9: - i = level * 2 + 10; - return i < duration ? (i < 1 ? 1 : i) : duration; - - case 10: - i = level * 3 + 10; - return i < duration ? (i < 1 ? 1 : i) : duration; - - case 11: - return std::min((level + 3) * 30, duration); - - case 12: - case 13: - case 14: - case 15: // Don't know what the real formula for this should be. Used by Skinspikes potion. - return duration; - - case 50: // Permanent. Cancelled by casting/combat for perm invis, non-lev zones for lev, curing poison/curse counters, etc. - return 72000; // 5 days until better method to make permanent - - //case 51: // Permanent. Cancelled when out of range of aura. Placeholder until appropriate duration identified. - - case 3600: - return duration ? duration : 3600; - - default: - Log.Out(Logs::General, Logs::None, "CalcBuffDuration_formula: unknown formula %d", formula); + switch (formula) { + case 1: + temp = level > 3 ? level / 2 : 1; + break; + case 2: + temp = level > 3 ? level / 2 + 5 : 6; + break; + case 3: + temp = 30 * level; + break; + case 4: // only used by 'LowerElement' + temp = 50; + break; + case 5: + temp = 2; + break; + case 6: + temp = level / 2 + 2; + break; + case 7: + temp = level; + break; + case 8: + temp = level + 10; + break; + case 9: + temp = 2 * level + 10; + break; + case 10: + temp = 3 * level + 10; + break; + case 11: + temp = 30 * (level + 3); + break; + case 12: + temp = level > 7 ? level / 4 : 1; + break; + case 13: + temp = 4 * level + 10; + break; + case 14: + temp = 5 * (level + 2); + break; + case 15: + temp = 10 * (level + 10); + break; + case 50: // Permanent. Cancelled by casting/combat for perm invis, non-lev zones for lev, curing poison/curse + // counters, etc. + return -1; + case 51: // Permanent. Cancelled when out of range of aura. + return -4; + default: + // the client function has another bool parameter that if true returns -2 -- unsure + if (formula < 200) return 0; + temp = formula; + break; } + if (duration && duration < temp) + temp = duration; + return temp; } // helper function for AddBuff to determine stacking @@ -3066,7 +3061,7 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid if (duration == 0) { duration = CalcBuffDuration(caster, this, spell_id); - if (caster) + if (caster && duration > 0) // negatives are perma buffs duration = caster->GetActSpellDuration(spell_id, duration); } diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 8369652b7..0313b8064 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -2504,7 +2504,7 @@ void ZoneDatabase::SaveMercBuffs(Merc *merc) { "TicsRemaining, PoisonCounters, DiseaseCounters, CurseCounters, " "CorruptionCounters, HitCount, MeleeRune, MagicRune, dot_rune, " "caston_x, Persistent, caston_y, caston_z, ExtraDIChance) " - "VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %i, %u, %i, %i, %i);", + "VALUES (%u, %u, %u, %u, %u, %d, %u, %u, %u, %u, %u, %u, %u, %i, %u, %i, %i, %i);", merc->GetMercID(), buffs[buffCount].spellid, buffs[buffCount].casterlevel, spells[buffs[buffCount].spellid].buffdurationformula, buffs[buffCount].ticsremaining, CalculatePoisonCounters(buffs[buffCount].spellid) > 0 ? buffs[buffCount].counters : 0, @@ -2982,7 +2982,7 @@ void ZoneDatabase::SaveBuffs(Client *client) { "caster_level, caster_name, ticsremaining, counters, numhits, melee_rune, " "magic_rune, persistent, dot_rune, caston_x, caston_y, caston_z, ExtraDIChance, " "instrument_mod) " - "VALUES('%u', '%u', '%u', '%u', '%s', '%u', '%u', '%u', '%u', '%u', '%u', '%u', " + "VALUES('%u', '%u', '%u', '%u', '%s', '%d', '%u', '%u', '%u', '%u', '%u', '%u', " "'%i', '%i', '%i', '%i', '%i')", client->CharacterID(), index, buffs[index].spellid, buffs[index].casterlevel, buffs[index].caster_name, buffs[index].ticsremaining, buffs[index].counters, buffs[index].numhits, buffs[index].melee_rune, @@ -3023,7 +3023,7 @@ void ZoneDatabase::LoadBuffs(Client *client) Client *caster = entity_list.GetClientByName(row[3]); uint32 caster_level = atoi(row[2]); - uint32 ticsremaining = atoul(row[4]); + int32 ticsremaining = atoi(row[4]); uint32 counters = atoul(row[5]); uint32 numhits = atoul(row[6]); uint32 melee_rune = atoul(row[7]); @@ -3128,12 +3128,12 @@ void ZoneDatabase::SavePetInfo(Client *client) query = StringFormat("INSERT INTO `character_pet_buffs` " "(`char_id`, `pet`, `slot`, `spell_id`, `caster_level`, " "`ticsremaining`, `counters`) " - "VALUES (%u, %u, %u, %u, %u, %u, %d)", + "VALUES (%u, %u, %u, %u, %u, %d, %d)", client->CharacterID(), pet, index, petinfo->Buffs[index].spellid, petinfo->Buffs[index].level, petinfo->Buffs[index].duration, petinfo->Buffs[index].counters); else - query += StringFormat(", (%u, %u, %u, %u, %u, %u, %d)", + query += StringFormat(", (%u, %u, %u, %u, %u, %d, %d)", client->CharacterID(), pet, index, petinfo->Buffs[index].spellid, petinfo->Buffs[index].level, petinfo->Buffs[index].duration, petinfo->Buffs[index].counters); @@ -3238,7 +3238,7 @@ void ZoneDatabase::LoadPetInfo(Client *client) { uint32 caster_level = atoi(row[3]); int caster_id = 0; // The castername field is currently unused - uint32 ticsremaining = atoul(row[5]); + int32 ticsremaining = atoi(row[5]); uint32 counters = atoul(row[6]); pi->Buffs[slot_id].spellid = spell_id;