[Feature] Add support for -1 extradmgskill to allow all skills to be scaled. (#3136)

* [Feature] Add support for -1 extradmgskill to allow all skills to be scaled.

- `$mob->GetSkillDmgAmt(skill_id)` now uses `int` instead of `uint16`.

- `statbonuses:GetSkillDamageAmount(skill_id)` now uses `-1` properly.
- `mob:GetSkillDmgAmt(skill_id)` now uses `int` instead of `uint16`.

- A `-1` value in `extradmgskill` denotes the ability to scale all skills at once.
- Consolidated `AddItemBonuses()`, `AdditiveWornBonuses()`, `CalcItemBonuses()`, and `CalcRecommendedLevelBonus()` to mob-based methods to avoid code duplication.
- Bots, NPCs, and Mercs can now use additive worn effects if the rule is enabled, as well as all other proper stat bonuses that only clients had before.
- No SQL update required to change `extradmgskill` and `extradmgamt` to `int` as they already are this type in the database, just had to adjust `item_data.h` and `shareddb.cpp`.

* Update mob.cpp

* Cleanup.

* Cleanup.

* Move #include <vector> to header.

* Add method for GetExtraDamageSkills

* fix additembonuses

* Update bonuses.cpp

* Update mob.cpp

* Out of bounds.

* Update bonuses.cpp

---------

Co-authored-by: Aeadoin <109764533+Aeadoin@users.noreply.github.com>
This commit is contained in:
Alex King 2023-03-25 20:26:01 -04:00 committed by GitHub
parent ec3ef411a1
commit 9d1ace627c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 569 additions and 1167 deletions

View File

@ -131,7 +131,7 @@ namespace EQ
Mounts?
Ornamentations?
GuildBanners?
Collectible?
Collectible?
Placeable?
(others?)
*/
@ -449,8 +449,8 @@ namespace EQ
int8 Shielding; // PoP: Shielding %
int8 StunResist; // PoP: Stun Resist %
int8 StrikeThrough; // PoP: Strike Through %
uint32 ExtraDmgSkill;
uint32 ExtraDmgAmt;
int32 ExtraDmgSkill;
int32 ExtraDmgAmt;
int8 SpellShield; // PoP: Spell Shield %
int8 Avoidance; // PoP: Avoidance +
int8 Accuracy; // PoP: Accuracy +

View File

@ -1107,8 +1107,8 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_
item.SkillModType = Strings::ToUnsignedInt(row[ItemField::skillmodtype]);
// Extra Damage Skill
item.ExtraDmgSkill = Strings::ToUnsignedInt(row[ItemField::extradmgskill]);
item.ExtraDmgAmt = Strings::ToUnsignedInt(row[ItemField::extradmgamt]);
item.ExtraDmgSkill = Strings::ToInt(row[ItemField::extradmgskill]);
item.ExtraDmgAmt = Strings::ToInt(row[ItemField::extradmgamt]);
// Bard
item.BardType = Strings::ToUnsignedInt(row[ItemField::bardtype]);

View File

@ -1,5 +1,5 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
@ -260,13 +260,31 @@ const std::map<EQ::skills::SkillType, std::string>& EQ::skills::GetSkillTypeMap(
return skill_type_map;
}
const std::vector<EQ::skills::SkillType>& EQ::skills::GetExtraDamageSkills()
{
static const std::vector<EQ::skills::SkillType> v = {
EQ::skills::SkillBackstab,
EQ::skills::SkillBash,
EQ::skills::SkillDragonPunch, // Same ID as Tail Rake
EQ::skills::SkillEagleStrike,
EQ::skills::SkillFlyingKick,
EQ::skills::SkillKick,
EQ::skills::SkillRoundKick,
EQ::skills::SkillRoundKick,
EQ::skills::SkillTigerClaw,
EQ::skills::SkillFrenzy
};
return v;
}
std::string EQ::skills::GetSkillName(SkillType skill)
{
if (skill >= Skill1HBlunt && skill <= Skill2HPiercing) {
auto skills = GetSkillTypeMap();
return skills[skill];
}
return std::string();
return {};
}
EQ::SkillProfile::SkillProfile()

View File

@ -1,5 +1,5 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
@ -24,6 +24,7 @@
#include <string>
#include <map>
#include <vector>
namespace EQ
@ -170,6 +171,7 @@ namespace EQ
bool IsMeleeDmg(SkillType skill);
extern const std::map<SkillType, std::string>& GetSkillTypeMap();
extern const std::vector<SkillType>& GetExtraDamageSkills();
std::string GetSkillName(SkillType skill);
} /*skills*/
@ -305,7 +307,7 @@ namespace EQ
uint32 operator[](int skill_id) const { return const_cast<SkillProfile*>(this)->GetSkill(skill_id); }
};
} /*EQEmu*/
#endif /*COMMON_SKILLS_H*/

File diff suppressed because it is too large Load Diff

View File

