diff --git a/src/PlayerbotAI.cpp b/src/PlayerbotAI.cpp index c8842cf4..c9d9d798 100644 --- a/src/PlayerbotAI.cpp +++ b/src/PlayerbotAI.cpp @@ -4323,7 +4323,7 @@ void PlayerbotAI::_fillGearScoreData(Player* player, Item* item, std::vectorInventoryType; - uint32 level = mixed ? proto->ItemLevel * (1 + proto->Quality) : proto->ItemLevel; + uint32 level = mixed ? proto->ItemLevel * PlayerbotAI::GetItemScoreMultiplier(ItemQualities(proto->Quality)) : proto->ItemLevel; switch (type) { @@ -5834,4 +5834,33 @@ void PlayerbotAI::PetFollow() charmInfo->RemoveStayPosition(); charmInfo->SetForcedSpell(0); charmInfo->SetForcedTargetGUID(); +} + +float PlayerbotAI::GetItemScoreMultiplier(ItemQualities quality) +{ + switch (quality) + { + // each quality increase 1.1x + case ITEM_QUALITY_POOR: + return 1.0f; + break; + case ITEM_QUALITY_NORMAL: + return 1.1f; + break; + case ITEM_QUALITY_UNCOMMON: + return 1.21f; + break; + case ITEM_QUALITY_RARE: + return 1.331f; + break; + case ITEM_QUALITY_EPIC: + return 1.4641f; + break; + case ITEM_QUALITY_LEGENDARY: + return 1.61051f; + break; + default: + break; + } + return 1.0f; } \ No newline at end of file diff --git a/src/PlayerbotAI.h b/src/PlayerbotAI.h index 73bc61a0..c2a94625 100644 --- a/src/PlayerbotAI.h +++ b/src/PlayerbotAI.h @@ -569,6 +569,7 @@ public: std::set GetAllCurrentQuestIds(); std::set GetCurrentIncompleteQuestIds(); void PetFollow(); + static float GetItemScoreMultiplier(ItemQualities quality); private: static void _fillGearScoreData(Player* player, Item* item, std::vector* gearScore, uint32& twoHandScore, diff --git a/src/factory/PlayerbotFactory.cpp b/src/factory/PlayerbotFactory.cpp index e03447cb..c83440db 100644 --- a/src/factory/PlayerbotFactory.cpp +++ b/src/factory/PlayerbotFactory.cpp @@ -2646,7 +2646,7 @@ void PlayerbotFactory::InitAmmo() bot->SetAmmo(entry); } -uint32 PlayerbotFactory::CalcMixedGearScore(uint32 gs, uint32 quality) { return gs * (quality + 1); } +uint32 PlayerbotFactory::CalcMixedGearScore(uint32 gs, uint32 quality) { return gs * PlayerbotAI::GetItemScoreMultiplier(ItemQualities(quality)); } void PlayerbotFactory::InitMounts() { diff --git a/src/factory/StatsWeightCalculator.cpp b/src/factory/StatsWeightCalculator.cpp index b0055272..dfb83943 100644 --- a/src/factory/StatsWeightCalculator.cpp +++ b/src/factory/StatsWeightCalculator.cpp @@ -12,6 +12,7 @@ #include "ItemTemplate.h" #include "ObjectMgr.h" #include "PlayerbotAI.h" +#include "PlayerbotFactory.h" #include "SharedDefines.h" #include "StatsCollector.h" #include "Unit.h" @@ -49,12 +50,12 @@ void StatsWeightCalculator::Reset() float StatsWeightCalculator::CalculateItem(uint32 itemId) { ItemTemplate const* proto = &sObjectMgr->GetItemTemplateStore()->at(itemId); - + if (!proto) return 0.0f; Reset(); - + collector_->CollectItemStats(proto); GenerateWeights(player_); @@ -67,25 +68,25 @@ float StatsWeightCalculator::CalculateItem(uint32 itemId) if (enable_item_set_bonus_) CalculateItemSetBonus(player_, proto); - + CalculateSocketBonus(player_, proto); if (enable_quality_blend_) // Blend with item quality and level - weight_ *= (proto->Quality + 1) * proto->ItemLevel; - + weight_ *= PlayerbotFactory::CalcMixedGearScore(proto->ItemLevel, proto->Quality); + return weight_; } float StatsWeightCalculator::CalculateEnchant(uint32 enchantId) { SpellItemEnchantmentEntry const* enchant = sSpellItemEnchantmentStore.LookupEntry(enchantId); - + if (!enchant) return 0.0f; Reset(); - + collector_->CollectEnchantStats(enchant); GenerateWeights(player_); @@ -121,7 +122,7 @@ void StatsWeightCalculator::GenerateBasicWeights(Player* player) stats_weights_[STATS_TYPE_CRIT] += 1.5f; stats_weights_[STATS_TYPE_HASTE] += 1.4f; stats_weights_[STATS_TYPE_RANGED_DPS] += 5.0f; - } + } else if (cls == CLASS_HUNTER && tab == HUNTER_TAB_MARKSMANSHIP) { stats_weights_[STATS_TYPE_AGILITY] += 2.2f; @@ -168,7 +169,7 @@ void StatsWeightCalculator::GenerateBasicWeights(Player* player) stats_weights_[STATS_TYPE_EXPERTISE] += 2.0f; stats_weights_[STATS_TYPE_MELEE_DPS] += 5.0f; } - else if (cls == CLASS_WARRIOR && tab == WARRIOR_TAB_FURY) // fury + else if (cls == CLASS_WARRIOR && tab == WARRIOR_TAB_FURY) // fury { stats_weights_[STATS_TYPE_AGILITY] += 1.8f; stats_weights_[STATS_TYPE_STRENGTH] += 2.6f; @@ -180,7 +181,7 @@ void StatsWeightCalculator::GenerateBasicWeights(Player* player) stats_weights_[STATS_TYPE_EXPERTISE] += 2.5f; stats_weights_[STATS_TYPE_MELEE_DPS] += 7.0f; } - else if (cls == CLASS_WARRIOR && tab == WARRIOR_TAB_ARMS) // arm + else if (cls == CLASS_WARRIOR && tab == WARRIOR_TAB_ARMS) // arm { stats_weights_[STATS_TYPE_AGILITY] += 1.6f; stats_weights_[STATS_TYPE_STRENGTH] += 2.3f; @@ -192,7 +193,7 @@ void StatsWeightCalculator::GenerateBasicWeights(Player* player) stats_weights_[STATS_TYPE_EXPERTISE] += 1.4f; stats_weights_[STATS_TYPE_MELEE_DPS] += 7.0f; } - else if (cls == CLASS_DEATH_KNIGHT && tab == DEATHKNIGHT_TAB_FROST) // frost dk + else if (cls == CLASS_DEATH_KNIGHT && tab == DEATHKNIGHT_TAB_FROST) // frost dk { stats_weights_[STATS_TYPE_AGILITY] += 1.8f; stats_weights_[STATS_TYPE_STRENGTH] += 2.6f; @@ -216,7 +217,7 @@ void StatsWeightCalculator::GenerateBasicWeights(Player* player) stats_weights_[STATS_TYPE_EXPERTISE] += 1.0f; stats_weights_[STATS_TYPE_MELEE_DPS] += 5.0f; } - else if (cls == CLASS_PALADIN && tab == PALADIN_TAB_RETRIBUTION) // retribution + else if (cls == CLASS_PALADIN && tab == PALADIN_TAB_RETRIBUTION) // retribution { stats_weights_[STATS_TYPE_AGILITY] += 1.1f; stats_weights_[STATS_TYPE_STRENGTH] += 2.5f; @@ -244,8 +245,7 @@ void StatsWeightCalculator::GenerateBasicWeights(Player* player) stats_weights_[STATS_TYPE_EXPERTISE] += 2.0f; stats_weights_[STATS_TYPE_MELEE_DPS] += 8.5f; } - else if (cls == CLASS_WARLOCK || - cls == CLASS_MAGE || + else if (cls == CLASS_WARLOCK || cls == CLASS_MAGE || (cls == CLASS_PRIEST && tab == PRIEST_TAB_SHADOW) || // shadow (cls == CLASS_SHAMAN && tab == SHAMAN_TAB_ELEMENTAL) || // element (cls == CLASS_DRUID && tab == DRUID_TAB_BALANCE)) // balance @@ -272,7 +272,8 @@ void StatsWeightCalculator::GenerateBasicWeights(Player* player) stats_weights_[STATS_TYPE_HASTE] += 1.0f; stats_weights_[STATS_TYPE_RANGED_DPS] += 1.0f; } - else if ((cls == CLASS_WARRIOR && tab == WARRIOR_TAB_PROTECTION) || (cls == CLASS_PALADIN && tab == PALADIN_TAB_PROTECTION)) + else if ((cls == CLASS_WARRIOR && tab == WARRIOR_TAB_PROTECTION) || + (cls == CLASS_PALADIN && tab == PALADIN_TAB_PROTECTION)) { stats_weights_[STATS_TYPE_AGILITY] += 2.0f; stats_weights_[STATS_TYPE_STRENGTH] += 1.0f; @@ -361,33 +362,33 @@ void StatsWeightCalculator::CalculateItemSetBonus(Player* player, ItemTemplate c if (player->ItemSetEff[i]) { ItemSetEffect* eff = player->ItemSetEff[i]; - + uint32 setId = eff->setid; if (itemSet != setId) continue; - - const ItemSetEntry *setEntry = sItemSetStore.LookupEntry(setId); + + const ItemSetEntry* setEntry = sItemSetStore.LookupEntry(setId); if (!setEntry) continue; - + uint32 itemCount = eff->item_count; uint32 max_items = 0; for (size_t j = 0; j < MAX_ITEM_SET_SPELLS; j++) max_items = std::max(max_items, setEntry->items_to_triggerspell[j]); if (itemCount < max_items) { - multiplier += 0.1f * itemCount; // 10% bonus for each item already equipped + multiplier += 0.1f * itemCount; // 10% bonus for each item already equipped } else { - multiplier = 1.0f; // All item set effect has been triggerred + multiplier = 1.0f; // All item set effect has been triggerred } break; } } if (i == player->ItemSetEff.size()) - multiplier = 1.05f; // this is the first item in the item set + multiplier = 1.05f; // this is the first item in the item set weight_ *= multiplier; } @@ -395,17 +396,18 @@ void StatsWeightCalculator::CalculateItemSetBonus(Player* player, ItemTemplate c void StatsWeightCalculator::CalculateSocketBonus(Player* player, ItemTemplate const* proto) { uint32 socketNum = 0; - for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT + MAX_GEM_SOCKETS; ++enchant_slot) + for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT + MAX_GEM_SOCKETS; + ++enchant_slot) { uint8 socketColor = proto->Socket[enchant_slot - SOCK_ENCHANTMENT_SLOT].Color; - - if (!socketColor) // no socket slot + + if (!socketColor) // no socket slot continue; socketNum++; } - float multiplier = 1.0f + socketNum * 0.03f; // 3% bonus for socket + float multiplier = 1.0f + socketNum * 0.03f; // 3% bonus for socket weight_ *= multiplier; } @@ -469,13 +471,13 @@ void StatsWeightCalculator::CalculateItemTypePenalty(ItemTemplate const* proto) { weight_ *= 0.1; } - if (cls == CLASS_ROGUE && player_->HasAura(13964) - && (proto->SubClass == ITEM_SUBCLASS_WEAPON_SWORD || proto->SubClass == ITEM_SUBCLASS_WEAPON_AXE)) + if (cls == CLASS_ROGUE && player_->HasAura(13964) && + (proto->SubClass == ITEM_SUBCLASS_WEAPON_SWORD || proto->SubClass == ITEM_SUBCLASS_WEAPON_AXE)) { weight_ *= 1.1; } - if (cls == CLASS_WARRIOR && player_->HasAura(12785) - && (proto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM || proto->SubClass == ITEM_SUBCLASS_WEAPON_AXE2)) + if (cls == CLASS_WARRIOR && player_->HasAura(12785) && + (proto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM || proto->SubClass == ITEM_SUBCLASS_WEAPON_AXE2)) { weight_ *= 1.1; } @@ -523,7 +525,7 @@ void StatsWeightCalculator::ApplyOverflowPenalty(Player* player) else if (hit_current >= hit_overflow * 0.8) stats_weights_[STATS_TYPE_HIT] /= 1.5; } - + { if (type_ == CollectorType::MELEE) { @@ -536,7 +538,7 @@ void StatsWeightCalculator::ApplyOverflowPenalty(Player* player) stats_weights_[STATS_TYPE_EXPERTISE] /= 1.5; } } - + { if (type_ == CollectorType::MELEE) { diff --git a/src/strategy/druid/DruidTriggers.cpp b/src/strategy/druid/DruidTriggers.cpp index d839f973..a083ade1 100644 --- a/src/strategy/druid/DruidTriggers.cpp +++ b/src/strategy/druid/DruidTriggers.cpp @@ -22,8 +22,6 @@ bool ThornsOnPartyTrigger::IsActive() return BuffOnPartyTrigger::IsActive() && !botAI->HasAura("thorns", GetTarget()); } -bool MoonfireTrigger::IsActive() { return DebuffTrigger::IsActive() && !GetTarget()->HasUnitState(UNIT_STATE_ROOT); } - bool EntanglingRootsKiteTrigger::IsActive() { return DebuffTrigger::IsActive() && AI_VALUE(uint8, "attacker count") < 3 && !GetTarget()->GetPower(POWER_MANA); diff --git a/src/strategy/druid/DruidTriggers.h b/src/strategy/druid/DruidTriggers.h index 3b8fdce7..bb8725f0 100644 --- a/src/strategy/druid/DruidTriggers.h +++ b/src/strategy/druid/DruidTriggers.h @@ -75,8 +75,6 @@ class MoonfireTrigger : public DebuffTrigger { public: MoonfireTrigger(PlayerbotAI* botAI) : DebuffTrigger(botAI, "moonfire", 1, true) {} - - bool IsActive() override; }; class FaerieFireTrigger : public DebuffTrigger diff --git a/src/strategy/values/EstimatedLifetimeValue.cpp b/src/strategy/values/EstimatedLifetimeValue.cpp index 4352934f..b69861c4 100644 --- a/src/strategy/values/EstimatedLifetimeValue.cpp +++ b/src/strategy/values/EstimatedLifetimeValue.cpp @@ -3,6 +3,7 @@ #include "AiFactory.h" #include "PlayerbotAI.h" #include "PlayerbotAIConfig.h" +#include "PlayerbotFactory.h" #include "Playerbots.h" #include "SharedDefines.h" @@ -26,13 +27,13 @@ float EstimatedGroupDpsValue::Calculate() { float totalDps; - std::vector groupPlayer={bot}; + std::vector groupPlayer = {bot}; if (Group* group = bot->GetGroup()) { for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next()) { Player* member = gref->GetSource(); - if (member == bot) // calculated + if (member == bot) // calculated continue; if (!member || !member->IsInWorld()) @@ -40,7 +41,7 @@ float EstimatedGroupDpsValue::Calculate() if (member->GetMapId() != bot->GetMapId()) continue; - + if (member->GetExactDist(bot) > sPlayerbotAIConfig->sightDistance) continue; @@ -59,16 +60,25 @@ float EstimatedGroupDpsValue::Calculate() float basicDps = GetBasicDps(player->GetLevel()); float basicGs = GetBasicGs(player->GetLevel()); uint32 mixedGearScore = PlayerbotAI::GetMixedGearScore(player, true, false, 12); - - float gap = (float)mixedGearScore / basicGs - 1; - float gs_modifier = gap * 3 + 1; + float gs_modifier = (float)mixedGearScore / basicGs; + // bonus for wotlk epic gear + if (mixedGearScore >= 300) + { + gs_modifier *= 1 + (mixedGearScore - 300) * 0.01; + } if (gs_modifier < 0.75) gs_modifier = 0.75; if (gs_modifier > 4) gs_modifier = 4; totalDps += basicDps * roleMultiplier * gs_modifier; } - + // Group buff bonus + if (groupPlayer.size() >= 25) + totalDps *= 1.2; + else if (groupPlayer.size() >= 10) + totalDps *= 1.1; + else if (groupPlayer.size() >= 5) + totalDps *= 1.05; return totalDps; } @@ -98,11 +108,11 @@ float EstimatedGroupDpsValue::GetBasicDps(uint32 level) } else if (level <= 70) { - basic_dps = 450 + (level - 60) * 40; + basic_dps = 550 + (level - 60) * 65; } else { - basic_dps = 750 + (level - 70) * 175; + basic_dps = 1200 + (level - 70) * 200; } return basic_dps; } @@ -113,23 +123,23 @@ float EstimatedGroupDpsValue::GetBasicGs(uint32 level) if (level <= 8) { - basic_gs = (level + 5) * 2; + basic_gs = PlayerbotFactory::CalcMixedGearScore(level + 5, ITEM_QUALITY_NORMAL); } else if (level <= 15) { - basic_gs = (level + 5) * 3; + basic_gs = PlayerbotFactory::CalcMixedGearScore(level + 5, ITEM_QUALITY_UNCOMMON); } else if (level <= 60) { - basic_gs = (level + 5) * 4; + basic_gs = PlayerbotFactory::CalcMixedGearScore(level + 5, ITEM_QUALITY_RARE); } else if (level <= 70) { - basic_gs = (85 + (level - 60) * 3) * 4; + basic_gs = PlayerbotFactory::CalcMixedGearScore(85 + (level - 60) * 3, ITEM_QUALITY_RARE); } else { - basic_gs = (155 + (level - 70) * 4) * 4; + basic_gs = PlayerbotFactory::CalcMixedGearScore(155 + (level - 70) * 4, ITEM_QUALITY_RARE); } return basic_gs; } \ No newline at end of file