Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Rules] Add Multiplier for Heroic Stats. #3014

Merged
merged 6 commits into from
Mar 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions common/ruletypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@ RULE_INT(Character, ItemEnduranceRegenCap, 15, "Limit on endurance regeneration
RULE_INT(Character, ItemExtraDmgCap, 150, "Cap for bonuses to melee skills like Bash, Frenzy, etc.")
RULE_INT(Character, HasteCap, 100, "Haste cap for non-v3(over haste) haste")
RULE_INT(Character, Hastev3Cap, 25, "Haste cap for v3(over haste) haste")
RULE_REAL(Character, HeroicStrengthMultiplier, 1.00, "Multplier scales benefits from Heroic Strength. Grants 25 Base Endurance, 0.05 Endurance Regen, 1 Melee Damage each Hit, and 1 Shield AC per 10 Heroic Strength.")
RULE_REAL(Character, HeroicStaminaMultiplier, 1.00, "Multplier scales benefits from Heroic Stamina. Grants 25 Base Endurance, 0.05 Endurance Regen, 100 Base HP, and 0.5 HP Regen per 10 Heroic Stamina.")
RULE_REAL(Character, HeroicAgilityMultiplier, 1.00, "Multplier scales benefits from Heroic Agility. Grants 25 Base Endurance, 0.05 Endurance Regen, and 1 Avoidance AC per 10 Heroic Agility. (Rule does not change Dodge Chance)")
RULE_REAL(Character, HeroicDexterityMultiplier, 1.00, "Multplier scales benefits from Heroic Dexterity. Grants 25 Base Endurance, 0.05 Endurance Regen, and 1 Archery/Throwing Damage each hit per 10 Heroic Dexterity. (Rule does not change Assassinate/Headshot/Block/Parry/Riposte Chances)")
RULE_REAL(Character, HeroicWisdomMultiplier, 1.00, "Multplier scales benefits from Heroic Wisdom. Grants 250 Base Mana, 1 Mana Regen per 25 Heroic Wisdom.")
RULE_REAL(Character, HeroicIntelligenceMultiplier, 1.00, "Multplier scales benefits from Heroic Intelligence. Grants 250 Base Mana, 1 Mana Regen per 25 Heroic Intelligence.")
RULE_INT(Character, SkillUpModifier, 100, "The probability for a skill-up is multiplied by value/100")
RULE_BOOL(Character, SharedBankPlat, false, "Shared bank platinum. Off by default to prevent duplication")
RULE_BOOL(Character, BindAnywhere, false, "Allows players to bind their soul anywhere in the world")
Expand Down
8 changes: 4 additions & 4 deletions zone/attack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ int Mob::compute_defense()
int defense = GetSkill(EQ::skills::SkillDefense) * 400 / 225;
defense += (8000 * (GetAGI() - 40)) / 36000;
if (IsOfClientBot()) {
defense += GetHeroicAGI() / 10;
defense += GetHeroicAGI() * RuleR(Character, HeroicAgilityMultiplier) / 10;
}

//516 SE_AC_Mitigation_Max_Percent
Expand Down Expand Up @@ -883,7 +883,7 @@ int Mob::ACSum(bool skip_caps)
shield_ac = CalcRecommendedLevelBonus(GetLevel(), inst->GetItemRecommendedLevel(true), inst->GetItemArmorClass(true));
}
}
shield_ac += GetHeroicSTR() / 10;
shield_ac += GetHeroicSTR() * RuleR(Character, HeroicStrengthMultiplier) / 10;
}
// EQ math
ac = (ac * 4) / 3;
Expand Down Expand Up @@ -5897,10 +5897,10 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraAttac
switch (hit.skill) {
case EQ::skills::SkillThrowing:
case EQ::skills::SkillArchery:
extra = GetHeroicDEX() / 10;
extra = GetHeroicDEX() * RuleR(Character, HeroicDexterityMultiplier) / 10;
break;
default:
extra = GetHeroicSTR() / 10;
extra = GetHeroicSTR() * RuleR(Character, HeroicStrengthMultiplier) / 10;
break;
}
hit.damage_done += extra;
Expand Down
66 changes: 37 additions & 29 deletions zone/bot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6693,10 +6693,10 @@ int64 Bot::CalcManaRegenCap() {
int64 cap = RuleI(Character, ItemManaRegenCap) + aabonuses.ItemManaRegenCap;
switch(GetCasterClass()) {
case 'I':
cap += (itembonuses.HeroicINT / 25);
cap += itembonuses.HeroicINT * RuleR(Character, HeroicIntelligenceMultiplier) / 25;
break;
case 'W':
cap += (itembonuses.HeroicWIS / 25);
cap += itembonuses.HeroicWIS * RuleR(Character, HeroicWisdomMultiplier) / 25;
break;
}
return (cap * RuleI(Character, ManaRegenMultiplier) / 100);
Expand Down Expand Up @@ -7088,8 +7088,9 @@ int32 Bot::LevelRegen() {

int64 Bot::CalcHPRegen() {
int32 regen = (LevelRegen() + itembonuses.HPRegen + spellbonuses.HPRegen);
regen += GetHeroicSTA() / 20;
regen += GetHeroicSTA() * RuleR(Character, HeroicStaminaMultiplier) / 20;
regen += (aabonuses.HPRegen + GroupLeadershipAAHealthRegeneration());

regen = ((regen * RuleI(Character, HPRegenMultiplier)) / 100);
return regen;
}
Expand All @@ -7109,9 +7110,9 @@ int64 Bot::CalcManaRegen() {
regen = (2 + spellbonuses.ManaRegen + itembonuses.ManaRegen);

if(GetCasterClass() == 'I')
regen += (itembonuses.HeroicINT / 25);
regen += itembonuses.HeroicINT * RuleR(Character, HeroicIntelligenceMultiplier) / 25;
else if(GetCasterClass() == 'W')
regen += (itembonuses.HeroicWIS / 25);
regen += itembonuses.HeroicWIS * RuleR(Character, HeroicWisdomMultiplier) / 25;
else
regen = 0;

Expand Down Expand Up @@ -7160,7 +7161,7 @@ int64 Bot::CalcMaxHP() {
int32 bot_hp = 0;
uint32 nd = 10000;
bot_hp += (GenerateBaseHitPoints() + itembonuses.HP);
bot_hp += (GetHeroicSTA() * 10);
bot_hp += GetHeroicSTA() * RuleR(Character, HeroicStaminaMultiplier) * 10;
nd += aabonuses.MaxHP;
bot_hp = ((float)bot_hp * (float)nd / (float)10000);
bot_hp += (spellbonuses.HP + aabonuses.HP);
Expand Down Expand Up @@ -7200,35 +7201,42 @@ int64 Bot::CalcMaxEndurance() {
int64 Bot::CalcBaseEndurance() {
int32 base_end = 0;
int32 base_endurance = 0;
int32 ConvertedStats = 0;
int32 converted_stats = 0;
int32 sta_end = 0;
int Stats = 0;
int stats = 0;
if (GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->ClientVersion() >= EQ::versions::ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) {
int HeroicStats = 0;
Stats = ((GetSTR() + GetSTA() + GetDEX() + GetAGI()) / 4);
HeroicStats = ((GetHeroicSTR() + GetHeroicSTA() + GetHeroicDEX() + GetHeroicAGI()) / 4);
if (Stats > 100) {
ConvertedStats = (((Stats - 100) * 5 / 2) + 100);
if (Stats > 201)
ConvertedStats -= ((Stats - 201) * 5 / 4);
} else
ConvertedStats = Stats;
double heroic_stats = 0;
stats = ((GetSTR() + GetSTA() + GetDEX() + GetAGI()) / 4);
double heroic_str = GetHeroicSTR() * RuleR(Character, HeroicStrengthMultiplier);
double heroic_sta = GetHeroicSTA() * RuleR(Character, HeroicStaminaMultiplier);
double heroic_dex = GetHeroicDEX() * RuleR(Character, HeroicDexterityMultiplier);
double heroic_agi = GetHeroicAGI() * RuleR(Character, HeroicAgilityMultiplier);
heroic_stats = (heroic_str + heroic_sta + heroic_dex + heroic_agi) / 4;

if (stats > 100) {
converted_stats = (((stats - 100) * 5 / 2) + 100);
if (stats > 201) {
converted_stats -= ((stats - 201) * 5 / 4);
}
} else {
converted_stats = stats;
}

if (GetLevel() < 41) {
sta_end = (GetLevel() * 75 * ConvertedStats / 1000);
sta_end = (GetLevel() * 75 * converted_stats / 1000);
base_endurance = (GetLevel() * 15);
} else if (GetLevel() < 81) {
sta_end = ((3 * ConvertedStats) + ((GetLevel() - 40) * 15 * ConvertedStats / 100));
sta_end = ((3 * converted_stats) + ((GetLevel() - 40) * 15 * converted_stats / 100));
base_endurance = (600 + ((GetLevel() - 40) * 30));
} else {
sta_end = (9 * ConvertedStats);
sta_end = (9 * converted_stats);
base_endurance = (1800 + ((GetLevel() - 80) * 18));
}
base_end = (base_endurance + sta_end + (HeroicStats * 10));
base_end = (base_endurance + sta_end + (heroic_stats * 10));
} else {
Stats = (GetSTR()+GetSTA()+GetDEX()+GetAGI());
int LevelBase = (GetLevel() * 15);
int at_most_800 = Stats;
stats = (GetSTR() + GetSTA() + GetDEX() + GetAGI());
int level_base = (GetLevel() * 15);
int at_most_800 = stats;
if(at_most_800 > 800)
at_most_800 = 800;

Expand All @@ -7237,16 +7245,16 @@ int64 Bot::CalcBaseEndurance() {
int Bonus800plus = 0;
int HalfBonus800plus = 0;
int BonusUpto800 = int(at_most_800 / 4) ;
if(Stats > 400) {
if(stats > 400) {
Bonus400to800 = int((at_most_800 - 400) / 4);
HalfBonus400to800 = int(std::max((at_most_800 - 400), 0) / 8);
if(Stats > 800) {
Bonus800plus = (int((Stats - 800) / 8) * 2);
HalfBonus800plus = int((Stats - 800) / 16);
if(stats > 800) {
Bonus800plus = (int((stats - 800) / 8) * 2);
HalfBonus800plus = int((stats - 800) / 16);
}
}
int bonus_sum = (BonusUpto800 + Bonus400to800 + HalfBonus400to800 + Bonus800plus + HalfBonus800plus);
base_end = LevelBase;
base_end = level_base;
base_end += ((bonus_sum * 3 * GetLevel()) / 40);
}
return base_end;
Expand Down
19 changes: 14 additions & 5 deletions zone/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6381,7 +6381,7 @@ void Client::SendStatsWindow(Client* client, bool use_window)
if(CalcMaxMana() > 0) {
cur_name = " M: ";
cur_field = itoa(GetMana());
total_field = itoa(CalcMaxMana());
total_field = itoa(GetMaxMana());
}
else { continue; }

Expand Down Expand Up @@ -6436,20 +6436,24 @@ void Client::SendStatsWindow(Client* client, bool use_window)
regen_row_color = color_red;

base_regen_field = itoa(LevelRegen());
item_regen_field = itoa(itembonuses.HPRegen);
item_regen_field = itoa(
itembonuses.HPRegen +(GetHeroicSTA() * RuleR(Character, HeroicStaminaMultiplier) / 20));
cap_regen_field = itoa(CalcHPRegenCap());
spell_regen_field = itoa(spellbonuses.HPRegen);
aa_regen_field = itoa(aabonuses.HPRegen);
total_regen_field = itoa(CalcHPRegen(true));
break;
}
case 1: {
if(CalcMaxMana() > 0) {
if(GetMaxMana() > 0) {
regen_row_header = "M: ";
regen_row_color = color_blue;

base_regen_field = itoa(CalcBaseManaRegen());
item_regen_field = itoa(itembonuses.ManaRegen);
int32 heroic_mana_regen = (GetCasterClass() == 'W') ?
GetHeroicWIS() * RuleR(Character, HeroicWisdomMultiplier) / 25 :
GetHeroicINT() * RuleR(Character, HeroicIntelligenceMultiplier) / 25;
item_regen_field = itoa(itembonuses.ManaRegen + heroic_mana_regen);
cap_regen_field = itoa(CalcManaRegenCap());
spell_regen_field = itoa(spellbonuses.ManaRegen);
aa_regen_field = itoa(aabonuses.ManaRegen);
Expand All @@ -6463,7 +6467,12 @@ void Client::SendStatsWindow(Client* client, bool use_window)
regen_row_color = color_green;

base_regen_field = itoa(((GetLevel() * 4 / 10) + 2));
item_regen_field = itoa(itembonuses.EnduranceRegen);
double heroic_str = GetHeroicSTR() * RuleR(Character, HeroicStrengthMultiplier);
double heroic_sta = GetHeroicSTA() * RuleR(Character, HeroicStaminaMultiplier);
double heroic_dex = GetHeroicDEX() * RuleR(Character, HeroicDexterityMultiplier);
double heroic_agi = GetHeroicAGI() * RuleR(Character, HeroicAgilityMultiplier);
double heroic_stats = (heroic_str + heroic_sta + heroic_dex + heroic_agi) / 4;
item_regen_field = itoa(itembonuses.EnduranceRegen + heroic_stats);
cap_regen_field = itoa(CalcEnduranceRegenCap());
spell_regen_field = itoa(spellbonuses.EnduranceRegen);
aa_regen_field = itoa(aabonuses.EnduranceRegen);
Expand Down
29 changes: 21 additions & 8 deletions zone/client_mods.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ int32 Client::LevelRegen()
int64 Client::CalcHPRegen(bool bCombat)
{
int64 item_regen = itembonuses.HPRegen; // worn spells and +regen, already capped
item_regen += GetHeroicSTA() / 20;
item_regen += GetHeroicSTA() * RuleR(Character, HeroicStaminaMultiplier) / 20;

item_regen += aabonuses.HPRegen;

Expand Down Expand Up @@ -491,7 +491,7 @@ int64 Client::CalcBaseHP()
auto base_data = database.GetBaseData(GetLevel(), GetClass());
if (base_data) {
base_hp += base_data->base_hp + (base_data->hp_factor * stats);
base_hp += (GetHeroicSTA() * 10);
base_hp += GetHeroicSTA() * RuleR(Character, HeroicStaminaMultiplier) * 10;
}
}
else {
Expand Down Expand Up @@ -623,7 +623,9 @@ int64 Client::CalcBaseMana()
}
auto base_data = database.GetBaseData(GetLevel(), GetClass());
if (base_data) {
max_m = base_data->base_mana + (ConvertedWisInt * base_data->mana_factor) + (GetHeroicINT() * 10);
max_m = base_data->base_mana +
(ConvertedWisInt * base_data->mana_factor) +
(GetHeroicINT() * RuleR(Character, HeroicIntelligenceMultiplier) * 10);
}
}
else {
Expand Down Expand Up @@ -655,7 +657,9 @@ int64 Client::CalcBaseMana()
}
auto base_data = database.GetBaseData(GetLevel(), GetClass());
if (base_data) {
max_m = base_data->base_mana + (ConvertedWisInt * base_data->mana_factor) + (GetHeroicWIS() * 10);
max_m = base_data->base_mana +
(ConvertedWisInt * base_data->mana_factor) +
((GetHeroicWIS() * RuleR(Character, HeroicWisdomMultiplier)) * 10);
}
}
else {
Expand Down Expand Up @@ -752,10 +756,10 @@ int64 Client::CalcManaRegen(bool bCombat)

switch (GetCasterClass()) {
case 'W':
heroic_bonus = GetHeroicWIS();
heroic_bonus = GetHeroicWIS() * RuleR(Character, HeroicWisdomMultiplier);
break;
default:
heroic_bonus = GetHeroicINT();
heroic_bonus = GetHeroicINT() * RuleR(Character, HeroicIntelligenceMultiplier);
break;
}

Expand Down Expand Up @@ -1686,8 +1690,13 @@ int64 Client::CalcBaseEndurance()
{
int64 base_end = 0;
if (ClientVersion() >= EQ::versions::ClientVersion::SoF && RuleB(Character, SoDClientUseSoDHPManaEnd)) {
double heroic_stats = (GetHeroicSTR() + GetHeroicSTA() + GetHeroicDEX() + GetHeroicAGI()) / 4.0f;
double heroic_str = GetHeroicSTR() * RuleR(Character, HeroicStrengthMultiplier);
double heroic_sta = GetHeroicSTA() * RuleR(Character, HeroicStaminaMultiplier);
double heroic_dex = GetHeroicDEX() * RuleR(Character, HeroicDexterityMultiplier);
double heroic_agi = GetHeroicAGI() * RuleR(Character, HeroicAgilityMultiplier);
double heroic_stats = (heroic_str + heroic_sta + heroic_dex + heroic_agi) / 4;
double stats = (GetSTR() + GetSTA() + GetDEX() + GetAGI()) / 4.0f;

if (stats > 201.0f) {
stats = 1.25f * (stats - 201.0f) + 352.5f;
}
Expand Down Expand Up @@ -1785,7 +1794,11 @@ int64 Client::CalcEnduranceRegen(bool bCombat)
if (encumbered)
base += level / -15;

auto item_bonus = GetHeroicAGI() + GetHeroicDEX() + GetHeroicSTA() + GetHeroicSTR();
double heroic_str = GetHeroicSTR() * RuleR(Character, HeroicStrengthMultiplier);
double heroic_sta = GetHeroicSTA() * RuleR(Character, HeroicStaminaMultiplier);
double heroic_dex = GetHeroicDEX() * RuleR(Character, HeroicDexterityMultiplier);
double heroic_agi = GetHeroicAGI() * RuleR(Character, HeroicAgilityMultiplier);
int32 item_bonus = heroic_str + heroic_sta + heroic_dex + heroic_agi;
item_bonus = item_bonus / 4 / 50;
item_bonus += itembonuses.EnduranceRegen; // this is capped already
base += item_bonus;
Expand Down
18 changes: 9 additions & 9 deletions zone/tune.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1049,7 +1049,7 @@ int64 Mob::TuneACSum(bool skip_caps, int ac_override, int add_ac)
shield_ac = CalcRecommendedLevelBonus(GetLevel(), inst->GetItemRecommendedLevel(true),inst->GetItemArmorClass(true));
}
}
shield_ac += GetHeroicSTR() / 10;
shield_ac += GetHeroicSTR() * RuleR(Character, HeroicStrengthMultiplier) / 10;
}
// EQ math
ac = (ac * 4) / 3;
Expand Down Expand Up @@ -1353,7 +1353,7 @@ int64 Mob::Tunecompute_defense(int avoidance_override, int add_avoidance)
defense = avoidance_override;
}
else {
defense += GetHeroicAGI() / 10;
defense += GetHeroicAGI() * RuleR(Character, HeroicAgilityMultiplier) / 10;
}
defense += add_avoidance; //1 pt = 10 heroic agi
}
Expand Down Expand Up @@ -1493,13 +1493,13 @@ void Mob::TuneCommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraA
if (IsOfClientBot()) {
int extra = 0;
switch (hit.skill) {
case EQ::skills::SkillThrowing:
case EQ::skills::SkillArchery:
extra = GetHeroicDEX() / 10;
break;
default:
extra = GetHeroicSTR() / 10;
break;
case EQ::skills::SkillThrowing:
case EQ::skills::SkillArchery:
extra = GetHeroicDEX() * RuleR(Character, HeroicDexterityMultiplier) / 10;
break;
default:
extra = GetHeroicSTR() * RuleR(Character, HeroicStrengthMultiplier) / 10;
break;
}
hit.damage_done += extra;
}
Expand Down