mirror of
https://github.com/liyunfan1223/mod-playerbots.git
synced 2026-06-20 23:49:25 +02:00
# Pull Request Feature - Enable multi node flying for bots - Bots currently only do node to node flying. This PR makes it so they can connect multiple noted. -- This is enabled by sending a vector containing the node sequence instead of a single destination node -- To minimize the run-time cost of searching for available nodes and connection, a cache of all possible connections is prepared at start up using a BFS search algorithm. Refactor - Move all world destination logic (cities, banks, inns) to existing Travel manager - Eliminate flightmastercache and integrate to new manager - replace SQLs calls with in-memory data search by core - Add in new map that stores creature areas by template. Clean up - Move other rpg files to related folder. (Next steps) The selection for where bots fly to should be smarter than it is. Instead of trying to determine where a bot can go, it should first decide where it should go, and then identify the correct way to get there. --- ## Feature Evaluation Please answer the following: - Describe the **minimum logic** required to achieve the intended behavior? - Describe the **cheapest implementation** that produces an acceptable result? - Describe the **runtime cost** when this logic executes across many bots? --- ## How to Test the Changes - Step-by-step instructions to test the change - Any required setup (e.g. multiple players, bots, specific configuration) - Expected behavior and how to verify it ## Complexity & Impact Does this change add new decision branches? - - [x[ No - - [ ] 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**) The call itself is fairly infrequent, and although now there are a greater number of paths available for the bots, I dont think it would be significant. ## Defaults & Configuration Does this change modify default bot behavior? - - [ ] No - - [x] Yes (**explain why**) If this introduces more advanced or AI-heavy logic: - - [x] Lightweight mode remains the default - - [ ] 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**) Gemini first suggested the use of a BFS algorithm. This was rewritten by me to actually work as intended. Verification by additional logging not present in final code. Claude code converted the SQL filtering to the atrocious if statements found in PrepareDestinationCache, but after verifying them it works. If there are better ways to do this Im open to it. --- ## 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 Anything that significantly improves realism at the cost of stability or performance should be carefully discussed before merging.
269 lines
6.8 KiB
C++
269 lines
6.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.
|
|
*/
|
|
|
|
#ifndef _PLAYERBOT_RPGSUBACTIONS_H
|
|
#define _PLAYERBOT_RPGSUBACTIONS_H
|
|
|
|
#include "Action.h"
|
|
#include "AiObject.h"
|
|
#include "Item.h"
|
|
|
|
class GuidPosition;
|
|
class ObjectGuid;
|
|
class PlayerbotAI;
|
|
|
|
class RpgHelper : public AiObject
|
|
{
|
|
public:
|
|
RpgHelper(PlayerbotAI* botAI) : AiObject(botAI) {}
|
|
virtual ~RpgHelper() = default;
|
|
void OnExecute(std::string nextAction = "rpg");
|
|
void BeforeExecute();
|
|
void AfterExecute(bool doDelay = true, bool waitForGroup = false);
|
|
|
|
virtual GuidPosition guidP();
|
|
virtual ObjectGuid guid();
|
|
virtual bool InRange();
|
|
|
|
private:
|
|
void setFacingTo(GuidPosition guidPosition);
|
|
void setFacing(GuidPosition guidPosition);
|
|
void setDelay(bool waitForGroup);
|
|
};
|
|
|
|
class RpgEnabled
|
|
{
|
|
public:
|
|
RpgEnabled(PlayerbotAI* botAI) { rpg = std::make_unique<RpgHelper>(botAI); }
|
|
|
|
protected:
|
|
std::unique_ptr<RpgHelper> rpg;
|
|
};
|
|
|
|
class RpgSubAction : public Action, public RpgEnabled
|
|
{
|
|
public:
|
|
RpgSubAction(PlayerbotAI* botAI, std::string const name = "rpg sub") : Action(botAI, name), RpgEnabled(botAI) {}
|
|
|
|
// Long range is possible?
|
|
bool isPossible() override;
|
|
// Short range can we do the action now?
|
|
bool isUseful() override;
|
|
|
|
bool Execute(Event event) override;
|
|
|
|
protected:
|
|
virtual std::string const ActionName();
|
|
virtual Event ActionEvent(Event event);
|
|
};
|
|
|
|
class RpgStayAction : public RpgSubAction
|
|
{
|
|
public:
|
|
RpgStayAction(PlayerbotAI* botAI, std::string const name = "rpg stay") : RpgSubAction(botAI, name) {}
|
|
|
|
bool isUseful() override;
|
|
bool Execute(Event event) override;
|
|
};
|
|
|
|
class RpgWorkAction : public RpgSubAction
|
|
{
|
|
public:
|
|
RpgWorkAction(PlayerbotAI* botAI, std::string const name = "rpg work") : RpgSubAction(botAI, name) {}
|
|
|
|
bool isUseful() override;
|
|
bool Execute(Event event) override;
|
|
};
|
|
|
|
class RpgEmoteAction : public RpgSubAction
|
|
{
|
|
public:
|
|
RpgEmoteAction(PlayerbotAI* botAI, std::string const name = "rpg emote") : RpgSubAction(botAI, name) {}
|
|
|
|
bool isUseful() override;
|
|
bool Execute(Event event) override;
|
|
};
|
|
|
|
class RpgCancelAction : public RpgSubAction
|
|
{
|
|
public:
|
|
RpgCancelAction(PlayerbotAI* botAI, std::string const name = "rpg cancel") : RpgSubAction(botAI, name) {}
|
|
|
|
bool Execute(Event event) override;
|
|
};
|
|
|
|
class RpgTaxiAction : public RpgSubAction
|
|
{
|
|
public:
|
|
RpgTaxiAction(PlayerbotAI* botAI, std::string const name = "rpg taxi") : RpgSubAction(botAI, name) {}
|
|
|
|
bool isUseful() override;
|
|
bool Execute(Event event) override;
|
|
};
|
|
|
|
class RpgDiscoverAction : public RpgTaxiAction
|
|
{
|
|
public:
|
|
RpgDiscoverAction(PlayerbotAI* botAI, std::string const name = "rpg discover") : RpgTaxiAction(botAI, name) {}
|
|
|
|
bool Execute(Event event) override;
|
|
};
|
|
|
|
class RpgStartQuestAction : public RpgSubAction
|
|
{
|
|
public:
|
|
RpgStartQuestAction(PlayerbotAI* botAI, std::string const name = "rpg start quest") : RpgSubAction(botAI, name) {}
|
|
|
|
private:
|
|
std::string const ActionName() override;
|
|
Event ActionEvent(Event event) override;
|
|
};
|
|
|
|
class RpgEndQuestAction : public RpgSubAction
|
|
{
|
|
public:
|
|
RpgEndQuestAction(PlayerbotAI* botAI, std::string const name = "rpg end quest") : RpgSubAction(botAI, name) {}
|
|
|
|
private:
|
|
std::string const ActionName() override;
|
|
Event ActionEvent(Event event) override;
|
|
};
|
|
|
|
class RpgBuyAction : public RpgSubAction
|
|
{
|
|
public:
|
|
RpgBuyAction(PlayerbotAI* botAI, std::string const name = "rpg buy") : RpgSubAction(botAI, name) {}
|
|
|
|
private:
|
|
std::string const ActionName() override;
|
|
Event ActionEvent(Event event) override;
|
|
};
|
|
|
|
class RpgSellAction : public RpgSubAction
|
|
{
|
|
public:
|
|
RpgSellAction(PlayerbotAI* botAI, std::string const name = "rpg sell") : RpgSubAction(botAI, name) {}
|
|
|
|
private:
|
|
std::string const ActionName() override;
|
|
Event ActionEvent(Event event) override;
|
|
};
|
|
|
|
class RpgRepairAction : public RpgSubAction
|
|
{
|
|
public:
|
|
RpgRepairAction(PlayerbotAI* botAI, std::string const name = "rpg repair") : RpgSubAction(botAI, name) {}
|
|
|
|
private:
|
|
std::string const ActionName() override;
|
|
};
|
|
|
|
class RpgTrainAction : public RpgSubAction
|
|
{
|
|
public:
|
|
RpgTrainAction(PlayerbotAI* botAI, std::string const name = "rpg train") : RpgSubAction(botAI, name) {}
|
|
|
|
bool isPossible() override;
|
|
bool isUseful() override;
|
|
|
|
private:
|
|
std::string const ActionName() override;
|
|
};
|
|
|
|
class RpgHealAction : public RpgSubAction
|
|
{
|
|
public:
|
|
RpgHealAction(PlayerbotAI* botAI, std::string const name = "rpg heal") : RpgSubAction(botAI, name) {}
|
|
|
|
bool Execute(Event event) override;
|
|
};
|
|
|
|
class RpgHomeBindAction : public RpgSubAction
|
|
{
|
|
public:
|
|
RpgHomeBindAction(PlayerbotAI* botAI, std::string const name = "rpg home bind") : RpgSubAction(botAI, name) {}
|
|
|
|
private:
|
|
std::string const ActionName() override;
|
|
};
|
|
|
|
class RpgQueueBgAction : public RpgSubAction
|
|
{
|
|
public:
|
|
RpgQueueBgAction(PlayerbotAI* botAI, std::string const name = "rpg queue bg") : RpgSubAction(botAI, name) {}
|
|
|
|
private:
|
|
std::string const ActionName() override;
|
|
};
|
|
|
|
class RpgBuyPetitionAction : public RpgSubAction
|
|
{
|
|
public:
|
|
RpgBuyPetitionAction(PlayerbotAI* botAI, std::string const name = "rpg buy petition") : RpgSubAction(botAI, name) {}
|
|
|
|
private:
|
|
std::string const ActionName() override;
|
|
};
|
|
|
|
class RpgUseAction : public RpgSubAction
|
|
{
|
|
public:
|
|
RpgUseAction(PlayerbotAI* botAI, std::string const name = "rpg use") : RpgSubAction(botAI, name) {}
|
|
|
|
private:
|
|
std::string const ActionName() override;
|
|
Event ActionEvent(Event event) override;
|
|
};
|
|
|
|
class RpgSpellAction : public RpgSubAction
|
|
{
|
|
public:
|
|
RpgSpellAction(PlayerbotAI* botAI, std::string const name = "rpg spell") : RpgSubAction(botAI, name) {}
|
|
|
|
private:
|
|
std::string const ActionName() override;
|
|
Event ActionEvent(Event event) override;
|
|
};
|
|
|
|
class RpgCraftAction : public RpgSubAction
|
|
{
|
|
public:
|
|
RpgCraftAction(PlayerbotAI* botAI, std::string const name = "rpg craft") : RpgSubAction(botAI, name) {}
|
|
|
|
private:
|
|
std::string const ActionName() override;
|
|
Event ActionEvent(Event event) override;
|
|
};
|
|
|
|
class RpgTradeUsefulAction : public RpgSubAction
|
|
{
|
|
public:
|
|
RpgTradeUsefulAction(PlayerbotAI* botAI, std::string const name = "rpg trade useful") : RpgSubAction(botAI, name) {}
|
|
|
|
std::vector<Item*> CanGiveItems(GuidPosition guidPosition);
|
|
|
|
bool Execute(Event event) override;
|
|
};
|
|
|
|
class RpgDuelAction : public RpgSubAction
|
|
{
|
|
public:
|
|
RpgDuelAction(PlayerbotAI* botAI, std::string const name = "rpg duel") : RpgSubAction(botAI, name) {}
|
|
|
|
bool isUseful() override;
|
|
bool Execute(Event event) override;
|
|
};
|
|
|
|
class RpgMountAnimAction : public RpgSubAction
|
|
{
|
|
public:
|
|
RpgMountAnimAction(PlayerbotAI* botAI, std::string const name = "rpg mount anim") : RpgSubAction(botAI, name) {}
|
|
|
|
bool isUseful() override;
|
|
bool Execute(Event event) override;
|
|
};
|
|
|
|
#endif
|