From 029ca52dd51caeb4d7b07a27de69b72bdf70c84d Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Sun, 28 Jul 2024 15:14:08 +0800 Subject: [PATCH 01/14] teleport for randomize first --- src/RandomPlayerbotMgr.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/RandomPlayerbotMgr.cpp b/src/RandomPlayerbotMgr.cpp index 639acd52..1a424d5e 100644 --- a/src/RandomPlayerbotMgr.cpp +++ b/src/RandomPlayerbotMgr.cpp @@ -1501,7 +1501,6 @@ void RandomPlayerbotMgr::Randomize(Player* bot) else { RandomizeFirst(bot); } - RandomTeleportForLevel(bot); } void RandomPlayerbotMgr::IncreaseLevel(Player* bot) @@ -1590,6 +1589,8 @@ void RandomPlayerbotMgr::RandomizeFirst(Player* bot) if (pmo) pmo->finish(); + + RandomTeleportForLevel(bot); } void RandomPlayerbotMgr::RandomizeMin(Player* bot) From 8a8a72c97712ea000e15bc610b5b4e15345e83a5 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Sun, 28 Jul 2024 15:14:54 +0800 Subject: [PATCH 02/14] [Initialization] Fix unique gem --- src/PlayerbotFactory.cpp | 65 +++++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 18 deletions(-) diff --git a/src/PlayerbotFactory.cpp b/src/PlayerbotFactory.cpp index 21409f18..e6ee1c34 100644 --- a/src/PlayerbotFactory.cpp +++ b/src/PlayerbotFactory.cpp @@ -136,6 +136,9 @@ void PlayerbotFactory::Init() continue; } ItemTemplate const* proto = sObjectMgr->GetItemTemplate(gemId); + if (proto->Flags & ITEM_FLAG_UNIQUE_EQUIPPABLE) { // unique gem + continue; + } if (!proto || !sGemPropertiesStore.LookupEntry(proto->GemProperties)) { continue; } @@ -2858,7 +2861,29 @@ void PlayerbotFactory::InitGlyphs(bool increment) if (!increment) { for (uint32 slotIndex = 0; slotIndex < MAX_GLYPH_SLOT_INDEX; ++slotIndex) { - bot->SetGlyph(slotIndex, 0, true); + uint32 glyph = bot->GetGlyph(slotIndex); + if (GlyphPropertiesEntry const* glyphEntry = sGlyphPropertiesStore.LookupEntry(glyph)) + { + bot->RemoveAurasDueToSpell(glyphEntry->SpellId); + + // Removed any triggered auras + Unit::AuraMap& ownedAuras = bot->GetOwnedAuras(); + for (Unit::AuraMap::iterator iter = ownedAuras.begin(); iter != ownedAuras.end();) + { + Aura* aura = iter->second; + if (SpellInfo const* triggeredByAuraSpellInfo = aura->GetTriggeredByAuraSpellInfo()) + { + if (triggeredByAuraSpellInfo->Id == glyphEntry->SpellId) + { + bot->RemoveOwnedAura(iter); + continue; + } + } + ++iter; + } + + bot->SetGlyph(slotIndex, 0, true); + } } } @@ -2957,6 +2982,8 @@ void PlayerbotFactory::InitGlyphs(bool increment) if (!glyph) { continue; } + GlyphPropertiesEntry const* glyphEntry = sGlyphPropertiesStore.LookupEntry(glyph); + bot->CastSpell(bot, glyphEntry->SpellId, TriggerCastFlags(TRIGGERED_FULL_MASK & ~(TRIGGERED_IGNORE_SHAPESHIFT | TRIGGERED_IGNORE_CASTER_AURASTATE))); bot->SetGlyph(realSlot, glyph, true); chosen.insert(glyph); } else { @@ -2990,7 +3017,9 @@ void PlayerbotFactory::InitGlyphs(bool increment) continue; chosen.insert(id); - + GlyphPropertiesEntry const* glyphEntry = sGlyphPropertiesStore.LookupEntry(id); + bot->CastSpell(bot, glyphEntry->SpellId, TriggerCastFlags(TRIGGERED_FULL_MASK & ~(TRIGGERED_IGNORE_SHAPESHIFT | TRIGGERED_IGNORE_CASTER_AURASTATE))); + bot->SetGlyph(realSlot, id, true); found = true; break; @@ -3847,7 +3876,7 @@ float PlayerbotFactory::CalculateItemScore(uint32 item_id, Player* bot) // todo: remove duplicate code if (cls == CLASS_HUNTER) { // AGILITY only - score += agility * 2.5 + attack_power + armor_penetration * 2 + rangeDps * 5 + hit * 2 + crit * 2 + haste * 2 + intellect; + score += agility * 2.5 + attack_power + armor_penetration * 2 + rangeDps * 5 + hit * 1.2 + crit * 2 + haste * 2 + intellect; } else if (cls == CLASS_WARLOCK || cls == CLASS_MAGE || (cls == CLASS_PRIEST && tab == 2) || // shadow @@ -3856,7 +3885,7 @@ float PlayerbotFactory::CalculateItemScore(uint32 item_id, Player* bot) ) { // SPELL DPS score += intellect * 0.5 + spirit * 0.5 + spell_power + spell_penetration - + hit * 1 + crit * 0.7 + haste * 1 + rangeDps; + + hit * 0.7 + crit * 0.7 + haste * 1 + rangeDps; } else if ((cls == CLASS_PALADIN && tab == 0) || // holy (cls == CLASS_PRIEST && tab != 2) || // discipline / holy (cls == CLASS_SHAMAN && tab == 2) || // heal @@ -3866,33 +3895,33 @@ float PlayerbotFactory::CalculateItemScore(uint32 item_id, Player* bot) score += intellect * 0.5 + spirit * 0.5 + spell_power + mana_regeneration * 0.5 + crit * 0.5 + haste * 1 + rangeDps; } else if (cls == CLASS_ROGUE || (cls == CLASS_DRUID && tab == 2 && !PlayerbotAI::IsTank(bot))) { // AGILITY mainly (STRENGTH also) - score += agility * 2 + strength + attack_power + armor_penetration * 1 + meleeDps * 5 + hit * 1.5 + crit * 1.5 + haste * 1.5 + expertise * 2.5; + score += agility * 2 + strength + attack_power + armor_penetration * 1 + meleeDps * 5 + hit * 1 + crit * 1.5 + haste * 1.5 + expertise * 1.5; } else if ((cls == CLASS_PALADIN && tab == 2) || // retribution (cls == CLASS_WARRIOR && tab != 2) || // arm / fury (cls == CLASS_DEATH_KNIGHT && tab != 0) // ice / unholy ) { // STRENGTH mainly (AGILITY also) - score += strength * 2 + agility + attack_power + armor_penetration + meleeDps * 5 + hit * 1.5 + crit * 1.5 + haste * 1.5 + expertise * 2; + score += strength * 2 + agility + attack_power + armor_penetration + meleeDps * 5 + hit * 1 + crit * 1.5 + haste * 1.5 + expertise * 1.5; } else if ((cls == CLASS_SHAMAN && tab == 1)) { // enhancement // STRENGTH mainly (AGILITY, INTELLECT also) score += strength * 1 + agility * 1.5 + intellect * 1.5 + attack_power + spell_power * 1.5 + armor_penetration * 0.5 + meleeDps * 5 - + hit * 1.5 + crit * 1.5 + haste * 1.5 + expertise * 2; + + hit * 1 + crit * 1.5 + haste * 1.5 + expertise * 1.2; } else if ((cls == CLASS_WARRIOR && tab == 2) || (cls == CLASS_PALADIN && tab == 1)) { // TANK WITH SHIELD score += strength * 1 + agility * 2 + attack_power * 0.2 + defense * 2.5 + parry * 2 + dodge * 2 + resilience * 2 + block * 2 + armor * 0.3 + stamina * 3 - + hit * 0.5 + crit * 0.2 + haste * 0.5 + expertise * 3; + + hit * 0.5 + crit * 0.2 + haste * 0.5 + expertise * 2; } else if (cls == CLASS_DEATH_KNIGHT && tab == 0){ // BLOOD DK TANK score += strength * 1 + agility * 2 + attack_power * 0.2 + defense * 3.5 + parry * 2 + dodge * 2 + resilience * 2 + armor * 0.3 + stamina * 2.5 - + hit * 0.5 + crit * 0.5 + haste * 0.5 + expertise * 3.5; + + hit * 0.5 + crit * 0.5 + haste * 0.5 + expertise * 2; } else { // BEAR DRUID TANK score += agility * 1.5 + strength * 1 + attack_power * 0.5 + armor_penetration * 0.5 + meleeDps * 2 + defense * 0.25 + dodge * 0.25 + armor * 0.3 + stamina * 1.5 - + hit * 1 + crit * 1 + haste * 0.5 + expertise * 3; + + hit * 1 + crit * 1 + haste * 0.5 + expertise * 2; } // penalty for different type armor if (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass >= ITEM_SUBCLASS_ARMOR_CLOTH && @@ -4269,7 +4298,7 @@ float PlayerbotFactory::CalculateEnchantScore(uint32 enchant_id, Player* bot) // todo: remove duplicate code if (cls == CLASS_HUNTER) { // AGILITY only - score += agility * 2.5 + attack_power + armor_penetration * 2 + dps * 5 + hit * 2 + crit * 2 + haste * 2.5 + intellect; + score += agility * 2.5 + attack_power + armor_penetration * 2 + dps * 5 + hit * 1.5 + crit * 2 + haste * 2.5 + intellect; } else if (cls == CLASS_WARLOCK || cls == CLASS_MAGE || (cls == CLASS_PRIEST && tab == 2) || // shadow @@ -4288,17 +4317,17 @@ float PlayerbotFactory::CalculateEnchantScore(uint32 enchant_id, Player* bot) score += intellect * 0.5 + spirit * 0.5 + spell_power + mana_regeneration * 0.5 + crit * 0.5 + haste * 1; } else if (cls == CLASS_ROGUE || (cls == CLASS_DRUID && tab == 2 && !PlayerbotAI::IsTank(bot))) { // AGILITY mainly (STRENGTH also) - score += agility * 2 + strength + attack_power + armor_penetration * 1 + dps * 5 + hit * 1.5 + crit * 1.5 + haste * 1.5 + expertise * 2.5; + score += agility * 2 + strength + attack_power + armor_penetration * 1 + dps * 5 + hit * 1.2 + crit * 1.5 + haste * 1.5 + expertise * 2.5; } else if ((cls == CLASS_PALADIN && tab == 2) || // retribution (cls == CLASS_WARRIOR && tab != 2) || // arm / fury (cls == CLASS_DEATH_KNIGHT && tab != 0) // ice / unholy ) { // STRENGTH mainly (AGILITY also) - score += strength * 2 + agility + attack_power + armor_penetration + dps * 5 + hit * 1.5 + crit * 1.5 + haste * 1.5 + expertise * 2; + score += strength * 2 + agility + attack_power + armor_penetration + dps * 5 + hit * 1.2 + crit * 1.5 + haste * 1.5 + expertise * 2; } else if ((cls == CLASS_SHAMAN && tab == 1)) { // enhancement // STRENGTH mainly (AGILITY, INTELLECT also) score += strength * 1 + agility * 1.5 + intellect * 1.5 + attack_power + spell_power * 1.5 + armor_penetration * 0.5 + dps * 5 - + hit * 1.5 + crit * 1.5 + haste * 1.5 + expertise * 2; + + hit * 1.2 + crit * 1.5 + haste * 1.5 + expertise * 2; } else if ((cls == CLASS_WARRIOR && tab == 2) || (cls == CLASS_PALADIN && tab == 1)) { // TANK WITH SHIELD @@ -4549,7 +4578,7 @@ float PlayerbotFactory::CalculateSpellScore(uint32 spell_id, Player* bot, uint32 // todo: remove duplicate code if (cls == CLASS_HUNTER) { // AGILITY only - score += agility * 2.5 + attack_power + armor_penetration * 2 + rangeDps * 5 + hit * 2 + crit * 2 + haste * 2.5 + intellect; + score += agility * 2.5 + attack_power + armor_penetration * 2 + rangeDps * 5 + hit * 1.5 + crit * 2 + haste * 2.5 + intellect; } else if (cls == CLASS_WARLOCK || cls == CLASS_MAGE || (cls == CLASS_PRIEST && tab == 2) || // shadow @@ -4568,17 +4597,17 @@ float PlayerbotFactory::CalculateSpellScore(uint32 spell_id, Player* bot, uint32 score += intellect * 0.5 + spirit * 0.5 + spell_power + mana_regeneration * 0.5 + crit * 0.5 + haste * 1 + rangeDps; } else if (cls == CLASS_ROGUE || (cls == CLASS_DRUID && tab == 2 && !PlayerbotAI::IsTank(bot))) { // AGILITY mainly (STRENGTH also) - score += agility * 2 + strength + attack_power + armor_penetration * 1 + meleeDps * 5 + hit * 1.5 + crit * 1.5 + haste * 1.5 + expertise * 2.5; + score += agility * 2 + strength + attack_power + armor_penetration * 1 + meleeDps * 5 + hit * 1.2 + crit * 1.5 + haste * 1.5 + expertise * 2.5; } else if ((cls == CLASS_PALADIN && tab == 2) || // retribution (cls == CLASS_WARRIOR && tab != 2) || // arm / fury (cls == CLASS_DEATH_KNIGHT && tab != 0) // ice / unholy ) { // STRENGTH mainly (AGILITY also) - score += strength * 2 + agility + attack_power + armor_penetration + meleeDps * 5 + hit * 1.5 + crit * 1.5 + haste * 1.5 + expertise * 2; + score += strength * 2 + agility + attack_power + armor_penetration + meleeDps * 5 + hit * 1.2 + crit * 1.5 + haste * 1.5 + expertise * 2; } else if ((cls == CLASS_SHAMAN && tab == 1)) { // enhancement // STRENGTH mainly (AGILITY, INTELLECT also) score += strength * 1 + agility * 1.5 + intellect * 1.5 + attack_power + spell_power * 1.5 + armor_penetration * 0.5 + meleeDps * 5 - + hit * 1.5 + crit * 1.5 + haste * 1.5 + expertise * 2; + + hit * 1.2 + crit * 1.5 + haste * 1.5 + expertise * 2; } else if ((cls == CLASS_WARRIOR && tab == 2) || (cls == CLASS_PALADIN && tab == 1)) { // TANK WITH SHIELD From 7c1aff09eb52ba12acac0c15c9edde2f73e71edd Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Sun, 28 Jul 2024 15:15:03 +0800 Subject: [PATCH 03/14] [Initialization] Ammo init --- src/RandomItemMgr.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/RandomItemMgr.cpp b/src/RandomItemMgr.cpp index c3b01ef5..1e1a18ab 100644 --- a/src/RandomItemMgr.cpp +++ b/src/RandomItemMgr.cpp @@ -2211,8 +2211,8 @@ void RandomItemMgr::BuildAmmoCache() { for (uint32 subClass = ITEM_SUBCLASS_ARROW; subClass <= ITEM_SUBCLASS_BULLET; subClass++) { - QueryResult results = WorldDatabase.Query("SELECT entry, Flags FROM item_template WHERE class = {} AND subclass = {} AND RequiredLevel <= {} AND stackable = 1000 " - "ORDER BY RequiredLevel DESC", ITEM_CLASS_PROJECTILE, subClass, level); + QueryResult results = WorldDatabase.Query("SELECT entry, Flags FROM item_template WHERE class = {} AND subclass = {} AND RequiredLevel <= {} " + "ORDER BY stackable DESC, RequiredLevel DESC", ITEM_CLASS_PROJECTILE, subClass, level); if (!results) continue; do { From f32ca5472a4a8ab538c09dc2ae10e5390aef72d0 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Sun, 28 Jul 2024 15:15:33 +0800 Subject: [PATCH 04/14] Unholy Deathknight --- src/strategy/deathknight/UnholyDKStrategy.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/strategy/deathknight/UnholyDKStrategy.cpp b/src/strategy/deathknight/UnholyDKStrategy.cpp index 5bc5f500..8edab828 100644 --- a/src/strategy/deathknight/UnholyDKStrategy.cpp +++ b/src/strategy/deathknight/UnholyDKStrategy.cpp @@ -72,12 +72,12 @@ UnholyDKStrategy::UnholyDKStrategy(PlayerbotAI* botAI) : GenericDKStrategy(botAI NextAction** UnholyDKStrategy::getDefaultActions() { return NextAction::array(0, - new NextAction("death and decay", ACTION_DEFAULT + 1.0f), - new NextAction("scourge strike", ACTION_DEFAULT + 0.8f), - new NextAction("horn of winter", ACTION_DEFAULT + 0.6f), - new NextAction("summon gargoyle", ACTION_DEFAULT + 0.4f), + new NextAction("death and decay", ACTION_DEFAULT + 0.5f), + new NextAction("horn of winter", ACTION_DEFAULT + 0.4f), + new NextAction("summon gargoyle", ACTION_DEFAULT + 0.3f), new NextAction("death coil", ACTION_DEFAULT + 0.2f), - new NextAction("melee", ACTION_DEFAULT), + new NextAction("scourge strike", ACTION_NORMAL + 0.1f), + new NextAction("melee", ACTION_DEFAULT), nullptr); } @@ -91,8 +91,8 @@ void UnholyDKStrategy::InitTriggers(std::vector& triggers) triggers.push_back(new TriggerNode("no desolation", NextAction::array(0, new NextAction("blood strike", ACTION_HIGH + 4), nullptr))); triggers.push_back(new TriggerNode("death and decay cooldown", NextAction::array(0, - new NextAction("ghoul frenzy", ACTION_DEFAULT + 5.0f), - new NextAction("scourge strike", ACTION_DEFAULT + 4.0f), + new NextAction("ghoul frenzy", ACTION_NORMAL + 5.0f), + new NextAction("scourge strike", ACTION_NORMAL + 4.0f), new NextAction("blood boil", ACTION_NORMAL + 3.0f), new NextAction("icy touch", ACTION_NORMAL + 2.0f), new NextAction("plague strike", ACTION_NORMAL + 1.0f), From 39d93e6a2f23fae933f0247fb1a6258d63f72b4d Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Sun, 28 Jul 2024 15:16:11 +0800 Subject: [PATCH 05/14] Account creation info message --- src/RandomPlayerbotFactory.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/RandomPlayerbotFactory.cpp b/src/RandomPlayerbotFactory.cpp index e1fec407..b1dfae8b 100644 --- a/src/RandomPlayerbotFactory.cpp +++ b/src/RandomPlayerbotFactory.cpp @@ -375,7 +375,7 @@ void RandomPlayerbotFactory::CreateRandomBots() LOG_INFO("playerbots", "Creating random bot accounts..."); std::vector> account_creations; - bool account_creation = false; + int account_creation = 0; for (uint32 accountNumber = 0; accountNumber < sPlayerbotAIConfig->randomBotAccountCount; ++accountNumber) { std::ostringstream out; @@ -389,7 +389,7 @@ void RandomPlayerbotFactory::CreateRandomBots() { continue; } - account_creation = true; + account_creation++; std::string password = ""; if (sPlayerbotAIConfig->randomBotRandomPassword) { @@ -408,6 +408,7 @@ void RandomPlayerbotFactory::CreateRandomBots() if (account_creation) { /* wait for async accounts create to make character create correctly, same as account delete */ + LOG_INFO("playerbots", "Waiting for {} accounts loading into database...", account_creation); std::this_thread::sleep_for(10ms * sPlayerbotAIConfig->randomBotAccountCount); } @@ -418,7 +419,7 @@ void RandomPlayerbotFactory::CreateRandomBots() std::unordered_map> names; std::vector> playerBots; std::vector sessionBots; - bool bot_creation = false; + int bot_creation = 0; for (uint32 accountNumber = 0; accountNumber < sPlayerbotAIConfig->randomBotAccountCount; ++accountNumber) { std::ostringstream out; @@ -441,7 +442,6 @@ void RandomPlayerbotFactory::CreateRandomBots() { continue; } - bot_creation = true; LOG_INFO("playerbots", "Creating random bot characters for account: [{}/{}]", accountNumber + 1, sPlayerbotAIConfig->randomBotAccountCount); RandomPlayerbotFactory factory(accountId); @@ -462,19 +462,23 @@ void RandomPlayerbotFactory::CreateRandomBots() continue; } - if (cls != 10) + if (cls != 10) { if (Player* playerBot = factory.CreateRandomBot(session, cls, names)) { playerBot->SaveToDB(true, false); sCharacterCache->AddCharacterCacheEntry(playerBot->GetGUID(), accountId, playerBot->GetName(), playerBot->getGender(), playerBot->getRace(), playerBot->getClass(), playerBot->GetLevel()); playerBot->CleanupsBeforeDelete(); delete playerBot; + bot_creation++; + } else { + LOG_ERROR("playerbots", "Fail to create character for account {}", accountId); } + } } } if (bot_creation) { - LOG_INFO("playerbots", "Waiting for {} characters loading into database...", totalCharCount); + LOG_INFO("playerbots", "Waiting for {} characters loading into database...", bot_creation); /* wait for characters load into database, or characters will fail to loggin */ std::this_thread::sleep_for(10s); } From 6b7b270b2667661b656e96ef70e93f05785a0ef5 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Sun, 28 Jul 2024 15:16:32 +0800 Subject: [PATCH 06/14] Remove can not enter message --- src/strategy/actions/UseMeetingStoneAction.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/strategy/actions/UseMeetingStoneAction.cpp b/src/strategy/actions/UseMeetingStoneAction.cpp index 5380d6f9..3ef3b0b1 100644 --- a/src/strategy/actions/UseMeetingStoneAction.cpp +++ b/src/strategy/actions/UseMeetingStoneAction.cpp @@ -164,15 +164,15 @@ bool SummonAction::SummonUsingNpcs(Player* summoner, Player* player) bool SummonAction::Teleport(Player* summoner, Player* player) { Player* master = GetMaster(); - if (master->GetMap() && master->GetMap()->IsDungeon()) { - InstanceMap* map = master->GetMap()->ToInstanceMap(); - if (map) { - if (map->CannotEnter(player) == Map::CANNOT_ENTER_MAX_PLAYERS) { - botAI->TellError("I can not enter this dungeon"); - return false; - } - } - } + // if (master->GetMap() && master->GetMap()->IsDungeon()) { + // InstanceMap* map = master->GetMap()->ToInstanceMap(); + // if (map) { + // if (map->CannotEnter(player, true) == Map::CANNOT_ENTER_MAX_PLAYERS) { + // botAI->TellError("I can not enter this dungeon"); + // return false; + // } + // } + // } if (!summoner->IsBeingTeleported() && !player->IsBeingTeleported()) { float followAngle = GetFollowAngle(); From 90aa76e3c341dc4db653446fbb92e464a5e23762 Mon Sep 17 00:00:00 2001 From: Atidot3 Date: Sun, 28 Jul 2024 13:50:50 +0200 Subject: [PATCH 07/14] Polish bot chatting --- src/strategy/actions/SuggestWhatToDoAction.cpp | 9 +++++---- src/strategy/generic/EmoteStrategy.cpp | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/strategy/actions/SuggestWhatToDoAction.cpp b/src/strategy/actions/SuggestWhatToDoAction.cpp index dc9241f8..6ebf6802 100644 --- a/src/strategy/actions/SuggestWhatToDoAction.cpp +++ b/src/strategy/actions/SuggestWhatToDoAction.cpp @@ -93,7 +93,7 @@ void SuggestWhatToDoAction::specificQuest() placeholders["%role"] = chat->FormatClass(bot, AiFactory::GetPlayerSpecTab(bot)); placeholders["%quest"] = chat->FormatQuest(quest); - spam(BOT_TEXT2("suggest_quest", placeholders), urand(0, 1) ? eTalkType::General : 0, urand(0, 2), urand(0, 2)); + spam(BOT_TEXT2("suggest_quest", placeholders), urand(0, 1) ? eTalkType::General : eTalkType::LookingForGroup, urand(0, 2), urand(0, 2)); } void SuggestWhatToDoAction::grindMaterials() @@ -225,7 +225,7 @@ void SuggestWhatToDoAction::something() out << entry->area_name[_dbc_locale]; placeholders["%zone"] = out.str(); - spam(BOT_TEXT2("suggest_something", placeholders), urand(0, 1) ? eTalkType::General : 0, urand(0, 2), urand(0, 2)); + spam(BOT_TEXT2("suggest_something", placeholders), eTalkType::General, !urand(0, 2), !urand(0, 3)); } void SuggestWhatToDoAction::spam(std::string msg, uint8 flags, bool worldChat, bool guild) @@ -413,7 +413,7 @@ bool SuggestDungeonAction::Execute(Event event) itemout << allowedInstances[urand(0, allowedInstances.size() - 1)]; placeholders["%instance"] = itemout.str(); - spam(BOT_TEXT2("suggest_instance", placeholders), urand(0, 1) ? eTalkType::LookingForGroup : 0, urand(0, 2), urand(0, 2)); + spam(BOT_TEXT2("suggest_instance", placeholders), urand(0, 1) ? eTalkType::LookingForGroup : eTalkType::General, urand(0, 2), urand(0, 2)); return true; } @@ -480,6 +480,7 @@ bool SuggestTradeAction::Execute(Event event) placeholders["%item"] = chat->FormatItem(proto, count); placeholders["%gold"] = chat->formatMoney(price); - spam(BOT_TEXT2("suggest_sell", placeholders), urand(0, 1) ? eTalkType::Trade : 0, urand(0, 1), urand(0, 5)); + + spam(BOT_TEXT2("suggest_sell", placeholders), urand(0, 1) ? eTalkType::Trade : eTalkType::General, !urand(0, 2), urand(0, 5)); return true; } diff --git a/src/strategy/generic/EmoteStrategy.cpp b/src/strategy/generic/EmoteStrategy.cpp index 002fdc41..6f8a35d9 100644 --- a/src/strategy/generic/EmoteStrategy.cpp +++ b/src/strategy/generic/EmoteStrategy.cpp @@ -9,7 +9,7 @@ void EmoteStrategy::InitTriggers(std::vector& triggers) { if (sPlayerbotAIConfig->randomBotEmote) { - triggers.push_back(new TriggerNode("seldom", NextAction::array(0, new NextAction("emote", 1.0f), nullptr))); + triggers.push_back(new TriggerNode("seldom", NextAction::array(0, new NextAction("emote", 10.0f), nullptr))); triggers.push_back(new TriggerNode("receive text emote", NextAction::array(0, new NextAction("emote", 10.0f), nullptr))); triggers.push_back(new TriggerNode("receive emote", NextAction::array(0, new NextAction("emote", 10.0f), nullptr))); } From f6056e0ec6b8b7407834f0f1bf7846e4cfbe2f40 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Mon, 29 Jul 2024 00:12:18 +0800 Subject: [PATCH 08/14] [Initialization] Mount for nightelf (remove Swift Zulian Tiger) --- src/PlayerbotFactory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PlayerbotFactory.cpp b/src/PlayerbotFactory.cpp index e6ee1c34..d66b8d3c 100644 --- a/src/PlayerbotFactory.cpp +++ b/src/PlayerbotFactory.cpp @@ -2574,7 +2574,7 @@ void PlayerbotFactory::InitMounts() break; case RACE_NIGHTELF: slow = { 10789, 8394, 10793 }; - fast = { 24252, 63637, 22723 }; + fast = { 23219, 23220, 63637 }; break; case RACE_UNDEAD_PLAYER: slow = { 17463, 17464, 17462 }; From 64c62b4ddb4470e03576a2a0e61b8d0bf5509787 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Mon, 29 Jul 2024 00:27:32 +0800 Subject: [PATCH 09/14] Revert stats weight calculation --- src/PlayerbotFactory.cpp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/PlayerbotFactory.cpp b/src/PlayerbotFactory.cpp index d66b8d3c..e8360991 100644 --- a/src/PlayerbotFactory.cpp +++ b/src/PlayerbotFactory.cpp @@ -3876,7 +3876,7 @@ float PlayerbotFactory::CalculateItemScore(uint32 item_id, Player* bot) // todo: remove duplicate code if (cls == CLASS_HUNTER) { // AGILITY only - score += agility * 2.5 + attack_power + armor_penetration * 2 + rangeDps * 5 + hit * 1.2 + crit * 2 + haste * 2 + intellect; + score += agility * 2.5 + attack_power + armor_penetration * 2 + rangeDps * 5 + hit * 2 + crit * 2 + haste * 2 + intellect; } else if (cls == CLASS_WARLOCK || cls == CLASS_MAGE || (cls == CLASS_PRIEST && tab == 2) || // shadow @@ -3885,7 +3885,7 @@ float PlayerbotFactory::CalculateItemScore(uint32 item_id, Player* bot) ) { // SPELL DPS score += intellect * 0.5 + spirit * 0.5 + spell_power + spell_penetration - + hit * 0.7 + crit * 0.7 + haste * 1 + rangeDps; + + hit * 1 + crit * 0.7 + haste * 1 + rangeDps; } else if ((cls == CLASS_PALADIN && tab == 0) || // holy (cls == CLASS_PRIEST && tab != 2) || // discipline / holy (cls == CLASS_SHAMAN && tab == 2) || // heal @@ -3895,33 +3895,33 @@ float PlayerbotFactory::CalculateItemScore(uint32 item_id, Player* bot) score += intellect * 0.5 + spirit * 0.5 + spell_power + mana_regeneration * 0.5 + crit * 0.5 + haste * 1 + rangeDps; } else if (cls == CLASS_ROGUE || (cls == CLASS_DRUID && tab == 2 && !PlayerbotAI::IsTank(bot))) { // AGILITY mainly (STRENGTH also) - score += agility * 2 + strength + attack_power + armor_penetration * 1 + meleeDps * 5 + hit * 1 + crit * 1.5 + haste * 1.5 + expertise * 1.5; + score += agility * 2 + strength + attack_power + armor_penetration * 1 + meleeDps * 5 + hit * 1.5 + crit * 1.5 + haste * 1.5 + expertise * 2.5; } else if ((cls == CLASS_PALADIN && tab == 2) || // retribution (cls == CLASS_WARRIOR && tab != 2) || // arm / fury (cls == CLASS_DEATH_KNIGHT && tab != 0) // ice / unholy ) { // STRENGTH mainly (AGILITY also) - score += strength * 2 + agility + attack_power + armor_penetration + meleeDps * 5 + hit * 1 + crit * 1.5 + haste * 1.5 + expertise * 1.5; + score += strength * 2 + agility + attack_power + armor_penetration + meleeDps * 5 + hit * 1.5 + crit * 1.5 + haste * 1.5 + expertise * 2; } else if ((cls == CLASS_SHAMAN && tab == 1)) { // enhancement // STRENGTH mainly (AGILITY, INTELLECT also) score += strength * 1 + agility * 1.5 + intellect * 1.5 + attack_power + spell_power * 1.5 + armor_penetration * 0.5 + meleeDps * 5 - + hit * 1 + crit * 1.5 + haste * 1.5 + expertise * 1.2; + + hit * 1.5 + crit * 1.5 + haste * 1.5 + expertise * 2; } else if ((cls == CLASS_WARRIOR && tab == 2) || (cls == CLASS_PALADIN && tab == 1)) { // TANK WITH SHIELD score += strength * 1 + agility * 2 + attack_power * 0.2 + defense * 2.5 + parry * 2 + dodge * 2 + resilience * 2 + block * 2 + armor * 0.3 + stamina * 3 - + hit * 0.5 + crit * 0.2 + haste * 0.5 + expertise * 2; + + hit * 0.5 + crit * 0.2 + haste * 0.5 + expertise * 3; } else if (cls == CLASS_DEATH_KNIGHT && tab == 0){ // BLOOD DK TANK score += strength * 1 + agility * 2 + attack_power * 0.2 + defense * 3.5 + parry * 2 + dodge * 2 + resilience * 2 + armor * 0.3 + stamina * 2.5 - + hit * 0.5 + crit * 0.5 + haste * 0.5 + expertise * 2; + + hit * 0.5 + crit * 0.5 + haste * 0.5 + expertise * 3.5; } else { // BEAR DRUID TANK score += agility * 1.5 + strength * 1 + attack_power * 0.5 + armor_penetration * 0.5 + meleeDps * 2 + defense * 0.25 + dodge * 0.25 + armor * 0.3 + stamina * 1.5 - + hit * 1 + crit * 1 + haste * 0.5 + expertise * 2; + + hit * 1 + crit * 1 + haste * 0.5 + expertise * 3; } // penalty for different type armor if (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass >= ITEM_SUBCLASS_ARMOR_CLOTH && @@ -4298,7 +4298,7 @@ float PlayerbotFactory::CalculateEnchantScore(uint32 enchant_id, Player* bot) // todo: remove duplicate code if (cls == CLASS_HUNTER) { // AGILITY only - score += agility * 2.5 + attack_power + armor_penetration * 2 + dps * 5 + hit * 1.5 + crit * 2 + haste * 2.5 + intellect; + score += agility * 2.5 + attack_power + armor_penetration * 2 + dps * 5 + hit * 2 + crit * 2 + haste * 2.5 + intellect; } else if (cls == CLASS_WARLOCK || cls == CLASS_MAGE || (cls == CLASS_PRIEST && tab == 2) || // shadow @@ -4317,17 +4317,17 @@ float PlayerbotFactory::CalculateEnchantScore(uint32 enchant_id, Player* bot) score += intellect * 0.5 + spirit * 0.5 + spell_power + mana_regeneration * 0.5 + crit * 0.5 + haste * 1; } else if (cls == CLASS_ROGUE || (cls == CLASS_DRUID && tab == 2 && !PlayerbotAI::IsTank(bot))) { // AGILITY mainly (STRENGTH also) - score += agility * 2 + strength + attack_power + armor_penetration * 1 + dps * 5 + hit * 1.2 + crit * 1.5 + haste * 1.5 + expertise * 2.5; + score += agility * 2 + strength + attack_power + armor_penetration * 1 + dps * 5 + hit * 1.5 + crit * 1.5 + haste * 1.5 + expertise * 2.5; } else if ((cls == CLASS_PALADIN && tab == 2) || // retribution (cls == CLASS_WARRIOR && tab != 2) || // arm / fury (cls == CLASS_DEATH_KNIGHT && tab != 0) // ice / unholy ) { // STRENGTH mainly (AGILITY also) - score += strength * 2 + agility + attack_power + armor_penetration + dps * 5 + hit * 1.2 + crit * 1.5 + haste * 1.5 + expertise * 2; + score += strength * 2 + agility + attack_power + armor_penetration + dps * 5 + hit * 1.5 + crit * 1.5 + haste * 1.5 + expertise * 2; } else if ((cls == CLASS_SHAMAN && tab == 1)) { // enhancement // STRENGTH mainly (AGILITY, INTELLECT also) score += strength * 1 + agility * 1.5 + intellect * 1.5 + attack_power + spell_power * 1.5 + armor_penetration * 0.5 + dps * 5 - + hit * 1.2 + crit * 1.5 + haste * 1.5 + expertise * 2; + + hit * 1.5 + crit * 1.5 + haste * 1.5 + expertise * 2; } else if ((cls == CLASS_WARRIOR && tab == 2) || (cls == CLASS_PALADIN && tab == 1)) { // TANK WITH SHIELD @@ -4578,7 +4578,7 @@ float PlayerbotFactory::CalculateSpellScore(uint32 spell_id, Player* bot, uint32 // todo: remove duplicate code if (cls == CLASS_HUNTER) { // AGILITY only - score += agility * 2.5 + attack_power + armor_penetration * 2 + rangeDps * 5 + hit * 1.5 + crit * 2 + haste * 2.5 + intellect; + score += agility * 2.5 + attack_power + armor_penetration * 2 + rangeDps * 5 + hit * 2 + crit * 2 + haste * 2.5 + intellect; } else if (cls == CLASS_WARLOCK || cls == CLASS_MAGE || (cls == CLASS_PRIEST && tab == 2) || // shadow @@ -4597,17 +4597,17 @@ float PlayerbotFactory::CalculateSpellScore(uint32 spell_id, Player* bot, uint32 score += intellect * 0.5 + spirit * 0.5 + spell_power + mana_regeneration * 0.5 + crit * 0.5 + haste * 1 + rangeDps; } else if (cls == CLASS_ROGUE || (cls == CLASS_DRUID && tab == 2 && !PlayerbotAI::IsTank(bot))) { // AGILITY mainly (STRENGTH also) - score += agility * 2 + strength + attack_power + armor_penetration * 1 + meleeDps * 5 + hit * 1.2 + crit * 1.5 + haste * 1.5 + expertise * 2.5; + score += agility * 2 + strength + attack_power + armor_penetration * 1 + meleeDps * 5 + hit * 1.5 + crit * 1.5 + haste * 1.5 + expertise * 2.5; } else if ((cls == CLASS_PALADIN && tab == 2) || // retribution (cls == CLASS_WARRIOR && tab != 2) || // arm / fury (cls == CLASS_DEATH_KNIGHT && tab != 0) // ice / unholy ) { // STRENGTH mainly (AGILITY also) - score += strength * 2 + agility + attack_power + armor_penetration + meleeDps * 5 + hit * 1.2 + crit * 1.5 + haste * 1.5 + expertise * 2; + score += strength * 2 + agility + attack_power + armor_penetration + meleeDps * 5 + hit * 1.5 + crit * 1.5 + haste * 1.5 + expertise * 2; } else if ((cls == CLASS_SHAMAN && tab == 1)) { // enhancement // STRENGTH mainly (AGILITY, INTELLECT also) score += strength * 1 + agility * 1.5 + intellect * 1.5 + attack_power + spell_power * 1.5 + armor_penetration * 0.5 + meleeDps * 5 - + hit * 1.2 + crit * 1.5 + haste * 1.5 + expertise * 2; + + hit * 1.5 + crit * 1.5 + haste * 1.5 + expertise * 2; } else if ((cls == CLASS_WARRIOR && tab == 2) || (cls == CLASS_PALADIN && tab == 1)) { // TANK WITH SHIELD From 06a63aa730ca63f391c94f2e8b58564d167af146 Mon Sep 17 00:00:00 2001 From: Atidot3 Date: Sun, 28 Jul 2024 18:42:51 +0200 Subject: [PATCH 10/14] fix current_zone_name incorrect values + refactoring guild broadcast simplier + refactoring randomTalk to actually use area / zone general etc --- src/PlayerbotMgr.cpp | 2 +- src/strategy/actions/AutoLearnSpellAction.cpp | 9 ++-- src/strategy/actions/LootAction.cpp | 9 ++-- .../actions/SuggestWhatToDoAction.cpp | 41 ++++++++++--------- src/strategy/actions/XpGainAction.cpp | 9 ++-- src/strategy/generic/EmoteStrategy.cpp | 13 +++--- 6 files changed, 43 insertions(+), 40 deletions(-) diff --git a/src/PlayerbotMgr.cpp b/src/PlayerbotMgr.cpp index f2fab8c4..1774b93e 100644 --- a/src/PlayerbotMgr.cpp +++ b/src/PlayerbotMgr.cpp @@ -526,7 +526,7 @@ void PlayerbotHolder::OnBotLogin(Player* const bot) // join standard channels AreaTableEntry const* current_zone = sAreaTableStore.LookupEntry(bot->GetAreaId()); ChannelMgr* cMgr = ChannelMgr::forTeam(bot->GetTeamId()); - std::string current_zone_name = current_zone ? current_zone->area_name[0] : ""; + std::string current_zone_name = current_zone ? current_zone->area_name[sWorld->GetDefaultDbcLocale()] : ""; if (current_zone && cMgr) { diff --git a/src/strategy/actions/AutoLearnSpellAction.cpp b/src/strategy/actions/AutoLearnSpellAction.cpp index f2d7688f..4ef4f1e8 100644 --- a/src/strategy/actions/AutoLearnSpellAction.cpp +++ b/src/strategy/actions/AutoLearnSpellAction.cpp @@ -41,13 +41,14 @@ void AutoLearnSpellAction::LearnSpells(std::ostringstream* out) Guild* guild = sGuildMgr->GetGuildById(bot->GetGuildId()); if (guild) { - std::map placeholders; - placeholders["%level"] = std::to_string(bot->GetLevel()); + std::string toSay = ""; if (urand(0, 3)) - guild->BroadcastToGuild(bot->GetSession(), false, BOT_TEXT2("Ding!", placeholders), LANG_UNIVERSAL); + toSay = "Ding !"; else - guild->BroadcastToGuild(bot->GetSession(), false, BOT_TEXT2("Yay level %level!", placeholders), LANG_UNIVERSAL); + toSay = "Yay level " + std::to_string(bot->GetLevel()) + " !"; + + guild->BroadcastToGuild(bot->GetSession(), false, toSay, LANG_UNIVERSAL); } } } diff --git a/src/strategy/actions/LootAction.cpp b/src/strategy/actions/LootAction.cpp index 595ff16f..ff383ef7 100644 --- a/src/strategy/actions/LootAction.cpp +++ b/src/strategy/actions/LootAction.cpp @@ -423,13 +423,14 @@ bool StoreLootAction::Execute(Event event) if (guild) { - std::map placeholders; - placeholders["%name"] = chat->FormatItem(proto); + std::string toSay = ""; if (urand(0, 3)) - guild->BroadcastToGuild(bot->GetSession(), false, BOT_TEXT2("Yay I looted %name!", placeholders), LANG_UNIVERSAL); + toSay = "Yay I looted " + chat->FormatItem(proto) + " !"; else - guild->BroadcastToGuild(bot->GetSession(), false, BOT_TEXT2("Guess who got a %name? Me!", placeholders), LANG_UNIVERSAL); + toSay = "Guess who got a " + chat->FormatItem(proto) + " ? Me !"; + + guild->BroadcastToGuild(bot->GetSession(), false, toSay, LANG_UNIVERSAL); } } diff --git a/src/strategy/actions/SuggestWhatToDoAction.cpp b/src/strategy/actions/SuggestWhatToDoAction.cpp index 6ebf6802..e9006fc6 100644 --- a/src/strategy/actions/SuggestWhatToDoAction.cpp +++ b/src/strategy/actions/SuggestWhatToDoAction.cpp @@ -18,11 +18,11 @@ enum eTalkType { - General = ChannelFlags::CHANNEL_FLAG_GENERAL | ChannelFlags::CHANNEL_FLAG_NOT_LFG, - Trade = ChannelFlags::CHANNEL_FLAG_CITY | ChannelFlags::CHANNEL_FLAG_GENERAL | ChannelFlags::CHANNEL_FLAG_NOT_LFG | ChannelFlags::CHANNEL_FLAG_TRADE, - LocalDefence = ChannelFlags::CHANNEL_FLAG_GENERAL | ChannelFlags::CHANNEL_FLAG_NOT_LFG, - GuildRecruitment = ChannelFlags::CHANNEL_FLAG_CITY | ChannelFlags::CHANNEL_FLAG_GENERAL | ChannelFlags::CHANNEL_FLAG_NOT_LFG, - LookingForGroup = ChannelFlags::CHANNEL_FLAG_LFG | ChannelFlags::CHANNEL_FLAG_GENERAL + /*0x18*/ General = ChannelFlags::CHANNEL_FLAG_GENERAL | ChannelFlags::CHANNEL_FLAG_NOT_LFG, + /*0x3C*/ Trade = ChannelFlags::CHANNEL_FLAG_CITY | ChannelFlags::CHANNEL_FLAG_GENERAL | ChannelFlags::CHANNEL_FLAG_NOT_LFG | ChannelFlags::CHANNEL_FLAG_TRADE, + /*0x18*/ LocalDefence = ChannelFlags::CHANNEL_FLAG_GENERAL | ChannelFlags::CHANNEL_FLAG_NOT_LFG, + /*x038*/ GuildRecruitment = ChannelFlags::CHANNEL_FLAG_CITY | ChannelFlags::CHANNEL_FLAG_GENERAL | ChannelFlags::CHANNEL_FLAG_NOT_LFG, + /*0x50*/ LookingForGroup = ChannelFlags::CHANNEL_FLAG_LFG | ChannelFlags::CHANNEL_FLAG_GENERAL }; std::map SuggestDungeonAction::instances; @@ -93,7 +93,7 @@ void SuggestWhatToDoAction::specificQuest() placeholders["%role"] = chat->FormatClass(bot, AiFactory::GetPlayerSpecTab(bot)); placeholders["%quest"] = chat->FormatQuest(quest); - spam(BOT_TEXT2("suggest_quest", placeholders), urand(0, 1) ? eTalkType::General : eTalkType::LookingForGroup, urand(0, 2), urand(0, 2)); + spam(BOT_TEXT2("suggest_quest", placeholders), urand(0, 1) ? eTalkType::General : 0, !urand(0, 2), !urand(0, 3)); } void SuggestWhatToDoAction::grindMaterials() @@ -225,7 +225,7 @@ void SuggestWhatToDoAction::something() out << entry->area_name[_dbc_locale]; placeholders["%zone"] = out.str(); - spam(BOT_TEXT2("suggest_something", placeholders), eTalkType::General, !urand(0, 2), !urand(0, 3)); + spam(BOT_TEXT2("suggest_something", placeholders), urand(0, 1) ? eTalkType::General : 0, !urand(0, 2), !urand(0, 3)); } void SuggestWhatToDoAction::spam(std::string msg, uint8 flags, bool worldChat, bool guild) @@ -238,30 +238,34 @@ void SuggestWhatToDoAction::spam(std::string msg, uint8 flags, bool worldChat, b if (!cMgr) return; + AreaTableEntry const* zone = sAreaTableStore.LookupEntry(bot->GetMap()->GetZoneId(bot->GetPhaseMask(), bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ())); + if (!zone) return; + /*AreaTableEntry const* area = sAreaTableStore.LookupEntry(bot->GetMap()->GetAreaId(bot->GetPhaseMask(), bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ())); + if (!area) return;*/ + + std::string areaname = zone->area_name[_dbc_locale]; + for (uint32 i = 0; i < sChatChannelsStore.GetNumRows(); ++i) { ChatChannelsEntry const* channel = sChatChannelsStore.LookupEntry(i); if (!channel) continue; - AreaTableEntry const* current_zone = GetAreaEntryByAreaID(bot->GetAreaId()); - if (!current_zone) - continue; - // combine full channel name char channelName[100]; Channel* chn = nullptr; - if ((channel->flags & CHANNEL_DBC_FLAG_LFG) != 0) + if (channel->ChannelID == 24 || (channel->flags & CHANNEL_DBC_FLAG_LFG) != 0) { std::string chanName = channel->pattern[_dbc_locale]; chn = cMgr->GetChannel(chanName, bot); } else { - snprintf(channelName, 100, channel->pattern[_dbc_locale], current_zone->area_name[_dbc_locale]); + snprintf(channelName, 100, channel->pattern[_dbc_locale], areaname); chn = cMgr->GetChannel(channelName, bot); } if (!chn) continue; + // skip world chat here if (chn->GetName() == "World") continue; @@ -269,8 +273,8 @@ void SuggestWhatToDoAction::spam(std::string msg, uint8 flags, bool worldChat, b if (flags != 0 && chn->GetFlags() != flags) continue; - // skip local defense - if (chn->GetChannelId() == 22) + // skip local defense and universal defense + if (chn->GetChannelId() == 22 || chn->GetChannelId() == 23) continue; // no filter, pick several options @@ -413,7 +417,7 @@ bool SuggestDungeonAction::Execute(Event event) itemout << allowedInstances[urand(0, allowedInstances.size() - 1)]; placeholders["%instance"] = itemout.str(); - spam(BOT_TEXT2("suggest_instance", placeholders), urand(0, 1) ? eTalkType::LookingForGroup : eTalkType::General, urand(0, 2), urand(0, 2)); + spam(BOT_TEXT2("suggest_instance", placeholders), urand(0, 1) ? eTalkType::LookingForGroup : 0, !urand(0, 2), !urand(0, 3)); return true; } @@ -423,9 +427,6 @@ SuggestTradeAction::SuggestTradeAction(PlayerbotAI* botAI) : SuggestWhatToDoActi bool SuggestTradeAction::Execute(Event event) { - if (!sRandomPlayerbotMgr->IsRandomBot(bot) || bot->GetGroup() || bot->GetInstanceId()) - return false; - uint32 quality = urand(0, 100); if (quality > 95) quality = ITEM_QUALITY_LEGENDARY; @@ -481,6 +482,6 @@ bool SuggestTradeAction::Execute(Event event) placeholders["%gold"] = chat->formatMoney(price); - spam(BOT_TEXT2("suggest_sell", placeholders), urand(0, 1) ? eTalkType::Trade : eTalkType::General, !urand(0, 2), urand(0, 5)); + spam(BOT_TEXT2("suggest_sell", placeholders), urand(0, 1) ? eTalkType::Trade : 0, !urand(0, 2), urand(0, 5)); return true; } diff --git a/src/strategy/actions/XpGainAction.cpp b/src/strategy/actions/XpGainAction.cpp index 155cb752..39ff7d4f 100644 --- a/src/strategy/actions/XpGainAction.cpp +++ b/src/strategy/actions/XpGainAction.cpp @@ -41,13 +41,14 @@ bool XpGainAction::Execute(Event event) Guild* guild = sGuildMgr->GetGuildById(bot->GetGuildId()); if (guild) { - std::map placeholders; - placeholders["%name"] = creature->GetName(); + std::string toSay = ""; if (urand(0, 3)) - guild->BroadcastToGuild(bot->GetSession(), false, BOT_TEXT2("Wow I just killed %name!", placeholders), LANG_UNIVERSAL); + toSay = "Wow I just killed " + creature->GetName() + " !"; else - guild->BroadcastToGuild(bot->GetSession(), false, BOT_TEXT2("Awesome that %name went down quickly!", placeholders), LANG_UNIVERSAL); + toSay = "Awesome that " + creature->GetName() + " went down quickly !"; + + guild->BroadcastToGuild(bot->GetSession(), false, toSay, LANG_UNIVERSAL); } } } diff --git a/src/strategy/generic/EmoteStrategy.cpp b/src/strategy/generic/EmoteStrategy.cpp index 6f8a35d9..d4a053bc 100644 --- a/src/strategy/generic/EmoteStrategy.cpp +++ b/src/strategy/generic/EmoteStrategy.cpp @@ -9,21 +9,20 @@ void EmoteStrategy::InitTriggers(std::vector& triggers) { if (sPlayerbotAIConfig->randomBotEmote) { - triggers.push_back(new TriggerNode("seldom", NextAction::array(0, new NextAction("emote", 10.0f), nullptr))); + triggers.push_back(new TriggerNode("seldom", NextAction::array(0, new NextAction("emote", 1.0f), nullptr))); triggers.push_back(new TriggerNode("receive text emote", NextAction::array(0, new NextAction("emote", 10.0f), nullptr))); triggers.push_back(new TriggerNode("receive emote", NextAction::array(0, new NextAction("emote", 10.0f), nullptr))); } if (sPlayerbotAIConfig->randomBotTalk) { - triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("suggest what to do", 1.0f), nullptr))); - triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("suggest trade", 1.0f), nullptr))); - triggers.push_back(new TriggerNode("seldom", NextAction::array(0, new NextAction("talk", 1.0f), nullptr))); + triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("suggest what to do", 35.0f), + new NextAction("suggest dungeon", 50.0f), + new NextAction("suggest trade", 65.0f), + new NextAction("talk", 10.0f), + nullptr))); } - if (sPlayerbotAIConfig->randomBotSuggestDungeons) - triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("suggest dungeon", 1.0f), nullptr))); - if (sPlayerbotAIConfig->enableGreet) triggers.push_back(new TriggerNode("new player nearby", NextAction::array(0, new NextAction("greet", 1.0f), nullptr))); From 1128e0280acb6e8ac7c82e1cd97d1b8405e80f6d Mon Sep 17 00:00:00 2001 From: Atidot3 Date: Sun, 28 Jul 2024 18:44:56 +0200 Subject: [PATCH 11/14] reduce spam --- src/strategy/generic/EmoteStrategy.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/strategy/generic/EmoteStrategy.cpp b/src/strategy/generic/EmoteStrategy.cpp index d4a053bc..d3b72fa3 100644 --- a/src/strategy/generic/EmoteStrategy.cpp +++ b/src/strategy/generic/EmoteStrategy.cpp @@ -16,10 +16,10 @@ void EmoteStrategy::InitTriggers(std::vector& triggers) if (sPlayerbotAIConfig->randomBotTalk) { - triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("suggest what to do", 35.0f), - new NextAction("suggest dungeon", 50.0f), - new NextAction("suggest trade", 65.0f), - new NextAction("talk", 10.0f), + triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("suggest what to do", 10.0f), + new NextAction("suggest dungeon", 3.0f), + new NextAction("suggest trade", 3.0f), + new NextAction("talk", 1.0f), nullptr))); } From cf9dca6b16ec153e03a609dcdf1323d3acba76bf Mon Sep 17 00:00:00 2001 From: Atidot3 Date: Sun, 28 Jul 2024 20:43:17 +0200 Subject: [PATCH 12/14] Add parameters to allow bot to talk in guild + fix multi guild same message + bot in group wont ask for dungeon --- src/PlayerbotAIConfig.cpp | 1 + src/PlayerbotAIConfig.h | 1 + src/strategy/actions/AutoLearnSpellAction.cpp | 2 +- src/strategy/actions/LootAction.cpp | 2 +- src/strategy/actions/SayAction.cpp | 2 +- src/strategy/actions/SuggestWhatToDoAction.cpp | 14 ++++++++------ src/strategy/actions/XpGainAction.cpp | 2 +- 7 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/PlayerbotAIConfig.cpp b/src/PlayerbotAIConfig.cpp index 94765f34..a859c9dd 100644 --- a/src/PlayerbotAIConfig.cpp +++ b/src/PlayerbotAIConfig.cpp @@ -143,6 +143,7 @@ bool PlayerbotAIConfig::Initialize() randomBotTalk = sConfigMgr->GetOption("AiPlayerbot.RandomBotTalk", false); randomBotEmote = sConfigMgr->GetOption("AiPlayerbot.RandomBotEmote", false); randomBotSuggestDungeons = sConfigMgr->GetOption("AiPlayerbot.RandomBotSuggestDungeons", true); + randomBotGuildTalk = sConfigMgr->GetOption("AiPlayerbot.RandomBotGuildTalk", false); suggestDungeonsInLowerCaseRandomly = sConfigMgr->GetOption("AiPlayerbot.SuggestDungeonsInLowerCaseRandomly", false); randomBotJoinBG = sConfigMgr->GetOption("AiPlayerbot.RandomBotJoinBG", true); randomBotAutoJoinBG = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinBG", false); diff --git a/src/PlayerbotAIConfig.h b/src/PlayerbotAIConfig.h index c008c051..129daee3 100644 --- a/src/PlayerbotAIConfig.h +++ b/src/PlayerbotAIConfig.h @@ -98,6 +98,7 @@ class PlayerbotAIConfig bool randomBotTalk; bool randomBotEmote; bool randomBotSuggestDungeons; + bool randomBotGuildTalk; bool suggestDungeonsInLowerCaseRandomly; bool randomBotJoinBG; bool randomBotAutoJoinBG; diff --git a/src/strategy/actions/AutoLearnSpellAction.cpp b/src/strategy/actions/AutoLearnSpellAction.cpp index 4ef4f1e8..24205a64 100644 --- a/src/strategy/actions/AutoLearnSpellAction.cpp +++ b/src/strategy/actions/AutoLearnSpellAction.cpp @@ -36,7 +36,7 @@ void AutoLearnSpellAction::LearnSpells(std::ostringstream* out) if (sPlayerbotAIConfig->autoLearnQuestSpells && sRandomPlayerbotMgr->IsRandomBot(bot))// || (!botAI->GetMaster() && sRandomPlayerbotMgr->IsRandomBot(bot))) LearnQuestSpells(out); - if (sPlayerbotAIConfig->randomBotTalk) + if (sPlayerbotAIConfig->randomBotGuildTalk) { Guild* guild = sGuildMgr->GetGuildById(bot->GetGuildId()); if (guild) diff --git a/src/strategy/actions/LootAction.cpp b/src/strategy/actions/LootAction.cpp index ff383ef7..10ae1ccc 100644 --- a/src/strategy/actions/LootAction.cpp +++ b/src/strategy/actions/LootAction.cpp @@ -417,7 +417,7 @@ bool StoreLootAction::Execute(Event event) if (proto->Quality >= ITEM_QUALITY_RARE && !urand(0, 1) && botAI->HasStrategy("emote", BOT_STATE_NON_COMBAT)) botAI->PlayEmote(TEXT_EMOTE_CHEER); - if (sPlayerbotAIConfig->randomBotTalk && bot->GetGuildId() && urand(0, 10) && proto->Quality >= ITEM_QUALITY_RARE) + if (sPlayerbotAIConfig->randomBotGuildTalk && bot->GetGuildId() && urand(0, 10) && proto->Quality >= ITEM_QUALITY_RARE) { Guild* guild = sGuildMgr->GetGuildById(bot->GetGuildId()); diff --git a/src/strategy/actions/SayAction.cpp b/src/strategy/actions/SayAction.cpp index e299736d..2bcca877 100644 --- a/src/strategy/actions/SayAction.cpp +++ b/src/strategy/actions/SayAction.cpp @@ -674,7 +674,7 @@ void ChatReplyAction::ChatReplyDo(Player* bot, uint32 type, uint32 guid1, uint32 else if (type == CHAT_MSG_GUILD) { - if (!bot->GetGuildId()) + if (!bot->GetGuildId() || !sPlayerbotAIConfig->randomBotGuildTalk) return; Guild* guild = sGuildMgr->GetGuildById(bot->GetGuildId()); diff --git a/src/strategy/actions/SuggestWhatToDoAction.cpp b/src/strategy/actions/SuggestWhatToDoAction.cpp index e9006fc6..776c1ac9 100644 --- a/src/strategy/actions/SuggestWhatToDoAction.cpp +++ b/src/strategy/actions/SuggestWhatToDoAction.cpp @@ -306,13 +306,13 @@ void SuggestWhatToDoAction::spam(std::string msg, uint8 flags, bool worldChat, b if (Channel* worldChannel = cMgr->GetChannel("World", bot)) worldChannel->Say(bot->GetGUID(), msg.c_str(), LANG_UNIVERSAL); } + } - if (guild && bot->GetGuildId()) - { - Guild* guild = sGuildMgr->GetGuildById(bot->GetGuildId()); - if (guild) - guild->BroadcastToGuild(bot->GetSession(), false, msg.c_str(), LANG_UNIVERSAL); - } + if (sPlayerbotAIConfig->randomBotGuildTalk && guild && bot->GetGuildId()) + { + Guild* guild = sGuildMgr->GetGuildById(bot->GetGuildId()); + if (guild) + guild->BroadcastToGuild(bot->GetSession(), false, msg.c_str(), LANG_UNIVERSAL); } } @@ -355,6 +355,8 @@ bool SuggestDungeonAction::Execute(Event event) { // TODO: use sPlayerbotDungeonSuggestionMgr + if (!sPlayerbotAIConfig->randomBotSuggestDungeons || bot->GetGroup()) return false; + if (instances.empty()) { instances["Ragefire Chasm"] = 15; diff --git a/src/strategy/actions/XpGainAction.cpp b/src/strategy/actions/XpGainAction.cpp index 39ff7d4f..8dc98ca6 100644 --- a/src/strategy/actions/XpGainAction.cpp +++ b/src/strategy/actions/XpGainAction.cpp @@ -33,7 +33,7 @@ bool XpGainAction::Execute(Event event) p >> groupBonus; // 8 group bonus } - if (sPlayerbotAIConfig->randomBotTalk && bot->GetGuildId() && urand(0, 10)) + if (sPlayerbotAIConfig->randomBotGuildTalk && bot->GetGuildId() && urand(0, 10)) { Creature* creature = botAI->GetCreature(guid); if (creature && (creature->isElite() || creature->isWorldBoss() || creature->GetLevel() > 61 || creature->GetLevel() > bot->GetLevel() + 4)) From 7d13192517d9b8b2b55964ed150d17c95ba17a0d Mon Sep 17 00:00:00 2001 From: Atidot3 Date: Sun, 28 Jul 2024 21:12:06 +0200 Subject: [PATCH 13/14] removed useless string --- src/strategy/actions/SuggestWhatToDoAction.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/strategy/actions/SuggestWhatToDoAction.cpp b/src/strategy/actions/SuggestWhatToDoAction.cpp index 776c1ac9..391978f1 100644 --- a/src/strategy/actions/SuggestWhatToDoAction.cpp +++ b/src/strategy/actions/SuggestWhatToDoAction.cpp @@ -243,8 +243,6 @@ void SuggestWhatToDoAction::spam(std::string msg, uint8 flags, bool worldChat, b /*AreaTableEntry const* area = sAreaTableStore.LookupEntry(bot->GetMap()->GetAreaId(bot->GetPhaseMask(), bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ())); if (!area) return;*/ - std::string areaname = zone->area_name[_dbc_locale]; - for (uint32 i = 0; i < sChatChannelsStore.GetNumRows(); ++i) { ChatChannelsEntry const* channel = sChatChannelsStore.LookupEntry(i); @@ -260,7 +258,7 @@ void SuggestWhatToDoAction::spam(std::string msg, uint8 flags, bool worldChat, b } else { - snprintf(channelName, 100, channel->pattern[_dbc_locale], areaname); + snprintf(channelName, 100, channel->pattern[_dbc_locale], zone->area_name[_dbc_locale]); chn = cMgr->GetChannel(channelName, bot); } if (!chn) From 74658389ecb2a4843a60fc68d45800da2cfd02e1 Mon Sep 17 00:00:00 2001 From: Revision Date: Mon, 29 Jul 2024 00:51:43 +0200 Subject: [PATCH 14/14] Fix compile errors related to sSpellMgr --- src/Playerbots.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Playerbots.h b/src/Playerbots.h index 7e678af3..2b467366 100644 --- a/src/Playerbots.h +++ b/src/Playerbots.h @@ -14,6 +14,7 @@ #include "RandomPlayerbotMgr.h" #include "SharedValueContext.h" #include "Spell.h" +#include "SpellMgr.h" #include "TravelNode.h" std::vector split(std::string const s, char delim);