@ -7009,354 +7009,6 @@ void Bot::ProcessBotInspectionRequest(Bot* inspectedBot, Client* client) {
}
}
void Bot::CalcItemBonuses(StatBonuses* newbon)
{
const EQ::ItemData* itemtmp = nullptr;
for (int i = EQ::invslot::BONUS_BEGIN; i <= EQ::invslot::BONUS_STAT_END; ++i) {
const EQ::ItemInstance* item = GetBotItem(i);
if (item) {
AddItemBonuses(item, newbon);
}
}
// Caps
if (newbon->HPRegen > CalcHPRegenCap())
newbon->HPRegen = CalcHPRegenCap();
if (newbon->ManaRegen > CalcManaRegenCap())
newbon->ManaRegen = CalcManaRegenCap();
if (newbon->EnduranceRegen > CalcEnduranceRegenCap())
newbon->EnduranceRegen = CalcEnduranceRegenCap();
}
void Bot::AddItemBonuses(const EQ::ItemInstance *inst, StatBonuses* newbon, bool isAug, bool isTribute, int rec_override) {
if (!inst || !inst->IsClassCommon())
{
return;
}
if (inst->GetAugmentType()==0 && isAug)
{
return;
}
const EQ::ItemData *item = inst->GetItem();
if (!isTribute && !inst->IsEquipable(GetBaseRace(),GetClass()))
{
if (item->ItemType != EQ::item::ItemTypeFood && item->ItemType != EQ::item::ItemTypeDrink)
return;
}
if (GetLevel() < inst->GetItemRequiredLevel(true))
{
return;
}
auto rec_level = isAug ? rec_override : inst->GetItemRecommendedLevel(true);
if (GetLevel() >= rec_level)
{
newbon->AC += item->AC;
newbon->HP += item->HP;
newbon->Mana += item->Mana;
newbon->Endurance += item->Endur;
newbon->ATK += item->Attack;
newbon->STR += (item->AStr + item->HeroicStr);
newbon->STA += (item->ASta + item->HeroicSta);
newbon->DEX += (item->ADex + item->HeroicDex);
newbon->AGI += (item->AAgi + item->HeroicAgi);
newbon->INT += (item->AInt + item->HeroicInt);
newbon->WIS += (item->AWis + item->HeroicWis);
newbon->CHA += (item->ACha + item->HeroicCha);
newbon->MR += (item->MR + item->HeroicMR);
newbon->FR += (item->FR + item->HeroicFR);
newbon->CR += (item->CR + item->HeroicCR);
newbon->PR += (item->PR + item->HeroicPR);
newbon->DR += (item->DR + item->HeroicDR);
newbon->Corrup += (item->SVCorruption + item->HeroicSVCorrup);
newbon->STRCapMod += item->HeroicStr;
newbon->STACapMod += item->HeroicSta;
newbon->DEXCapMod += item->HeroicDex;
newbon->AGICapMod += item->HeroicAgi;
newbon->INTCapMod += item->HeroicInt;
newbon->WISCapMod += item->HeroicWis;
newbon->CHACapMod += item->HeroicCha;
newbon->MRCapMod += item->HeroicMR;
newbon->CRCapMod += item->HeroicFR;
newbon->FRCapMod += item->HeroicCR;
newbon->PRCapMod += item->HeroicPR;
newbon->DRCapMod += item->HeroicDR;
newbon->CorrupCapMod += item->HeroicSVCorrup;
newbon->HeroicSTR += item->HeroicStr;
newbon->HeroicSTA += item->HeroicSta;
newbon->HeroicDEX += item->HeroicDex;
newbon->HeroicAGI += item->HeroicAgi;
newbon->HeroicINT += item->HeroicInt;
newbon->HeroicWIS += item->HeroicWis;
newbon->HeroicCHA += item->HeroicCha;
newbon->HeroicMR += item->HeroicMR;
newbon->HeroicFR += item->HeroicFR;
newbon->HeroicCR += item->HeroicCR;
newbon->HeroicPR += item->HeroicPR;
newbon->HeroicDR += item->HeroicDR;
newbon->HeroicCorrup += item->HeroicSVCorrup;
}
else
{
int lvl = GetLevel();
newbon->AC += CalcRecommendedLevelBonus( lvl, rec_level, item->AC );
newbon->HP += CalcRecommendedLevelBonus( lvl, rec_level, item->HP );
newbon->Mana += CalcRecommendedLevelBonus( lvl, rec_level, item->Mana );
newbon->Endurance += CalcRecommendedLevelBonus( lvl, rec_level, item->Endur );
newbon->ATK += CalcRecommendedLevelBonus( lvl, rec_level, item->Attack );
newbon->STR += CalcRecommendedLevelBonus( lvl, rec_level, (item->AStr + item->HeroicStr) );
newbon->STA += CalcRecommendedLevelBonus( lvl, rec_level, (item->ASta + item->HeroicSta) );
newbon->DEX += CalcRecommendedLevelBonus( lvl, rec_level, (item->ADex + item->HeroicDex) );
newbon->AGI += CalcRecommendedLevelBonus( lvl, rec_level, (item->AAgi + item->HeroicAgi) );
newbon->INT += CalcRecommendedLevelBonus( lvl, rec_level, (item->AInt + item->HeroicInt) );
newbon->WIS += CalcRecommendedLevelBonus( lvl, rec_level, (item->AWis + item->HeroicWis) );
newbon->CHA += CalcRecommendedLevelBonus( lvl, rec_level, (item->ACha + item->HeroicCha) );
newbon->MR += CalcRecommendedLevelBonus( lvl, rec_level, (item->MR + item->HeroicMR) );
newbon->FR += CalcRecommendedLevelBonus( lvl, rec_level, (item->FR + item->HeroicFR) );
newbon->CR += CalcRecommendedLevelBonus( lvl, rec_level, (item->CR + item->HeroicCR) );
newbon->PR += CalcRecommendedLevelBonus( lvl, rec_level, (item->PR + item->HeroicPR) );
newbon->DR += CalcRecommendedLevelBonus( lvl, rec_level, (item->DR + item->HeroicDR) );
newbon->Corrup += CalcRecommendedLevelBonus( lvl, rec_level, (item->SVCorruption + item->HeroicSVCorrup) );
newbon->STRCapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicStr );
newbon->STACapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicSta );
newbon->DEXCapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicDex );
newbon->AGICapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicAgi );
newbon->INTCapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicInt );
newbon->WISCapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicWis );
newbon->CHACapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicCha );
newbon->MRCapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicMR );
newbon->CRCapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicFR );
newbon->FRCapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicCR );
newbon->PRCapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicPR );
newbon->DRCapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicDR );
newbon->CorrupCapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicSVCorrup );
newbon->HeroicSTR += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicStr );
newbon->HeroicSTA += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicSta );
newbon->HeroicDEX += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicDex );
newbon->HeroicAGI += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicAgi );
newbon->HeroicINT += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicInt );
newbon->HeroicWIS += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicWis );
newbon->HeroicCHA += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicCha );
newbon->HeroicMR += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicMR );
newbon->HeroicFR += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicFR );
newbon->HeroicCR += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicCR );
newbon->HeroicPR += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicPR );
newbon->HeroicDR += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicDR );
newbon->HeroicCorrup += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicSVCorrup );
}
//FatherNitwit: New style haste, shields, and regens
if (newbon->haste < (int32)item->Haste) {
newbon->haste = item->Haste;
}
if (item->Regen > 0)
newbon->HPRegen += item->Regen;
if (item->ManaRegen > 0)
newbon->ManaRegen += item->ManaRegen;
if (item->EnduranceRegen > 0)
newbon->EnduranceRegen += item->EnduranceRegen;
if (item->DamageShield > 0) {
if ((newbon->DamageShield + item->DamageShield) > RuleI(Character, ItemDamageShieldCap))
newbon->DamageShield = RuleI(Character, ItemDamageShieldCap);
else
newbon->DamageShield += item->DamageShield;
}
if (item->SpellShield > 0) {
if ((newbon->SpellShield + item->SpellShield) > RuleI(Character, ItemSpellShieldingCap))
newbon->SpellShield = RuleI(Character, ItemSpellShieldingCap);
else
newbon->SpellShield += item->SpellShield;
}
if (item->Shielding > 0) {
if ((newbon->MeleeMitigation + item->Shielding) > RuleI(Character, ItemShieldingCap))
newbon->MeleeMitigation = RuleI(Character, ItemShieldingCap);
else
newbon->MeleeMitigation += item->Shielding;
}
if (item->StunResist > 0) {
if ((newbon->StunResist + item->StunResist) > RuleI(Character, ItemStunResistCap))
newbon->StunResist = RuleI(Character, ItemStunResistCap);
else
newbon->StunResist += item->StunResist;
}
if (item->StrikeThrough > 0) {
if ((newbon->StrikeThrough + item->StrikeThrough) > RuleI(Character, ItemStrikethroughCap))
newbon->StrikeThrough = RuleI(Character, ItemStrikethroughCap);
else
newbon->StrikeThrough += item->StrikeThrough;
}
if (item->Avoidance > 0) {
if ((newbon->AvoidMeleeChance + item->Avoidance) > RuleI(Character, ItemAvoidanceCap))
newbon->AvoidMeleeChance = RuleI(Character, ItemAvoidanceCap);
else
newbon->AvoidMeleeChance += item->Avoidance;
}
if (item->Accuracy > 0) {
if ((newbon->HitChance + item->Accuracy) > RuleI(Character, ItemAccuracyCap))
newbon->HitChance = RuleI(Character, ItemAccuracyCap);
else
newbon->HitChance += item->Accuracy;
}
if (item->CombatEffects > 0) {
if ((newbon->ProcChance + item->CombatEffects) > RuleI(Character, ItemCombatEffectsCap))
newbon->ProcChance = RuleI(Character, ItemCombatEffectsCap);
else
newbon->ProcChance += item->CombatEffects;
}
if (item->DotShielding > 0) {
if ((newbon->DoTShielding + item->DotShielding) > RuleI(Character, ItemDoTShieldingCap))
newbon->DoTShielding = RuleI(Character, ItemDoTShieldingCap);
else
newbon->DoTShielding += item->DotShielding;
}
if (item->HealAmt > 0) {
if ((newbon->HealAmt + item->HealAmt) > RuleI(Character, ItemHealAmtCap))
newbon->HealAmt = RuleI(Character, ItemHealAmtCap);
else
newbon->HealAmt += item->HealAmt;
}
if (item->SpellDmg > 0) {
if ((newbon->SpellDmg + item->SpellDmg) > RuleI(Character, ItemSpellDmgCap))
newbon->SpellDmg = RuleI(Character, ItemSpellDmgCap);
else
newbon->SpellDmg += item->SpellDmg;
}
if (item->Clairvoyance > 0) {
if ((newbon->Clairvoyance + item->Clairvoyance) > RuleI(Character, ItemClairvoyanceCap))
newbon->Clairvoyance = RuleI(Character, ItemClairvoyanceCap);
else
newbon->Clairvoyance += item->Clairvoyance;
}
if (item->DSMitigation > 0) {
if ((newbon->DSMitigation + item->DSMitigation) > RuleI(Character, ItemDSMitigationCap))
newbon->DSMitigation = RuleI(Character, ItemDSMitigationCap);
else
newbon->DSMitigation += item->DSMitigation;
}
if (item->Worn.Effect > 0 && item->Worn.Type == EQ::item::ItemEffectWorn) {// latent effects
ApplySpellsBonuses(item->Worn.Effect, item->Worn.Level, newbon, 0, item->Worn.Type);
}
if (item->Focus.Effect>0 && (item->Focus.Type == EQ::item::ItemEffectFocus)) { // focus effects
ApplySpellsBonuses(item->Focus.Effect, item->Focus.Level, newbon, 0);
}
switch(item->BardType)
{
case EQ::item::ItemTypeAllInstrumentTypes: // (e.g. Singing Short Sword)
{
if (item->BardValue > newbon->singingMod)
newbon->singingMod = item->BardValue;
if (item->BardValue > newbon->brassMod)
newbon->brassMod = item->BardValue;
if (item->BardValue > newbon->stringedMod)
newbon->stringedMod = item->BardValue;
if (item->BardValue > newbon->percussionMod)
newbon->percussionMod = item->BardValue;
if (item->BardValue > newbon->windMod)
newbon->windMod = item->BardValue;
break;
}
case EQ::item::ItemTypeSinging:
{
if (item->BardValue > newbon->singingMod)
newbon->singingMod = item->BardValue;
break;
}
case EQ::item::ItemTypeWindInstrument:
{
if (item->BardValue > newbon->windMod)
newbon->windMod = item->BardValue;
break;
}
case EQ::item::ItemTypeStringedInstrument:
{
if (item->BardValue > newbon->stringedMod)
newbon->stringedMod = item->BardValue;
break;
}
case EQ::item::ItemTypeBrassInstrument:
{
if (item->BardValue > newbon->brassMod)
newbon->brassMod = item->BardValue;
break;
}
case EQ::item::ItemTypePercussionInstrument:
{
if (item->BardValue > newbon->percussionMod)
newbon->percussionMod = item->BardValue;
break;
}
}
if (item->SkillModValue != 0 && item->SkillModType <= EQ::skills::HIGHEST_SKILL) {
if ((item->SkillModValue > 0 && newbon->skillmod[item->SkillModType] < item->SkillModValue) ||
(item->SkillModValue < 0 && newbon->skillmod[item->SkillModType] > item->SkillModValue))
{
newbon->skillmod[item->SkillModType] = item->SkillModValue;
}
}
if (item->ExtraDmgAmt != 0 && item->ExtraDmgSkill <= EQ::skills::HIGHEST_SKILL) {
if (
RuleI(Character, ItemExtraDmgCap) >= 0 &&
(newbon->SkillDamageAmount[item->ExtraDmgSkill] + item->ExtraDmgAmt) > RuleI(Character, ItemExtraDmgCap)
) {
newbon->SkillDamageAmount[item->ExtraDmgSkill] = RuleI(Character, ItemExtraDmgCap);
} else {
newbon->SkillDamageAmount[item->ExtraDmgSkill] += item->ExtraDmgAmt;
}
}
if (!isAug)
{
for (int i = EQ::invaug::SOCKET_BEGIN; i <= EQ::invaug::SOCKET_END; i++)
AddItemBonuses(inst->GetAugment(i),newbon,true, false, rec_level);
}
}
int Bot::CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat)
{
if ( (reclevel > 0) && (level < reclevel) )
{
int32 statmod = (level * 10000 / reclevel) * basestat;
if ( statmod < 0 )
{
statmod -= 5000;
return (statmod/10000);
}
else
{
statmod += 5000;
return (statmod/10000);
}
}
return 0;
}
// This method is intended to call all necessary methods to do all bot stat calculations, including spell buffs, equipment, AA bonsues, etc.
void Bot::CalcBotStats(bool showtext) {
if (!GetBotOwner())

View File

@ -184,9 +184,7 @@ public:
void RogueAssassinate(Mob* other) override;
void DoClassAttacks(Mob *target, bool IsRiposte=false);
void CalcBonuses() override;
void CalcItemBonuses(StatBonuses* newbon);
void AddItemBonuses(const EQ::ItemInstance *inst, StatBonuses* newbon, bool isAug = false, bool isTribute = false, int rec_override = 0);
int CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat);
void MakePet(uint16 spell_id, const char* pettype, const char *petname = nullptr) override;
FACTION_VALUE GetReverseFactionCon(Mob* iOther) override;
inline bool IsPet() override { return false; }

