[FIX] Finalized structure! (do not start fixing PR merge structure conflict till this is merged) (#2025)

Finalized
This commit is contained in:
bashermens
2026-01-17 14:38:12 +01:00
committed by GitHub
parent a1137dbddc
commit aeaaee15da
1120 changed files with 27 additions and 27 deletions

View File

@@ -0,0 +1,116 @@
/*
* 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 "CustomStrategy.h"
#include <regex>
#include <stdexcept>
#include "Playerbots.h"
std::map<std::string, std::string> CustomStrategy::actionLinesCache;
NextAction toNextAction(std::string const action)
{
std::vector<std::string> tokens = split(action, '!');
if (tokens[0].empty())
throw std::invalid_argument("Invalid action");
if (tokens.size() == 2)
return NextAction(tokens[0], atof(tokens[1].c_str()));
if (tokens.size() == 1)
return NextAction(tokens[0], ACTION_NORMAL);
LOG_ERROR("playerbots", "Invalid action {}", action.c_str());
throw std::invalid_argument("Invalid action");
}
std::vector<NextAction> toNextActionArray(const std::string actions)
{
const std::vector<std::string> tokens = split(actions, ',');
std::vector<NextAction> res = {};
for (const std::string token : tokens)
{
res.push_back(toNextAction(token));
}
return res;
}
TriggerNode* toTriggerNode(std::string const actionLine)
{
std::vector<std::string> tokens = split(actionLine, '>');
if (tokens.size() == 2)
return new TriggerNode(tokens[0], toNextActionArray(tokens[1]));
LOG_ERROR("playerbots", "Invalid action line {}", actionLine.c_str());
return nullptr;
}
CustomStrategy::CustomStrategy(PlayerbotAI* botAI) : Strategy(botAI), Qualified() {}
void CustomStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{
if (actionLines.empty())
{
if (actionLinesCache[qualifier].empty())
{
LoadActionLines((uint32)botAI->GetBot()->GetGUID().GetCounter());
if (actionLines.empty())
LoadActionLines(0);
}
else
{
std::vector<std::string> tokens = split(actionLinesCache[qualifier], '\n');
std::regex tpl("\\(nullptr,\\s*'.+',\\s*'(.+)'\\)(,|;)");
for (std::vector<std::string>::iterator i = tokens.begin(); i != tokens.end(); ++i)
{
std::string const line = *i;
for (std::sregex_iterator j = std::sregex_iterator(line.begin(), line.end(), tpl);
j != std::sregex_iterator(); ++j)
{
std::smatch match = *j;
std::string const actionLine = match[1].str();
if (!actionLine.empty())
actionLines.push_back(actionLine);
}
}
}
}
for (std::vector<std::string>::iterator i = actionLines.begin(); i != actionLines.end(); ++i)
{
if (TriggerNode* tn = toTriggerNode(*i))
triggers.push_back(tn);
}
}
void CustomStrategy::LoadActionLines(uint32 owner)
{
PlayerbotsDatabasePreparedStatement* stmt =
PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_CUSTOM_STRATEGY_BY_OWNER_AND_NAME);
stmt->SetData(0, owner);
stmt->SetData(1, qualifier);
PreparedQueryResult result = PlayerbotsDatabase.Query(stmt);
if (result)
{
do
{
Field* fields = result->Fetch();
std::string const action = fields[1].Get<std::string>();
actionLines.push_back(action);
} while (result->NextRow());
}
}
void CustomStrategy::Reset()
{
actionLines.clear();
actionLinesCache[qualifier].clear();
}

View File

@@ -0,0 +1,31 @@
/*
* 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_CUSTOMSTRATEGY_H
#define _PLAYERBOT_CUSTOMSTRATEGY_H
#include <map>
#include "Strategy.h"
class PlayerbotAI;
class CustomStrategy : public Strategy, public Qualified
{
public:
CustomStrategy(PlayerbotAI* botAI);
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
std::string const getName() override { return std::string("custom::" + qualifier); }
void Reset();
static std::map<std::string, std::string> actionLinesCache;
private:
std::vector<std::string> actionLines;
void LoadActionLines(uint32 owner);
};
#endif

View File

@@ -0,0 +1,145 @@
/*
* 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 "Strategy.h"
#include "Playerbots.h"
class ActionNodeFactoryInternal : public NamedObjectFactory<ActionNode>
{
public:
ActionNodeFactoryInternal()
{
creators["melee"] = &melee;
creators["healthstone"] = &healthstone;
creators["be near"] = &follow_master_random;
creators["attack anything"] = &attack_anything;
creators["move random"] = &move_random;
creators["move to loot"] = &move_to_loot;
creators["food"] = &food;
creators["drink"] = &drink;
creators["mana potion"] = &mana_potion;
creators["healing potion"] = &healing_potion;
creators["flee"] = &flee;
}
private:
static ActionNode* melee([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode(
"melee",
/*P*/ {},
/*A*/ {},
/*C*/ {}
);
}
static ActionNode* healthstone([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode(
"healthstone",
/*P*/ {},
/*A*/ { NextAction("healing potion") },
/*C*/ {}
);
}
static ActionNode* follow_master_random([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode(
"be near",
/*P*/ {},
/*A*/ { NextAction("follow") },
/*C*/ {}
);
}
static ActionNode* attack_anything([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode(
"attack anything",
/*P*/ {},
/*A*/ {},
/*C*/ {}
);
}
static ActionNode* move_random([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode(
"move random",
/*P*/ {},
/*A*/ { NextAction("stay line") },
/*C*/ {}
);
}
static ActionNode* move_to_loot([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode(
"move to loot",
/*P*/ {},
/*A*/ {},
/*C*/ {}
);
}
static ActionNode* food([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode(
"food",
/*P*/ {},
/*A*/ {},
/*C*/ {}
);
}
static ActionNode* drink([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode(
"drink",
/*P*/ {},
/*A*/ {},
/*C*/ {}
);
}
static ActionNode* mana_potion([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode(
"mana potion",
/*P*/ {},
/*A*/ {},
/*C*/ {}
);
}
static ActionNode* healing_potion([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode(
"healing potion",
/*P*/ {},
/*A*/ { NextAction("food") },
/*C*/ {}
);
}
static ActionNode* flee([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode(
"flee",
/*P*/ {},
/*A*/ {},
/*C*/ {}
);
}
};
Strategy::Strategy(PlayerbotAI* botAI) : PlayerbotAIAware(botAI)
{
actionNodeFactories.Add(new ActionNodeFactoryInternal());
}
ActionNode* Strategy::GetAction(std::string const name) { return actionNodeFactories.GetContextObject(name, botAI); }

View File

@@ -0,0 +1,76 @@
/*
* 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_STRATEGY_H
#define _PLAYERBOT_STRATEGY_H
#include "Action.h"
#include "Multiplier.h"
#include "NamedObjectContext.h"
#include "PlayerbotAIAware.h"
#include "Trigger.h"
enum StrategyType : uint32
{
STRATEGY_TYPE_GENERIC = 0,
STRATEGY_TYPE_COMBAT = 1,
STRATEGY_TYPE_NONCOMBAT = 2,
STRATEGY_TYPE_TANK = 4,
STRATEGY_TYPE_DPS = 8,
STRATEGY_TYPE_HEAL = 16,
STRATEGY_TYPE_RANGED = 32,
STRATEGY_TYPE_MELEE = 64
};
// enum ActionPriority
// {
// ACTION_IDLE = 0,
// ACTION_DEFAULT = 5,
// ACTION_NORMAL = 10,
// ACTION_HIGH = 20,
// ACTION_MOVE = 30,
// ACTION_INTERRUPT = 40,
// ACTION_DISPEL = 50,
// ACTION_RAID = 60,
// ACTION_LIGHT_HEAL = 10,
// ACTION_MEDIUM_HEAL = 20,
// ACTION_CRITICAL_HEAL = 30,
// ACTION_EMERGENCY = 90
// };
static float ACTION_IDLE = 0.0f;
static float ACTION_BG = 1.0f;
static float ACTION_DEFAULT = 5.0f;
static float ACTION_NORMAL = 10.0f;
static float ACTION_HIGH = 20.0f;
static float ACTION_MOVE = 30.0f;
static float ACTION_INTERRUPT = 40.0f;
static float ACTION_DISPEL = 50.0f;
static float ACTION_RAID = 60.0f;
static float ACTION_LIGHT_HEAL = 10.0f;
static float ACTION_MEDIUM_HEAL = 20.0f;
static float ACTION_CRITICAL_HEAL = 30.0f;
static float ACTION_EMERGENCY = 90.0f;
class Strategy : public PlayerbotAIAware
{
public:
Strategy(PlayerbotAI* botAI);
virtual ~Strategy() {}
virtual std::vector<NextAction> getDefaultActions() { return {}; }
virtual void InitTriggers([[maybe_unused]] std::vector<TriggerNode*>& triggers) {}
virtual void InitMultipliers([[maybe_unused]] std::vector<Multiplier*>& multipliers) {}
virtual std::string const getName() = 0;
virtual uint32 GetType() const { return STRATEGY_TYPE_GENERIC; }
virtual ActionNode* GetAction(std::string const name);
void Update() {}
void Reset() {}
public:
NamedObjectFactoryList<ActionNode> actionNodeFactories;
};
#endif