diff --git a/src/server/game/AI/NpcBots/bot_ai.cpp b/src/server/game/AI/NpcBots/bot_ai.cpp index 11de246f0bf2d..936874410f6d5 100644 --- a/src/server/game/AI/NpcBots/bot_ai.cpp +++ b/src/server/game/AI/NpcBots/bot_ai.cpp @@ -3491,6 +3491,11 @@ void bot_ai::ReceiveEmote(Player* player, uint32 emote) for (uint32 st = UNIT_STATE_DIED; st <= UNIT_STATE_FOLLOW_FORMATION_MOVE; st <<= 1u, ++counter) if (me->HasUnitState(st)) report << "\n UNIT_STATE_" << counter << " (" << st << ")"; + report << "\nmovement flags:"; + counter = 1; + for (uint32 st = MOVEMENTFLAG_FORWARD; st <= MOVEMENTFLAG_HOVER; st <<= 1u, ++counter) + if (me->HasUnitState(st)) + report << "\n MOVEMENTFLAG_" << counter << " (" << st << ")"; report << "\nProblems:"; @@ -11740,7 +11745,8 @@ void bot_ai::OnAttackStop(Unit const* target) ////////// void bot_ai::SpawnKillReward(Player* looter) const { - ASSERT(IsWanderer()); + if (!BotMgr::GetBotWandererKillRewardMoney() && !BotMgr::GetBotWandererKillRewardItemMaxCount()) + return; if (!me->GetMap()->GetEntry()->IsContinent()) return; @@ -11751,12 +11757,6 @@ void bot_ai::SpawnKillReward(Player* looter) const } void bot_ai::FillKillReward(GameObject* go) const { - static const uint32 MAX_KILL_REWARD_ITEMS = 2; - - ASSERT(IsWanderer()); - ASSERT(go->GetEntry() == GO_BOT_MONEY_BAG); - ASSERT((go->GetSpellId() - go->GetEntry()) == me->GetEntry()); - go->SetObjectScale(0.875f); Loot& loot = go->loot; @@ -11764,41 +11764,45 @@ void bot_ai::FillKillReward(GameObject* go) const loot.clear(); loot.loot_type = LOOT_CORPSE; - //gold - float lvl = float(std::min<uint8>(me->GetLevel(), DEFAULT_MAX_LEVEL)); - float gold = 125.0f; - switch (me->GetLevel() / 10) - { - case 0: gold *= 0.100f; break; - case 1: gold *= 0.125f; break; - case 2: gold *= 0.175f; break; - case 3: gold *= 0.225f; break; - case 4: gold *= 0.300f; break; - case 5: gold *= 0.400f; break; - case 6: gold *= 0.550f; break; - case 7: gold *= 0.750f; break; - default:gold *= 1.000f; break; - } + uint32 basegold = BotMgr::GetBotWandererKillRewardMoney(); + uint32 maxitems = BotMgr::GetBotWandererKillRewardItemMaxCount(); + uint32 maxquality = BotMgr::GetBotWandererKillRewardItemMaxQuality(); - loot.gold = uint32(lvl * std::min<float>(std::max<float>(gold + _killsCount * gold * 0.04f - _deathsCount * gold * 0.4f, gold), gold * 10.0f)); + if (!basegold && !maxitems) + return; - //items - uint32 loot_items_count = 0; - for (Item const* item : _equips) + if (basegold) { - if (item) + float lvl = float(std::min<uint8>(me->GetLevel(), DEFAULT_MAX_LEVEL)); + float gold = basegold; + switch (me->GetLevel() / 10) { - ItemTemplate const* proto = item->GetTemplate(); - if (proto->Quality == ITEM_QUALITY_UNCOMMON || proto->Quality == ITEM_QUALITY_RARE) - { - if (roll_chance_f(5.0f)) - { - loot.AddItem(LootStoreItem(proto->ItemId, 0, 100.0f, false, 0, 0, 1, 1)); + case 0: gold *= 0.100f; break; + case 1: gold *= 0.125f; break; + case 2: gold *= 0.175f; break; + case 3: gold *= 0.225f; break; + case 4: gold *= 0.300f; break; + case 5: gold *= 0.400f; break; + case 6: gold *= 0.550f; break; + case 7: gold *= 0.750f; break; + default: break; + } + gold = std::min<float>(std::max<float>(gold + _killsCount * gold * 0.04f - _deathsCount * gold * 0.4f, gold), gold * 10.0f) / float(DEFAULT_MAX_LEVEL) * lvl; + } - if (++loot_items_count >= std::min<uint32>(MAX_KILL_REWARD_ITEMS, MAX_NR_LOOT_ITEMS)) - break; - } - } + if (maxitems) + { + std::list<uint32> random_items; + for (Item const* item : _equips) + { + if (item && item->GetTemplate()->Quality <= maxquality) + random_items.push_back(item->GetEntry()); + } + if (!random_items.empty()) + { + Bcore::Containers::RandomResize(random_items, maxitems); + for (uint32 itemd_id : random_items) + loot.AddItem(LootStoreItem(itemd_id, 0, 100.0f, false, 0, 0, 1, 1)); } } } diff --git a/src/server/game/AI/NpcBots/botmgr.cpp b/src/server/game/AI/NpcBots/botmgr.cpp index ffb1d61d36ab5..748b686dd1213 100644 --- a/src/server/game/AI/NpcBots/botmgr.cpp +++ b/src/server/game/AI/NpcBots/botmgr.cpp @@ -73,6 +73,9 @@ uint32 _npcBotEngageDelayDPS_default; uint32 _npcBotEngageDelayHeal_default; uint32 _npcBotOwnerExpireTime; uint32 _desiredWanderingBotsCount; +uint32 _killrewardWandererMoneyBase; +uint32 _killrewardWandererItemCount; +uint32 _killrewardWandererItemQuality; uint32 _targetBGPlayersPerTeamCount_AV; uint32 _targetBGPlayersPerTeamCount_WS; uint32 _targetBGPlayersPerTeamCount_AB; @@ -440,6 +443,9 @@ void BotMgr::LoadConfig(bool reload) _botStatLimits_block = sConfigMgr->GetFloatDefault("NpcBot.Stats.Limits.Block", 95.0f); _botStatLimits_crit = sConfigMgr->GetFloatDefault("NpcBot.Stats.Limits.Crit", 95.0f); _desiredWanderingBotsCount = sConfigMgr->GetIntDefault("NpcBot.WanderingBots.Continents.Count", 0); + _killrewardWandererMoneyBase = sConfigMgr->GetIntDefault("NpcBot.WanderingBots.KillReward.Money", 0); + _killrewardWandererItemCount = sConfigMgr->GetIntDefault("NpcBot.WanderingBots.KillReward.ItemCount", 0); + _killrewardWandererItemQuality = sConfigMgr->GetIntDefault("NpcBot.WanderingBots.KillReward.ItemQuality", int(ITEM_QUALITY_RARE)); _mult_xpgain_wanderer = sConfigMgr->GetFloatDefault("NpcBot.WanderingBots.Continents.XPGain", 1.0f); _enableWanderingBotsBG = sConfigMgr->GetBoolDefault("NpcBot.WanderingBots.BG.Enable", false); _enableConfigLevelCapBG = sConfigMgr->GetBoolDefault("NpcBot.WanderingBots.BG.CapLevel", false); @@ -648,6 +654,8 @@ void BotMgr::LoadConfig(bool reload) RoundToInterval(_mult_dmg_seawitch, 0.1f, 10.f); RoundToInterval(_mult_dmg_cryptlord, 0.1f, 10.f); RoundToInterval(_bothk_rate_honor, 0.1f, 10.f); + RoundToInterval(_killrewardWandererItemCount, uint32(0), uint32(MAX_NR_LOOT_ITEMS)); + RoundToInterval(_killrewardWandererItemQuality, uint32(ITEM_QUALITY_POOR), uint32(ITEM_QUALITY_HEIRLOOM)); } void BotMgr::ResolveConfigConflicts() @@ -3181,6 +3189,18 @@ uint32 BotMgr::GetBotWandererMaxItemLevel(uint8 level) { return _botwanderer_itemlvl_level_brackets[std::min<size_t>(BRACKETS_COUNT - 1, level / 10)]; } +uint32 BotMgr::GetBotWandererKillRewardMoney() +{ + return _killrewardWandererMoneyBase; +} +uint32 BotMgr::GetBotWandererKillRewardItemMaxCount() +{ + return _killrewardWandererItemCount; +} +uint32 BotMgr::GetBotWandererKillRewardItemMaxQuality() +{ + return _killrewardWandererItemQuality; +} float BotMgr::GetBotDamageModByClass(uint8 botclass) { switch (botclass) diff --git a/src/server/game/AI/NpcBots/botmgr.h b/src/server/game/AI/NpcBots/botmgr.h index 53d5752e9add2..ea06ad8440454 100644 --- a/src/server/game/AI/NpcBots/botmgr.h +++ b/src/server/game/AI/NpcBots/botmgr.h @@ -177,6 +177,9 @@ class TC_GAME_API BotMgr static float GetBotWandererXPGainMod(); static PctBrackets GetBotWandererLevelBrackets(); static uint32 GetBotWandererMaxItemLevel(uint8 level); + static uint32 GetBotWandererKillRewardMoney(); + static uint32 GetBotWandererKillRewardItemMaxCount(); + static uint32 GetBotWandererKillRewardItemMaxQuality(); static float GetBotDamageModByClass(uint8 botclass); static float GetBotDamageModByLevel(uint8 botlevel); static float GetBotHealingModByLevel(uint8 botlevel); diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 40f6128c45abb..ee15db5604bce 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -4667,6 +4667,25 @@ NpcBot.WanderingBots.Continents.Maps = 0,1,530,571 NpcBot.WanderingBots.Continents.XPGain = 1.0 +# +# NpcBot.WanderingBots.KillReward.Money +# NpcBot.WanderingBots.KillReward.ItemCount +# NpcBot.WanderingBots.KillReward.ItemQuality +# Description: Wandering bot kill loot reward. World maps only. +# Money: Amount of money (in copper) to drop at level 80, +# before level and kill count vs death count normalization. +# ItemCount: Maximum number of items to drop, item ids are taken from +# bot equipment. Range: 0..18. +# ItemQuality: Maximum quality of dropped items. Most bots are equipped +# with 2/3/4 (uncommon/rare/epic) Range: 0..7. +# Default: 0 - (NpcBot.WanderingBots.KillReward.Money) +# 0 - (NpcBot.WanderingBots.KillReward.ItemCount) +# 0 - (NpcBot.WanderingBots.KillReward.ItemQuality) + +NpcBot.WanderingBots.KillReward.Money = 0 +NpcBot.WanderingBots.KillReward.ItemCount = 0 +NpcBot.WanderingBots.KillReward.ItemQuality = 0 + # # NpcBot.WanderingBots.MaxItemLevel.Levels # Description: Maximum item ilevel to generate for wandering bots per level bracket: