mirror of
https://github.com/mod-playerbots/mod-playerbots.git
synced 2026-02-23 12:04:34 +00:00
# Pull Request This change replaces the non‑standard WorldPosition::getX/getY/getZ/getO/getMapId wrappers with the core getters (GetPositionX/Y/Z, GetOrientation, GetMapId) and removes the redundant wrappers. Goal: align the module with AzerothCore conventions, reduce local adapters, and improve long‑term maintainability. --- ## Design Philosophy This is a structural cleanup only (coordinate access) and does not alter any AI behavior or decision logic. It follows the stability/performance-first philosophy and does not add branches or extra runtime work. Before submitting: yes, this change aligns with the principles of stability, performance, and predictability. Principles: - **Stability before intelligence** A stable system is always preferred over a smarter one. - **Performance is a shared resource** Any increase in bot cost affects all players and all bots. - **Simple logic scales better than smart logic** Predictable behavior under load is more valuable than perfect decisions. - **Complexity must justify itself** If a feature cannot clearly explain its cost, it should not exist. - **Defaults must be cheap** Expensive behavior must always be optional and clearly communicated. - **Bots should look reasonable, not perfect** The goal is believable behavior, not human simulation. Before submitting, confirm that this change aligns with those principles. --- ## Feature Evaluation Please answer the following: - Minimum logic required: use core getters (GetPositionX/Y/Z, GetMapId, GetOrientation) wherever coordinates are needed. - Cheapest implementation: direct call replacement and removal of redundant wrappers. - Runtime cost: negligible (same data access, no additional logic). --- ## How to Test the Changes - No functional testing required (behavior‑neutral refactor). - Recommended: compile the module and run a normal server startup as validation. ## Complexity & Impact Does this change add new decision branches? - - [x] No - - [x] Yes (**explain below**) Does this change increase per-bot or per-tick processing? - - [x] No - - [ ] Yes (**describe and justify impact**) Could this logic scale poorly under load? - - [x] No - - [ ] Yes (**explain why**) --- ## Defaults & Configuration Does this change modify default bot behavior? - - [x] No - - [ ] Yes (**explain why**) If this introduces more advanced or AI-heavy logic: - - [x] Lightweight mode remains the default - - [x] More complex behavior is optional and thereby configurable --- ## AI Assistance Was AI assistance (e.g. ChatGPT or similar tools) used while working on this change? - - [ ] No - - [x] Yes (**explain below**) If yes, please specify: - AI tool or model used: Copilot - Purpose of usage: Translate this PR text from french to English --- ## Final Checklist - - [x] Stability is not compromised - - [x] Performance impact is understood, tested, and acceptable - - [x] Added logic complexity is justified and explained - - [x] Documentation updated if needed --- ## Notes for Reviewers This is a core-friendly cleanup only, with no behavioral change. No additional logic or CPU cost is introduced.
158 lines
4.8 KiB
C++
158 lines
4.8 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 "RtscAction.h"
|
|
|
|
#include "Playerbots.h"
|
|
#include "RTSCValues.h"
|
|
|
|
bool RTSCAction::Execute(Event event)
|
|
{
|
|
std::string const command = event.getParam();
|
|
|
|
Player* master = botAI->GetMaster();
|
|
|
|
if (!master)
|
|
return false;
|
|
|
|
if (command != "reset" && !master->HasSpell(RTSC_MOVE_SPELL))
|
|
{
|
|
master->learnSpell(RTSC_MOVE_SPELL, false);
|
|
botAI->TellMasterNoFacing("RTS control enabled.");
|
|
botAI->TellMasterNoFacing("Aedm (Awesome energetic do move) spell trained.");
|
|
}
|
|
else if (command == "reset")
|
|
{
|
|
if (master->HasSpell(RTSC_MOVE_SPELL))
|
|
{
|
|
master->removeSpell(RTSC_MOVE_SPELL, SPEC_MASK_ALL, false);
|
|
botAI->TellMasterNoFacing("RTS control spell removed.");
|
|
}
|
|
|
|
RESET_AI_VALUE(bool, "RTSC selected");
|
|
RESET_AI_VALUE(std::string, "RTSC next spell action");
|
|
|
|
for (auto value : botAI->GetAiObjectContext()->GetValues())
|
|
if (value.find("RTSC saved location::") != std::string::npos)
|
|
RESET_AI_VALUE(WorldPosition, value.c_str());
|
|
|
|
return true;
|
|
}
|
|
|
|
bool selected = AI_VALUE(bool, "RTSC selected");
|
|
|
|
if (command == "select" && !selected)
|
|
{
|
|
SET_AI_VALUE(bool, "RTSC selected", true);
|
|
master->SendPlaySpellVisual(bot->GetGUID(), 5036);
|
|
return true;
|
|
}
|
|
else if (command == "cancel")
|
|
{
|
|
RESET_AI_VALUE(bool, "RTSC selected");
|
|
RESET_AI_VALUE(std::string, "RTSC next spell action");
|
|
if (selected)
|
|
master->SendPlaySpellVisual(bot->GetGUID(), 6372);
|
|
return true;
|
|
}
|
|
else if (command == "toggle")
|
|
{
|
|
if (!selected)
|
|
{
|
|
SET_AI_VALUE(bool, "RTSC selected", true);
|
|
master->SendPlaySpellVisual(bot->GetGUID(), 5036);
|
|
}
|
|
else
|
|
{
|
|
SET_AI_VALUE(bool, "RTSC selected", false);
|
|
master->SendPlaySpellVisual(bot->GetGUID(), 6372);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
else if (command.find("save here ") != std::string::npos)
|
|
{
|
|
std::string const locationName = command.substr(10);
|
|
|
|
WorldPosition spellPosition(bot);
|
|
SET_AI_VALUE2(WorldPosition, "RTSC saved location", locationName, spellPosition);
|
|
|
|
Creature* wpCreature =
|
|
bot->SummonCreature(15631, spellPosition.GetPositionX(), spellPosition.GetPositionY(),
|
|
spellPosition.GetPositionZ(), spellPosition.GetOrientation(), TEMPSUMMON_TIMED_DESPAWN,
|
|
2000.0f);
|
|
wpCreature->SetObjectScale(0.5f);
|
|
|
|
return true;
|
|
}
|
|
else if (command.find("unsave ") != std::string::npos)
|
|
{
|
|
std::string const locationName = command.substr(7);
|
|
|
|
RESET_AI_VALUE2(WorldPosition, "RTSC saved location", locationName);
|
|
|
|
return true;
|
|
}
|
|
|
|
if (command.find("save ") != std::string::npos || command == "move")
|
|
{
|
|
SET_AI_VALUE(std::string, "RTSC next spell action", command);
|
|
|
|
return true;
|
|
}
|
|
|
|
if (command.find("show ") != std::string::npos)
|
|
{
|
|
std::string const locationName = command.substr(5);
|
|
WorldPosition spellPosition = AI_VALUE2(WorldPosition, "RTSC saved location", locationName);
|
|
|
|
if (spellPosition)
|
|
{
|
|
Creature* wpCreature =
|
|
bot->SummonCreature(15631, spellPosition.GetPositionX(), spellPosition.GetPositionY(),
|
|
spellPosition.GetPositionZ(), spellPosition.GetOrientation(),
|
|
TEMPSUMMON_TIMED_DESPAWN, 2000.0f);
|
|
wpCreature->SetObjectScale(0.5f);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
if (command.find("show") != std::string::npos)
|
|
{
|
|
std::ostringstream out;
|
|
out << "saved: ";
|
|
|
|
for (auto value : botAI->GetAiObjectContext()->GetValues())
|
|
if (value.find("RTSC saved location::") != std::string::npos)
|
|
if (AI_VALUE2(WorldPosition, "RTSC saved location", value.substr(21).c_str()))
|
|
out << value.substr(21).c_str() << ",";
|
|
|
|
out.seekp(-1, out.cur);
|
|
out << ".";
|
|
|
|
botAI->TellMasterNoFacing(out);
|
|
}
|
|
|
|
if (command.find("go ") != std::string::npos)
|
|
{
|
|
std::string const locationName = command.substr(3);
|
|
WorldPosition spellPosition = AI_VALUE2(WorldPosition, "RTSC saved location", locationName);
|
|
|
|
if (spellPosition)
|
|
return MoveToSpell(spellPosition, false);
|
|
|
|
return true;
|
|
}
|
|
else if (command == "last")
|
|
{
|
|
WorldPosition spellPosition = AI_VALUE(WorldPosition, "see spell location");
|
|
if (spellPosition)
|
|
return MoveToSpell(spellPosition);
|
|
}
|
|
|
|
return false;
|
|
}
|