From bc6199a86f6cf2f5b51a1783ec2686bb4a6c889e Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Fri, 6 Feb 2015 02:49:42 -0500 Subject: [PATCH] Implemented a better method for developers who want to have additivie worn bonuses than what was prior implemented. Removed old rule RuleB(Spells, AdditiveBonusValues) Replaced with new rule RuleI(AdditiveBonusWornType) The rule value denotes a specific 'worntype' that is to be checked on items. If the items 'worntype' matches the rules worntype then any worn effect on that item will be cacluated additively instead of taking the highest value. This will also stack with regular worn effects that take highest value. Unless the value is set to (2) which is what all live items use. If set to 2 then all worn effects will be calculated additively (same as what the old rule did). In laymans terms. You can take 3 Cleave I items and put them on a character and they will all add together if you set the worn type = 3 and the rule = 3. Which would also add to any regular cleave set to worn type = 2. Hope you enjoyed the novel. --- common/ruletypes.h | 2 +- .../2015_2_6_AdditiveBonusWornType.sql | 4 + zone/bonuses.cpp | 106 +++++++++++++----- zone/bot.cpp | 4 +- zone/client.h | 1 + zone/merc.cpp | 4 +- zone/mob.h | 2 +- zone/mob_ai.cpp | 2 +- 8 files changed, 92 insertions(+), 33 deletions(-) create mode 100644 utils/sql/git/optional/2015_2_6_AdditiveBonusWornType.sql diff --git a/common/ruletypes.h b/common/ruletypes.h index ff88115e2..12a8a0737 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -300,7 +300,7 @@ RULE_INT ( Spells, MaxCastTimeReduction, 50) //Max percent your spell cast time RULE_INT ( Spells, RootBreakFromSpells, 55) //Chance for root to break when cast on. RULE_INT ( Spells, DeathSaveCharismaMod, 3) //Determines how much charisma effects chance of death save firing. RULE_INT ( Spells, DivineInterventionHeal, 8000) //Divine intervention heal amount. -RULE_BOOL ( Spells, AdditiveBonusValues, false) //Allow certain bonuses to be calculated by adding together the value from each item, instead of taking the highest value. (ie Add together all Cleave Effects) +RULE_INT ( Spells, AdditiveBonusWornType, 0) //Calc worn bonuses to add together (instead of taking highest) if set to THIS worn type. (2=Will covert live items automatically) RULE_BOOL ( Spells, UseCHAScribeHack, false) //ScribeSpells and TrainDiscs quest functions will ignore entries where field 12 is CHA. What's the best way to do this? RULE_BOOL ( Spells, BuffLevelRestrictions, true) //Buffs will not land on low level toons like live RULE_INT ( Spells, RootBreakCheckChance, 70) //Determines chance for a root break check to occur each buff tick. diff --git a/utils/sql/git/optional/2015_2_6_AdditiveBonusWornType.sql b/utils/sql/git/optional/2015_2_6_AdditiveBonusWornType.sql new file mode 100644 index 000000000..aab88bd9f --- /dev/null +++ b/utils/sql/git/optional/2015_2_6_AdditiveBonusWornType.sql @@ -0,0 +1,4 @@ +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Spells:AdditiveBonusWornType', '0', 'Calcs worn bonuses to add together (instead of taking highest) if item set to THIS worn type. Will stack with regular worn bonuses. (2=Will cause all live items to use this behavior)'); + +-- This is no longer used - Set the above value equal to 2 to achieve the same effect. +DELETE FROM `rule_values` WHERE rule_name LIKE "Spells:AdditiveBonusValues"; diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 4aa13519b..ea3174a54 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -169,6 +169,17 @@ void Client::CalcItemBonuses(StatBonuses* newbon) { continue; AddItemBonuses(inst, newbon, false, true); } + + //Optional ability to have worn effects calculate as an addititive bonus instead of highest value + if (RuleI(Spells, AdditiveBonusWornType) && RuleI(Spells, AdditiveBonusWornType) != ET_WornEffect){ + for (i = MainCharm; i < MainAmmo; i++) { + const ItemInst* inst = m_inv[i]; + if(inst == 0) + continue; + AdditiveWornBonuses(inst, newbon); + } + } + // Caps if(newbon->HPRegen > CalcHPRegenCap()) newbon->HPRegen = CalcHPRegenCap(); @@ -410,12 +421,12 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAu else newbon->DSMitigation += item->DSMitigation; } - if (item->Worn.Effect>0 && (item->Worn.Type == ET_WornEffect)) { // latent effects - ApplySpellsBonuses(item->Worn.Effect, item->Worn.Level, newbon, 0, true, true); + if (item->Worn.Effect > 0 && item->Worn.Type == ET_WornEffect) {// latent effects + ApplySpellsBonuses(item->Worn.Effect, item->Worn.Level, newbon, 0, item->Worn.Type); } if (item->Focus.Effect>0 && (item->Focus.Type == ET_Focus)) { // focus effects - ApplySpellsBonuses(item->Focus.Effect, item->Focus.Level, newbon, 0, true, false); + ApplySpellsBonuses(item->Focus.Effect, item->Focus.Level, newbon, 0); } switch(item->BardType) @@ -537,6 +548,45 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAu } +void Client::AdditiveWornBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug) { + + /* + Powerful Non-live like option allows developers to add worn effects on items that + can stack with other worn effects of the same spell effect type, instead of only taking the highest value. + Ie Cleave I = 40 pct cleave - So if you equip 3 cleave I items you will have a 120 pct cleave bonus. + To enable use RuleI(Spells, AdditiveBonusWornType) + Setting value = 2 Will force all live items to automatically be calculated additivily + Setting value to anything else will indicate the item 'worntype' that if set to the same, will cause the bonuses to use this calculation + which will also stack with regular (worntype 2) effects. [Ie set rule = 3 and item worntype = 3] + */ + + if(!inst || !inst->IsType(ItemClassCommon)) + return; + + if(inst->GetAugmentType()==0 && isAug == true) + return; + + const Item_Struct *item = inst->GetItem(); + + if(!inst->IsEquipable(GetBaseRace(),GetClass())) + return; + + if(GetLevel() < item->ReqLevel) + return; + + if (item->Worn.Effect > 0 && item->Worn.Type == RuleI(Spells, AdditiveBonusWornType)) + ApplySpellsBonuses(item->Worn.Effect, item->Worn.Level, newbon, 0, item->Worn.Type);// Non-live like - Addititive latent effects + + + if (!isAug) + { + int i; + for (i = 0; i < EmuConstants::ITEM_COMMON_SIZE; i++) { + AdditiveWornBonuses(inst->GetAugment(i),newbon,true); + } + } +} + void Client::CalcEdibleBonuses(StatBonuses* newbon) { uint32 i; @@ -1393,7 +1443,7 @@ void Mob::CalcSpellBonuses(StatBonuses* newbon) int buff_count = GetMaxTotalSlots(); for(i = 0; i < buff_count; i++) { if(buffs[i].spellid != SPELL_UNKNOWN){ - ApplySpellsBonuses(buffs[i].spellid, buffs[i].casterlevel, newbon, buffs[i].casterid, false, false, buffs[i].ticsremaining,i); + ApplySpellsBonuses(buffs[i].spellid, buffs[i].casterlevel, newbon, buffs[i].casterid, false,0, buffs[i].ticsremaining,i); if (buffs[i].numhits > 0) Numhits(true); @@ -1416,10 +1466,11 @@ void Mob::CalcSpellBonuses(StatBonuses* newbon) if (GetClass() == BARD) newbon->ManaRegen = 0; // Bards do not get mana regen from spells. } -void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* new_bonus, uint16 casterId, bool item_bonus, bool IsWornEffect, uint32 ticsremaining, int buffslot, +void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* new_bonus, uint16 casterId, uint8 WornType, uint32 ticsremaining, int buffslot, bool IsAISpellEffect, uint16 effect_id, int32 se_base, int32 se_limit, int32 se_max) { int i, effect_value, base2, max, effectid; + bool AdditiveWornBonus = false; Mob *caster = nullptr; if(!IsAISpellEffect && !IsValidSpell(spell_id)) @@ -1439,15 +1490,19 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne uint8 focus = IsFocusEffect(spell_id, i); if (focus) { - if (!IsWornEffect) - new_bonus->FocusEffects[focus] = static_cast(spells[spell_id].effectid[i]); + if (WornType){ + if (RuleB(Spells, UseAdditiveFocusFromWornSlot)) + new_bonus->FocusEffectsWorn[focus] += spells[spell_id].base[i]; + } - else if (RuleB(Spells, UseAdditiveFocusFromWornSlot)) - new_bonus->FocusEffectsWorn[focus] += spells[spell_id].base[i]; + else + new_bonus->FocusEffects[focus] = static_cast(spells[spell_id].effectid[i]); continue; } + if (WornType && (RuleI(Spells, AdditiveBonusWornType) == WornType)) + AdditiveWornBonus = true; effectid = spells[spell_id].effectid[i]; effect_value = CalcSpellEffectValue(spell_id, i, casterlevel, caster, ticsremaining); @@ -1813,7 +1868,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_CriticalHitChance: { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) { + if (AdditiveWornBonus) { if(base2 == -1) new_bonus->CriticalHitChance[HIGHEST_SKILL+1] += effect_value; else @@ -1839,7 +1894,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_CrippBlowChance: { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) + if (AdditiveWornBonus) new_bonus->CrippBlowChance += effect_value; else if((effect_value < 0) && (new_bonus->CrippBlowChance > effect_value)) @@ -1853,7 +1908,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_AvoidMeleeChance: { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) + if (AdditiveWornBonus) new_bonus->AvoidMeleeChanceEffect += effect_value; else if((effect_value < 0) && (new_bonus->AvoidMeleeChanceEffect > effect_value)) @@ -1866,7 +1921,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_RiposteChance: { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) + if (AdditiveWornBonus) new_bonus->RiposteChance += effect_value; else if((effect_value < 0) && (new_bonus->RiposteChance > effect_value)) @@ -1879,7 +1934,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_DodgeChance: { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) + if (AdditiveWornBonus) new_bonus->DodgeChance += effect_value; else if((effect_value < 0) && (new_bonus->DodgeChance > effect_value)) @@ -1892,7 +1947,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_ParryChance: { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) + if (AdditiveWornBonus) new_bonus->ParryChance += effect_value; else if((effect_value < 0) && (new_bonus->ParryChance > effect_value)) @@ -1905,7 +1960,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_DualWieldChance: { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) + if (AdditiveWornBonus) new_bonus->DualWieldChance += effect_value; else if((effect_value < 0) && (new_bonus->DualWieldChance > effect_value)) @@ -1919,7 +1974,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_DoubleAttackChance: { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) + if (AdditiveWornBonus) new_bonus->DoubleAttackChance += effect_value; else if((effect_value < 0) && (new_bonus->DoubleAttackChance > effect_value)) @@ -1933,7 +1988,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_TripleAttackChance: { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) + if (AdditiveWornBonus) new_bonus->TripleAttackChance += effect_value; else if((effect_value < 0) && (new_bonus->TripleAttackChance > effect_value)) @@ -1946,7 +2001,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_MeleeLifetap: { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) + if (AdditiveWornBonus) new_bonus->MeleeLifetap += spells[spell_id].base[i]; else if((effect_value < 0) && (new_bonus->MeleeLifetap > effect_value)) @@ -1995,7 +2050,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_HundredHands: { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) + if (AdditiveWornBonus) new_bonus->HundredHands += effect_value; if (effect_value > 0 && effect_value > new_bonus->HundredHands) @@ -2017,7 +2072,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_HitChance: { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus){ + if (AdditiveWornBonus){ if(base2 == -1) new_bonus->HitChanceEffect[HIGHEST_SKILL+1] += effect_value; else @@ -2084,7 +2139,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_ProcChance: { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) + if (AdditiveWornBonus) new_bonus->ProcChanceSPA += effect_value; else if((effect_value < 0) && (new_bonus->ProcChanceSPA > effect_value)) @@ -2122,7 +2177,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_DivineSave: { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) { + if (AdditiveWornBonus) { new_bonus->DivineSaveChance[0] += effect_value; new_bonus->DivineSaveChance[1] = 0; } @@ -2131,7 +2186,6 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne { new_bonus->DivineSaveChance[0] = effect_value; new_bonus->DivineSaveChance[1] = base2; - //SetDeathSaveChance(true); } break; } @@ -3051,12 +3105,12 @@ void NPC::CalcItemBonuses(StatBonuses *newbon) newbon->ProcChance += cur->CombatEffects; } if (cur->Worn.Effect>0 && (cur->Worn.Type == ET_WornEffect)) { // latent effects - ApplySpellsBonuses(cur->Worn.Effect, cur->Worn.Level, newbon); + ApplySpellsBonuses(cur->Worn.Effect, cur->Worn.Level, newbon, cur->Worn.Type); } if (RuleB(Spells, NPC_UseFocusFromItems)){ if (cur->Focus.Effect>0 && (cur->Focus.Type == ET_Focus)){ // focus effects - ApplySpellsBonuses(cur->Focus.Effect, cur->Focus.Level, newbon, 0, true); + ApplySpellsBonuses(cur->Focus.Effect, cur->Focus.Level, newbon); } } diff --git a/zone/bot.cpp b/zone/bot.cpp index c39696576..4b42fac37 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -10959,7 +10959,7 @@ void Bot::CalcItemBonuses() } } if ((itemtmp->Worn.Effect != 0) && (itemtmp->Worn.Type == ET_WornEffect)) { // latent effects - ApplySpellsBonuses(itemtmp->Worn.Effect, itemtmp->Worn.Level, &itembonuses); + ApplySpellsBonuses(itemtmp->Worn.Effect, itemtmp->Worn.Level, &itembonuses,0,itemtmp->Worn.Type); } } } @@ -11043,7 +11043,7 @@ void Bot::CalcItemBonuses() } } if ((itemtmp->Worn.Effect != 0) && (itemtmp->Worn.Type == ET_WornEffect)) { // latent effects - ApplySpellsBonuses(itemtmp->Worn.Effect, itemtmp->Worn.Level, &itembonuses); + ApplySpellsBonuses(itemtmp->Worn.Effect, itemtmp->Worn.Level, &itembonuses,0,itemtmp->Worn.Type); } } } diff --git a/zone/client.h b/zone/client.h index 9248fb742..a2cb823f1 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1257,6 +1257,7 @@ protected: friend class Mob; void CalcItemBonuses(StatBonuses* newbon); void AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug = false, bool isTribute = false); + void AdditiveWornBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug = false); int CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat); void CalcEdibleBonuses(StatBonuses* newbon); void CalcAABonuses(StatBonuses* newbon); diff --git a/zone/merc.cpp b/zone/merc.cpp index 2fea4aba4..059ccb316 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -449,11 +449,11 @@ void Merc::AddItemBonuses(const Item_Struct *item, StatBonuses* newbon) { newbon->DSMitigation += item->DSMitigation; } if (item->Worn.Effect>0 && (item->Worn.Type == ET_WornEffect)) { // latent effects - ApplySpellsBonuses(item->Worn.Effect, item->Worn.Level, newbon, 0, true); + ApplySpellsBonuses(item->Worn.Effect, item->Worn.Level, newbon, 0, item->Worn.Type); } if (item->Focus.Effect>0 && (item->Focus.Type == ET_Focus)) { // focus effects - ApplySpellsBonuses(item->Focus.Effect, item->Focus.Level, newbon, 0, true); + ApplySpellsBonuses(item->Focus.Effect, item->Focus.Level, newbon, 0); } switch(item->BardType) diff --git a/zone/mob.h b/zone/mob.h index 46531b819..e7318007e 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -194,7 +194,7 @@ public: bool IsBeneficialAllowed(Mob *target); virtual int GetCasterLevel(uint16 spell_id); void ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* newbon, uint16 casterID = 0, - bool item_bonus = false, bool IsWornEffect = false, uint32 ticsremaining = 0, int buffslot = -1, + uint8 WornType = 0, uint32 ticsremaining = 0, int buffslot = -1, 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/mob_ai.cpp b/zone/mob_ai.cpp index 371a8e523..452ca71fd 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -2559,7 +2559,7 @@ void NPC::ApplyAISpellEffects(StatBonuses* newbon) for(int i=0; i < AIspellsEffects.size(); i++) { - ApplySpellsBonuses(0, 0, newbon, 0, false, 0,-1, + ApplySpellsBonuses(0, 0, newbon, 0, 0, 0,-1, true, AIspellsEffects[i].spelleffectid, AIspellsEffects[i].base, AIspellsEffects[i].limit,AIspellsEffects[i].max); }