View File

@ -1645,9 +1645,6 @@ public:
protected:
friend class Mob;
void CalcItemBonuses(StatBonuses* newbon);
void AddItemBonuses(const EQ::ItemInstance *inst, StatBonuses* newbon, bool isAug = false, bool isTribute = false, int rec_override = 0, bool ammo_slot_item = false);
void AdditiveWornBonuses(const EQ::ItemInstance *inst, StatBonuses* newbon, bool isAug = false);
void CalcEdibleBonuses(StatBonuses* newbon);
void MakeBuffFadePacket(uint16 spell_id, int slot_id, bool send_message = true);
bool client_data_loaded;

View File

@ -1964,10 +1964,10 @@ int Lua_Mob::GetFcDamageAmtIncoming(Lua_Mob caster, int32 spell_id)
return self->GetFcDamageAmtIncoming(caster, spell_id);
}
int Lua_Mob::GetSkillDmgAmt(uint16 skill)
int Lua_Mob::GetSkillDmgAmt(int skill_id)
{
Lua_Safe_Call_Int();
return self->GetSkillDmgAmt(skill);
return self->GetSkillDmgAmt(skill_id);
}
void Lua_Mob::SetAllowBeneficial(bool value) {

View File

@ -392,7 +392,7 @@ public:
int GetModSkillDmgTaken(int skill);
int GetSkillDmgTaken(int skill);
int GetFcDamageAmtIncoming(Lua_Mob caster, int32 spell_id);
int GetSkillDmgAmt(uint16 skill);
int GetSkillDmgAmt(int skill_id);
void SetAllowBeneficial(bool value);
bool GetAllowBeneficial();
bool IsBeneficialAllowed(Lua_Mob target);

View File

@ -1,5 +1,7 @@
#ifdef LUA_EQEMU
#include "../common/data_verification.h"
#include "lua.hpp"
#include <luabind/luabind.hpp>
@ -1097,7 +1099,11 @@ int32 Lua_StatBonuses::GetSkillReuseTime(int idx) const {
int32 Lua_StatBonuses::GetSkillDamageAmount(int idx) const {
Lua_Safe_Call_Int();
return self->SkillDamageAmount[idx];
if (!EQ::ValueWithin(idx, ALL_SKILLS, EQ::skills::HIGHEST_SKILL)) {
return 0;
}
return idx == ALL_SKILLS ? self->SkillDamageAmount[EQ::skills::HIGHEST_SKILL + 1] : self->SkillDamageAmount[idx];
}
int Lua_StatBonuses::GetHPPercCap(int idx) const {

View File

@ -190,391 +190,6 @@ float Merc::GetDefaultSize() {
return MercSize;
}
int Merc::CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat)
{
if( (reclevel > 0) && (level < reclevel) )
{
int32 statmod = (level * 10000 / reclevel) * basestat;
if( statmod < 0 )
{
statmod -= 5000;
return (statmod/10000);
}
else
{
statmod += 5000;
return (statmod/10000);
}
}
return 0;
}
void Merc::CalcItemBonuses(StatBonuses* newbon) {
//memset assumed to be done by caller.
unsigned int i;
//should not include 21 (SLOT_AMMO)
for (i = EQ::invslot::BONUS_BEGIN; i <= EQ::invslot::BONUS_STAT_END; i++) {
if (i == EQ::invslot::slotAmmo)
continue;
if (equipment[i] == 0)
continue;
const EQ::ItemData * itm = database.GetItem(equipment[i]);
if (itm)
AddItemBonuses(itm, newbon);
}
// Caps
if(newbon->HPRegen > CalcHPRegenCap())
newbon->HPRegen = CalcHPRegenCap();
if(newbon->ManaRegen > CalcManaRegenCap())
newbon->ManaRegen = CalcManaRegenCap();
if(newbon->EnduranceRegen > CalcEnduranceRegenCap())
newbon->EnduranceRegen = CalcEnduranceRegenCap();
SetAttackTimer();
}
void Merc::AddItemBonuses(const EQ::ItemData *item, StatBonuses* newbon) {
if(GetLevel() < item->ReqLevel)
{
return;
}
if(GetLevel() >= item->RecLevel)
{
newbon->AC += item->AC;
newbon->HP += item->HP;
newbon->Mana += item->Mana;
newbon->Endurance += item->Endur;
newbon->STR += (item->AStr + item->HeroicStr);
newbon->STA += (item->ASta + item->HeroicSta);
newbon->DEX += (item->ADex + item->HeroicDex);
newbon->AGI += (item->AAgi + item->HeroicAgi);
newbon->INT += (item->AInt + item->HeroicInt);
newbon->WIS += (item->AWis + item->HeroicWis);
newbon->CHA += (item->ACha + item->HeroicCha);
newbon->MR += (item->MR + item->HeroicMR);
newbon->FR += (item->FR + item->HeroicFR);
newbon->CR += (item->CR + item->HeroicCR);
newbon->PR += (item->PR + item->HeroicPR);
newbon->DR += (item->DR + item->HeroicDR);
newbon->Corrup += (item->SVCorruption + item->HeroicSVCorrup);
newbon->STRCapMod += item->HeroicStr;
newbon->STACapMod += item->HeroicSta;
newbon->DEXCapMod += item->HeroicDex;
newbon->AGICapMod += item->HeroicAgi;
newbon->INTCapMod += item->HeroicInt;
newbon->WISCapMod += item->HeroicWis;
newbon->CHACapMod += item->HeroicCha;
newbon->MRCapMod += item->HeroicMR;
newbon->CRCapMod += item->HeroicFR;
newbon->FRCapMod += item->HeroicCR;
newbon->PRCapMod += item->HeroicPR;
newbon->DRCapMod += item->HeroicDR;
newbon->CorrupCapMod += item->HeroicSVCorrup;
newbon->HeroicSTR += item->HeroicStr;
newbon->HeroicSTA += item->HeroicSta;
newbon->HeroicDEX += item->HeroicDex;
newbon->HeroicAGI += item->HeroicAgi;
newbon->HeroicINT += item->HeroicInt;
newbon->HeroicWIS += item->HeroicWis;
newbon->HeroicCHA += item->HeroicCha;
newbon->HeroicMR += item->HeroicMR;
newbon->HeroicFR += item->HeroicFR;
newbon->HeroicCR += item->HeroicCR;
newbon->HeroicPR += item->HeroicPR;
newbon->HeroicDR += item->HeroicDR;
newbon->HeroicCorrup += item->HeroicSVCorrup;
}
else
{
int lvl = GetLevel();
int reclvl = item->RecLevel;
newbon->AC += CalcRecommendedLevelBonus( lvl, reclvl, item->AC );
newbon->HP += CalcRecommendedLevelBonus( lvl, reclvl, item->HP );
newbon->Mana += CalcRecommendedLevelBonus( lvl, reclvl, item->Mana );
newbon->Endurance += CalcRecommendedLevelBonus( lvl, reclvl, item->Endur );
newbon->STR += CalcRecommendedLevelBonus( lvl, reclvl, (item->AStr + item->HeroicStr) );
newbon->STA += CalcRecommendedLevelBonus( lvl, reclvl, (item->ASta + item->HeroicSta) );
newbon->DEX += CalcRecommendedLevelBonus( lvl, reclvl, (item->ADex + item->HeroicDex) );
newbon->AGI += CalcRecommendedLevelBonus( lvl, reclvl, (item->AAgi + item->HeroicAgi) );
newbon->INT += CalcRecommendedLevelBonus( lvl, reclvl, (item->AInt + item->HeroicInt) );
newbon->WIS += CalcRecommendedLevelBonus( lvl, reclvl, (item->AWis + item->HeroicWis) );
newbon->CHA += CalcRecommendedLevelBonus( lvl, reclvl, (item->ACha + item->HeroicCha) );
newbon->MR += CalcRecommendedLevelBonus( lvl, reclvl, (item->MR + item->HeroicMR) );
newbon->FR += CalcRecommendedLevelBonus( lvl, reclvl, (item->FR + item->HeroicFR) );
newbon->CR += CalcRecommendedLevelBonus( lvl, reclvl, (item->CR + item->HeroicCR) );
newbon->PR += CalcRecommendedLevelBonus( lvl, reclvl, (item->PR + item->HeroicPR) );
newbon->DR += CalcRecommendedLevelBonus( lvl, reclvl, (item->DR + item->HeroicDR) );
newbon->Corrup += CalcRecommendedLevelBonus( lvl, reclvl, (item->SVCorruption + item->HeroicSVCorrup) );
newbon->STRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicStr );
newbon->STACapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicSta );
newbon->DEXCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicDex );
newbon->AGICapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicAgi );
newbon->INTCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicInt );
newbon->WISCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicWis );
newbon->CHACapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicCha );
newbon->MRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicMR );
newbon->CRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicFR );
newbon->FRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicCR );
newbon->PRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicPR );
newbon->DRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicDR );
newbon->CorrupCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicSVCorrup );
newbon->HeroicSTR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicStr );
newbon->HeroicSTA += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicSta );
newbon->HeroicDEX += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicDex );
newbon->HeroicAGI += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicAgi );
newbon->HeroicINT += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicInt );
newbon->HeroicWIS += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicWis );
newbon->HeroicCHA += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicCha );
newbon->HeroicMR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicMR );
newbon->HeroicFR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicFR );
newbon->HeroicCR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicCR );
newbon->HeroicPR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicPR );
newbon->HeroicDR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicDR );
newbon->HeroicCorrup += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicSVCorrup );
}
//FatherNitwit: New style haste, shields, and regens
if(newbon->haste < item->Haste) {
newbon->haste = item->Haste;
}
if(item->Regen > 0)
newbon->HPRegen += item->Regen;
if(item->ManaRegen > 0)
newbon->ManaRegen += item->ManaRegen;
if(item->EnduranceRegen > 0)
newbon->EnduranceRegen += item->EnduranceRegen;
if(item->Attack > 0) {
unsigned int cap = RuleI(Character, ItemATKCap);
cap += itembonuses.ItemATKCap + spellbonuses.ItemATKCap + aabonuses.ItemATKCap;
if((newbon->ATK + item->Attack) > cap)
newbon->ATK = RuleI(Character, ItemATKCap);
else
newbon->ATK += item->Attack;
}
if(item->DamageShield > 0) {
if((newbon->DamageShield + item->DamageShield) > RuleI(Character, ItemDamageShieldCap))
newbon->DamageShield = RuleI(Character, ItemDamageShieldCap);
else
newbon->DamageShield += item->DamageShield;
}
if(item->SpellShield > 0) {
if((newbon->SpellShield + item->SpellShield) > RuleI(Character, ItemSpellShieldingCap))
newbon->SpellShield = RuleI(Character, ItemSpellShieldingCap);
else
newbon->SpellShield += item->SpellShield;
}
if(item->Shielding > 0) {
if((newbon->MeleeMitigation + item->Shielding) > RuleI(Character, ItemShieldingCap))
newbon->MeleeMitigation = RuleI(Character, ItemShieldingCap);
else
newbon->MeleeMitigation += item->Shielding;
}
if(item->StunResist > 0) {
if((newbon->StunResist + item->StunResist) > RuleI(Character, ItemStunResistCap))
newbon->StunResist = RuleI(Character, ItemStunResistCap);
else
newbon->StunResist += item->StunResist;
}
if(item->StrikeThrough > 0) {
if((newbon->StrikeThrough + item->StrikeThrough) > RuleI(Character, ItemStrikethroughCap))
newbon->StrikeThrough = RuleI(Character, ItemStrikethroughCap);
else
newbon->StrikeThrough += item->StrikeThrough;
}
if(item->Avoidance > 0) {
if((newbon->AvoidMeleeChance + item->Avoidance) > RuleI(Character, ItemAvoidanceCap))
newbon->AvoidMeleeChance = RuleI(Character, ItemAvoidanceCap);
else
newbon->AvoidMeleeChance += item->Avoidance;
}
if(item->Accuracy > 0) {
if((newbon->HitChance + item->Accuracy) > RuleI(Character, ItemAccuracyCap))
newbon->HitChance = RuleI(Character, ItemAccuracyCap);
else
newbon->HitChance += item->Accuracy;
}
if(item->CombatEffects > 0) {
if((newbon->ProcChance + item->CombatEffects) > RuleI(Character, ItemCombatEffectsCap))
newbon->ProcChance = RuleI(Character, ItemCombatEffectsCap);
else
newbon->ProcChance += item->CombatEffects;
}
if(item->DotShielding > 0) {
if((newbon->DoTShielding + item->DotShielding) > RuleI(Character, ItemDoTShieldingCap))
newbon->DoTShielding = RuleI(Character, ItemDoTShieldingCap);
else
newbon->DoTShielding += item->DotShielding;
}
if(item->HealAmt > 0) {
if((newbon->HealAmt + item->HealAmt) > RuleI(Character, ItemHealAmtCap))
newbon->HealAmt = RuleI(Character, ItemHealAmtCap);
else
newbon->HealAmt += item->HealAmt;
}
if(item->SpellDmg > 0) {
if((newbon->SpellDmg + item->SpellDmg) > RuleI(Character, ItemSpellDmgCap))
newbon->SpellDmg = RuleI(Character, ItemSpellDmgCap);
else
newbon->SpellDmg += item->SpellDmg;
}
if(item->Clairvoyance > 0) {
if((newbon->Clairvoyance + item->Clairvoyance) > RuleI(Character, ItemClairvoyanceCap))
newbon->Clairvoyance = RuleI(Character, ItemClairvoyanceCap);
else
newbon->Clairvoyance += item->Clairvoyance;
}
if(item->DSMitigation > 0) {
if((newbon->DSMitigation + item->DSMitigation) > RuleI(Character, ItemDSMitigationCap))
newbon->DSMitigation = RuleI(Character, ItemDSMitigationCap);
else
newbon->DSMitigation += item->DSMitigation;
}
if (item->Worn.Effect>0 && (item->Worn.Type == EQ::item::ItemEffectWorn)) { // latent effects
ApplySpellsBonuses(item->Worn.Effect, item->Worn.Level, newbon, 0, item->Worn.Type);
}
if (item->Focus.Effect>0 && (item->Focus.Type == EQ::item::ItemEffectFocus)) { // focus effects
ApplySpellsBonuses(item->Focus.Effect, item->Focus.Level, newbon, 0);
}
switch(item->BardType)
{
case 51: /* All (e.g. Singing Short Sword) */
{
if(item->BardValue > newbon->singingMod)
newbon->singingMod = item->BardValue;
if(item->BardValue > newbon->brassMod)
newbon->brassMod = item->BardValue;
if(item->BardValue > newbon->stringedMod)
newbon->stringedMod = item->BardValue;
if(item->BardValue > newbon->percussionMod)
newbon->percussionMod = item->BardValue;
if(item->BardValue > newbon->windMod)
newbon->windMod = item->BardValue;
break;
}
case 50: /* Singing */
{
if(item->BardValue > newbon->singingMod)
newbon->singingMod = item->BardValue;
break;
}
case 23: /* Wind */
{
if(item->BardValue > newbon->windMod)
newbon->windMod = item->BardValue;
break;
}
case 24: /* stringed */
{
if(item->BardValue > newbon->stringedMod)
newbon->stringedMod = item->BardValue;
break;
}
case 25: /* brass */
{
if(item->BardValue > newbon->brassMod)
newbon->brassMod = item->BardValue;
break;
}
case 26: /* Percussion */
{
if(item->BardValue > newbon->percussionMod)
newbon->percussionMod = item->BardValue;
break;
}
}
if (item->SkillModValue != 0 && item->SkillModType <= EQ::skills::HIGHEST_SKILL){
if ((item->SkillModValue > 0 && newbon->skillmod[item->SkillModType] < item->SkillModValue) ||
(item->SkillModValue < 0 && newbon->skillmod[item->SkillModType] > item->SkillModValue))
{
newbon->skillmod[item->SkillModType] = item->SkillModValue;
}
}
// Add Item Faction Mods
if (item->FactionMod1)
{
if (item->FactionAmt1 > 0 && item->FactionAmt1 > GetItemFactionBonus(item->FactionMod1))
{
AddItemFactionBonus(item->FactionMod1, item->FactionAmt1);
}
else if (item->FactionAmt1 < 0 && item->FactionAmt1 < GetItemFactionBonus(item->FactionMod1))
{
AddItemFactionBonus(item->FactionMod1, item->FactionAmt1);
}
}
if (item->FactionMod2)
{
if (item->FactionAmt2 > 0 && item->FactionAmt2 > GetItemFactionBonus(item->FactionMod2))
{
AddItemFactionBonus(item->FactionMod2, item->FactionAmt2);
}
else if (item->FactionAmt2 < 0 && item->FactionAmt2 < GetItemFactionBonus(item->FactionMod2))
{
AddItemFactionBonus(item->FactionMod2, item->FactionAmt2);
}
}
if (item->FactionMod3)
{
if (item->FactionAmt3 > 0 && item->FactionAmt3 > GetItemFactionBonus(item->FactionMod3))
{
AddItemFactionBonus(item->FactionMod3, item->FactionAmt3);
}
else if (item->FactionAmt3 < 0 && item->FactionAmt3 < GetItemFactionBonus(item->FactionMod3))
{
AddItemFactionBonus(item->FactionMod3, item->FactionAmt3);
}
}
if (item->FactionMod4)
{
if (item->FactionAmt4 > 0 && item->FactionAmt4 > GetItemFactionBonus(item->FactionMod4))
{
AddItemFactionBonus(item->FactionMod4, item->FactionAmt4);
}
else if (item->FactionAmt4 < 0 && item->FactionAmt4 < GetItemFactionBonus(item->FactionMod4))
{
AddItemFactionBonus(item->FactionMod4, item->FactionAmt4);
}
}
if (item->ExtraDmgAmt != 0 && item->ExtraDmgSkill <= EQ::skills::HIGHEST_SKILL) {
if (
RuleI(Character, ItemExtraDmgCap) >= 0 &&
(newbon->SkillDamageAmount[item->ExtraDmgSkill] + item->ExtraDmgAmt) > RuleI(Character, ItemExtraDmgCap)
) {
newbon->SkillDamageAmount[item->ExtraDmgSkill] = RuleI(Character, ItemExtraDmgCap);
} else {
newbon->SkillDamageAmount[item->ExtraDmgSkill] += item->ExtraDmgAmt;
}
}
}
int Merc::GroupLeadershipAAHealthEnhancement()
{
Group *g = GetGroup();

View File

@ -268,10 +268,6 @@ public:
bool FindTarget();
protected:
void CalcItemBonuses(StatBonuses* newbon);
void AddItemBonuses(const EQ::ItemData *item, StatBonuses* newbon);
int CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat);
int64 GetFocusEffect(focusType type, uint16 spell_id, bool from_buff_tic = false);
std::vector<MercSpell> merc_spells;

