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();