From 0dfd6dd50b54a23e92596159eb68118332b1e770 Mon Sep 17 00:00:00 2001 From: trickerer Date: Thu, 5 Dec 2024 11:24:36 +0700 Subject: [PATCH] NPCBots: Fix being unable to attack wandering bots in FFAPvP server mode. Set wandering bots' faction to Neutral Hostile instead of Hostile To All to prevent guards' reaction towards neutral team wandering bots --- .../game/AI/NpcBots/bot_GridNotifiers.h | 2 +- src/server/game/AI/NpcBots/bot_ai.cpp | 37 ++++++++++----- src/server/game/AI/NpcBots/botcommands.cpp | 4 +- src/server/game/AI/NpcBots/botcommon.h | 2 +- src/server/game/AI/NpcBots/botdatamgr.cpp | 46 +++++++++++-------- src/server/game/AI/NpcBots/botdatamgr.h | 1 + src/server/game/AI/NpcBots/bpet_ai.cpp | 2 +- src/server/game/Entities/Unit/Unit.cpp | 4 ++ 8 files changed, 62 insertions(+), 36 deletions(-) diff --git a/src/server/game/AI/NpcBots/bot_GridNotifiers.h b/src/server/game/AI/NpcBots/bot_GridNotifiers.h index cd6e91ace8da1..938410e6a8461 100644 --- a/src/server/game/AI/NpcBots/bot_GridNotifiers.h +++ b/src/server/game/AI/NpcBots/bot_GridNotifiers.h @@ -111,7 +111,7 @@ class NearestHostileUnitCheck NearestHostileUnitCheck(NearestHostileUnitCheck const&) = delete; explicit NearestHostileUnitCheck(Unit const* unit, float dist, bool magic, bot_ai const* m_ai, bool targetCCed, bool withSecondary) : me(unit), m_range(dist), byspell(magic), ai(m_ai), AttackCCed(targetCCed), checkSecondary(withSecondary) - { free = ai->IAmFree(); berserk = free && (ai->IsWanderer() || unit->GetFaction() == 14); } + { free = ai->IAmFree(); berserk = free && (ai->IsWanderer() || unit->GetFaction() == FACTION_TEMPLATE_NEUTRAL_HOSTILE); } explicit NearestHostileUnitCheck(Unit const* unit, float dist, bool magic, bot_ai const* m_ai) : NearestHostileUnitCheck(unit, dist, magic, m_ai, true, false) {} diff --git a/src/server/game/AI/NpcBots/bot_ai.cpp b/src/server/game/AI/NpcBots/bot_ai.cpp index f85f83bf69d69..172a63804a6c3 100644 --- a/src/server/game/AI/NpcBots/bot_ai.cpp +++ b/src/server/game/AI/NpcBots/bot_ai.cpp @@ -1404,7 +1404,7 @@ void bot_ai::BuffAndHealGroup(uint32 diff) if (HealTarget(me, diff)) return; - if (me->GetFaction() == 14 || me->HasAura(BERSERK)) + if (me->GetFaction() == FACTION_TEMPLATE_NEUTRAL_HOSTILE || me->HasAura(BERSERK)) return; std::list targets2; @@ -1659,7 +1659,7 @@ void bot_ai::ResurrectGroup(uint32 spell_id) if (IAmFree()) { - if (me->GetFaction() == 14 || me->HasAura(BERSERK)) + if (me->GetFaction() == FACTION_TEMPLATE_NEUTRAL_HOSTILE || me->HasAura(BERSERK)) return; WorldObject* playerOrCorpse = GetNearbyRezTarget(); @@ -1825,7 +1825,7 @@ void bot_ai::CureGroup(uint32 cureSpell, uint32 diff) if (botPet && !me->IsInCombat() && _canCureTarget(botPet, cureSpell)) targets.push_back(botPet); - if (!(me->GetFaction() == 14 || me->HasAura(BERSERK))) + if (!(me->GetFaction() == FACTION_TEMPLATE_NEUTRAL_HOSTILE || me->HasAura(BERSERK))) { std::list targets1; GetNearbyFriendlyTargetsList(targets1, 30); @@ -3630,7 +3630,7 @@ bool bot_ai::IsInBotParty(Unit const* unit) const if (IAmFree()) { - if (me->GetFaction() == 14 || unit->GetFaction() == 14) + if (me->GetFaction() == FACTION_TEMPLATE_NEUTRAL_HOSTILE || unit->GetFaction() == FACTION_TEMPLATE_NEUTRAL_HOSTILE) return false; if (me->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP) || @@ -3801,7 +3801,7 @@ bool bot_ai::CanBotAttack(Unit const* target, int8 byspell, bool secondary) cons return false; if (me->GetFaction() == 35 && IAmFree() && target->GetTypeId() == TYPEID_UNIT && target->GetVictim() != me) return false; - if ((target->GetFaction() == 35 || target->GetFaction() == me->GetFaction()) && me->GetFaction() != 14) + if ((target->GetFaction() == 35 || target->GetFaction() == me->GetFaction()) && me->GetFaction() != FACTION_TEMPLATE_NEUTRAL_HOSTILE) return false; if (!CanBotAttackOnVehicle()) return false; @@ -3814,6 +3814,13 @@ bool bot_ai::CanBotAttack(Unit const* target, int8 byspell, bool secondary) cons return false; if (BotMgr::EnableWanderingUntargetNpcFlightmaster() && target->IsTaxi()) return false; + //do not attack friendly targets in FFAPvP mode + if (me->IsFFAPvP() && me->GetFaction() == FACTION_TEMPLATE_NEUTRAL_HOSTILE) + { + uint32 base_faction = BotDataMgr::GetDefaultFactionForBotRace(me->GetRace()); + if (me->GetFaction() != base_faction && Unit::GetFactionReactionTo(sFactionTemplateStore.LookupEntry(base_faction), target) >= REP_FRIENDLY) + return false; + } } if (IAmFree()) @@ -3863,7 +3870,7 @@ bool bot_ai::CanBotAttack(Unit const* target, int8 byspell, bool secondary) cons } } - if (master->IsInCombat() || target->IsInCombat() || IsWanderer() || (IAmFree() && me->GetFaction() == 14) || pulling) + if (master->IsInCombat() || target->IsInCombat() || IsWanderer() || (IAmFree() && me->GetFaction() == FACTION_TEMPLATE_NEUTRAL_HOSTILE) || pulling) { //if master is killed pursue to the end) if (!master->IsAlive() || target->IsControlledByPlayer() || pulling || (followdist > 0 && (master->GetDistance(target) <= foldist || HasBotCommandState(BOT_COMMAND_STAY)))) @@ -10758,9 +10765,9 @@ bool bot_ai::OnGossipSelect(Player* player, Creature* creature/* == me*/, uint32 } else if (reason == -1) { - me->SetFaction(14); + me->SetFaction(FACTION_TEMPLATE_NEUTRAL_HOSTILE); if (botPet) - botPet->SetFaction(14); + botPet->SetFaction(FACTION_TEMPLATE_NEUTRAL_HOSTILE); BotYell(LocalizedNpcText(player, BOT_TEXT_DIE), player); me->Attack(player, true); break; @@ -10847,9 +10854,9 @@ bool bot_ai::OnGossipSelect(Player* player, Creature* creature/* == me*/, uint32 } //if (urand(1,100) <= 25) //{ - // me->SetFaction(14); + // me->SetFaction(FACTION_TEMPLATE_HATES_EVERYTHING_1); // if (Creature* pet = GetBotsPet()) - // pet->SetFaction(14); + // pet->SetFaction(FACTION_TEMPLATE_HATES_EVERYTHING_1); // BotSay("Fool...", player); // me->Attack(player, true); //} @@ -15003,7 +15010,7 @@ void bot_ai::InitFaction() { uint32 faction = _botData->faction; - //if (faction == 14) + //if (faction == FACTION_TEMPLATE_HATES_EVERYTHING_1) // faction = 35; me->SetFaction(faction); @@ -16370,6 +16377,9 @@ void bot_ai::OnDeath([[maybe_unused]] Unit* attacker/* = nullptr*/) void bot_ai::KilledUnit(Unit* u) { + if (u->GetOwnerGUID() == me->GetGUID() || u->GetGUID() == me->GetGUID()) + return; + ++_killsCount; if (u->IsControlledByPlayer() || u->IsPvP() || u->IsNPCBotOrPet()) { @@ -19323,6 +19333,11 @@ WanderNode const* bot_ai::GetNextWanderNode(Position const* fromPos, uint8 lvl, }; uint32 faction = me->GetFaction(); + if (me->IsFFAPvP()) + { + ChrRacesEntry const* rentry = sChrRacesStore.LookupEntry(me->GetRace()); + faction = (_botclass >= BOT_CLASS_EX_START) ? FACTION_TEMPLATE_NEUTRAL_HOSTILE : rentry ? rentry->FactionID : FACTION_TEMPLATE_NEUTRAL_HOSTILE; + } //Node got deleted (or forced)! Select close point and go from there NodeList nlinks; diff --git a/src/server/game/AI/NpcBots/botcommands.cpp b/src/server/game/AI/NpcBots/botcommands.cpp index b9055f1f2f2b5..6b528f26727cd 100644 --- a/src/server/game/AI/NpcBots/botcommands.cpp +++ b/src/server/game/AI/NpcBots/botcommands.cpp @@ -3156,7 +3156,7 @@ class script_bot_commands : public CommandScript else if ((*factionStr)[0] == 'h') factionId = 1801; //Horde else if ((*factionStr)[0] == 'm') - factionId = 14; //Monsters + factionId = FACTION_TEMPLATE_NEUTRAL_HOSTILE; //Monsters else if ((*factionStr)[0] == 'f') factionId = 35; //Friendly to all @@ -3343,7 +3343,7 @@ class script_bot_commands : public CommandScript if (teamid) { ChrRacesEntry const* rentry = sChrRacesStore.LookupEntry(race); - uint32 faction = rentry ? rentry->FactionID : 14; + uint32 faction = rentry ? rentry->FactionID : FACTION_TEMPLATE_NEUTRAL_HOSTILE; TeamId team = BotDataMgr::GetTeamIdForFaction(faction); if (*teamid != uint8(team)) diff --git a/src/server/game/AI/NpcBots/botcommon.h b/src/server/game/AI/NpcBots/botcommon.h index 2f789c6743133..4fe4ddf3194a9 100644 --- a/src/server/game/AI/NpcBots/botcommon.h +++ b/src/server/game/AI/NpcBots/botcommon.h @@ -133,7 +133,7 @@ enum BotCommonValues //COMMON GAMEEVENTS GAME_EVENT_WINTER_VEIL = 2, //COMMON FACTIONS - FACTION_TEMPLATE_HATES_EVERYTHING_1 = 2150, //faction 966 - Monster spar buddy + FACTION_TEMPLATE_NEUTRAL_HOSTILE = FACTION_CREATURE, // 2150 //Hates players and other bots, not attacked by guards //SOUNDS SOUND_FREEZE_IMPACT_WINDWALK = 29, SOUND_AXE_2H_IMPACT_FLESH_CRIT = 158, diff --git a/src/server/game/AI/NpcBots/botdatamgr.cpp b/src/server/game/AI/NpcBots/botdatamgr.cpp index f1b936bd7dd22..436c1932993b0 100644 --- a/src/server/game/AI/NpcBots/botdatamgr.cpp +++ b/src/server/game/AI/NpcBots/botdatamgr.cpp @@ -231,15 +231,15 @@ struct WanderingBotsGenerator using NodeVec = std::vector; const std::map wbot_faction_for_ex_class = { - {BOT_CLASS_BM, 14u/*2u*/}, - {BOT_CLASS_SPHYNX, 14u}, - {BOT_CLASS_ARCHMAGE, 14u/*1u*/}, - {BOT_CLASS_DREADLORD, 14u}, - {BOT_CLASS_SPELLBREAKER, 14u/*1610u*/}, - {BOT_CLASS_DARK_RANGER, 14u}, - {BOT_CLASS_NECROMANCER, 14u}, - {BOT_CLASS_SEA_WITCH, 14u}, - {BOT_CLASS_CRYPT_LORD, 14u} + {BOT_CLASS_BM, FACTION_TEMPLATE_NEUTRAL_HOSTILE/*2u*/}, + {BOT_CLASS_SPHYNX, FACTION_TEMPLATE_NEUTRAL_HOSTILE}, + {BOT_CLASS_ARCHMAGE, FACTION_TEMPLATE_NEUTRAL_HOSTILE/*1u*/}, + {BOT_CLASS_DREADLORD, FACTION_TEMPLATE_NEUTRAL_HOSTILE}, + {BOT_CLASS_SPELLBREAKER, FACTION_TEMPLATE_NEUTRAL_HOSTILE/*1610u*/}, + {BOT_CLASS_DARK_RANGER, FACTION_TEMPLATE_NEUTRAL_HOSTILE}, + {BOT_CLASS_NECROMANCER, FACTION_TEMPLATE_NEUTRAL_HOSTILE}, + {BOT_CLASS_SEA_WITCH, FACTION_TEMPLATE_NEUTRAL_HOSTILE}, + {BOT_CLASS_CRYPT_LORD, FACTION_TEMPLATE_NEUTRAL_HOSTILE} }; uint32 next_bot_id; @@ -286,12 +286,6 @@ struct WanderingBotsGenerator _spareBotIdsPerClassMap.erase(c); } - uint32 GetDefaultFactionForRaceClass(uint8 bot_class, uint8 bot_race) const - { - ChrRacesEntry const* rentry = sChrRacesStore.LookupEntry(bot_race); - return (bot_class >= BOT_CLASS_EX_START) ? wbot_faction_for_ex_class.find(bot_class)->second : rentry ? rentry->FactionID : 14u; - } - bool GenerateWanderingBotToSpawn(std::pair const& spareBotPair, uint8 desired_bracket, NodeVec const& spawns_a, NodeVec const& spawns_h, NodeVec const& spawns_n, bool immediate, PvPDifficultyEntry const* bracketEntry, NpcBotRegistry* registry) @@ -304,7 +298,7 @@ struct WanderingBotsGenerator const uint32 orig_entry = spareBotPair.second; CreatureTemplate const* orig_template = ASSERT_NOTNULL(sObjectMgr->GetCreatureTemplate(orig_entry)); NpcBotExtras const* orig_extras = ASSERT_NOTNULL(BotDataMgr::SelectNpcBotExtras(orig_entry)); - uint32 bot_faction = GetDefaultFactionForRaceClass(bot_class, orig_extras->race); + uint32 bot_faction = BotDataMgr::GetDefaultFactionForBotRace(orig_extras->race); NodeVec const* bot_spawn_nodes; TeamId bot_team = BotDataMgr::GetTeamIdForFaction(bot_faction); @@ -361,6 +355,12 @@ struct WanderingBotsGenerator bot_template.minlevel = std::min(std::max(desired_bracket * 10, spawnLoc->GetLevels().first), max_level); bot_template.maxlevel = std::min(std::min(desired_bracket * 10 + 9, spawnLoc->GetLevels().second), max_level); bot_template.flags_extra &= ~(CREATURE_FLAG_EXTRA_NO_XP); + + if (sWorld->IsFFAPvPRealm()) + { + bot_template.faction = FACTION_TEMPLATE_NEUTRAL_HOSTILE; + bot_faction = FACTION_TEMPLATE_NEUTRAL_HOSTILE; + } } bot_template.InitializeQueryData(); @@ -422,14 +422,14 @@ struct WanderingBotsGenerator if (kv.first >= BOT_CLASS_EX_START) { auto cit = wbot_faction_for_ex_class.find(kv.first); - if (cit != wbot_faction_for_ex_class.cend() && cit->second == FACTION_MONSTER) + if (cit != wbot_faction_for_ex_class.cend() && cit->second == FACTION_TEMPLATE_NEUTRAL_HOSTILE) continue; } for (uint32 entry : kv.second) { NpcBotExtras const* extras = ASSERT_NOTNULL(BotDataMgr::SelectNpcBotExtras(entry)); - uint32 bot_faction = GetDefaultFactionForRaceClass(kv.first, extras->race); + uint32 bot_faction = BotDataMgr::GetDefaultFactionForBotRace(extras->race); TeamId bot_team = BotDataMgr::GetTeamIdForFaction(bot_faction); if (teamId == bot_team) ++count; @@ -542,7 +542,7 @@ struct WanderingBotsGenerator for (uint32 spareBotId : kv.second) { NpcBotExtras const* orig_extras = ASSERT_NOTNULL(BotDataMgr::SelectNpcBotExtras(spareBotId)); - uint32 bot_faction = GetDefaultFactionForRaceClass(kv.first, orig_extras->race); + uint32 bot_faction = BotDataMgr::GetDefaultFactionForBotRace(orig_extras->race); uint32 botTeam = BotDataMgr::GetTeamForFaction(bot_faction); if (int32(botTeam) != team) @@ -3191,7 +3191,7 @@ int32 BotDataMgr::GetBotBaseReputation(Creature const* bot, FactionEntry const* if (bot->IsNPCBotPet()) bot = bot->GetBotPetAI()->GetPetsOwner(); - uint32 raceMask = bot->GetFaction() == 14 ? 0 : bot->GetRaceMask(); + uint32 raceMask = GetDefaultFactionForBotRace(bot->GetRace()) == FACTION_TEMPLATE_NEUTRAL_HOSTILE ? 0 : bot->GetRaceMask(); uint32 classMask = bot->GetClassMask(); int32 minRep = 42999; @@ -3209,6 +3209,12 @@ int32 BotDataMgr::GetBotBaseReputation(Creature const* bot, FactionEntry const* return std::min(minRep, 0); } +uint32 BotDataMgr::GetDefaultFactionForBotRace(uint8 bot_race) +{ + ChrRacesEntry const* rentry = sChrRacesStore.LookupEntry(bot_race); + return rentry ? rentry->FactionID : FACTION_TEMPLATE_NEUTRAL_HOSTILE; +} + TeamId BotDataMgr::GetTeamIdForFaction(uint32 factionTemplateId) { if (FactionTemplateEntry const* fte = sFactionTemplateStore.LookupEntry(factionTemplateId)) diff --git a/src/server/game/AI/NpcBots/botdatamgr.h b/src/server/game/AI/NpcBots/botdatamgr.h index 4a2e942330877..eb9ab68cf0b35 100644 --- a/src/server/game/AI/NpcBots/botdatamgr.h +++ b/src/server/game/AI/NpcBots/botdatamgr.h @@ -260,6 +260,7 @@ class BotDataMgr static uint8 GetMaxLevelForMapId(uint32 mapId); static uint8 GetMinLevelForBotClass(uint8 m_class); static int32 GetBotBaseReputation(Creature const* bot, FactionEntry const* factionEntry); + static uint32 GetDefaultFactionForBotRace(uint8 bot_race); static TeamId GetTeamIdForFaction(uint32 factionTemplateId); static uint32 GetTeamForFaction(uint32 factionTemplateId); diff --git a/src/server/game/AI/NpcBots/bpet_ai.cpp b/src/server/game/AI/NpcBots/bpet_ai.cpp index fd63713d2c44c..4619eb09cb24b 100644 --- a/src/server/game/AI/NpcBots/bpet_ai.cpp +++ b/src/server/game/AI/NpcBots/bpet_ai.cpp @@ -1415,7 +1415,7 @@ bool bot_pet_ai::IsInBotParty(Unit const* unit) const if (IAmFree()) { - if (me->GetFaction() == 14 || unit->GetFaction() == 14) + if (me->GetFaction() == FACTION_TEMPLATE_NEUTRAL_HOSTILE || unit->GetFaction() == FACTION_TEMPLATE_NEUTRAL_HOSTILE) return false; if (me->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP) || diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index d54a74bb549e2..1d7578e292432 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -12580,6 +12580,8 @@ bool Unit::IsInPartyWith(Unit const* unit) const return (pla->GetGroup() && pla->GetGroup() == bot->GetBotGroup()) ? pla->GetSubGroup() == bot->GetSubGroup() : !!pla->GetBotMgr()->GetBot(bot->GetGUID()); if (u1->IsNPCBot() && u2->IsNPCBot() && u1->ToCreature()->GetBotGroup() && u1->ToCreature()->GetBotGroup() == u2->ToCreature()->GetBotGroup()) return u1->ToCreature()->GetSubGroup() == u2->ToCreature()->GetSubGroup(); + if (u1->IsNPCBot() && u2->IsNPCBot() && u1->IsFFAPvP() && u2->IsFFAPvP()) + return false; //end npcbot return u1->GetTypeId() == TYPEID_UNIT && u2->GetTypeId() == TYPEID_UNIT && u1->GetFaction() == u2->GetFaction(); @@ -12607,6 +12609,8 @@ bool Unit::IsInRaidWith(Unit const* unit) const return (pla->GetGroup() && pla->GetGroup() == bot->GetBotGroup()) ? true : !!pla->GetBotMgr()->GetBot(bot->GetGUID()); if (u1->IsNPCBot() && u2->IsNPCBot() && u1->ToCreature()->GetBotGroup()) return u1->ToCreature()->GetBotGroup() == u2->ToCreature()->GetBotGroup(); + if (u1->IsNPCBot() && u2->IsNPCBot() && u1->IsFFAPvP() && u2->IsFFAPvP()) + return false; //end npcbot return u1->GetTypeId() == TYPEID_UNIT && u2->GetTypeId() == TYPEID_UNIT && u1->GetFaction() == u2->GetFaction();