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); }