[Feature] Add Data Bucket support for scaling of Heroic Stats. (#3058)

* [Feature] Add Data Bucket support for scaling of Heroic Stats.

* update

* fixes, still reworking logic

* fixes, still reworking logic

* logic done

* logic done

* fixes

* Cleanup

* Cleanup

* Cleanup naming, verify behaviors

* formatting

* formatting

* fix issue with endurance and mana.

* update rule desc

* cleanup

* DataBucket Struct

* Cleanup data_bucket.cpp and add constants

* cleanup

* changes

* formatting

* fix from merge

* escape keyword `key`

* Add `key` to generator, run repository-generator.pl

* fix for change to key

* cleanup

* formatting

* formatting

* typo
This commit is contained in:
Aeadoin
2023-03-23 21:42:13 -04:00
committed by GitHub
parent abc27ab423
commit 59ad91a140
28 changed files with 433 additions and 243 deletions
+22 -91
View File
@@ -3284,8 +3284,7 @@ bool Bot::Spawn(Client* botCharacterOwner) {
m_targetable = true;
entity_list.AddBot(this, true, true);
GetBotOwnerDataBuckets();
GetBotDataBuckets();
DataBucket::GetDataBuckets(this);
LoadBotSpellSettings();
if (!AI_AddBotSpells(GetBotSpellID())) {
GetBotOwner()->CastToClient()->Message(
@@ -5461,10 +5460,10 @@ int64 Bot::CalcMaxMana() {
switch(GetCasterClass()) {
case 'I':
max_mana = (GenerateBaseManaPoints() + itembonuses.Mana + spellbonuses.Mana + GroupLeadershipAAManaEnhancement());
max_mana += (GetHeroicINT() * 10);
max_mana += itembonuses.heroic_max_mana;
case 'W': {
max_mana = (GenerateBaseManaPoints() + itembonuses.Mana + spellbonuses.Mana + GroupLeadershipAAManaEnhancement());
max_mana += (GetHeroicWIS() * 10);
max_mana += itembonuses.heroic_max_mana;
break;
}
case 'N': {
@@ -6001,11 +6000,13 @@ void Bot::CalcBonuses() {
memset(&itembonuses, 0, sizeof(StatBonuses));
GenerateBaseStats();
CalcItemBonuses(&itembonuses);
CalcHeroicBonuses(&itembonuses);
CalcSpellBonuses(&spellbonuses);
CalcAABonuses(&aabonuses);
SetAttackTimer();
CalcSeeInvisibleLevel();
CalcInvisibleLevel();
ProcessItemCaps();
CalcATK();
CalcSTR();
CalcSTA();
@@ -6037,15 +6038,7 @@ int64 Bot::CalcHPRegenCap() {
}
int64 Bot::CalcManaRegenCap() {
int64 cap = RuleI(Character, ItemManaRegenCap) + aabonuses.ItemManaRegenCap;
switch(GetCasterClass()) {
case 'I':
cap += itembonuses.HeroicINT * RuleR(Character, HeroicIntelligenceMultiplier) / 25;
break;
case 'W':
cap += itembonuses.HeroicWIS * RuleR(Character, HeroicWisdomMultiplier) / 25;
break;
}
int64 cap = RuleI(Character, ItemManaRegenCap) + aabonuses.ItemManaRegenCap + itembonuses.heroic_mana_regen;
return (cap * RuleI(Character, ManaRegenMultiplier) / 100);
}
@@ -6435,7 +6428,7 @@ int32 Bot::LevelRegen() {
int64 Bot::CalcHPRegen() {
int32 regen = (LevelRegen() + itembonuses.HPRegen + spellbonuses.HPRegen);
regen += GetHeroicSTA() * RuleR(Character, HeroicStaminaMultiplier) / 20;
regen += itembonuses.heroic_hp_regen;
regen += (aabonuses.HPRegen + GroupLeadershipAAHealthRegeneration());
regen = ((regen * RuleI(Character, HPRegenMultiplier)) / 100);
@@ -6456,15 +6449,8 @@ int64 Bot::CalcManaRegen() {
} else
regen = (2 + spellbonuses.ManaRegen + itembonuses.ManaRegen);
if(GetCasterClass() == 'I')
regen += itembonuses.HeroicINT * RuleR(Character, HeroicIntelligenceMultiplier) / 25;
else if(GetCasterClass() == 'W')
regen += itembonuses.HeroicWIS * RuleR(Character, HeroicWisdomMultiplier) / 25;
regen += aabonuses.ManaRegen + itembonuses.heroic_mana_regen;
else
regen = 0;
regen += aabonuses.ManaRegen;
regen = ((regen * RuleI(Character, ManaRegenMultiplier)) / 100);
float mana_regen_rate = RuleR(Bots, ManaRegen);
if (mana_regen_rate < 0.0f)
@@ -6509,7 +6495,7 @@ int64 Bot::CalcMaxHP() {
int32 bot_hp = 0;
uint32 nd = 10000;
bot_hp += (GenerateBaseHitPoints() + itembonuses.HP);
bot_hp += GetHeroicSTA() * RuleR(Character, HeroicStaminaMultiplier) * 10;
bot_hp += itembonuses.heroic_max_hp;
nd += aabonuses.MaxHP;
bot_hp = ((float)bot_hp * (float)nd / (float)10000);
bot_hp += (spellbonuses.HP + aabonuses.HP);
@@ -6553,13 +6539,7 @@ int64 Bot::CalcBaseEndurance() {
int32 sta_end = 0;
int stats = 0;
if (GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->ClientVersion() >= EQ::versions::ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) {
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);
@@ -6580,7 +6560,7 @@ int64 Bot::CalcBaseEndurance() {
sta_end = (9 * converted_stats);
base_endurance = (1800 + ((GetLevel() - 80) * 18));
}
base_end = (base_endurance + sta_end + (heroic_stats * 10));
base_end = base_endurance + sta_end + itembonuses.heroic_max_end;
} else {
stats = (GetSTR() + GetSTA() + GetDEX() + GetAGI());
@@ -6593,7 +6573,8 @@ int64 Bot::CalcBaseEndurance() {
int HalfBonus400to800 = 0;
int Bonus800plus = 0;
int HalfBonus800plus = 0;
int BonusUpto800 = int(at_most_800 / 4) ;
auto BonusUpto800 = int(at_most_800 / 4) ;
if(stats > 400) {
Bonus400to800 = int((at_most_800 - 400) / 4);
@@ -8768,62 +8749,7 @@ void Bot::OwnerMessage(const std::string& message)
);
}
bool Bot::GetBotOwnerDataBuckets()
{
auto bot_owner = GetBotOwner();
if (!bot_owner) {
return false;
}
const auto query = fmt::format(
"SELECT `key`, `value` FROM data_buckets WHERE `key` LIKE '{}-%'",
Strings::Escape(bot_owner->GetBucketKey())
);
auto results = database.QueryDatabase(query);
if (!results.Success()) {
return false;
}
bot_owner_data_buckets.clear();
if (!results.RowCount()) {
return true;
}
for (auto row : results) {
bot_owner_data_buckets.insert(std::pair<std::string,std::string>(row[0], row[1]));
}
return true;
}
bool Bot::GetBotDataBuckets()
{
const auto query = fmt::format(
"SELECT `key`, `value` FROM data_buckets WHERE `key` LIKE '{}-%'",
Strings::Escape(GetBucketKey())
);
auto results = database.QueryDatabase(query);
if (!results.Success()) {
return false;
}
bot_data_buckets.clear();
if (!results.RowCount()) {
return true;
}
for (auto row : results) {
bot_data_buckets.insert(std::pair<std::string,std::string>(row[0], row[1]));
}
return true;
}
bool Bot::CheckDataBucket(const std::string& bucket_name, const std::string& bucket_value, uint8 bucket_comparison)
bool Bot::CheckDataBucket(std::string bucket_name, const std::string& bucket_value, uint8 bucket_comparison)
{
if (!bucket_name.empty() && !bucket_value.empty()) {
auto full_name = fmt::format(
@@ -8832,7 +8758,7 @@ bool Bot::CheckDataBucket(const std::string& bucket_name, const std::string& buc
bucket_name
);
auto player_value = bot_data_buckets[full_name];
auto player_value = DataBucket::CheckBucketKey(this, full_name);
if (player_value.empty() && GetBotOwner()) {
full_name = fmt::format(
"{}-{}",
@@ -8840,13 +8766,13 @@ bool Bot::CheckDataBucket(const std::string& bucket_name, const std::string& buc
bucket_name
);
player_value = bot_owner_data_buckets[full_name];
player_value = DataBucket::CheckBucketKey(GetBotOwner(), full_name);
if (player_value.empty()) {
return false;
}
}
if (zone->CheckDataBucket(bucket_comparison, bucket_value, player_value)) {
if (zone->CompareDataBucket(bucket_comparison, bucket_value, player_value)) {
return true;
}
}
@@ -9351,6 +9277,12 @@ float Bot::GetBotCasterMaxRange(float melee_distance_max) {// Calculate caster d
return caster_distance_max;
}
int32 Bot::CalcItemATKCap()
{
return RuleI(Character, ItemATKCap) + itembonuses.ItemATKCap + spellbonuses.ItemATKCap + aabonuses.ItemATKCap;
}
bool Bot::CheckSpawnConditions(Client* c) {
if (c->GetFeigned()) {
@@ -9386,5 +9318,4 @@ bool Bot::CheckSpawnConditions(Client* c) {
return true;
}
uint8 Bot::spell_casting_chances[SPELL_TYPE_COUNT][PLAYER_CLASS_COUNT][EQ::constants::STANCE_TYPE_COUNT][cntHSND] = { 0 };