mirror of
https://github.com/liyunfan1223/mod-playerbots.git
synced 2026-06-21 07:59:25 +02:00
### Summary This PR restores the Naxxramas raid strategies that were removed in commit 686fe513b25bbb20ccfcc89f08ee8c4b498a263e . The reintroduced logic is core‑friendly (no AzerothCore script headers or internal boss AI/EventMap dependencies), and the Naxxramas actions have been refactored into per‑boss files for better maintainability. ### Motivation The previous removal was meant to avoid core modifications and unblock upstreaming. This PR brings the strategies back while adhering to that requirement, using only observable state and mod‑playerbots helpers. ### What’s included - Re‑enabled the Naxxramas strategies previously removed. - Replaced core script header dependencies with observable checks (auras, casts, unit flags, flight state, etc.). - Split the Naxxramas action logic into per‑boss source files to avoid a “god file” and ease future maintenance. - Minor, non‑intrusive behavior improvements aligned with existing helpers. ### Future work Some strategies may still require refinement or more advanced handling later. This PR focuses on restoring the baseline logic without core dependencies, while keeping changes minimal and safe. **Any contributions are welcome to further improve and fine‑tune the Naxxramas strategies.** ### Testing Tested in some Naxx boxx. No server crash and boss killed :D Note: I'll make another PR with revised scripts when this one are merged --------- Co-authored-by: Keleborn <22352763+Celandriel@users.noreply.github.com> Co-authored-by: bash <hermensb@gmail.com> Co-authored-by: Revision <tkn963@gmail.com> Co-authored-by: kadeshar <kadeshar@gmail.com>
266 lines
7.5 KiB
C++
266 lines
7.5 KiB
C++
/*
|
|
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
|
|
* and/or modify it under version 3 of the License, or (at your option), any later version.
|
|
*/
|
|
|
|
#include "ChatShortcutActions.h"
|
|
|
|
#include "Event.h"
|
|
#include "Formations.h"
|
|
#include "Playerbots.h"
|
|
#include "PositionValue.h"
|
|
|
|
void PositionsResetAction::ResetReturnPosition()
|
|
{
|
|
PositionMap& posMap = context->GetValue<PositionMap&>("position")->Get();
|
|
PositionInfo pos = posMap["return"];
|
|
pos.Reset();
|
|
posMap["return"] = pos;
|
|
}
|
|
|
|
void PositionsResetAction::SetReturnPosition(float x, float y, float z)
|
|
{
|
|
PositionMap& posMap = context->GetValue<PositionMap&>("position")->Get();
|
|
PositionInfo pos = posMap["return"];
|
|
pos.Set(x, y, z, botAI->GetBot()->GetMapId());
|
|
posMap["return"] = pos;
|
|
}
|
|
|
|
void PositionsResetAction::ResetStayPosition()
|
|
{
|
|
PositionMap& posMap = context->GetValue<PositionMap&>("position")->Get();
|
|
PositionInfo pos = posMap["stay"];
|
|
pos.Reset();
|
|
posMap["stay"] = pos;
|
|
}
|
|
|
|
void PositionsResetAction::SetStayPosition(float x, float y, float z)
|
|
{
|
|
PositionMap& posMap = context->GetValue<PositionMap&>("position")->Get();
|
|
PositionInfo pos = posMap["stay"];
|
|
pos.Set(x, y, z, botAI->GetBot()->GetMapId());
|
|
posMap["stay"] = pos;
|
|
}
|
|
|
|
bool FollowChatShortcutAction::Execute(Event /*event*/)
|
|
{
|
|
Player* master = GetMaster();
|
|
if (!master)
|
|
return false;
|
|
|
|
// botAI->Reset();
|
|
botAI->ChangeStrategy("+follow,-passive,-grind,-move from group", BOT_STATE_NON_COMBAT);
|
|
botAI->ChangeStrategy("-stay,-follow,-passive,-grind,-move from group", BOT_STATE_COMBAT);
|
|
botAI->GetAiObjectContext()->GetValue<GuidVector>("prioritized targets")->Reset();
|
|
|
|
PositionMap& posMap = context->GetValue<PositionMap&>("position")->Get();
|
|
PositionInfo pos = posMap["return"];
|
|
pos.Reset();
|
|
posMap["return"] = pos;
|
|
|
|
pos = posMap["stay"];
|
|
pos.Reset();
|
|
posMap["stay"] = pos;
|
|
|
|
if (bot->IsInCombat())
|
|
{
|
|
Formation* formation = AI_VALUE(Formation*, "formation");
|
|
std::string const target = formation->GetTargetName();
|
|
bool moved = false;
|
|
if (!target.empty())
|
|
moved = Follow(AI_VALUE(Unit*, target));
|
|
else
|
|
{
|
|
WorldLocation loc = formation->GetLocation();
|
|
if (Formation::IsNullLocation(loc) || loc.GetMapId() == -1)
|
|
return false;
|
|
|
|
MovementPriority priority = botAI->GetState() == BOT_STATE_COMBAT ? MovementPriority::MOVEMENT_COMBAT : MovementPriority::MOVEMENT_NORMAL;
|
|
moved = MoveTo(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ(), false, false, false,
|
|
true, priority);
|
|
}
|
|
|
|
if (Pet* pet = bot->GetPet())
|
|
botAI->PetFollow();
|
|
|
|
if (moved)
|
|
{
|
|
botAI->TellMaster("Following");
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/* Default mechanics takes care of this now.
|
|
if (bot->GetMapId() != master->GetMapId() || (master && bot->GetDistance(master) >
|
|
sPlayerbotAIConfig.sightDistance))
|
|
{
|
|
if (bot->isDead())
|
|
{
|
|
bot->ResurrectPlayer(1.0f, false);
|
|
botAI->TellMasterNoFacing("Back from the grave!");
|
|
}
|
|
else
|
|
botAI->TellMaster("You are too far away from me! I will there soon.");
|
|
|
|
bot->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TELEPORTED | AURA_INTERRUPT_FLAG_CHANGE_MAP);
|
|
bot->TeleportTo(master->GetMapId(), master->GetPositionX(), master->GetPositionY(), master->GetPositionZ(),
|
|
master->GetOrientation()); return true;
|
|
}
|
|
*/
|
|
|
|
botAI->TellMaster("Following");
|
|
return true;
|
|
}
|
|
|
|
bool StayChatShortcutAction::Execute(Event /*event*/)
|
|
{
|
|
Player* master = GetMaster();
|
|
if (!master)
|
|
return false;
|
|
|
|
botAI->Reset();
|
|
botAI->ChangeStrategy("+stay,-passive,-move from group", BOT_STATE_NON_COMBAT);
|
|
botAI->ChangeStrategy("+stay,-follow,-passive,-move from group", BOT_STATE_COMBAT);
|
|
|
|
SetReturnPosition(bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ());
|
|
SetStayPosition(bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ());
|
|
|
|
botAI->TellMaster("Staying");
|
|
return true;
|
|
}
|
|
|
|
bool MoveFromGroupChatShortcutAction::Execute(Event /*event*/)
|
|
{
|
|
Player* master = GetMaster();
|
|
if (!master)
|
|
return false;
|
|
|
|
// dont need to remove stay or follow, move from group takes priority over both
|
|
// (see their isUseful() methods)
|
|
botAI->ChangeStrategy("+move from group", BOT_STATE_NON_COMBAT);
|
|
botAI->ChangeStrategy("+move from group", BOT_STATE_COMBAT);
|
|
|
|
botAI->TellMaster("Moving away from group");
|
|
return true;
|
|
}
|
|
|
|
bool FleeChatShortcutAction::Execute(Event /*event*/)
|
|
{
|
|
Player* master = GetMaster();
|
|
if (!master)
|
|
return false;
|
|
|
|
botAI->Reset();
|
|
botAI->ChangeStrategy("+follow,-stay,+passive", BOT_STATE_NON_COMBAT);
|
|
botAI->ChangeStrategy("+follow,-stay,+passive", BOT_STATE_COMBAT);
|
|
|
|
ResetReturnPosition();
|
|
ResetStayPosition();
|
|
|
|
if (bot->GetMapId() != master->GetMapId() || bot->GetDistance(master) > sPlayerbotAIConfig.sightDistance)
|
|
{
|
|
botAI->TellError("I will not flee with you - too far away");
|
|
return true;
|
|
}
|
|
|
|
botAI->TellMaster("Fleeing");
|
|
return true;
|
|
}
|
|
|
|
bool GoawayChatShortcutAction::Execute(Event /*event*/)
|
|
{
|
|
Player* master = GetMaster();
|
|
if (!master)
|
|
return false;
|
|
|
|
botAI->Reset();
|
|
botAI->ChangeStrategy("+runaway,-stay", BOT_STATE_NON_COMBAT);
|
|
botAI->ChangeStrategy("+runaway,-stay", BOT_STATE_COMBAT);
|
|
|
|
ResetReturnPosition();
|
|
ResetStayPosition();
|
|
|
|
botAI->TellMaster("Running away");
|
|
return true;
|
|
}
|
|
|
|
bool GrindChatShortcutAction::Execute(Event /*event*/)
|
|
{
|
|
Player* master = GetMaster();
|
|
if (!master)
|
|
return false;
|
|
|
|
botAI->Reset();
|
|
botAI->ChangeStrategy("+grind,-passive,-stay", BOT_STATE_NON_COMBAT);
|
|
|
|
ResetReturnPosition();
|
|
ResetStayPosition();
|
|
|
|
botAI->TellMaster("Grinding");
|
|
return true;
|
|
}
|
|
|
|
bool TankAttackChatShortcutAction::Execute(Event /*event*/)
|
|
{
|
|
Player* master = GetMaster();
|
|
if (!master)
|
|
return false;
|
|
|
|
if (!botAI->IsTank(bot))
|
|
return false;
|
|
|
|
botAI->Reset();
|
|
botAI->ChangeStrategy("-passive", BOT_STATE_NON_COMBAT);
|
|
botAI->ChangeStrategy("-passive", BOT_STATE_COMBAT);
|
|
|
|
ResetReturnPosition();
|
|
ResetStayPosition();
|
|
|
|
botAI->TellMaster("Attacking");
|
|
return true;
|
|
}
|
|
|
|
bool MaxDpsChatShortcutAction::Execute(Event /*event*/)
|
|
{
|
|
Player* master = GetMaster();
|
|
if (!master)
|
|
return false;
|
|
|
|
if (!botAI->ContainsStrategy(STRATEGY_TYPE_DPS))
|
|
return false;
|
|
|
|
botAI->Reset();
|
|
|
|
botAI->ChangeStrategy("-threat,-conserve mana,-cast time,+dps debuff,+boost", BOT_STATE_COMBAT);
|
|
botAI->TellMaster("Max DPS!");
|
|
|
|
return true;
|
|
}
|
|
|
|
bool NaxxChatShortcutAction::Execute(Event /*event*/)
|
|
{
|
|
Player* master = GetMaster();
|
|
if (!master)
|
|
return false;
|
|
|
|
botAI->Reset();
|
|
botAI->ChangeStrategy("+naxx", BOT_STATE_NON_COMBAT);
|
|
botAI->ChangeStrategy("+naxx", BOT_STATE_COMBAT);
|
|
botAI->TellMasterNoFacing("Add Naxx Strategies!");
|
|
// bot->Say("Add Naxx Strategies!", LANG_UNIVERSAL);
|
|
return true;
|
|
}
|
|
|
|
bool BwlChatShortcutAction::Execute(Event /*event*/)
|
|
{
|
|
Player* master = GetMaster();
|
|
if (!master)
|
|
return false;
|
|
|
|
botAI->Reset();
|
|
botAI->ChangeStrategy("+bwl", BOT_STATE_NON_COMBAT);
|
|
botAI->ChangeStrategy("+bwl", BOT_STATE_COMBAT);
|
|
botAI->TellMasterNoFacing("Add Bwl Strategies!");
|
|
return true;
|
|
}
|