View File

@ -16,6 +16,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/data_verification.h"
#include "../common/spdat.h"
#include "../common/strings.h"
#include "../common/misc_functions.h"
@ -3999,7 +4000,7 @@ void Mob::QuestJournalledSay(Client *QuestInitiator, const char *str, Journal::O
const char *Mob::GetCleanName()
{
if (!strlen(clean_name)) {
if (!strlen(clean_name)) {
CleanMobName(GetName(), clean_name);
}
@ -5549,16 +5550,41 @@ int16 Mob::GetSkillReuseTime(uint16 skill)
return skill_reduction;
}
int Mob::GetSkillDmgAmt(uint16 skill)
int Mob::GetSkillDmgAmt(int skill_id)
{
int skill_dmg = 0;
// All skill dmg(only spells do this) + Skill specific
skill_dmg += spellbonuses.SkillDamageAmount[EQ::skills::HIGHEST_SKILL + 1] + itembonuses.SkillDamageAmount[EQ::skills::HIGHEST_SKILL + 1] + aabonuses.SkillDamageAmount[EQ::skills::HIGHEST_SKILL + 1]
+ itembonuses.SkillDamageAmount[skill] + spellbonuses.SkillDamageAmount[skill] + aabonuses.SkillDamageAmount[skill];
if (!EQ::ValueWithin(skill_id, ALL_SKILLS, EQ::skills::HIGHEST_SKILL)) {
return skill_dmg;
}
skill_dmg += spellbonuses.SkillDamageAmount2[EQ::skills::HIGHEST_SKILL + 1] + itembonuses.SkillDamageAmount2[EQ::skills::HIGHEST_SKILL + 1]
+ itembonuses.SkillDamageAmount2[skill] + spellbonuses.SkillDamageAmount2[skill];
skill_dmg += (
spellbonuses.SkillDamageAmount[EQ::skills::HIGHEST_SKILL + 1] +
itembonuses.SkillDamageAmount[EQ::skills::HIGHEST_SKILL + 1] +
aabonuses.SkillDamageAmount[EQ::skills::HIGHEST_SKILL + 1]
);
if (skill_id != ALL_SKILLS) {
skill_dmg += (
itembonuses.SkillDamageAmount[skill_id] +
spellbonuses.SkillDamageAmount[skill_id] +
aabonuses.SkillDamageAmount[skill_id]
);
}
skill_dmg += (
spellbonuses.SkillDamageAmount2[EQ::skills::HIGHEST_SKILL + 1] +
itembonuses.SkillDamageAmount2[EQ::skills::HIGHEST_SKILL + 1] +
aabonuses.SkillDamageAmount2[EQ::skills::HIGHEST_SKILL + 1]
);
if (skill_id != ALL_SKILLS) {
skill_dmg += (
itembonuses.SkillDamageAmount2[skill_id] +
spellbonuses.SkillDamageAmount2[skill_id] +
aabonuses.SkillDamageAmount2[skill_id]
);
}
return skill_dmg;
}

View File

@ -664,8 +664,6 @@ public:
virtual int32 CalcItemATKCap() { return 0; }
virtual bool IsSitting() const { return false; }
int CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat);
void CopyHateList(Mob* to);
//Group
@ -953,7 +951,7 @@ public:
int16 GetMeleeDmgPositionMod(Mob* defender);
int16 GetSkillReuseTime(uint16 skill);
int GetCriticalChanceBonus(uint16 skill);
int GetSkillDmgAmt(uint16 skill);
int GetSkillDmgAmt(int skill_id);
int16 GetPositionalDmgAmt(Mob* defender);
inline bool CanBlockSpell() const { return(spellbonuses.FocusEffects[focusBlockNextSpell]); }
bool DoHPToManaCovert(int32 mana_cost = 0);
@ -1378,6 +1376,11 @@ public:
void ApplyAABonuses(const AA::Rank &rank, StatBonuses* newbon);
bool CheckAATimer(int timer);
void CalcItemBonuses(StatBonuses* b);
void AddItemBonuses(const EQ::ItemInstance* inst, StatBonuses* b, bool is_augment = false, bool is_tribute = false, int recommended_level_override = 0, bool is_ammo_item = false);
void AdditiveWornBonuses(const EQ::ItemInstance* inst, StatBonuses* b, bool is_augment = false);
int CalcRecommendedLevelBonus(uint8 current_level, uint8 recommended_level, int base_stat);
int NPCAssistCap() { return npc_assist_cap; }
void AddAssistCap() { ++npc_assist_cap; }
void DelAssistCap() { --npc_assist_cap; }

View File

@ -162,7 +162,6 @@ public:
virtual void SetTarget(Mob* mob);
virtual uint16 GetSkill(EQ::skills::SkillType skill_num) const { if (skill_num <= EQ::skills::HIGHEST_SKILL) { return skills[skill_num]; } return 0; }
void CalcItemBonuses(StatBonuses *newbon);
virtual void CalcBonuses();
virtual int GetCurrentBuffSlots() const { return RuleI(Spells, MaxBuffSlotsNPC); }
virtual int GetCurrentSongSlots() const { return RuleI(Spells, MaxSongSlotsNPC); }

View File

@ -2517,7 +2517,7 @@ void Perl_Mob_ApplySpellBuff(Mob* self, int spell_id, int duration) // @categori
self->ApplySpellBuff(spell_id, duration);
}
int Perl_Mob_GetSkillDmgAmt(Mob* self, uint16 skill_id)
int Perl_Mob_GetSkillDmgAmt(Mob* self, int skill_id)
{
return self->GetSkillDmgAmt(skill_id);
}