NextAction refactoring to eliminate sentinel arrays and pointers (#1923)

<!--
> [!WARNING]
> **This is a DRAFT PR.**
> The structure is not definitive. The code might not be optimised yet.
It might not even start nor compile yet.
> **Don't panic.  It's going to be ok. 👌 We can make modifications, we
can fix things.** 😁
-->
# Description

This PR aims to refactor the NextAction declaration to achieve two
goals:

## Eliminate C-style sentinel arrays

Currently, a double pointer (`NextAction**`) approach is being used.
This an old pre-C++11 (< 2011) trick before `std::vector<>` became a
thing.
This approach is painful for developers because they constantly need to
declare their `NextAction` arrays as:
```cpp
NextAction::array(0, new NextAction("foo", 1.0f), nullptr)
```
Instead of:
```cpp
{ new NextAction("foo", 1.0f) }
```
The first argument of `NextAction::array` is actually a hack. It is used
to have a named argument so `va_args` can find the remaining arguments.
It is set to 0 everywhere but in fact does nothing. This is very
confusing to people unfamiliar with this antiquated syntax.
The last argument `nullptr` is what we call a sentinel. It's a `nullptr`
because `va_args` is looking for a `nullptr` to stop iterating. It's
also a hack and also leads to confusion.

## Eliminate unnecessary pointers for `NextAction`

Pointers can be used for several reasons, to cite a few:
- Indicate strong, absolute identity.
- Provide strong but transferable ownership (unlike references).
- When a null value is acceptable (`nullptr`).
- When copy is expensive.

`NextAction` meets none of these criteria:
- It has no identity because it is purely behavioural.
- It is never owned by anything as it is passed around and never fetched
from a registry.
- The only situations where it can be `nullptr` are errors that should
in fact throw an `std::invalid_argument` instead.
- They are extremely small objects that embark a single `std::string`
and a single `float`.

Pointers should be avoided when not strictly necessary because they can
quickly lead to undefined behaviour due to unhandled `nullptr`
situations. They also make the syntax heavier due to the necessity to
constantly check for `nullptr`. Finally, they aren't even good for
performance in that situation because shifting a pointer so many times
is likely more expensive than copying such a trivial object.

# End goal

The end goal is to declare `NextAction` arrays this way:
```cpp
{ NextAction("foo", 1.0f) }
```

> [!NOTE]
> Additional note: `NextAction` is nothing but a hacky proxy to an
`Action` constructor. This should eventually be reworked to use handles
instead of strings. This would make copying `NextAction` even cheaper
and remove the need for the extremely heavy stringly typed current
approach. Stringly typed entities are a known anti-pattern so we need to
move on from those.
This commit is contained in:
Nicolas Lebacq
2026-01-06 11:37:39 +00:00
committed by GitHub
parent b13fb7d12a
commit c9cc4324d3
197 changed files with 6795 additions and 4054 deletions

View File

@@ -3409,13 +3409,14 @@ void TravelMgr::LoadQuestTravelTable()
{ {
Strategy* strat = con->GetStrategy(stratName); Strategy* strat = con->GetStrategy(stratName);
if (strat->getDefaultActions()) const std::vector<NextAction> defaultActions = strat->getDefaultActions();
for (uint32 i = 0; i < NextAction::size(strat->getDefaultActions()); i++)
{
NextAction* nextAction = strat->getDefaultActions()[i];
if (defaultActions.size() > 0)
{
for (NextAction nextAction : defaultActions)
{
std::ostringstream aout; std::ostringstream aout;
aout << nextAction->getRelevance() << "," << nextAction->getName() aout << nextAction.getRelevance() << "," << nextAction.getName()
<< ",,S:" << stratName; << ",,S:" << stratName;
if (actions.find(aout.str().c_str()) != actions.end()) if (actions.find(aout.str().c_str()) != actions.end())
@@ -3427,27 +3428,24 @@ void TravelMgr::LoadQuestTravelTable()
actions.insert_or_assign(aout.str().c_str(), classSpecLevel); actions.insert_or_assign(aout.str().c_str(), classSpecLevel);
} }
}
std::vector<TriggerNode*> triggers; std::vector<TriggerNode*> triggers;
strat->InitTriggers(triggers); strat->InitTriggers(triggers);
for (auto& triggerNode : triggers)
{
// out << " TN:" << triggerNode->getName();
for (TriggerNode*& triggerNode : triggers)
{
if (Trigger* trigger = con->GetTrigger(triggerNode->getName())) if (Trigger* trigger = con->GetTrigger(triggerNode->getName()))
{ {
triggerNode->setTrigger(trigger); triggerNode->setTrigger(trigger);
NextAction** nextActions = triggerNode->getHandlers(); std::vector<NextAction> nextActions = triggerNode->getHandlers();
for (uint32 i = 0; i < NextAction::size(nextActions); i++) // for (uint32_t i = 0; i < nextActions.size(); ++i)
for (NextAction nextAction : nextActions)
{ {
NextAction* nextAction = nextActions[i];
// out << " A:" << nextAction->getName() << "(" <<
// nextAction->getRelevance() << ")";
std::ostringstream aout; std::ostringstream aout;
aout << nextAction->getRelevance() << "," << nextAction->getName() aout << nextAction.getRelevance() << "," << nextAction.getName()
<< "," << triggerNode->getName() << "," << stratName; << "," << triggerNode->getName() << "," << stratName;
if (actions.find(aout.str().c_str()) != actions.end()) if (actions.find(aout.str().c_str()) != actions.end())

View File

@@ -8,90 +8,6 @@
#include "Playerbots.h" #include "Playerbots.h"
#include "Timer.h" #include "Timer.h"
uint32 NextAction::size(NextAction** actions)
{
if (!actions)
return 0;
uint32 size = 0;
for (size = 0; actions[size];)
++size;
return size;
}
NextAction** NextAction::clone(NextAction** actions)
{
if (!actions)
return nullptr;
uint32 size = NextAction::size(actions);
NextAction** res = new NextAction*[size + 1];
for (uint32 i = 0; i < size; i++)
res[i] = new NextAction(*actions[i]);
res[size] = nullptr;
return res;
}
NextAction** NextAction::merge(NextAction** left, NextAction** right)
{
uint32 leftSize = NextAction::size(left);
uint32 rightSize = NextAction::size(right);
NextAction** res = new NextAction*[leftSize + rightSize + 1];
for (uint32 i = 0; i < leftSize; i++)
res[i] = new NextAction(*left[i]);
for (uint32 i = 0; i < rightSize; i++)
res[leftSize + i] = new NextAction(*right[i]);
res[leftSize + rightSize] = nullptr;
NextAction::destroy(left);
NextAction::destroy(right);
return res;
}
NextAction** NextAction::array(uint32 nil, ...)
{
va_list vl;
va_start(vl, nil);
uint32 size = 0;
NextAction* cur = nullptr;
do
{
cur = va_arg(vl, NextAction*);
++size;
} while (cur);
va_end(vl);
NextAction** res = new NextAction*[size];
va_start(vl, nil);
for (uint32 i = 0; i < size; i++)
res[i] = va_arg(vl, NextAction*);
va_end(vl);
return res;
}
void NextAction::destroy(NextAction** actions)
{
if (!actions)
return;
for (uint32 i = 0; actions[i]; i++)
delete actions[i];
delete[] actions;
}
Value<Unit*>* Action::GetTargetValue() { return context->GetValue<Unit*>(GetTargetName()); } Value<Unit*>* Action::GetTargetValue() { return context->GetValue<Unit*>(GetTargetName()); }
Unit* Action::GetTarget() { return GetTargetValue()->Get(); } Unit* Action::GetTarget() { return GetTargetValue()->Get(); }
@@ -101,4 +17,4 @@ ActionBasket::ActionBasket(ActionNode* action, float relevance, bool skipPrerequ
{ {
} }
bool ActionBasket::isExpired(uint32 msecs) { return getMSTime() - created >= msecs; } bool ActionBasket::isExpired(uint32_t msecs) { return getMSTime() - created >= msecs; }

View File

@@ -3,8 +3,7 @@
* and/or modify it under version 3 of the License, or (at your option), any later version. * and/or modify it under version 3 of the License, or (at your option), any later version.
*/ */
#ifndef _PLAYERBOT_ACTION_H #pragma once
#define _PLAYERBOT_ACTION_H
#include "AiObject.h" #include "AiObject.h"
#include "Common.h" #include "Common.h"
@@ -24,15 +23,26 @@ public:
std::string const getName() { return name; } std::string const getName() { return name; }
float getRelevance() { return relevance; } float getRelevance() { return relevance; }
static uint32 size(NextAction** actions); static std::vector<NextAction> merge(std::vector<NextAction> const& what, std::vector<NextAction> const& with)
static NextAction** clone(NextAction** actions); {
static NextAction** merge(NextAction** what, NextAction** with); std::vector<NextAction> result = {};
static NextAction** array(uint32 nil, ...);
static void destroy(NextAction** actions); for (NextAction const& action : what)
{
result.push_back(action);
}
for (NextAction const& action : with)
{
result.push_back(action);
}
return result;
};
private: private:
float relevance; float relevance;
std::string const name; std::string name;
}; };
class Action : public AiNamedObject class Action : public AiNamedObject
@@ -52,9 +62,9 @@ public:
virtual bool Execute([[maybe_unused]] Event event) { return true; } virtual bool Execute([[maybe_unused]] Event event) { return true; }
virtual bool isPossible() { return true; } virtual bool isPossible() { return true; }
virtual bool isUseful() { return true; } virtual bool isUseful() { return true; }
virtual NextAction** getPrerequisites() { return nullptr; } virtual std::vector<NextAction> getPrerequisites() { return {}; }
virtual NextAction** getAlternatives() { return nullptr; } virtual std::vector<NextAction> getAlternatives() { return {}; }
virtual NextAction** getContinuers() { return nullptr; } virtual std::vector<NextAction> getContinuers() { return {}; }
virtual ActionThreatType getThreatType() { return ActionThreatType::None; } virtual ActionThreatType getThreatType() { return ActionThreatType::None; }
void Update() {} void Update() {}
void Reset() {} void Reset() {}
@@ -73,39 +83,44 @@ protected:
class ActionNode class ActionNode
{ {
public: public:
ActionNode(std::string const name, NextAction** prerequisites = nullptr, NextAction** alternatives = nullptr, ActionNode(
NextAction** continuers = nullptr) std::string name,
: name(name), action(nullptr), continuers(continuers), alternatives(alternatives), prerequisites(prerequisites) std::vector<NextAction> prerequisites = {},
{ std::vector<NextAction> alternatives = {},
} // reorder arguments - whipowill std::vector<NextAction> continuers = {}
) :
name(std::move(name)),
action(nullptr),
continuers(continuers),
alternatives(alternatives),
prerequisites(prerequisites)
{}
virtual ~ActionNode() virtual ~ActionNode() = default;
{
NextAction::destroy(prerequisites);
NextAction::destroy(alternatives);
NextAction::destroy(continuers);
}
Action* getAction() { return action; } Action* getAction() { return action; }
void setAction(Action* action) { this->action = action; } void setAction(Action* action) { this->action = action; }
std::string const getName() { return name; } const std::string getName() { return name; }
NextAction** getContinuers() { return NextAction::merge(NextAction::clone(continuers), action->getContinuers()); } std::vector<NextAction> getContinuers()
NextAction** getAlternatives()
{ {
return NextAction::merge(NextAction::clone(alternatives), action->getAlternatives()); return NextAction::merge(this->continuers, action->getContinuers());
} }
NextAction** getPrerequisites() std::vector<NextAction> getAlternatives()
{ {
return NextAction::merge(NextAction::clone(prerequisites), action->getPrerequisites()); return NextAction::merge(this->alternatives, action->getAlternatives());
}
std::vector<NextAction> getPrerequisites()
{
return NextAction::merge(this->prerequisites, action->getPrerequisites());
} }
private: private:
std::string const name; const std::string name;
Action* action; Action* action;
NextAction** continuers; std::vector<NextAction> continuers;
NextAction** alternatives; std::vector<NextAction> alternatives;
NextAction** prerequisites; std::vector<NextAction> prerequisites;
}; };
class ActionBasket class ActionBasket
@@ -121,14 +136,12 @@ public:
bool isSkipPrerequisites() { return skipPrerequisites; } bool isSkipPrerequisites() { return skipPrerequisites; }
void AmendRelevance(float k) { relevance *= k; } void AmendRelevance(float k) { relevance *= k; }
void setRelevance(float relevance) { this->relevance = relevance; } void setRelevance(float relevance) { this->relevance = relevance; }
bool isExpired(uint32 msecs); bool isExpired(uint32_t msecs);
private: private:
ActionNode* action; ActionNode* action;
float relevance; float relevance;
bool skipPrerequisites; bool skipPrerequisites;
Event event; Event event;
uint32 created; uint32_t created;
}; };
#endif

View File

@@ -42,9 +42,6 @@ protected:
// TRIGGERS // TRIGGERS
// //
#define NEXT_TRIGGERS(name, relevance) \
virtual NextAction* getNextAction() { return new NextAction(name, relevance); }
#define BEGIN_TRIGGER(clazz, super) \ #define BEGIN_TRIGGER(clazz, super) \
class clazz : public super \ class clazz : public super \
{ \ { \
@@ -78,14 +75,6 @@ protected:
clazz(PlayerbotAI* botAI) : BuffOnPartyTrigger(botAI, spell) {} \ clazz(PlayerbotAI* botAI) : BuffOnPartyTrigger(botAI, spell) {} \
} }
#define BUFF_PARTY_TRIGGER_A(clazz, spell) \
class clazz : public BuffOnPartyTrigger \
{ \
public: \
clazz(PlayerbotAI* botAI) : BuffOnPartyTrigger(botAI, spell) {} \
bool IsActive() override; \
}
#define DEBUFF_TRIGGER(clazz, spell) \ #define DEBUFF_TRIGGER(clazz, spell) \
class clazz : public DebuffTrigger \ class clazz : public DebuffTrigger \
{ \ { \
@@ -296,14 +285,6 @@ protected:
clazz(PlayerbotAI* botAI) : CastHealingSpellAction(botAI, spell) {} \ clazz(PlayerbotAI* botAI) : CastHealingSpellAction(botAI, spell) {} \
} }
#define HEAL_ACTION_U(clazz, spell, useful) \
class clazz : public CastHealingSpellAction \
{ \
public: \
clazz(PlayerbotAI* botAI) : CastHealingSpellAction(botAI, spell) {} \
bool isUseful() override { return useful; } \
}
#define HEAL_PARTY_ACTION(clazz, spell, estAmount, manaEfficiency) \ #define HEAL_PARTY_ACTION(clazz, spell, estAmount, manaEfficiency) \
class clazz : public HealPartyMemberAction \ class clazz : public HealPartyMemberAction \
{ \ { \
@@ -404,14 +385,6 @@ protected:
clazz(PlayerbotAI* botAI) : CastReachTargetSpellAction(botAI, spell, range) {} \ clazz(PlayerbotAI* botAI) : CastReachTargetSpellAction(botAI, spell, range) {} \
} }
#define REACH_ACTION_U(clazz, spell, range, useful) \
class clazz : public CastReachTargetSpellAction \
{ \
public: \
clazz(PlayerbotAI* botAI) : CastReachTargetSpellAction(botAI, spell, range) {} \
bool isUseful() override { return useful; } \
}
#define ENEMY_HEALER_ACTION(clazz, spell) \ #define ENEMY_HEALER_ACTION(clazz, spell) \
class clazz : public CastSpellOnEnemyHealerAction \ class clazz : public CastSpellOnEnemyHealerAction \
{ \ { \
@@ -440,10 +413,6 @@ protected:
clazz(PlayerbotAI* botAI) : CastProtectSpellAction(botAI, spell) {} \ clazz(PlayerbotAI* botAI) : CastProtectSpellAction(botAI, spell) {} \
} }
#define END_RANGED_SPELL_ACTION() \
} \
;
#define BEGIN_SPELL_ACTION(clazz, name) \ #define BEGIN_SPELL_ACTION(clazz, name) \
class clazz : public CastSpellAction \ class clazz : public CastSpellAction \
{ \ { \
@@ -472,42 +441,4 @@ protected:
public: \ public: \
clazz(PlayerbotAI* botAI) : CastMeleeSpellAction(botAI, name) {} clazz(PlayerbotAI* botAI) : CastMeleeSpellAction(botAI, name) {}
#define END_RANGED_SPELL_ACTION() \
} \
;
#define BEGIN_BUFF_ON_PARTY_ACTION(clazz, name) \
class clazz : public BuffOnPartyAction \
{ \
public: \
clazz(PlayerbotAI* botAI) : BuffOnPartyAction(botAI, name) {}
//
// Action node
//
// node_name , action, prerequisite
#define ACTION_NODE_P(name, spell, pre) \
static ActionNode* name([[maybe_unused]] PlayerbotAI* botAI) \
{ \
return new ActionNode(spell, /*P*/ NextAction::array(0, new NextAction(pre), nullptr), /*A*/ nullptr, \
/*C*/ nullptr); \
}
// node_name , action, alternative
#define ACTION_NODE_A(name, spell, alt) \
static ActionNode* name([[maybe_unused]] PlayerbotAI* botAI) \
{ \
return new ActionNode(spell, /*P*/ nullptr, /*A*/ NextAction::array(0, new NextAction(alt), nullptr), \
/*C*/ nullptr); \
}
// node_name , action, continuer
#define ACTION_NODE_C(name, spell, con) \
static ActionNode* name([[maybe_unused]] PlayerbotAI* botAI) \
{ \
return new ActionNode(spell, /*P*/ nullptr, /*A*/ nullptr, \
/*C*/ NextAction::array(0, new NextAction(con), nullptr)); \
}
#endif #endif

View File

@@ -6,36 +6,40 @@
#include "CustomStrategy.h" #include "CustomStrategy.h"
#include <regex> #include <regex>
#include <stdexcept>
#include "Playerbots.h" #include "Playerbots.h"
std::map<std::string, std::string> CustomStrategy::actionLinesCache; std::map<std::string, std::string> CustomStrategy::actionLinesCache;
NextAction* toNextAction(std::string const action) NextAction toNextAction(std::string const action)
{ {
std::vector<std::string> tokens = split(action, '!'); std::vector<std::string> tokens = split(action, '!');
if (tokens.size() == 2 && !tokens[0].empty())
return new NextAction(tokens[0], atof(tokens[1].c_str())); if (tokens[0].empty())
else if (tokens.size() == 1 && !tokens[0].empty()) throw std::invalid_argument("Invalid action");
return new NextAction(tokens[0], ACTION_NORMAL);
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()); LOG_ERROR("playerbots", "Invalid action {}", action.c_str());
return nullptr;
throw std::invalid_argument("Invalid action");
} }
NextAction** toNextActionArray(std::string const actions) std::vector<NextAction> toNextActionArray(const std::string actions)
{ {
std::vector<std::string> tokens = split(actions, ','); const std::vector<std::string> tokens = split(actions, ',');
NextAction** res = new NextAction*[tokens.size() + 1]; std::vector<NextAction> res = {};
uint32 index = 0; for (const std::string token : tokens)
for (std::vector<std::string>::iterator i = tokens.begin(); i != tokens.end(); ++i)
{ {
if (NextAction* na = toNextAction(*i)) res.push_back(toNextAction(token));
res[index++] = na;
} }
res[index++] = nullptr;
return res; return res;
} }

View File

@@ -258,25 +258,29 @@ ActionNode* Engine::CreateActionNode(std::string const name)
return node; return node;
return new ActionNode(name, return new ActionNode(name,
/*P*/ nullptr, /*P*/ {},
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
bool Engine::MultiplyAndPush(NextAction** actions, float forceRelevance, bool skipPrerequisites, Event event, bool Engine::MultiplyAndPush(
char const* pushType) std::vector<NextAction> actions,
float forceRelevance,
bool skipPrerequisites,
Event event,
char const* pushType
)
{ {
bool pushed = false; bool pushed = false;
if (actions)
{
for (uint32 j = 0; actions[j]; j++)
{
if (NextAction* nextAction = actions[j])
{
ActionNode* action = CreateActionNode(nextAction->getName());
InitializeAction(action);
float k = nextAction->getRelevance(); for (NextAction nextAction : actions)
{
ActionNode* action = this->CreateActionNode(nextAction.getName());
this->InitializeAction(action);
float k = nextAction.getRelevance();
if (forceRelevance > 0.0f) if (forceRelevance > 0.0f)
{ {
k = forceRelevance; k = forceRelevance;
@@ -284,22 +288,15 @@ bool Engine::MultiplyAndPush(NextAction** actions, float forceRelevance, bool sk
if (k > 0) if (k > 0)
{ {
LogAction("PUSH:%s - %f (%s)", action->getName().c_str(), k, pushType); this->LogAction("PUSH:%s - %f (%s)", action->getName().c_str(), k, pushType);
queue.Push(new ActionBasket(action, k, skipPrerequisites, event)); queue.Push(new ActionBasket(action, k, skipPrerequisites, event));
pushed = true; pushed = true;
continue;
} }
else
{
delete action; delete action;
}
delete nextAction;
}
else
break;
}
delete[] actions;
} }
return pushed; return pushed;
@@ -530,10 +527,10 @@ std::vector<std::string> Engine::GetStrategies()
void Engine::PushAgain(ActionNode* actionNode, float relevance, Event event) void Engine::PushAgain(ActionNode* actionNode, float relevance, Event event)
{ {
NextAction** nextAction = new NextAction*[2]; std::vector<NextAction> nextAction = { NextAction(actionNode->getName(), relevance) };
nextAction[0] = new NextAction(actionNode->getName(), relevance);
nextAction[1] = nullptr;
MultiplyAndPush(nextAction, relevance, true, event, "again"); MultiplyAndPush(nextAction, relevance, true, event, "again");
delete actionNode; delete actionNode;
} }
@@ -563,6 +560,13 @@ bool Engine::ListenAndExecute(Action* action, Event event)
{ {
bool actionExecuted = false; bool actionExecuted = false;
if (action == nullptr)
{
LOG_ERROR("playerbots", "Action is nullptr");
return actionExecuted;
}
if (actionExecutionListeners.Before(action, event)) if (actionExecutionListeners.Before(action, event))
{ {
actionExecuted = actionExecutionListeners.AllowExecution(action, event) ? action->Execute(event) : true; actionExecuted = actionExecutionListeners.AllowExecution(action, event) ? action->Execute(event) : true;

View File

@@ -90,7 +90,7 @@ public:
bool testMode; bool testMode;
private: private:
bool MultiplyAndPush(NextAction** actions, float forceRelevance, bool skipPrerequisites, Event event, bool MultiplyAndPush(std::vector<NextAction> actions, float forceRelevance, bool skipPrerequisites, Event event,
const char* pushType); const char* pushType);
void Reset(); void Reset();
void ProcessTriggers(bool minimal); void ProcessTriggers(bool minimal);

View File

@@ -28,90 +28,112 @@ public:
private: private:
static ActionNode* melee([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* melee([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("melee", return new ActionNode(
/*P*/ nullptr, "melee",
/*A*/ nullptr, /*P*/ {},
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* healthstone([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* healthstone([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("healthstone", return new ActionNode(
/*P*/ nullptr, "healthstone",
/*A*/ NextAction::array(0, new NextAction("healing potion"), nullptr), /*P*/ {},
/*C*/ nullptr); /*A*/ { NextAction("healing potion") },
/*C*/ {}
);
} }
static ActionNode* follow_master_random([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* follow_master_random([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("be near", return new ActionNode(
/*P*/ nullptr, "be near",
/*A*/ NextAction::array(0, new NextAction("follow"), nullptr), /*P*/ {},
/*C*/ nullptr); /*A*/ { NextAction("follow") },
/*C*/ {}
);
} }
static ActionNode* attack_anything([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* attack_anything([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("attack anything", return new ActionNode(
/*P*/ nullptr, "attack anything",
/*A*/ nullptr, /*P*/ {},
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* move_random([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* move_random([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("move random", return new ActionNode(
/*P*/ nullptr, "move random",
/*A*/ NextAction::array(0, new NextAction("stay line"), nullptr), /*P*/ {},
/*C*/ nullptr); /*A*/ { NextAction("stay line") },
/*C*/ {}
);
} }
static ActionNode* move_to_loot([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* move_to_loot([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("move to loot", return new ActionNode(
/*P*/ nullptr, "move to loot",
/*A*/ nullptr, /*P*/ {},
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* food([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* food([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("food", return new ActionNode(
/*P*/ nullptr, "food",
/*A*/ nullptr, /*P*/ {},
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* drink([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* drink([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("drink", return new ActionNode(
/*P*/ nullptr, "drink",
/*A*/ nullptr, /*P*/ {},
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* mana_potion([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* mana_potion([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("mana potion", return new ActionNode(
/*P*/ nullptr, "mana potion",
/*A*/ nullptr, /*P*/ {},
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* healing_potion([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* healing_potion([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("healing potion", return new ActionNode(
/*P*/ nullptr, "healing potion",
/*A*/ NextAction::array(0, new NextAction("food"), nullptr), /*P*/ {},
/*C*/ nullptr); /*A*/ { NextAction("food") },
/*C*/ {}
);
} }
static ActionNode* flee([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* flee([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("flee", return new ActionNode(
/*P*/ nullptr, "flee",
/*A*/ nullptr, /*P*/ {},
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
}; };

View File

@@ -60,7 +60,7 @@ public:
Strategy(PlayerbotAI* botAI); Strategy(PlayerbotAI* botAI);
virtual ~Strategy() {} virtual ~Strategy() {}
virtual NextAction** getDefaultActions() { return nullptr; } virtual std::vector<NextAction> getDefaultActions() { return {}; }
virtual void InitTriggers([[maybe_unused]] std::vector<TriggerNode*>& triggers) {} virtual void InitTriggers([[maybe_unused]] std::vector<TriggerNode*>& triggers) {}
virtual void InitMultipliers([[maybe_unused]] std::vector<Multiplier*>& multipliers) {} virtual void InitMultipliers([[maybe_unused]] std::vector<Multiplier*>& multipliers) {}
virtual std::string const getName() = 0; virtual std::string const getName() = 0;

View File

@@ -3,8 +3,7 @@
* and/or modify it under version 3 of the License, or (at your option), any later version. * and/or modify it under version 3 of the License, or (at your option), any later version.
*/ */
#ifndef _PLAYERBOT_TRIGGER_H #pragma once
#define _PLAYERBOT_TRIGGER_H
#include "Action.h" #include "Action.h"
#include "Common.h" #include "Common.h"
@@ -15,7 +14,11 @@ class Unit;
class Trigger : public AiNamedObject class Trigger : public AiNamedObject
{ {
public: public:
Trigger(PlayerbotAI* botAI, std::string const name = "trigger", int32 checkInterval = 1); Trigger(
PlayerbotAI* botAI,
const std::string name = "trigger",
int32_t checkInterval = 1
);
virtual ~Trigger() {} virtual ~Trigger() {}
@@ -23,7 +26,7 @@ public:
virtual void ExternalEvent([[maybe_unused]] std::string const param, [[maybe_unused]] Player* owner = nullptr) {} virtual void ExternalEvent([[maybe_unused]] std::string const param, [[maybe_unused]] Player* owner = nullptr) {}
virtual void ExternalEvent([[maybe_unused]] WorldPacket& packet, [[maybe_unused]] Player* owner = nullptr) {} virtual void ExternalEvent([[maybe_unused]] WorldPacket& packet, [[maybe_unused]] Player* owner = nullptr) {}
virtual bool IsActive() { return false; } virtual bool IsActive() { return false; }
virtual NextAction** getHandlers() { return nullptr; } virtual std::vector<NextAction> getHandlers() { return {}; }
void Update() {} void Update() {}
virtual void Reset() {} virtual void Reset() {}
virtual Unit* GetTarget(); virtual Unit* GetTarget();
@@ -33,32 +36,49 @@ public:
bool needCheck(uint32 now); bool needCheck(uint32 now);
protected: protected:
int32 checkInterval; int32_t checkInterval;
uint32 lastCheckTime; uint32_t lastCheckTime;
}; };
class TriggerNode class TriggerNode
{ {
public: public:
TriggerNode(std::string const name, NextAction** handlers = nullptr) TriggerNode(
: trigger(nullptr), handlers(handlers), name(name) const std::string& name,
{ std::vector<NextAction> handlers = {}
} // reorder args - whipowill ) :
trigger(nullptr),
virtual ~TriggerNode() { NextAction::destroy(handlers); } handlers(std::move(handlers)),
name(name)
{}
Trigger* getTrigger() { return trigger; } Trigger* getTrigger() { return trigger; }
void setTrigger(Trigger* trigger) { this->trigger = trigger; } void setTrigger(Trigger* trigger) { this->trigger = trigger; }
std::string const getName() { return name; } const std::string getName() { return name; }
NextAction** getHandlers() { return NextAction::merge(NextAction::clone(handlers), trigger->getHandlers()); } std::vector<NextAction> getHandlers()
{
std::vector<NextAction> result = this->handlers;
float getFirstRelevance() { return handlers[0] ? handlers[0]->getRelevance() : -1; } if (trigger != nullptr)
{
std::vector<NextAction> extra = trigger->getHandlers();
result.insert(result.end(), extra.begin(), extra.end());
}
return result;
}
float getFirstRelevance()
{
if (this->handlers.size() > 0)
return this->handlers[0].getRelevance();
return -1;
}
private: private:
Trigger* trigger; Trigger* trigger;
NextAction** handlers; std::vector<NextAction> handlers;
std::string const name; const std::string name;
}; };
#endif

View File

@@ -78,20 +78,17 @@ float ChooseRpgTargetAction::getMaxRelevance(GuidPosition guidP)
if (!trigger->IsActive()) if (!trigger->IsActive())
continue; continue;
NextAction** nextActions = triggerNode->getHandlers(); std::vector<NextAction> nextActions = triggerNode->getHandlers();
bool isRpg = false; bool isRpg = false;
for (int32 i = 0; i < NextAction::size(nextActions); i++) for (NextAction nextAction : nextActions)
{ {
NextAction* nextAction = nextActions[i]; Action* action = botAI->GetAiObjectContext()->GetAction(nextAction.getName());
Action* action = botAI->GetAiObjectContext()->GetAction(nextAction->getName());
if (dynamic_cast<RpgEnabled*>(action)) if (dynamic_cast<RpgEnabled*>(action))
isRpg = true; isRpg = true;
} }
NextAction::destroy(nextActions);
if (isRpg) if (isRpg)
{ {

View File

@@ -265,11 +265,6 @@ CastShootAction::CastShootAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "s
} }
} }
NextAction** CastSpellAction::getPrerequisites()
{
return nullptr;
}
Value<Unit*>* CastDebuffSpellOnAttackerAction::GetTargetValue() Value<Unit*>* CastDebuffSpellOnAttackerAction::GetTargetValue()
{ {
return context->GetValue<Unit*>("attacker without aura", spell); return context->GetValue<Unit*>("attacker without aura", spell);

View File

@@ -27,7 +27,11 @@ public:
bool isUseful() override; bool isUseful() override;
ActionThreatType getThreatType() override { return ActionThreatType::Single; } ActionThreatType getThreatType() override { return ActionThreatType::Single; }
NextAction** getPrerequisites() override; std::vector<NextAction> getPrerequisites() override
{
return {};
}
std::string const getSpell() { return spell; } std::string const getSpell() { return spell; }
protected: protected:
@@ -193,10 +197,12 @@ public:
ResurrectPartyMemberAction(PlayerbotAI* botAI, std::string const spell) : CastSpellAction(botAI, spell) {} ResurrectPartyMemberAction(PlayerbotAI* botAI, std::string const spell) : CastSpellAction(botAI, spell) {}
std::string const GetTargetName() override { return "party member to resurrect"; } std::string const GetTargetName() override { return "party member to resurrect"; }
NextAction** getPrerequisites() override std::vector<NextAction> getPrerequisites() override
{ {
return NextAction::merge(NextAction::array(0, new NextAction("reach party member to resurrect"), NULL), return NextAction::merge(
Action::getPrerequisites()); { NextAction("reach party member to resurrect") },
Action::getPrerequisites()
);
} }
}; };

View File

@@ -68,17 +68,15 @@ bool RpgAction::SetNextRpgAction()
triggerNode->setTrigger(trigger); triggerNode->setTrigger(trigger);
NextAction** nextActions = triggerNode->getHandlers(); std::vector<NextAction> nextActions = triggerNode->getHandlers();
Trigger* trigger = triggerNode->getTrigger(); Trigger* trigger = triggerNode->getTrigger();
bool isChecked = false; bool isChecked = false;
for (int32 i = 0; i < NextAction::size(nextActions); i++) for (NextAction nextAction : nextActions)
{ {
NextAction* nextAction = nextActions[i]; if (nextAction.getRelevance() > 5.0f)
if (nextAction->getRelevance() > 5.0f)
continue; continue;
if (!isChecked && !trigger->IsActive()) if (!isChecked && !trigger->IsActive())
@@ -86,14 +84,13 @@ bool RpgAction::SetNextRpgAction()
isChecked = true; isChecked = true;
Action* action = botAI->GetAiObjectContext()->GetAction(nextAction->getName()); Action* action = botAI->GetAiObjectContext()->GetAction(nextAction.getName());
if (!dynamic_cast<RpgEnabled*>(action) || !action->isPossible() || !action->isUseful()) if (!dynamic_cast<RpgEnabled*>(action) || !action->isPossible() || !action->isUseful())
continue; continue;
actions.push_back(action); actions.push_back(action);
relevances.push_back((nextAction->getRelevance() - 1) * 500); relevances.push_back((nextAction.getRelevance() - 1) * 500);
} }
NextAction::destroy(nextActions);
} }
} }

View File

@@ -12,25 +12,10 @@ class BloodDKStrategyActionNodeFactory : public NamedObjectFactory<ActionNode>
public: public:
BloodDKStrategyActionNodeFactory() BloodDKStrategyActionNodeFactory()
{ {
// creators["melee"] = &melee;
// creators["blood strike"] = &blood_strike;
creators["rune strike"] = &rune_strike; creators["rune strike"] = &rune_strike;
creators["heart strike"] = &heart_strike; creators["heart strike"] = &heart_strike;
creators["death strike"] = &death_strike; creators["death strike"] = &death_strike;
// creators["death grip"] = &death_grip;
// creators["plague strike"] = &plague_strike;
// creators["pestilence"] = &pestilence;
creators["icy touch"] = &icy_touch; creators["icy touch"] = &icy_touch;
// creators["obliterate"] = &obliterate;
// creators["blood boil"] = &blood_boil;
// creators["mark of_blood"] = &mark_of_blood;
// creators["blood presence"] = &blood_presence;
// creators["rune tap"] = &rune_tap;
// creators["vampiric blood"] = &vampiric_blood;
// creators["death pact"] = &death_pact;
// creators["death rune_mastery"] = &death_rune_mastery;
// creators["hysteria"] = &hysteria;
// creators["dancing weapon"] = &dancing_weapon;
creators["dark command"] = &dark_command; creators["dark command"] = &dark_command;
creators["taunt spell"] = &dark_command; creators["taunt spell"] = &dark_command;
} }
@@ -38,39 +23,61 @@ public:
private: private:
static ActionNode* rune_strike([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* rune_strike([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("rune strike", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("frost presence"), nullptr), "rune strike",
/*A*/ nullptr, {
/*C*/ nullptr); NextAction("frost presence")
},
/*A*/ {},
/*C*/ {}
);
} }
static ActionNode* icy_touch([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* icy_touch([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("icy touch", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("frost presence"), nullptr), "icy touch",
/*A*/ nullptr, {
/*C*/ nullptr); NextAction("frost presence")
},
/*A*/ {},
/*C*/ {}
);
} }
static ActionNode* heart_strike([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* heart_strike([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("heart strike", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("frost presence"), nullptr), "heart strike",
/*A*/ nullptr, {
/*C*/ nullptr); NextAction("frost presence")
},
/*A*/ {},
/*C*/ {}
);
} }
static ActionNode* death_strike([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* death_strike([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("death strike", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("frost presence"), nullptr), "death strike",
/*A*/ nullptr, {
/*C*/ nullptr); NextAction("frost presence")
},
/*A*/ {},
/*C*/ {}
);
} }
static ActionNode* dark_command([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* dark_command([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("dark command", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("frost presence"), NULL), "dark command",
/*A*/ NextAction::array(0, new NextAction("death grip"), NULL), {
/*C*/ NULL); NextAction("frost presence")
},
/*A*/ {
NextAction("death grip")
},
/*C*/ {}
);
} }
}; };
@@ -79,33 +86,80 @@ BloodDKStrategy::BloodDKStrategy(PlayerbotAI* botAI) : GenericDKStrategy(botAI)
actionNodeFactories.Add(new BloodDKStrategyActionNodeFactory()); actionNodeFactories.Add(new BloodDKStrategyActionNodeFactory());
} }
NextAction** BloodDKStrategy::getDefaultActions() std::vector<NextAction> BloodDKStrategy::getDefaultActions()
{ {
return NextAction::array( return {
0, new NextAction("rune strike", ACTION_DEFAULT + 0.8f), new NextAction("icy touch", ACTION_DEFAULT + 0.7f), NextAction("rune strike", ACTION_DEFAULT + 0.8f),
new NextAction("heart strike", ACTION_DEFAULT + 0.6f), new NextAction("blood strike", ACTION_DEFAULT + 0.5f), NextAction("icy touch", ACTION_DEFAULT + 0.7f),
new NextAction("dancing rune weapon", ACTION_DEFAULT + 0.4f), NextAction("heart strike", ACTION_DEFAULT + 0.6f),
new NextAction("death coil", ACTION_DEFAULT + 0.3f), new NextAction("plague strike", ACTION_DEFAULT + 0.2f), NextAction("blood strike", ACTION_DEFAULT + 0.5f),
new NextAction("horn of winter", ACTION_DEFAULT + 0.1f), new NextAction("melee", ACTION_DEFAULT), NULL); NextAction("dancing rune weapon", ACTION_DEFAULT + 0.4f),
NextAction("death coil", ACTION_DEFAULT + 0.3f),
NextAction("plague strike", ACTION_DEFAULT + 0.2f),
NextAction("horn of winter", ACTION_DEFAULT + 0.1f),
NextAction("melee", ACTION_DEFAULT)
};
} }
void BloodDKStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void BloodDKStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
GenericDKStrategy::InitTriggers(triggers); GenericDKStrategy::InitTriggers(triggers);
triggers.push_back(new TriggerNode(
"rune strike", NextAction::array(0, new NextAction("rune strike", ACTION_NORMAL + 3), nullptr)));
triggers.push_back( triggers.push_back(
new TriggerNode("blood tap", NextAction::array(0, new NextAction("blood tap", ACTION_HIGH + 5), nullptr))); new TriggerNode(
triggers.push_back( "rune strike",
new TriggerNode("lose aggro", NextAction::array(0, new NextAction("dark command", ACTION_HIGH + 3), nullptr))); {
triggers.push_back( NextAction("rune strike", ACTION_NORMAL + 3)
new TriggerNode("low health", NextAction::array(0, new NextAction("army of the dead", ACTION_HIGH + 4), }
new NextAction("death strike", ACTION_HIGH + 3), nullptr))); )
triggers.push_back( );
new TriggerNode("critical health", NextAction::array(0, new NextAction("vampiric blood", ACTION_HIGH + 5), nullptr))); triggers.push_back(
triggers.push_back( new TriggerNode(
new TriggerNode("icy touch", NextAction::array(0, new NextAction("icy touch", ACTION_HIGH + 2), nullptr))); "blood tap",
triggers.push_back(new TriggerNode( {
"plague strike", NextAction::array(0, new NextAction("plague strike", ACTION_HIGH + 2), nullptr))); NextAction("blood tap", ACTION_HIGH + 5)
}
)
);
triggers.push_back(
new TriggerNode(
"lose aggro",
{
NextAction("dark command", ACTION_HIGH + 3)
}
)
);
triggers.push_back(
new TriggerNode(
"low health",
{
NextAction("army of the dead", ACTION_HIGH + 4),
NextAction("death strike", ACTION_HIGH + 3)
}
)
);
triggers.push_back(
new TriggerNode(
"critical health",
{
NextAction("vampiric blood", ACTION_HIGH + 5)
}
)
);
triggers.push_back(
new TriggerNode(
"icy touch",
{
NextAction("icy touch", ACTION_HIGH + 2)
}
)
);
triggers.push_back(
new TriggerNode(
"plague strike",
{
NextAction("plague strike", ACTION_HIGH + 2)
}
)
);
} }

View File

@@ -17,7 +17,7 @@ public:
void InitTriggers(std::vector<TriggerNode*>& triggers) override; void InitTriggers(std::vector<TriggerNode*>& triggers) override;
std::string const getName() override { return "blood"; } std::string const getName() override { return "blood"; }
NextAction** getDefaultActions() override; std::vector<NextAction> getDefaultActions() override;
uint32 GetType() const override { return STRATEGY_TYPE_TANK | STRATEGY_TYPE_MELEE; } uint32 GetType() const override { return STRATEGY_TYPE_TANK | STRATEGY_TYPE_MELEE; }
}; };

View File

@@ -11,39 +11,40 @@
#include "SpellInfo.h" #include "SpellInfo.h"
#include "SpellMgr.h" #include "SpellMgr.h"
NextAction** CastDeathchillAction::getPrerequisites() std::vector<NextAction> CastDeathchillAction::getPrerequisites()
{ {
return NextAction::merge(NextAction::array(0, new NextAction("frost presence"), nullptr), return NextAction::merge({ NextAction("frost presence") },
CastSpellAction::getPrerequisites()); CastSpellAction::getPrerequisites());
} }
NextAction** CastUnholyMeleeSpellAction::getPrerequisites() std::vector<NextAction> CastUnholyMeleeSpellAction::getPrerequisites()
{ {
return NextAction::merge(NextAction::array(0, new NextAction("unholy presence"), nullptr), return NextAction::merge({ NextAction("unholy presence") },
CastMeleeSpellAction::getPrerequisites()); CastMeleeSpellAction::getPrerequisites());
} }
NextAction** CastFrostMeleeSpellAction::getPrerequisites() std::vector<NextAction> CastFrostMeleeSpellAction::getPrerequisites()
{ {
return NextAction::merge(NextAction::array(0, new NextAction("frost presence"), nullptr), return NextAction::merge({ NextAction("frost presence") },
CastMeleeSpellAction::getPrerequisites()); CastMeleeSpellAction::getPrerequisites());
} }
NextAction** CastBloodMeleeSpellAction::getPrerequisites() std::vector<NextAction> CastBloodMeleeSpellAction::getPrerequisites()
{ {
return NextAction::merge(NextAction::array(0, new NextAction("blood presence"), nullptr), return NextAction::merge({ NextAction("blood presence") },
CastMeleeSpellAction::getPrerequisites()); CastMeleeSpellAction::getPrerequisites());
} }
bool CastRaiseDeadAction::Execute(Event event) bool CastRaiseDeadAction::Execute(Event event)
{ {
bool result = CastBuffSpellAction::Execute(event); const bool result = CastBuffSpellAction::Execute(event);
if (!result) if (!result)
{
return false; return false;
}
uint32 spellId = AI_VALUE2(uint32, "spell id", spell); const uint32_t spellId = AI_VALUE2(uint32_t, "spell id", spell);
// SpellInfo const *spellInfo = sSpellMgr->GetSpellInfo(spellId);
bot->AddSpellCooldown(spellId, 0, 3 * 60 * 1000); bot->AddSpellCooldown(spellId, 0, 3 * 60 * 1000);
return true; return true;
} }

View File

@@ -34,7 +34,7 @@ class CastDeathchillAction : public CastBuffSpellAction
public: public:
CastDeathchillAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "deathchill") {} CastDeathchillAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "deathchill") {}
NextAction** getPrerequisites() override; std::vector<NextAction> getPrerequisites() override;
}; };
class CastDarkCommandAction : public CastSpellAction class CastDarkCommandAction : public CastSpellAction
@@ -52,7 +52,7 @@ class CastUnholyMeleeSpellAction : public CastMeleeSpellAction
public: public:
CastUnholyMeleeSpellAction(PlayerbotAI* botAI, std::string const spell) : CastMeleeSpellAction(botAI, spell) {} CastUnholyMeleeSpellAction(PlayerbotAI* botAI, std::string const spell) : CastMeleeSpellAction(botAI, spell) {}
NextAction** getPrerequisites() override; std::vector<NextAction> getPrerequisites() override;
}; };
// Frost presence // Frost presence
@@ -61,7 +61,7 @@ class CastFrostMeleeSpellAction : public CastMeleeSpellAction
public: public:
CastFrostMeleeSpellAction(PlayerbotAI* botAI, std::string const spell) : CastMeleeSpellAction(botAI, spell) {} CastFrostMeleeSpellAction(PlayerbotAI* botAI, std::string const spell) : CastMeleeSpellAction(botAI, spell) {}
NextAction** getPrerequisites() override; std::vector<NextAction> getPrerequisites() override;
}; };
// Blood presence // Blood presence
@@ -70,7 +70,7 @@ class CastBloodMeleeSpellAction : public CastMeleeSpellAction
public: public:
CastBloodMeleeSpellAction(PlayerbotAI* botAI, std::string const spell) : CastMeleeSpellAction(botAI, spell) {} CastBloodMeleeSpellAction(PlayerbotAI* botAI, std::string const spell) : CastMeleeSpellAction(botAI, spell) {}
NextAction** getPrerequisites() override; std::vector<NextAction> getPrerequisites() override;
}; };
class CastRuneStrikeAction : public CastMeleeSpellAction class CastRuneStrikeAction : public CastMeleeSpellAction
@@ -79,10 +79,6 @@ public:
CastRuneStrikeAction(PlayerbotAI* botAI) : CastMeleeSpellAction(botAI, "rune strike") {} CastRuneStrikeAction(PlayerbotAI* botAI) : CastMeleeSpellAction(botAI, "rune strike") {}
}; };
// debuff
// BEGIN_DEBUFF_ACTION(CastPestilenceAction, "pestilence")
// END_SPELL_ACTION()
class CastPestilenceAction : public CastSpellAction class CastPestilenceAction : public CastSpellAction
{ {
public: public:
@@ -90,20 +86,12 @@ public:
ActionThreatType getThreatType() override { return ActionThreatType::None; } ActionThreatType getThreatType() override { return ActionThreatType::None; }
}; };
// debuff
// BEGIN_DEBUFF_ACTION(CastHowlingBlastAction, "howling blast")
// END_SPELL_ACTION()
class CastHowlingBlastAction : public CastSpellAction class CastHowlingBlastAction : public CastSpellAction
{ {
public: public:
CastHowlingBlastAction(PlayerbotAI* ai) : CastSpellAction(ai, "howling blast") {} CastHowlingBlastAction(PlayerbotAI* ai) : CastSpellAction(ai, "howling blast") {}
}; };
// debuff it
// BEGIN_DEBUFF_ACTION(CastIcyTouchAction, "icy touch")
// END_SPELL_ACTION()
class CastIcyTouchAction : public CastSpellAction class CastIcyTouchAction : public CastSpellAction
{ {
public: public:
@@ -126,8 +114,6 @@ class CastPlagueStrikeAction : public CastSpellAction
public: public:
CastPlagueStrikeAction(PlayerbotAI* ai) : CastSpellAction(ai, "plague strike") {} CastPlagueStrikeAction(PlayerbotAI* ai) : CastSpellAction(ai, "plague strike") {}
}; };
// BEGIN_DEBUFF_ACTION(CastPlagueStrikeAction, "plague strike")
// END_SPELL_ACTION()
class CastPlagueStrikeOnAttackerAction : public CastDebuffSpellOnMeleeAttackerAction class CastPlagueStrikeOnAttackerAction : public CastDebuffSpellOnMeleeAttackerAction
{ {

View File

@@ -16,66 +16,68 @@ public:
creators["obliterate"] = &obliterate; creators["obliterate"] = &obliterate;
creators["howling blast"] = &howling_blast; creators["howling blast"] = &howling_blast;
creators["frost strike"] = &frost_strike; creators["frost strike"] = &frost_strike;
// creators["chains of ice"] = &chains_of_ice;
creators["rune strike"] = &rune_strike; creators["rune strike"] = &rune_strike;
// creators["icy clutch"] = &icy_clutch;
// creators["horn of winter"] = &horn_of_winter;
// creators["killing machine"] = &killing_machine;
// creators["frost presence"] = &frost_presence;
// creators["deathchill"] = &deathchill;
// creators["icebound fortitude"] = &icebound_fortitude;
// creators["mind freeze"] = &mind_freeze;
// creators["hungering cold"] = &hungering_cold;
creators["unbreakable armor"] = &unbreakable_armor; creators["unbreakable armor"] = &unbreakable_armor;
// creators["improved icy talons"] = &improved_icy_talons;
} }
private: private:
static ActionNode* icy_touch([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* icy_touch([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("icy touch", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("blood presence"), nullptr), "icy touch",
/*A*/ nullptr, /*P*/ { NextAction("blood presence") },
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* obliterate([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* obliterate([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("obliterate", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("blood presence"), nullptr), "obliterate",
/*A*/ nullptr, /*P*/ { NextAction("blood presence") },
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* rune_strike([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* rune_strike([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("rune strike", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("blood presence"), nullptr), "rune strike",
/*A*/ NextAction::array(0, new NextAction("melee"), nullptr), /*P*/ { NextAction("blood presence") },
/*C*/ nullptr); /*A*/ { NextAction("melee") },
/*C*/ {}
);
} }
static ActionNode* frost_strike([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* frost_strike([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("frost strike", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("blood presence"), nullptr), "frost strike",
/*A*/ nullptr, /*P*/ { NextAction("blood presence") },
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* howling_blast([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* howling_blast([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("howling blast", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("blood presence"), nullptr), "howling blast",
/*A*/ nullptr, /*P*/ { NextAction("blood presence") },
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* unbreakable_armor([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* unbreakable_armor([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("unbreakable armor", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("blood tap"), nullptr), "unbreakable armor",
/*A*/ nullptr, /*P*/ { NextAction("blood tap") },
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
}; };
@@ -84,41 +86,84 @@ FrostDKStrategy::FrostDKStrategy(PlayerbotAI* botAI) : GenericDKStrategy(botAI)
actionNodeFactories.Add(new FrostDKStrategyActionNodeFactory()); actionNodeFactories.Add(new FrostDKStrategyActionNodeFactory());
} }
NextAction** FrostDKStrategy::getDefaultActions() std::vector<NextAction> FrostDKStrategy::getDefaultActions()
{ {
return NextAction::array( return {
0, new NextAction("obliterate", ACTION_DEFAULT + 0.7f), NextAction("obliterate", ACTION_DEFAULT + 0.7f),
new NextAction("frost strike", ACTION_DEFAULT + 0.4f), NextAction("frost strike", ACTION_DEFAULT + 0.4f),
new NextAction("empower rune weapon", ACTION_DEFAULT + 0.3f), NextAction("empower rune weapon", ACTION_DEFAULT + 0.3f),
new NextAction("horn of winter", ACTION_DEFAULT + 0.1f), new NextAction("melee", ACTION_DEFAULT), NULL); NextAction("horn of winter", ACTION_DEFAULT + 0.1f),
NextAction("melee", ACTION_DEFAULT)
};
} }
void FrostDKStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void FrostDKStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
GenericDKStrategy::InitTriggers(triggers); GenericDKStrategy::InitTriggers(triggers);
triggers.push_back(new TriggerNode( triggers.push_back(
"unbreakable armor", NextAction::array(0, new NextAction("unbreakable armor", ACTION_DEFAULT + 0.6f), nullptr))); new TriggerNode(
"unbreakable armor",
triggers.push_back(new TriggerNode( {
"freezing fog", NextAction::array(0, new NextAction("howling blast", ACTION_DEFAULT + 0.5f), nullptr))); NextAction("unbreakable armor", ACTION_DEFAULT + 0.6f)
}
triggers.push_back(new TriggerNode( )
"high blood rune", NextAction::array(0, new NextAction("blood strike", ACTION_DEFAULT + 0.2f), nullptr))); );
triggers.push_back(new TriggerNode(
"army of the dead", NextAction::array(0, new NextAction("army of the dead", ACTION_HIGH + 6), nullptr)));
triggers.push_back( triggers.push_back(
new TriggerNode("icy touch", NextAction::array(0, new NextAction("icy touch", ACTION_HIGH + 2), nullptr))); new TriggerNode(
triggers.push_back(new TriggerNode( "freezing fog",
"plague strike", NextAction::array(0, new NextAction("plague strike", ACTION_HIGH + 2), nullptr))); {
// triggers.push_back(new TriggerNode("empower rune weapon", NextAction::array(0, new NextAction("empower rune NextAction("howling blast", ACTION_DEFAULT + 0.5f)
// weapon", ACTION_NORMAL + 4), nullptr))); }
)
);
triggers.push_back(
new TriggerNode(
"high blood rune",
{
NextAction("blood strike", ACTION_DEFAULT + 0.2f)
}
)
);
triggers.push_back(
new TriggerNode(
"army of the dead",
{
NextAction("army of the dead", ACTION_HIGH + 6)
}
)
);
triggers.push_back(
new TriggerNode(
"icy touch",
{
NextAction("icy touch", ACTION_HIGH + 2)
}
)
);
triggers.push_back(
new TriggerNode(
"plague strike",
{
NextAction("plague strike", ACTION_HIGH + 2)
}
)
);
} }
void FrostDKAoeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void FrostDKAoeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back( triggers.push_back(
new TriggerNode("medium aoe", NextAction::array(0, new NextAction("howling blast", ACTION_HIGH + 4), nullptr))); new TriggerNode(
"medium aoe",
{
NextAction("howling blast", ACTION_HIGH + 4)
}
)
);
} }

View File

@@ -17,7 +17,7 @@ public:
void InitTriggers(std::vector<TriggerNode*>& triggers) override; void InitTriggers(std::vector<TriggerNode*>& triggers) override;
std::string const getName() override { return "frost"; } std::string const getName() override { return "frost"; }
NextAction** getDefaultActions() override; std::vector<NextAction> getDefaultActions() override;
uint32 GetType() const override { return STRATEGY_TYPE_COMBAT | STRATEGY_TYPE_DPS | STRATEGY_TYPE_MELEE; } uint32 GetType() const override { return STRATEGY_TYPE_COMBAT | STRATEGY_TYPE_DPS | STRATEGY_TYPE_MELEE; }
}; };

View File

@@ -20,17 +20,17 @@ private:
static ActionNode* bone_shield([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* bone_shield([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("bone shield", return new ActionNode("bone shield",
/*P*/ nullptr, /*P*/ {},
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* horn_of_winter([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* horn_of_winter([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("horn of winter", return new ActionNode("horn of winter",
/*P*/ nullptr, /*P*/ {},
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
}; };
@@ -44,19 +44,18 @@ void GenericDKNonCombatStrategy::InitTriggers(std::vector<TriggerNode*>& trigger
NonCombatStrategy::InitTriggers(triggers); NonCombatStrategy::InitTriggers(triggers);
triggers.push_back( triggers.push_back(
new TriggerNode("no pet", NextAction::array(0, new NextAction("raise dead", ACTION_NORMAL + 1), nullptr))); new TriggerNode("no pet", { NextAction("raise dead", ACTION_NORMAL + 1) }));
triggers.push_back( triggers.push_back(
new TriggerNode("horn of winter", NextAction::array(0, new NextAction("horn of winter", 21.0f), nullptr))); new TriggerNode("horn of winter", { NextAction("horn of winter", 21.0f) }));
triggers.push_back( triggers.push_back(
new TriggerNode("bone shield", NextAction::array(0, new NextAction("bone shield", 21.0f), nullptr))); new TriggerNode("bone shield", { NextAction("bone shield", 21.0f) }));
triggers.push_back( triggers.push_back(
new TriggerNode("has pet", NextAction::array(0, new NextAction("toggle pet spell", 60.0f), NULL))); new TriggerNode("has pet", { NextAction("toggle pet spell", 60.0f) }));
triggers.push_back( triggers.push_back(
new TriggerNode("new pet", NextAction::array(0, new NextAction("set pet stance", 60.0f), NULL))); new TriggerNode("new pet", { NextAction("set pet stance", 60.0f) }));
} }
void DKBuffDpsStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void DKBuffDpsStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
// triggers.push_back(new TriggerNode("improved icy talons", NextAction::array(0, new NextAction("improved icy
// talons", 19.0f), nullptr)));
} }

View File

@@ -54,105 +54,105 @@ private:
static ActionNode* death_coil([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* death_coil([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("death coil", return new ActionNode("death coil",
/*P*/ nullptr, /*P*/ {},
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* death_grip([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* death_grip([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("death grip", return new ActionNode("death grip",
/*P*/ nullptr, /*P*/ {},
/*A*/ NextAction::array(0, new NextAction("icy touch"), nullptr), /*A*/ { NextAction("icy touch") },
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* plague_strike([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* plague_strike([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("plague strike", return new ActionNode("plague strike",
/*P*/ nullptr, /*P*/ {},
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* icy_touch([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* icy_touch([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("icy touch", return new ActionNode("icy touch",
/*P*/ nullptr, /*P*/ {},
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* heart_strike([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* heart_strike([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("heart strike", return new ActionNode("heart strike",
/*P*/ nullptr, /*P*/ {},
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* pestilence([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* pestilence([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("pestilence", return new ActionNode("pestilence",
/*P*/ nullptr, /*P*/ {},
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* horn_of_winter([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* horn_of_winter([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("horn of winter", return new ActionNode("horn of winter",
/*P*/ nullptr, /*P*/ {},
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* bone_shield([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* bone_shield([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("bone shield", return new ActionNode("bone shield",
/*P*/ nullptr, /*P*/ {},
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* killing_machine([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* killing_machine([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("killing machine", return new ActionNode("killing machine",
/*P*/ nullptr, /*P*/ {},
/*A*/ NextAction::array(0, new NextAction("improved icy talons"), nullptr), /*A*/ { NextAction("improved icy talons") },
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* corpse_explosion([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* corpse_explosion([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("corpse explosion", return new ActionNode("corpse explosion",
/*P*/ nullptr, /*P*/ {},
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* death_and_decay([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* death_and_decay([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("death and decay", return new ActionNode("death and decay",
/*P*/ nullptr, /*P*/ {},
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* anti_magic_zone([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* anti_magic_zone([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("anti magic zone", return new ActionNode("anti magic zone",
/*P*/ nullptr, /*P*/ {},
/*A*/ NextAction::array(0, new NextAction("anti magic shell"), nullptr), /*A*/ { NextAction("anti magic shell") },
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* icebound_fortitude([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* icebound_fortitude([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("icebound fortitude", return new ActionNode("icebound fortitude",
/*P*/ nullptr, /*P*/ {},
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
}; };
@@ -165,36 +165,29 @@ void GenericDKStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
MeleeCombatStrategy::InitTriggers(triggers); MeleeCombatStrategy::InitTriggers(triggers);
// triggers.push_back(new TriggerNode("high aoe", NextAction::array(0, new NextAction("anti magic shell",
// ACTION_NORMAL + 3), nullptr))); triggers.push_back(new TriggerNode("death coil", NextAction::array(0, new
// NextAction("death coil", ACTION_NORMAL + 3), nullptr))); triggers.push_back(new TriggerNode("critical aoe heal",
// NextAction::array(0, new NextAction("anti magic zone", ACTION_EMERGENCY + 1), nullptr)));
triggers.push_back( triggers.push_back(
new TriggerNode("no pet", NextAction::array(0, new NextAction("raise dead", ACTION_NORMAL + 5), nullptr))); new TriggerNode("no pet", { NextAction("raise dead", ACTION_NORMAL + 5) }));
triggers.push_back( triggers.push_back(
new TriggerNode("has pet", NextAction::array(0, new NextAction("toggle pet spell", 60.0f), nullptr))); new TriggerNode("has pet", { NextAction("toggle pet spell", 60.0f) }));
triggers.push_back( triggers.push_back(
new TriggerNode("new pet", NextAction::array(0, new NextAction("set pet stance", 60.0f), nullptr))); new TriggerNode("new pet", { NextAction("set pet stance", 60.0f) }));
triggers.push_back( triggers.push_back(
new TriggerNode("mind freeze", NextAction::array(0, new NextAction("mind freeze", ACTION_HIGH + 1), nullptr))); new TriggerNode("mind freeze", { NextAction("mind freeze", ACTION_HIGH + 1) }));
triggers.push_back( triggers.push_back(
new TriggerNode("mind freeze on enemy healer", new TriggerNode("mind freeze on enemy healer",
NextAction::array(0, new NextAction("mind freeze on enemy healer", ACTION_HIGH + 1), nullptr))); { NextAction("mind freeze on enemy healer", ACTION_HIGH + 1) }));
triggers.push_back(new TriggerNode( triggers.push_back(new TriggerNode(
"horn of winter", NextAction::array(0, new NextAction("horn of winter", ACTION_NORMAL + 1), nullptr))); "horn of winter", { NextAction("horn of winter", ACTION_NORMAL + 1) }));
triggers.push_back(new TriggerNode("critical health", triggers.push_back(new TriggerNode("critical health",
NextAction::array(0, new NextAction("death pact", ACTION_HIGH + 5), nullptr))); { NextAction("death pact", ACTION_HIGH + 5) }));
triggers.push_back( triggers.push_back(
new TriggerNode("low health", NextAction::array(0, new NextAction("icebound fortitude", ACTION_HIGH + 5), new TriggerNode("low health", { NextAction("icebound fortitude", ACTION_HIGH + 5),
new NextAction("rune tap", ACTION_HIGH + 4), nullptr))); NextAction("rune tap", ACTION_HIGH + 4) }));
triggers.push_back( triggers.push_back(
new TriggerNode("medium aoe", NextAction::array(0, new NextAction("death and decay", ACTION_HIGH + 9), new TriggerNode("medium aoe", { NextAction("death and decay", ACTION_HIGH + 9),
new NextAction("pestilence", ACTION_NORMAL + 4), NextAction("pestilence", ACTION_NORMAL + 4),
new NextAction("blood boil", ACTION_NORMAL + 3), nullptr))); NextAction("blood boil", ACTION_NORMAL + 3) }));
// triggers.push_back(new TriggerNode("light aoe", NextAction::array(0,
// new NextAction("pestilence", ACTION_NORMAL + 4),
// nullptr)));
triggers.push_back( triggers.push_back(
new TriggerNode("pestilence glyph", NextAction::array(0, new NextAction("pestilence", ACTION_HIGH + 9), NULL))); new TriggerNode("pestilence glyph", { NextAction("pestilence", ACTION_HIGH + 9) }));
} }

View File

@@ -1,4 +1,4 @@
#/* /*
* 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. * 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.
*/ */
@@ -11,21 +11,8 @@ class UnholyDKStrategyActionNodeFactory : public NamedObjectFactory<ActionNode>
public: public:
UnholyDKStrategyActionNodeFactory() UnholyDKStrategyActionNodeFactory()
{ {
// Unholy
// creators["bone shield"] = &bone_shield;
// creators["plague strike"] = &plague_strike;
// creators["death grip"] = &death_grip;
// creators["death coil"] = &death_coil;
creators["death strike"] = &death_strike; creators["death strike"] = &death_strike;
// creators["unholy blight"] = &unholy_blight;
creators["scourge strike"] = &scourge_strike; creators["scourge strike"] = &scourge_strike;
// creators["death and decay"] = &death_and_decay;
// creators["unholy pressence"] = &unholy_pressence;
// creators["raise dead"] = &raise_dead;
// creators["army of the dead"] = &army of the dead;
// creators["summon gargoyle"] = &army of the dead;
// creators["anti magic shell"] = &anti_magic_shell;
// creators["anti magic zone"] = &anti_magic_zone;
creators["ghoul frenzy"] = &ghoul_frenzy; creators["ghoul frenzy"] = &ghoul_frenzy;
creators["corpse explosion"] = &corpse_explosion; creators["corpse explosion"] = &corpse_explosion;
creators["icy touch"] = &icy_touch; creators["icy touch"] = &icy_touch;
@@ -34,39 +21,49 @@ public:
private: private:
static ActionNode* death_strike([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* death_strike([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("death strike", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("blood presence"), nullptr), "death strike",
/*A*/ nullptr, /*P*/ { NextAction("blood presence") },
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* ghoul_frenzy([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* ghoul_frenzy([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("ghoul frenzy", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("blood presence"), nullptr), "ghoul frenzy",
/*A*/ nullptr, /*P*/ { NextAction("blood presence") },
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* corpse_explosion([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* corpse_explosion([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("corpse explosion", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("blood presence"), nullptr), "corpse explosion",
/*A*/ nullptr, /*P*/ { NextAction("blood presence") },
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* scourge_strike([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* scourge_strike([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("scourge strike", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("blood presence"), nullptr), "scourge strike",
/*A*/ nullptr, /*P*/ { NextAction("blood presence") },
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* icy_touch([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* icy_touch([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("icy touch", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("blood presence"), nullptr), "icy touch",
/*A*/ nullptr, /*P*/ { NextAction("blood presence") },
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
}; };
@@ -75,69 +72,121 @@ UnholyDKStrategy::UnholyDKStrategy(PlayerbotAI* botAI) : GenericDKStrategy(botAI
actionNodeFactories.Add(new UnholyDKStrategyActionNodeFactory()); actionNodeFactories.Add(new UnholyDKStrategyActionNodeFactory());
} }
NextAction** UnholyDKStrategy::getDefaultActions() std::vector<NextAction> UnholyDKStrategy::getDefaultActions()
{ {
return NextAction::array( return {
0, new NextAction("death and decay", ACTION_HIGH + 5), NextAction("death and decay", ACTION_HIGH + 5),
new NextAction("summon gargoyle", ACTION_DEFAULT + 0.4f), NextAction("summon gargoyle", ACTION_DEFAULT + 0.4f),
// new NextAction("empower rune weapon", ACTION_DEFAULT + 0.3f), NextAction("horn of winter", ACTION_DEFAULT + 0.2f),
new NextAction("horn of winter", ACTION_DEFAULT + 0.2f), NextAction("death coil", ACTION_DEFAULT + 0.1f),
new NextAction("death coil", ACTION_DEFAULT + 0.1f), NextAction("melee", ACTION_DEFAULT)
new NextAction("melee", ACTION_DEFAULT), nullptr); };
} }
void UnholyDKStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void UnholyDKStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
GenericDKStrategy::InitTriggers(triggers); GenericDKStrategy::InitTriggers(triggers);
triggers.push_back(new TriggerNode(
"death and decay cooldown", NextAction::array(0,
new NextAction("ghoul frenzy", ACTION_DEFAULT + 0.9f),
new NextAction("scourge strike", ACTION_DEFAULT + 0.8f),
new NextAction("icy touch", ACTION_DEFAULT + 0.7f),
new NextAction("blood strike", ACTION_DEFAULT + 0.6f),
new NextAction("plague strike", ACTION_DEFAULT + 0.5f),
nullptr)));
triggers.push_back(new TriggerNode("dd cd and no desolation",
NextAction::array(0, new NextAction("blood strike", ACTION_DEFAULT + 0.75f), nullptr)));
// triggers.push_back(
// new TriggerNode("icy touch", NextAction::array(0, new NextAction("icy touch", ACTION_HIGH + 2), nullptr)));
// triggers.push_back(new TriggerNode(
// "plague strike", NextAction::array(0, new NextAction("plague strike", ACTION_HIGH + 1), nullptr)));
triggers.push_back(new TriggerNode(
"high frost rune", NextAction::array(0,
new NextAction("icy touch", ACTION_NORMAL + 3), nullptr)));
triggers.push_back(new TriggerNode(
"high blood rune", NextAction::array(0, new NextAction("blood strike", ACTION_NORMAL + 2), nullptr)));
triggers.push_back(new TriggerNode(
"high unholy rune", NextAction::array(0,
new NextAction("plague strike", ACTION_NORMAL + 1), nullptr)));
triggers.push_back( triggers.push_back(
new TriggerNode("dd cd and plague strike 3s", NextAction::array(0, new NextAction("plague strike", ACTION_HIGH + 1), nullptr))); new TriggerNode(
"death and decay cooldown",
{
NextAction("ghoul frenzy", ACTION_DEFAULT + 0.9f),
NextAction("scourge strike", ACTION_DEFAULT + 0.8f),
NextAction("icy touch", ACTION_DEFAULT + 0.7f),
NextAction("blood strike", ACTION_DEFAULT + 0.6f),
NextAction("plague strike", ACTION_DEFAULT + 0.5f),
}
)
);
triggers.push_back( triggers.push_back(
new TriggerNode("dd cd and icy touch 3s", NextAction::array(0, new NextAction("icy touch", ACTION_HIGH + 2), nullptr))); new TriggerNode(
"dd cd and no desolation",
{
NextAction("blood strike", ACTION_DEFAULT + 0.75f)
}
)
);
triggers.push_back( triggers.push_back(
new TriggerNode("no rune", NextAction::array(0, new NextAction("empower rune weapon", ACTION_HIGH + 1), nullptr))); new TriggerNode(
"high frost rune",
// triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction(, ACTION_NORMAL + 2), nullptr))); {
triggers.push_back(new TriggerNode( NextAction("icy touch", ACTION_NORMAL + 3)
"army of the dead", NextAction::array(0, new NextAction("army of the dead", ACTION_HIGH + 6), nullptr))); }
)
);
triggers.push_back( triggers.push_back(
new TriggerNode("bone shield", NextAction::array(0, new NextAction("bone shield", ACTION_HIGH + 3), nullptr))); new TriggerNode(
"high blood rune",
{
NextAction("blood strike", ACTION_NORMAL + 2)
}
)
);
triggers.push_back(
new TriggerNode(
"high unholy rune",
{
NextAction("plague strike", ACTION_NORMAL + 1)
}
)
);
triggers.push_back(
new TriggerNode("dd cd and plague strike 3s",
{
NextAction("plague strike", ACTION_HIGH + 1)
}
)
);
triggers.push_back(
new TriggerNode("dd cd and icy touch 3s",
{
NextAction("icy touch", ACTION_HIGH + 2)
}
)
);
triggers.push_back(
new TriggerNode("no rune",
{
NextAction("empower rune weapon", ACTION_HIGH + 1)
}
)
);
triggers.push_back(
new TriggerNode(
"army of the dead",
{
NextAction("army of the dead", ACTION_HIGH + 6)
}
)
);
triggers.push_back(
new TriggerNode("bone shield",
{
NextAction("bone shield", ACTION_HIGH + 3)
}
)
);
} }
void UnholyDKAoeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void UnholyDKAoeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode( triggers.push_back(
"loot available", NextAction::array(0, new NextAction("corpse explosion", ACTION_NORMAL + 1), nullptr))); new TriggerNode(
triggers.push_back(new TriggerNode( "loot available",
"medium aoe", NextAction::array(0, new NextAction("death and decay", ACTION_NORMAL + 3), {
new NextAction("corpse explosion", ACTION_NORMAL + 3), nullptr))); NextAction("corpse explosion", ACTION_NORMAL + 1)
}
)
);
triggers.push_back(
new TriggerNode(
"medium aoe",
{
NextAction("death and decay", ACTION_NORMAL + 3),
NextAction("corpse explosion", ACTION_NORMAL + 3)
}
)
);
} }

View File

@@ -17,7 +17,7 @@ public:
void InitTriggers(std::vector<TriggerNode*>& triggers) override; void InitTriggers(std::vector<TriggerNode*>& triggers) override;
std::string const getName() override { return "unholy"; } std::string const getName() override { return "unholy"; }
NextAction** getDefaultActions() override; std::vector<NextAction> getDefaultActions() override;
uint32 GetType() const override { return STRATEGY_TYPE_COMBAT | STRATEGY_TYPE_DPS | STRATEGY_TYPE_MELEE; } uint32 GetType() const override { return STRATEGY_TYPE_COMBAT | STRATEGY_TYPE_DPS | STRATEGY_TYPE_MELEE; }
}; };

View File

@@ -30,107 +30,132 @@ public:
private: private:
static ActionNode* melee([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* melee([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("melee", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("feral charge - bear"), nullptr), "melee",
/*A*/ nullptr, /*P*/ { NextAction("feral charge - bear") },
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* feral_charge_bear([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* feral_charge_bear([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("feral charge - bear", return new ActionNode(
/*P*/ nullptr, "feral charge - bear",
/*A*/ NextAction::array(0, new NextAction("reach melee"), nullptr), /*P*/ {},
/*C*/ nullptr); /*A*/ { NextAction("reach melee") },
/*C*/ {}
);
} }
static ActionNode* swipe_bear([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* swipe_bear([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("swipe (bear)", return new ActionNode(
/*P*/ nullptr, "swipe (bear)",
/*A*/ nullptr, /*P*/ {},
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* faerie_fire_feral([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* faerie_fire_feral([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("faerie fire (feral)", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("feral charge - bear"), nullptr), "faerie fire (feral)",
/*A*/ nullptr, /*P*/ { NextAction("feral charge - bear") },
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* bear_form([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* bear_form([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("bear form", return new ActionNode(
/*P*/ nullptr, "bear form",
/*A*/ nullptr, /*P*/ {},
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* dire_bear_form([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* dire_bear_form([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("dire bear form", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr), "dire bear form",
/*A*/ NextAction::array(0, new NextAction("bear form"), nullptr), /*P*/ { NextAction("caster form") },
/*C*/ nullptr); /*A*/ { NextAction("bear form") },
/*C*/ {}
);
} }
static ActionNode* mangle_bear([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* mangle_bear([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("mangle (bear)", return new ActionNode(
/*P*/ nullptr, "mangle (bear)",
// /*A*/ NextAction::array(0, new NextAction("lacerate"), nullptr), /*P*/ {},
nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {}
);
} }
static ActionNode* maul([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* maul([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("maul", return new ActionNode(
/*P*/ nullptr, "maul",
/*A*/ NextAction::array(0, new NextAction("melee"), nullptr), /*P*/ {},
/*C*/ nullptr); /*A*/ { NextAction("melee") },
/*C*/ {}
);
} }
static ActionNode* bash([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* bash([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("bash", return new ActionNode(
/*P*/ nullptr, "bash",
/*A*/ NextAction::array(0, new NextAction("melee"), nullptr), /*P*/ {},
/*C*/ nullptr); /*A*/ { NextAction("melee") },
/*C*/ {}
);
} }
static ActionNode* swipe([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* swipe([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("swipe", return new ActionNode(
/*P*/ nullptr, "swipe",
/*A*/ NextAction::array(0, new NextAction("melee"), nullptr), /*P*/ {},
/*C*/ nullptr); /*A*/ { NextAction("melee") },
/*C*/ {}
);
} }
static ActionNode* lacerate([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* lacerate([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("lacerate", return new ActionNode(
/*P*/ nullptr, "lacerate",
/*A*/ NextAction::array(0, new NextAction("maul"), nullptr), /*P*/ {},
/*C*/ nullptr); /*A*/ { NextAction("maul") },
/*C*/ {}
);
} }
static ActionNode* growl([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* growl([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("growl", return new ActionNode(
/*P*/ nullptr, "growl",
/*A*/ nullptr, /*P*/ {},
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* demoralizing_roar([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* demoralizing_roar([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("demoralizing roar", return new ActionNode(
/*P*/ nullptr, "demoralizing roar",
/*A*/ nullptr, /*P*/ {},
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
}; };
@@ -139,38 +164,93 @@ BearTankDruidStrategy::BearTankDruidStrategy(PlayerbotAI* botAI) : FeralDruidStr
actionNodeFactories.Add(new BearTankDruidStrategyActionNodeFactory()); actionNodeFactories.Add(new BearTankDruidStrategyActionNodeFactory());
} }
NextAction** BearTankDruidStrategy::getDefaultActions() std::vector<NextAction> BearTankDruidStrategy::getDefaultActions()
{ {
return NextAction::array( return {
0, new NextAction("mangle (bear)", ACTION_DEFAULT + 0.5f), NextAction("mangle (bear)", ACTION_DEFAULT + 0.5f),
new NextAction("faerie fire (feral)", ACTION_DEFAULT + 0.4f), new NextAction("lacerate", ACTION_DEFAULT + 0.3f), NextAction("faerie fire (feral)", ACTION_DEFAULT + 0.4f),
new NextAction("maul", ACTION_DEFAULT + 0.2f), new NextAction("enrage", ACTION_DEFAULT + 0.1f), NextAction("lacerate", ACTION_DEFAULT + 0.3f),
new NextAction("melee", ACTION_DEFAULT), nullptr); NextAction("maul", ACTION_DEFAULT + 0.2f),
NextAction("enrage", ACTION_DEFAULT + 0.1f),
NextAction("melee", ACTION_DEFAULT)
};
} }
void BearTankDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void BearTankDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
FeralDruidStrategy::InitTriggers(triggers); FeralDruidStrategy::InitTriggers(triggers);
triggers.push_back(new TriggerNode(
"enemy out of melee", NextAction::array(0, new NextAction("feral charge - bear", ACTION_NORMAL + 8), nullptr)));
// triggers.push_back(new TriggerNode("thorns", NextAction::array(0, new NextAction("thorns", ACTION_HIGH + 9),
// nullptr)));
triggers.push_back( triggers.push_back(
new TriggerNode("bear form", NextAction::array(0, new NextAction("dire bear form", ACTION_HIGH + 8), nullptr))); new TriggerNode(
triggers.push_back(new TriggerNode( "enemy out of melee",
"low health", NextAction::array(0, new NextAction("frenzied regeneration", ACTION_HIGH + 7), nullptr))); {
triggers.push_back(new TriggerNode( NextAction("feral charge - bear", ACTION_NORMAL + 8)
"faerie fire (feral)", NextAction::array(0, new NextAction("faerie fire (feral)", ACTION_HIGH + 7), nullptr))); }
triggers.push_back( )
new TriggerNode("lose aggro", NextAction::array(0, new NextAction("growl", ACTION_HIGH + 8), nullptr))); );
triggers.push_back( triggers.push_back(
new TriggerNode("medium aoe", NextAction::array(0, new NextAction("demoralizing roar", ACTION_HIGH + 6), new TriggerNode(
new NextAction("swipe (bear)", ACTION_HIGH + 6), nullptr))); "bear form",
triggers.push_back( {
new TriggerNode("light aoe", NextAction::array(0, new NextAction("swipe (bear)", ACTION_HIGH + 5), nullptr))); NextAction("dire bear form", ACTION_HIGH + 8)
triggers.push_back( }
new TriggerNode("bash", NextAction::array(0, new NextAction("bash", ACTION_INTERRUPT + 2), nullptr))); )
triggers.push_back( );
new TriggerNode("bash on enemy healer", triggers.push_back(
NextAction::array(0, new NextAction("bash on enemy healer", ACTION_INTERRUPT + 1), nullptr))); new TriggerNode(
"low health",
{
NextAction("frenzied regeneration", ACTION_HIGH + 7)
}
)
);
triggers.push_back(
new TriggerNode(
"faerie fire (feral)",
{
NextAction("faerie fire (feral)", ACTION_HIGH + 7)
}
)
);
triggers.push_back(
new TriggerNode(
"lose aggro",
{
NextAction("growl", ACTION_HIGH + 8)
}
)
);
triggers.push_back(
new TriggerNode(
"medium aoe",
{
NextAction("demoralizing roar", ACTION_HIGH + 6),
NextAction("swipe (bear)", ACTION_HIGH + 6)
}
)
);
triggers.push_back(
new TriggerNode(
"light aoe",
{
NextAction("swipe (bear)", ACTION_HIGH + 5)
}
)
);
triggers.push_back(
new TriggerNode(
"bash",
{
NextAction("bash", ACTION_INTERRUPT + 2)
}
)
);
triggers.push_back(
new TriggerNode(
"bash on enemy healer",
{
NextAction("bash on enemy healer", ACTION_INTERRUPT + 1)
}
)
);
} }

View File

@@ -17,7 +17,7 @@ public:
void InitTriggers(std::vector<TriggerNode*>& triggers) override; void InitTriggers(std::vector<TriggerNode*>& triggers) override;
std::string const getName() override { return "bear"; } std::string const getName() override { return "bear"; }
NextAction** getDefaultActions() override; std::vector<NextAction> getDefaultActions() override;
uint32 GetType() const override { return STRATEGY_TYPE_TANK | STRATEGY_TYPE_MELEE; } uint32 GetType() const override { return STRATEGY_TYPE_TANK | STRATEGY_TYPE_MELEE; }
}; };

View File

@@ -28,82 +28,102 @@ public:
private: private:
static ActionNode* faerie_fire([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* faerie_fire([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("faerie fire", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("moonkin form"), nullptr), "faerie fire",
/*A*/ nullptr, /*P*/ { NextAction("moonkin form") },
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* hibernate([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* hibernate([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("hibernate", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("moonkin form"), nullptr), "hibernate",
/*A*/ NextAction::array(0, new NextAction("entangling roots"), nullptr), /*P*/ { NextAction("moonkin form") },
/*C*/ nullptr); /*A*/ { NextAction("entangling roots") },
/*C*/ {}
);
} }
static ActionNode* entangling_roots([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* entangling_roots([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("entangling roots", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("moonkin form"), nullptr), "entangling roots",
/*A*/ nullptr, /*P*/ { NextAction("moonkin form") },
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* entangling_roots_on_cc([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* entangling_roots_on_cc([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("entangling roots on cc", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("moonkin form"), nullptr), "entangling roots on cc",
/*A*/ nullptr, /*P*/ { NextAction("moonkin form") },
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* wrath([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* wrath([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("wrath", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("moonkin form"), nullptr), "wrath",
/*A*/ nullptr, /*P*/ { NextAction("moonkin form") },
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* starfall([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* starfall([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("starfall", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("moonkin form"), nullptr), "starfall",
/*A*/ nullptr, /*P*/ { NextAction("moonkin form") },
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* insect_swarm([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* insect_swarm([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("insect swarm", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("moonkin form"), nullptr), "insect swarm",
/*A*/ nullptr, /*P*/ { NextAction("moonkin form") },
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* moonfire([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* moonfire([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("moonfire", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("moonkin form"), nullptr), "moonfire",
/*A*/ nullptr, /*P*/ { NextAction("moonkin form") },
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* starfire([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* starfire([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("starfire", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("moonkin form"), nullptr), "starfire",
/*A*/ nullptr, /*P*/ { NextAction("moonkin form") },
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* moonkin_form([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* moonkin_form([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("moonkin form", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr), "moonkin form",
/*A*/ nullptr, /*P*/ { NextAction("caster form") },
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
}; };
@@ -113,55 +133,122 @@ CasterDruidStrategy::CasterDruidStrategy(PlayerbotAI* botAI) : GenericDruidStrat
actionNodeFactories.Add(new ShapeshiftDruidStrategyActionNodeFactory()); actionNodeFactories.Add(new ShapeshiftDruidStrategyActionNodeFactory());
} }
NextAction** CasterDruidStrategy::getDefaultActions() std::vector<NextAction> CasterDruidStrategy::getDefaultActions()
{ {
return NextAction::array(0, return {
new NextAction("starfall", ACTION_HIGH + 1.0f), NextAction("starfall", ACTION_HIGH + 1.0f),
new NextAction("force of nature", ACTION_DEFAULT + 1.0f), NextAction("force of nature", ACTION_DEFAULT + 1.0f),
new NextAction("wrath", ACTION_DEFAULT + 0.1f), NextAction("wrath", ACTION_DEFAULT + 0.1f),
// new NextAction("starfire", ACTION_NORMAL), };
nullptr);
} }
void CasterDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void CasterDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
GenericDruidStrategy::InitTriggers(triggers); GenericDruidStrategy::InitTriggers(triggers);
// triggers.push_back(new TriggerNode("enemy out of spell", NextAction::array(0, new NextAction("reach spell",
// ACTION_MOVE), nullptr)));
triggers.push_back(new TriggerNode("eclipse (lunar) cooldown",
NextAction::array(0, new NextAction("starfire", ACTION_DEFAULT + 0.2f), nullptr)));
triggers.push_back(new TriggerNode("eclipse (solar) cooldown",
NextAction::array(0, new NextAction("wrath", ACTION_DEFAULT + 0.2f), nullptr)));
triggers.push_back(new TriggerNode(
"insect swarm", NextAction::array(0, new NextAction("insect swarm", ACTION_NORMAL + 5), nullptr)));
triggers.push_back( triggers.push_back(
new TriggerNode("moonfire", NextAction::array(0, new NextAction("moonfire", ACTION_NORMAL + 4), nullptr))); new TriggerNode(
"eclipse (lunar) cooldown",
{
NextAction("starfire", ACTION_DEFAULT + 0.2f)
}
)
);
triggers.push_back( triggers.push_back(
new TriggerNode("eclipse (solar)", NextAction::array(0, new NextAction("wrath", ACTION_NORMAL + 6), nullptr))); new TriggerNode(
triggers.push_back(new TriggerNode("eclipse (lunar)", "eclipse (solar) cooldown",
NextAction::array(0, new NextAction("starfire", ACTION_NORMAL + 6), nullptr))); {
NextAction("wrath", ACTION_DEFAULT + 0.2f)
}
)
);
triggers.push_back( triggers.push_back(
new TriggerNode("medium mana", NextAction::array(0, new NextAction("innervate", ACTION_HIGH + 9), nullptr))); new TriggerNode(
"insect swarm",
triggers.push_back(new TriggerNode("enemy too close for spell", {
NextAction::array(0, new NextAction("flee", ACTION_MOVE + 9), nullptr))); NextAction("insect swarm", ACTION_NORMAL + 5)
}
)
);
triggers.push_back(
new TriggerNode(
"moonfire",
{
NextAction("moonfire", ACTION_NORMAL + 4)
}
)
);
triggers.push_back(
new TriggerNode(
"eclipse (solar)",
{
NextAction("wrath", ACTION_NORMAL + 6)
}
)
);
triggers.push_back(
new TriggerNode(
"eclipse (lunar)",
{
NextAction("starfire", ACTION_NORMAL + 6)
}
)
);
triggers.push_back(
new TriggerNode(
"medium mana",
{
NextAction("innervate", ACTION_HIGH + 9)
}
)
);
triggers.push_back(
new TriggerNode(
"enemy too close for spell",
{
NextAction("flee", ACTION_MOVE + 9)
}
)
);
} }
void CasterDruidAoeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void CasterDruidAoeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back( triggers.push_back(
new TriggerNode("hurricane channel check", NextAction::array(0, new NextAction("cancel channel", ACTION_HIGH + 2), nullptr))); new TriggerNode(
"hurricane channel check",
{
NextAction("cancel channel", ACTION_HIGH + 2)
}
)
);
triggers.push_back( triggers.push_back(
new TriggerNode("medium aoe", NextAction::array(0, new NextAction("hurricane", ACTION_HIGH + 1), nullptr))); new TriggerNode(
triggers.push_back(new TriggerNode( "medium aoe",
"light aoe", NextAction::array(0, new NextAction("insect swarm on attacker", ACTION_NORMAL + 3), {
new NextAction("moonfire on attacker", ACTION_NORMAL + 3), NULL))); NextAction("hurricane", ACTION_HIGH + 1)
}
)
);
triggers.push_back(
new TriggerNode(
"light aoe",
{
NextAction("insect swarm on attacker", ACTION_NORMAL + 3),
NextAction("moonfire on attacker", ACTION_NORMAL + 3)
}
)
);
} }
void CasterDruidDebuffStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void CasterDruidDebuffStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back( triggers.push_back(
new TriggerNode("faerie fire", NextAction::array(0, new NextAction("faerie fire", ACTION_HIGH), nullptr))); new TriggerNode(
"faerie fire",
{
NextAction("faerie fire", ACTION_HIGH)
}
)
);
} }

View File

@@ -18,7 +18,7 @@ public:
public: public:
void InitTriggers(std::vector<TriggerNode*>& triggers) override; void InitTriggers(std::vector<TriggerNode*>& triggers) override;
std::string const getName() override { return "caster"; } std::string const getName() override { return "caster"; }
NextAction** getDefaultActions() override; std::vector<NextAction> getDefaultActions() override;
uint32 GetType() const override { return STRATEGY_TYPE_COMBAT | STRATEGY_TYPE_DPS | STRATEGY_TYPE_RANGED; } uint32 GetType() const override { return STRATEGY_TYPE_COMBAT | STRATEGY_TYPE_DPS | STRATEGY_TYPE_RANGED; }
}; };

View File

@@ -28,90 +28,112 @@ public:
private: private:
static ActionNode* faerie_fire_feral([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* faerie_fire_feral([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("faerie fire (feral)", return new ActionNode(
/*P*/ nullptr, "faerie fire (feral)",
/*A*/ nullptr, /*P*/ {},
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* melee([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* melee([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("melee", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("feral charge - cat"), nullptr), "melee",
/*A*/ nullptr, /*P*/ { NextAction("feral charge - cat") },
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* feral_charge_cat([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* feral_charge_cat([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("feral charge - cat", return new ActionNode(
/*P*/ nullptr, "feral charge - cat",
/*A*/ NextAction::array(0, new NextAction("reach melee"), nullptr), /*P*/ {},
/*C*/ nullptr); /*A*/ { NextAction("reach melee") },
/*C*/ {}
);
} }
static ActionNode* cat_form([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* cat_form([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("cat form", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr), "cat form",
/*A*/ nullptr, /*P*/ { NextAction("caster form") },
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* claw([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* claw([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("claw", return new ActionNode(
/*P*/ nullptr, "claw",
/*A*/ NextAction::array(0, new NextAction("melee"), nullptr), /*P*/ {},
/*C*/ nullptr); /*A*/ { NextAction("melee") },
/*C*/ {}
);
} }
static ActionNode* mangle_cat([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* mangle_cat([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("mangle (cat)", return new ActionNode(
/*P*/ nullptr, "mangle (cat)",
/*A*/ nullptr, /*P*/ {},
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* rake([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* rake([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("rake", return new ActionNode(
/*P*/ nullptr, "rake",
/*A*/ nullptr, /*P*/ {},
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* ferocious_bite([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* ferocious_bite([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("ferocious bite", return new ActionNode(
/*P*/ nullptr, "ferocious bite",
/*A*/ NextAction::array(0, new NextAction("rip"), nullptr), /*P*/ {},
/*C*/ nullptr); /*A*/ { NextAction("rip") },
/*C*/ {}
);
} }
static ActionNode* rip([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* rip([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("rip", return new ActionNode(
/*P*/ nullptr, "rip",
/*A*/ nullptr, /*P*/ {},
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* pounce([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* pounce([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("pounce", return new ActionNode(
/*P*/ nullptr, "pounce",
/*A*/ NextAction::array(0, new NextAction("ravage"), nullptr), /*P*/ {},
/*C*/ nullptr); /*A*/ { NextAction("ravage") },
/*C*/ {}
);
} }
static ActionNode* ravage([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* ravage([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("ravage", return new ActionNode(
/*P*/ nullptr, "ravage",
/*A*/ NextAction::array(0, new NextAction("shred"), nullptr), /*P*/ {},
/*C*/ nullptr); /*A*/ { NextAction("shred") },
/*C*/ {}
);
} }
}; };
@@ -120,9 +142,11 @@ CatDpsDruidStrategy::CatDpsDruidStrategy(PlayerbotAI* botAI) : FeralDruidStrateg
actionNodeFactories.Add(new CatDpsDruidStrategyActionNodeFactory()); actionNodeFactories.Add(new CatDpsDruidStrategyActionNodeFactory());
} }
NextAction** CatDpsDruidStrategy::getDefaultActions() std::vector<NextAction> CatDpsDruidStrategy::getDefaultActions()
{ {
return NextAction::array(0, new NextAction("tiger's fury", ACTION_DEFAULT + 0.1f), nullptr); return {
NextAction("tiger's fury", ACTION_DEFAULT + 0.1f)
};
} }
void CatDpsDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void CatDpsDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
@@ -130,50 +154,161 @@ void CatDpsDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
FeralDruidStrategy::InitTriggers(triggers); FeralDruidStrategy::InitTriggers(triggers);
// Default priority // Default priority
triggers.push_back(new TriggerNode("almost full energy available",
NextAction::array(0, new NextAction("shred", ACTION_DEFAULT + 0.4f), nullptr)));
triggers.push_back(new TriggerNode("combo points not full",
NextAction::array(0, new NextAction("shred", ACTION_DEFAULT + 0.4f), nullptr)));
triggers.push_back(new TriggerNode("almost full energy available",
NextAction::array(0, new NextAction("mangle (cat)", ACTION_DEFAULT + 0.3f), nullptr)));
triggers.push_back(new TriggerNode("combo points not full and high energy",
NextAction::array(0, new NextAction("mangle (cat)", ACTION_DEFAULT + 0.3f), nullptr)));
triggers.push_back(new TriggerNode("almost full energy available",
NextAction::array(0, new NextAction("claw", ACTION_DEFAULT + 0.2f), nullptr)));
triggers.push_back(new TriggerNode("combo points not full and high energy",
NextAction::array(0, new NextAction("claw", ACTION_DEFAULT + 0.2f), nullptr)));
triggers.push_back( triggers.push_back(
new TriggerNode("faerie fire (feral)", new TriggerNode(
NextAction::array(0, new NextAction("faerie fire (feral)", ACTION_DEFAULT + 0.0f), nullptr))); "almost full energy available",
{
NextAction("shred", ACTION_DEFAULT + 0.4f)
}
)
);
triggers.push_back(
new TriggerNode(
"combo points not full",
{
NextAction("shred", ACTION_DEFAULT + 0.4f)
}
)
);
triggers.push_back(
new TriggerNode(
"almost full energy available",
{
NextAction("mangle (cat)", ACTION_DEFAULT + 0.3f)
}
)
);
triggers.push_back(
new TriggerNode(
"combo points not full and high energy",
{
NextAction("mangle (cat)", ACTION_DEFAULT + 0.3f)
}
)
);
triggers.push_back(
new TriggerNode(
"almost full energy available",
{
NextAction("claw", ACTION_DEFAULT + 0.2f)
}
)
);
triggers.push_back(
new TriggerNode(
"combo points not full and high energy",
{
NextAction("claw", ACTION_DEFAULT + 0.2f)
}
)
);
triggers.push_back(
new TriggerNode(
"faerie fire (feral)",
{
NextAction("faerie fire (feral)", ACTION_DEFAULT + 0.0f)
}
)
);
// Main spell // Main spell
triggers.push_back( triggers.push_back(
new TriggerNode("cat form", NextAction::array(0, new NextAction("cat form", ACTION_HIGH + 8), nullptr))); new TriggerNode(
"cat form", {
NextAction("cat form", ACTION_HIGH + 8)
}
)
);
triggers.push_back( triggers.push_back(
new TriggerNode("savage roar", NextAction::array(0, new NextAction("savage roar", ACTION_HIGH + 7), nullptr))); new TriggerNode(
triggers.push_back(new TriggerNode("combo points available", "savage roar", {
NextAction::array(0, new NextAction("rip", ACTION_HIGH + 6), nullptr))); NextAction("savage roar", ACTION_HIGH + 7)
triggers.push_back(new TriggerNode( }
"ferocious bite time", NextAction::array(0, new NextAction("ferocious bite", ACTION_HIGH + 5), nullptr))); )
);
triggers.push_back( triggers.push_back(
new TriggerNode("target with combo points almost dead", new TriggerNode(
NextAction::array(0, new NextAction("ferocious bite", ACTION_HIGH + 4), nullptr))); "combo points available",
triggers.push_back(new TriggerNode("mangle (cat)", {
NextAction::array(0, new NextAction("mangle (cat)", ACTION_HIGH + 3), nullptr))); NextAction("rip", ACTION_HIGH + 6)
triggers.push_back(new TriggerNode("rake", NextAction::array(0, new NextAction("rake", ACTION_HIGH + 2), nullptr))); }
)
);
triggers.push_back( triggers.push_back(
new TriggerNode("medium threat", NextAction::array(0, new NextAction("cower", ACTION_HIGH + 1), nullptr))); new TriggerNode(
"ferocious bite time",
{
NextAction("ferocious bite", ACTION_HIGH + 5)
}
)
);
triggers.push_back(
new TriggerNode(
"target with combo points almost dead",
{
NextAction("ferocious bite", ACTION_HIGH + 4)
}
)
);
triggers.push_back(
new TriggerNode(
"mangle (cat)",
{
NextAction("mangle (cat)", ACTION_HIGH + 3)
}
)
);
triggers.push_back(
new TriggerNode(
"rake",
{
NextAction("rake", ACTION_HIGH + 2)
}
)
);
triggers.push_back(
new TriggerNode(
"medium threat",
{
NextAction("cower", ACTION_HIGH + 1)
}
)
);
// AOE // AOE
triggers.push_back( triggers.push_back(
new TriggerNode("medium aoe", NextAction::array(0, new NextAction("swipe (cat)", ACTION_HIGH + 3), nullptr))); new TriggerNode(
triggers.push_back(new TriggerNode( "medium aoe",
"light aoe", NextAction::array(0, new NextAction("rake on attacker", ACTION_HIGH + 2), nullptr))); {
// Reach target NextAction("swipe (cat)", ACTION_HIGH + 3)
triggers.push_back(new TriggerNode( }
"enemy out of melee", NextAction::array(0, new NextAction("feral charge - cat", ACTION_HIGH + 9), nullptr))); )
);
triggers.push_back( triggers.push_back(
new TriggerNode("enemy out of melee", NextAction::array(0, new NextAction("dash", ACTION_HIGH + 8), nullptr))); new TriggerNode(
"light aoe",
{
NextAction("rake on attacker", ACTION_HIGH + 2)
}
)
);
// Reach target
triggers.push_back(
new TriggerNode(
"enemy out of melee",
{
NextAction("feral charge - cat", ACTION_HIGH + 9)
}
)
);
triggers.push_back(
new TriggerNode(
"enemy out of melee",
{
NextAction("dash", ACTION_HIGH + 8)
}
)
);
} }
void CatAoeDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) {} void CatAoeDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) {}

View File

@@ -18,7 +18,7 @@ public:
public: public:
void InitTriggers(std::vector<TriggerNode*>& triggers) override; void InitTriggers(std::vector<TriggerNode*>& triggers) override;
std::string const getName() override { return "cat"; } std::string const getName() override { return "cat"; }
NextAction** getDefaultActions() override; std::vector<NextAction> getDefaultActions() override;
uint32 GetType() const override { return STRATEGY_TYPE_COMBAT | STRATEGY_TYPE_MELEE; } uint32 GetType() const override { return STRATEGY_TYPE_COMBAT | STRATEGY_TYPE_MELEE; }
}; };

View File

@@ -11,15 +11,15 @@
#include "AoeValues.h" #include "AoeValues.h"
#include "TargetValue.h" #include "TargetValue.h"
NextAction** CastAbolishPoisonAction::getAlternatives() std::vector<NextAction> CastAbolishPoisonAction::getAlternatives()
{ {
return NextAction::merge(NextAction::array(0, new NextAction("cure poison"), nullptr), return NextAction::merge({ NextAction("cure poison") },
CastSpellAction::getPrerequisites()); CastSpellAction::getPrerequisites());
} }
NextAction** CastAbolishPoisonOnPartyAction::getAlternatives() std::vector<NextAction> CastAbolishPoisonOnPartyAction::getAlternatives()
{ {
return NextAction::merge(NextAction::array(0, new NextAction("cure poison on party"), nullptr), return NextAction::merge({ NextAction("cure poison on party") },
CastSpellAction::getPrerequisites()); CastSpellAction::getPrerequisites());
} }
@@ -60,15 +60,15 @@ bool CastStarfallAction::isUseful()
return true; return true;
} }
NextAction** CastReviveAction::getPrerequisites() std::vector<NextAction> CastReviveAction::getPrerequisites()
{ {
return NextAction::merge(NextAction::array(0, new NextAction("caster form"), nullptr), return NextAction::merge({ NextAction("caster form") },
ResurrectPartyMemberAction::getPrerequisites()); ResurrectPartyMemberAction::getPrerequisites());
} }
NextAction** CastRebirthAction::getPrerequisites() std::vector<NextAction> CastRebirthAction::getPrerequisites()
{ {
return NextAction::merge(NextAction::array(0, new NextAction("caster form"), nullptr), return NextAction::merge({ NextAction("caster form") },
ResurrectPartyMemberAction::getPrerequisites()); ResurrectPartyMemberAction::getPrerequisites());
} }

View File

@@ -74,7 +74,7 @@ class CastReviveAction : public ResurrectPartyMemberAction
public: public:
CastReviveAction(PlayerbotAI* botAI) : ResurrectPartyMemberAction(botAI, "revive") {} CastReviveAction(PlayerbotAI* botAI) : ResurrectPartyMemberAction(botAI, "revive") {}
NextAction** getPrerequisites() override; std::vector<NextAction> getPrerequisites() override;
}; };
class CastRebirthAction : public ResurrectPartyMemberAction class CastRebirthAction : public ResurrectPartyMemberAction
@@ -82,7 +82,7 @@ class CastRebirthAction : public ResurrectPartyMemberAction
public: public:
CastRebirthAction(PlayerbotAI* botAI) : ResurrectPartyMemberAction(botAI, "rebirth") {} CastRebirthAction(PlayerbotAI* botAI) : ResurrectPartyMemberAction(botAI, "rebirth") {}
NextAction** getPrerequisites() override; std::vector<NextAction> getPrerequisites() override;
bool isUseful() override; bool isUseful() override;
}; };
@@ -223,7 +223,7 @@ class CastAbolishPoisonAction : public CastCureSpellAction
{ {
public: public:
CastAbolishPoisonAction(PlayerbotAI* botAI) : CastCureSpellAction(botAI, "abolish poison") {} CastAbolishPoisonAction(PlayerbotAI* botAI) : CastCureSpellAction(botAI, "abolish poison") {}
NextAction** getAlternatives() override; std::vector<NextAction> getAlternatives() override;
}; };
class CastAbolishPoisonOnPartyAction : public CurePartyMemberAction class CastAbolishPoisonOnPartyAction : public CurePartyMemberAction
@@ -233,7 +233,7 @@ public:
{ {
} }
NextAction** getAlternatives() override; std::vector<NextAction> getAlternatives() override;
}; };
class CastBarkskinAction : public CastBuffSpellAction class CastBarkskinAction : public CastBuffSpellAction

View File

@@ -17,9 +17,9 @@ bool CastBearFormAction::isUseful()
return CastBuffSpellAction::isUseful() && !botAI->HasAura("dire bear form", GetTarget()); return CastBuffSpellAction::isUseful() && !botAI->HasAura("dire bear form", GetTarget());
} }
NextAction** CastDireBearFormAction::getAlternatives() std::vector<NextAction> CastDireBearFormAction::getAlternatives()
{ {
return NextAction::merge(NextAction::array(0, new NextAction("bear form"), nullptr), return NextAction::merge({ NextAction("bear form") },
CastSpellAction::getAlternatives()); CastSpellAction::getAlternatives());
} }

View File

@@ -24,7 +24,7 @@ class CastDireBearFormAction : public CastBuffSpellAction
public: public:
CastDireBearFormAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "dire bear form") {} CastDireBearFormAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "dire bear form") {}
NextAction** getAlternatives() override; std::vector<NextAction> getAlternatives() override;
}; };
class CastCatFormAction : public CastBuffSpellAction class CastCatFormAction : public CastBuffSpellAction

View File

@@ -26,65 +26,65 @@ private:
static ActionNode* survival_instincts([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* survival_instincts([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("survival instincts", return new ActionNode("survival instincts",
/*P*/ nullptr, /*P*/ {},
/*A*/ NextAction::array(0, new NextAction("barkskin"), nullptr), /*A*/ { NextAction("barkskin") },
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* thorns([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* thorns([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("thorns", return new ActionNode("thorns",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr), /*P*/ { NextAction("caster form") },
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* omen_of_clarity([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* omen_of_clarity([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("omen of clarity", return new ActionNode("omen of clarity",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr), /*P*/ { NextAction("caster form") },
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* cure_poison([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* cure_poison([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("cure poison", return new ActionNode("cure poison",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr), /*P*/ { NextAction("caster form") },
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* cure_poison_on_party([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* cure_poison_on_party([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("cure poison on party", return new ActionNode("cure poison on party",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr), /*P*/ { NextAction("caster form") },
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* abolish_poison([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* abolish_poison([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("abolish poison", return new ActionNode("abolish poison",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr), /*P*/ { NextAction("caster form") },
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* abolish_poison_on_party([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* abolish_poison_on_party([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("abolish poison on party", return new ActionNode("abolish poison on party",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr), /*P*/ { NextAction("caster form") },
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* prowl([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* prowl([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("prowl", return new ActionNode("prowl",
/*P*/ NextAction::array(0, new NextAction("cat form"), nullptr), /*P*/ { NextAction("cat form") },
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
}; };
@@ -98,20 +98,16 @@ void FeralDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
GenericDruidStrategy::InitTriggers(triggers); GenericDruidStrategy::InitTriggers(triggers);
// triggers.push_back(new TriggerNode("not facing target", NextAction::array(0, new NextAction("set facing",
// ACTION_NORMAL + 7), nullptr)));
triggers.push_back(new TriggerNode( triggers.push_back(new TriggerNode(
"enemy out of melee", NextAction::array(0, new NextAction("reach melee", ACTION_HIGH + 1), nullptr))); "enemy out of melee", { NextAction("reach melee", ACTION_HIGH + 1) }));
// triggers.push_back(new TriggerNode("enemy too close for melee", NextAction::array(0, new NextAction("move out of
// enemy contact", ACTION_NORMAL + 8), nullptr)));
triggers.push_back(new TriggerNode( triggers.push_back(new TriggerNode(
"critical health", NextAction::array(0, new NextAction("survival instincts", ACTION_EMERGENCY + 1), nullptr))); "critical health", { NextAction("survival instincts", ACTION_EMERGENCY + 1) }));
triggers.push_back(new TriggerNode( triggers.push_back(new TriggerNode(
"omen of clarity", NextAction::array(0, new NextAction("omen of clarity", ACTION_HIGH + 9), nullptr))); "omen of clarity", { NextAction("omen of clarity", ACTION_HIGH + 9) }));
triggers.push_back(new TriggerNode("player has flag", triggers.push_back(new TriggerNode("player has flag",
NextAction::array(0, new NextAction("dash", ACTION_EMERGENCY + 2), nullptr))); { NextAction("dash", ACTION_EMERGENCY + 2) }));
triggers.push_back(new TriggerNode("enemy flagcarrier near", triggers.push_back(new TriggerNode("enemy flagcarrier near",
NextAction::array(0, new NextAction("dash", ACTION_EMERGENCY + 2), nullptr))); { NextAction("dash", ACTION_EMERGENCY + 2) }));
triggers.push_back( triggers.push_back(
new TriggerNode("berserk", NextAction::array(0, new NextAction("berserk", ACTION_HIGH + 6), nullptr))); new TriggerNode("berserk", { NextAction("berserk", ACTION_HIGH + 6) }));
} }

View File

@@ -27,49 +27,49 @@ private:
static ActionNode* regrowth([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* regrowth([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("regrowth", return new ActionNode("regrowth",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr), /*P*/ { NextAction("caster form") },
/*A*/ NextAction::array(0, new NextAction("healing touch"), nullptr), /*A*/ { NextAction("healing touch") },
/*C*/ NextAction::array(0, new NextAction("melee", 10.0f), nullptr)); /*C*/ { NextAction("melee", 10.0f) });
} }
static ActionNode* rejuvenation([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* rejuvenation([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("rejuvenation", return new ActionNode("rejuvenation",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr), /*P*/ { NextAction("caster form") },
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* healing_touch([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* healing_touch([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("healing touch", return new ActionNode("healing touch",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr), /*P*/ { NextAction("caster form") },
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* regrowth_on_party([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* regrowth_on_party([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("regrowth on party", return new ActionNode("regrowth on party",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr), /*P*/ { NextAction("caster form") },
/*A*/ NextAction::array(0, new NextAction("healing touch on party"), nullptr), /*A*/ { NextAction("healing touch on party") },
/*C*/ NextAction::array(0, new NextAction("melee", 10.0f), nullptr)); /*C*/ { NextAction("melee", 10.0f) });
} }
static ActionNode* rejuvenation_on_party([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* rejuvenation_on_party([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("rejuvenation on party", return new ActionNode("rejuvenation on party",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr), /*P*/ { NextAction("caster form") },
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* healing_touch_on_party([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* healing_touch_on_party([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("healing touch on party", return new ActionNode("healing touch on party",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr), /*P*/ { NextAction("caster form") },
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
}; };

View File

@@ -29,76 +29,69 @@ private:
static ActionNode* thorns([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* thorns([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("thorns", return new ActionNode("thorns",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr), /*P*/ { NextAction("caster form") },
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* thorns_on_party([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* thorns_on_party([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("thorns on party", return new ActionNode("thorns on party",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr), /*P*/ { NextAction("caster form") },
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* mark_of_the_wild([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* mark_of_the_wild([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("mark of the wild", return new ActionNode("mark of the wild",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr), /*P*/ { NextAction("caster form") },
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* mark_of_the_wild_on_party([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* mark_of_the_wild_on_party([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("mark of the wild on party", return new ActionNode("mark of the wild on party",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr), /*P*/ { NextAction("caster form") },
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* regrowth_on_party([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* regrowth_on_party([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("regrowth on party", return new ActionNode("regrowth on party",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr), /*P*/ { NextAction("caster form") },
/*A*/ NULL, /*A*/ {},
/*C*/ NULL); /*C*/ {});
} }
static ActionNode* rejuvenation_on_party([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* rejuvenation_on_party([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("rejuvenation on party", return new ActionNode("rejuvenation on party",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr), /*P*/ { NextAction("caster form") },
/*A*/ NULL, /*A*/ {},
/*C*/ NULL); /*C*/ {});
} }
static ActionNode* remove_curse_on_party([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* remove_curse_on_party([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("remove curse on party", return new ActionNode("remove curse on party",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr), /*P*/ { NextAction("caster form") },
/*A*/ NULL, /*A*/ {},
/*C*/ NULL); /*C*/ {});
} }
static ActionNode* abolish_poison_on_party([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* abolish_poison_on_party([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("abolish poison on party", return new ActionNode("abolish poison on party",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr), /*P*/ { NextAction("caster form") },
/*A*/ NULL, /*A*/ {},
/*C*/ NULL); /*C*/ {});
} }
static ActionNode* revive([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* revive([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("revive", return new ActionNode("revive",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr), /*P*/ { NextAction("caster form") },
/*A*/ NULL, /*A*/ {},
/*C*/ NULL); /*C*/ {});
} }
// static ActionNode* innervate([[maybe_unused]] PlayerbotAI* botAI)
// {
// return new ActionNode ("innervate",
// /*P*/ nullptr,
// /*A*/ NextAction::array(0, new NextAction("drink"), nullptr),
// /*C*/ nullptr);
// }
}; };
GenericDruidNonCombatStrategy::GenericDruidNonCombatStrategy(PlayerbotAI* botAI) : NonCombatStrategy(botAI) GenericDruidNonCombatStrategy::GenericDruidNonCombatStrategy(PlayerbotAI* botAI) : NonCombatStrategy(botAI)
@@ -110,79 +103,73 @@ void GenericDruidNonCombatStrategy::InitTriggers(std::vector<TriggerNode*>& trig
{ {
NonCombatStrategy::InitTriggers(triggers); NonCombatStrategy::InitTriggers(triggers);
triggers.push_back(new TriggerNode("mark of the wild", NextAction::array(0, new NextAction("mark of the wild", 14.0f), nullptr))); triggers.push_back(new TriggerNode("mark of the wild", { NextAction("mark of the wild", 14.0f) }));
// triggers.push_back(new TriggerNode("thorns", NextAction::array(0, new NextAction("thorns", 12.0f), nullptr))); triggers.push_back(new TriggerNode("party member cure poison", { NextAction("abolish poison on party", 20.0f) }));
// triggers.push_back(new TriggerNode("cure poison", NextAction::array(0, new NextAction("abolish poison", 21.0f), triggers.push_back(new TriggerNode("party member dead", { NextAction("revive", ACTION_CRITICAL_HEAL + 10) }));
// nullptr)));
triggers.push_back(new TriggerNode("party member cure poison", NextAction::array(0, new NextAction("abolish poison on party", 20.0f), nullptr)));
triggers.push_back(new TriggerNode("party member dead", NextAction::array(0, new NextAction("revive", ACTION_CRITICAL_HEAL + 10), nullptr)));
// triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("innervate", ACTION_EMERGENCY
// + 5), nullptr))); triggers.push_back(new TriggerNode("swimming", NextAction::array(0, new NextAction("aquatic
// form", 1.0f), nullptr)));
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("apply oil", 1.0f), nullptr))); triggers.push_back(new TriggerNode("often", { NextAction("apply oil", 1.0f) }));
triggers.push_back( triggers.push_back(
new TriggerNode("party member critical health", new TriggerNode("party member critical health",
NextAction::array(0, {
new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 7), NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 7),
new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 6), NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 6),
new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 5), NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 5),
nullptr))); }));
triggers.push_back( triggers.push_back(
new TriggerNode("party member low health", new TriggerNode("party member low health",
NextAction::array(0, {
new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 5), NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 5),
new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 4), NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 4),
new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 3), NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 3),
nullptr))); }));
triggers.push_back( triggers.push_back(
new TriggerNode("party member medium health", new TriggerNode("party member medium health",
NextAction::array(0, new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 3), { NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 3),
new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 2), NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 2),
new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 1), NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 1),
nullptr))); }));
triggers.push_back( triggers.push_back(
new TriggerNode("party member almost full health", new TriggerNode("party member almost full health",
NextAction::array(0, new NextAction("wild growth on party", ACTION_LIGHT_HEAL + 3), new NextAction("rejuvenation on party", ACTION_LIGHT_HEAL + 2), NULL))); { NextAction("wild growth on party", ACTION_LIGHT_HEAL + 3), NextAction("rejuvenation on party", ACTION_LIGHT_HEAL + 2) }));
triggers.push_back( triggers.push_back(
new TriggerNode("party member remove curse", new TriggerNode("party member remove curse",
NextAction::array(0, new NextAction("remove curse on party", ACTION_DISPEL + 7), nullptr))); { NextAction("remove curse on party", ACTION_DISPEL + 7) }));
triggers.push_back( triggers.push_back(
new TriggerNode("new pet", NextAction::array(0, new NextAction("set pet stance", 60.0f), nullptr))); new TriggerNode("new pet", { NextAction("set pet stance", 60.0f) }));
triggers.push_back(new TriggerNode("party member critical health", NextAction::array(0, triggers.push_back(new TriggerNode("party member critical health", {
new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 7), NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 7),
new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 6), NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 6),
new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 5), NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 5),
nullptr))); }));
triggers.push_back(new TriggerNode("party member low health", NextAction::array(0, triggers.push_back(new TriggerNode("party member low health", {
new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 5), NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 5),
new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 4), NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 4),
new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 3), NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 3),
nullptr))); }));
triggers.push_back(new TriggerNode("party member medium health", NextAction::array(0, triggers.push_back(new TriggerNode("party member medium health", {
new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 3), NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 3),
new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 2), NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 2),
new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 1), NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 1),
nullptr))); }));
triggers.push_back(new TriggerNode("party member almost full health", NextAction::array(0, triggers.push_back(new TriggerNode("party member almost full health", {
new NextAction("wild growth on party", ACTION_LIGHT_HEAL + 3), NextAction("wild growth on party", ACTION_LIGHT_HEAL + 3),
new NextAction("rejuvenation on party", ACTION_LIGHT_HEAL + 2), NextAction("rejuvenation on party", ACTION_LIGHT_HEAL + 2),
nullptr))); }));
triggers.push_back(new TriggerNode("party member remove curse", NextAction::array(0, triggers.push_back(new TriggerNode("party member remove curse", {
new NextAction("remove curse on party", ACTION_DISPEL + 7), NextAction("remove curse on party", ACTION_DISPEL + 7),
nullptr))); }));
int specTab = AiFactory::GetPlayerSpecTab(botAI->GetBot()); int specTab = AiFactory::GetPlayerSpecTab(botAI->GetBot());
if (specTab == 0 || specTab == 2) // Balance or Restoration if (specTab == 0 || specTab == 2) // Balance or Restoration
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("apply oil", 1.0f), nullptr))); triggers.push_back(new TriggerNode("often", { NextAction("apply oil", 1.0f) }));
if (specTab == 1) // Feral if (specTab == 1) // Feral
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("apply stone", 1.0f), nullptr))); triggers.push_back(new TriggerNode("often", { NextAction("apply stone", 1.0f) }));
} }
@@ -195,13 +182,13 @@ void GenericDruidBuffStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
NonCombatStrategy::InitTriggers(triggers); NonCombatStrategy::InitTriggers(triggers);
triggers.push_back(new TriggerNode("mark of the wild on party", NextAction::array(0, triggers.push_back(new TriggerNode("mark of the wild on party", {
new NextAction("mark of the wild on party", 13.0f), NextAction("mark of the wild on party", 13.0f),
nullptr))); }));
triggers.push_back(new TriggerNode("thorns on main tank", NextAction::array(0, triggers.push_back(new TriggerNode("thorns on main tank", {
new NextAction("thorns on main tank", 11.0f), NextAction("thorns on main tank", 11.0f),
nullptr))); }));
triggers.push_back(new TriggerNode("thorns", NextAction::array(0, triggers.push_back(new TriggerNode("thorns", {
new NextAction("thorns", 10.0f), NextAction("thorns", 10.0f),
nullptr))); }));
} }

View File

@@ -27,73 +27,73 @@ private:
static ActionNode* melee([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* melee([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("melee", return new ActionNode("melee",
/*P*/ nullptr, /*P*/ {},
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* caster_form([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* caster_form([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("caster form", return new ActionNode("caster form",
/*P*/ nullptr, /*P*/ {},
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* cure_poison([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* cure_poison([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("cure poison", return new ActionNode("cure poison",
/*P*/ nullptr, /*P*/ {},
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* cure_poison_on_party([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* cure_poison_on_party([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("cure poison on party", return new ActionNode("cure poison on party",
/*P*/ nullptr, /*P*/ {},
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* abolish_poison([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* abolish_poison([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("abolish poison", return new ActionNode("abolish poison",
/*P*/ nullptr, /*P*/ {},
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* abolish_poison_on_party([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* abolish_poison_on_party([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("abolish poison on party", return new ActionNode("abolish poison on party",
/*P*/ nullptr, /*P*/ {},
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* rebirth([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* rebirth([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("rebirth", return new ActionNode("rebirth",
/*P*/ nullptr, /*P*/ {},
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* entangling_roots_on_cc([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* entangling_roots_on_cc([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("entangling roots on cc", return new ActionNode("entangling roots on cc",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr), /*P*/ { NextAction("caster form") },
/*A*/ nullptr, /*A*/ {},
/*C*/ nullptr); /*C*/ {});
} }
static ActionNode* innervate([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* innervate([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("innervate", return new ActionNode("innervate",
/*P*/ nullptr, /*P*/ {},
/*A*/ NextAction::array(0, new NextAction("mana potion"), nullptr), /*A*/ { NextAction("mana potion") },
/*C*/ nullptr); /*C*/ {});
} }
}; };
@@ -107,70 +107,52 @@ void GenericDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
CombatStrategy::InitTriggers(triggers); CombatStrategy::InitTriggers(triggers);
triggers.push_back( triggers.push_back(
new TriggerNode("low health", NextAction::array(0, new NextAction("barkskin", ACTION_HIGH + 7), nullptr))); new TriggerNode("low health", { NextAction("barkskin", ACTION_HIGH + 7) }));
// triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("regrowth",
// ACTION_MEDIUM_HEAL + 2), nullptr))); triggers.push_back(new TriggerNode("party member low health",
// NextAction::array(0, new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 1), nullptr)));
// triggers.push_back(new TriggerNode("critical health", NextAction::array(0, new NextAction("regrowth",
// ACTION_CRITICAL_HEAL + 2), new NextAction("healing touch", ACTION_CRITICAL_HEAL + 2), nullptr)));
// triggers.push_back(new TriggerNode("party member critical health", NextAction::array(0, new NextAction("regrowth
// on party", ACTION_CRITICAL_HEAL + 1), new NextAction("healing touch on party", ACTION_CRITICAL_HEAL + 1),
// nullptr))); triggers.push_back(new TriggerNode("party member dead", NextAction::array(0, new
// NextAction("rebirth", ACTION_HIGH + 1), nullptr))); triggers.push_back(new TriggerNode("low mana",
// NextAction::array(0, new NextAction("innervate", ACTION_EMERGENCY + 5), nullptr)));
triggers.push_back(new TriggerNode("combat party member dead", triggers.push_back(new TriggerNode("combat party member dead",
NextAction::array(0, new NextAction("rebirth", ACTION_HIGH + 9), NULL))); { NextAction("rebirth", ACTION_HIGH + 9) }));
triggers.push_back(new TriggerNode("being attacked", triggers.push_back(new TriggerNode("being attacked",
NextAction::array(0, new NextAction("nature's grasp", ACTION_HIGH + 1), nullptr))); { NextAction("nature's grasp", ACTION_HIGH + 1) }));
triggers.push_back(new TriggerNode("new pet", NextAction::array(0, new NextAction("set pet stance", 60.0f), nullptr))); triggers.push_back(new TriggerNode("new pet", { NextAction("set pet stance", 60.0f) }));
} }
void DruidCureStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void DruidCureStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
// triggers.push_back(new TriggerNode("cure poison", NextAction::array(0, new NextAction("abolish poison",
// ACTION_DISPEL + 2), nullptr)));
triggers.push_back( triggers.push_back(
new TriggerNode("party member cure poison", new TriggerNode("party member cure poison",
NextAction::array(0, new NextAction("abolish poison on party", ACTION_DISPEL + 1), nullptr))); { NextAction("abolish poison on party", ACTION_DISPEL + 1) }));
triggers.push_back( triggers.push_back(
new TriggerNode("party member remove curse", new TriggerNode("party member remove curse",
NextAction::array(0, new NextAction("remove curse on party", ACTION_DISPEL + 7), NULL))); { NextAction("remove curse on party", ACTION_DISPEL + 7) }));
} }
void DruidBoostStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void DruidBoostStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode( triggers.push_back(new TriggerNode(
"nature's swiftness", NextAction::array(0, new NextAction("nature's swiftness", ACTION_HIGH + 9), nullptr))); "nature's swiftness", { NextAction("nature's swiftness", ACTION_HIGH + 9) }));
} }
void DruidCcStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void DruidCcStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode( triggers.push_back(new TriggerNode(
"entangling roots", NextAction::array(0, new NextAction("entangling roots on cc", ACTION_HIGH + 2), nullptr))); "entangling roots", { NextAction("entangling roots on cc", ACTION_HIGH + 2) }));
triggers.push_back(new TriggerNode( triggers.push_back(new TriggerNode(
"entangling roots kite", NextAction::array(0, new NextAction("entangling roots", ACTION_HIGH + 2), nullptr))); "entangling roots kite", { NextAction("entangling roots", ACTION_HIGH + 2) }));
triggers.push_back(new TriggerNode( triggers.push_back(new TriggerNode(
"hibernate", NextAction::array(0, new NextAction("hibernate on cc", ACTION_HIGH + 3), nullptr))); "hibernate", { NextAction("hibernate on cc", ACTION_HIGH + 3) }));
} }
void DruidHealerDpsStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void DruidHealerDpsStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back( triggers.push_back(
new TriggerNode("healer should attack", new TriggerNode("healer should attack",
NextAction::array(0, {
new NextAction("cancel tree form", ACTION_DEFAULT + 0.3f), NextAction("cancel tree form", ACTION_DEFAULT + 0.3f),
new NextAction("moonfire", ACTION_DEFAULT + 0.2f), NextAction("moonfire", ACTION_DEFAULT + 0.2f),
new NextAction("wrath", ACTION_DEFAULT + 0.1f), NextAction("wrath", ACTION_DEFAULT + 0.1f),
new NextAction("starfire", ACTION_DEFAULT), NextAction("starfire", ACTION_DEFAULT),
nullptr))); }));
// long cast time
// triggers.push_back(
// new TriggerNode("medium aoe and healer should attack",
// NextAction::array(0,
// new NextAction("hurricane", ACTION_DEFAULT + 0.7f),
// nullptr)));
} }

View File

@@ -12,40 +12,16 @@ class HealDruidStrategyActionNodeFactory : public NamedObjectFactory<ActionNode>
public: public:
HealDruidStrategyActionNodeFactory() { HealDruidStrategyActionNodeFactory() {
creators["nourish on party"] = &nourtish_on_party; creators["nourish on party"] = &nourtish_on_party;
// creators["wild growth on party"] = &wild_growth_on_party;
// creators["rejuvenation on party"] = &rejuvenation_on_party;
// creators["regrowth on party"] = &regrowth_on_party;
} }
private: private:
static ActionNode* nourtish_on_party([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* nourtish_on_party([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("nourish on party", return new ActionNode("nourish on party",
/*P*/ nullptr, /*P*/ {},
/*A*/ NextAction::array(0, new NextAction("healing touch on party"), nullptr), /*A*/ { NextAction("healing touch on party") },
/*C*/ nullptr); /*C*/ {});
} }
// static ActionNode* wild_growth_on_party([[maybe_unused]] PlayerbotAI* botAI)
// {
// return new ActionNode("wild growth on party",
// /*P*/ NextAction::array(0, new NextAction("tree form"), nullptr),
// /*A*/ nullptr,
// /*C*/ nullptr);
// }
// static ActionNode* rejuvenation_on_party([[maybe_unused]] PlayerbotAI* botAI)
// {
// return new ActionNode("rejuvenation on party",
// /*P*/ NextAction::array(0, new NextAction("tree form"), nullptr),
// /*A*/ nullptr,
// /*C*/ nullptr);
// }
// static ActionNode* regrowth_on_party([[maybe_unused]] PlayerbotAI* botAI)
// {
// return new ActionNode("regrowth on party",
// /*P*/ NextAction::array(0, new NextAction("tree form"), nullptr),
// /*A*/ nullptr,
// /*C*/ nullptr);
// }
}; };
HealDruidStrategy::HealDruidStrategy(PlayerbotAI* botAI) : GenericDruidStrategy(botAI) HealDruidStrategy::HealDruidStrategy(PlayerbotAI* botAI) : GenericDruidStrategy(botAI)
@@ -57,73 +33,69 @@ void HealDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
GenericDruidStrategy::InitTriggers(triggers); GenericDruidStrategy::InitTriggers(triggers);
// triggers.push_back(
// new TriggerNode("tree form", NextAction::array(0, new NextAction("tree form", ACTION_HIGH + 1), nullptr)));
triggers.push_back(new TriggerNode( triggers.push_back(new TriggerNode(
"party member to heal out of spell range", "party member to heal out of spell range",
NextAction::array(0, new NextAction("reach party member to heal", ACTION_CRITICAL_HEAL + 9), nullptr))); { NextAction("reach party member to heal", ACTION_CRITICAL_HEAL + 9) }));
// CRITICAL // CRITICAL
triggers.push_back( triggers.push_back(
new TriggerNode("party member critical health", new TriggerNode("party member critical health",
NextAction::array(0, {
new NextAction("tree form", ACTION_CRITICAL_HEAL + 4.1f), NextAction("tree form", ACTION_CRITICAL_HEAL + 4.1f),
new NextAction("swiftmend on party", ACTION_CRITICAL_HEAL + 4), NextAction("swiftmend on party", ACTION_CRITICAL_HEAL + 4),
new NextAction("regrowth on party", ACTION_CRITICAL_HEAL + 3), NextAction("regrowth on party", ACTION_CRITICAL_HEAL + 3),
new NextAction("wild growth on party", ACTION_CRITICAL_HEAL + 2), NextAction("wild growth on party", ACTION_CRITICAL_HEAL + 2),
new NextAction("nourish on party", ACTION_CRITICAL_HEAL + 1), NextAction("nourish on party", ACTION_CRITICAL_HEAL + 1),
// new NextAction("healing touch on party", ACTION_CRITICAL_HEAL + 0), }));
nullptr)));
triggers.push_back( triggers.push_back(
new TriggerNode("party member critical health", new TriggerNode("party member critical health",
NextAction::array(0, new NextAction("nature's swiftness", ACTION_CRITICAL_HEAL + 4), nullptr))); { NextAction("nature's swiftness", ACTION_CRITICAL_HEAL + 4) }));
triggers.push_back(new TriggerNode( triggers.push_back(new TriggerNode(
"group heal setting", "group heal setting",
NextAction::array(0, {
new NextAction("tree form", ACTION_MEDIUM_HEAL + 2.3f), NextAction("tree form", ACTION_MEDIUM_HEAL + 2.3f),
new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 2.2f), NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 2.2f),
new NextAction("rejuvenation on not full", ACTION_MEDIUM_HEAL + 2.1f), NextAction("rejuvenation on not full", ACTION_MEDIUM_HEAL + 2.1f),
nullptr))); }));
triggers.push_back( triggers.push_back(
new TriggerNode("medium group heal setting", new TriggerNode("medium group heal setting",
NextAction::array(0, {
new NextAction("tree form", ACTION_CRITICAL_HEAL + 0.6f), NextAction("tree form", ACTION_CRITICAL_HEAL + 0.6f),
new NextAction("tranquility", ACTION_CRITICAL_HEAL + 0.5f), nullptr))); NextAction("tranquility", ACTION_CRITICAL_HEAL + 0.5f) }));
// LOW // LOW
triggers.push_back( triggers.push_back(
new TriggerNode("party member low health", new TriggerNode("party member low health",
NextAction::array(0, new NextAction("tree form", ACTION_MEDIUM_HEAL + 1.5f), { NextAction("tree form", ACTION_MEDIUM_HEAL + 1.5f),
new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 1.4f), NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 1.4f),
new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 1.3f), NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 1.3f),
new NextAction("swiftmend on party", ACTION_MEDIUM_HEAL + 1.2), NextAction("swiftmend on party", ACTION_MEDIUM_HEAL + 1.2),
new NextAction("nourish on party", ACTION_MEDIUM_HEAL + 1.1f), NextAction("nourish on party", ACTION_MEDIUM_HEAL + 1.1f),
nullptr))); }));
// MEDIUM // MEDIUM
triggers.push_back( triggers.push_back(
new TriggerNode("party member medium health", new TriggerNode("party member medium health",
NextAction::array(0, {
new NextAction("tree form", ACTION_MEDIUM_HEAL + 0.5f), NextAction("tree form", ACTION_MEDIUM_HEAL + 0.5f),
new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 0.4f), NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 0.4f),
new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 0.3f), NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 0.3f),
new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 0.2f), NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 0.2f),
new NextAction("nourish on party", ACTION_MEDIUM_HEAL + 0.1f), nullptr))); NextAction("nourish on party", ACTION_MEDIUM_HEAL + 0.1f) }));
// almost full // almost full
triggers.push_back( triggers.push_back(
new TriggerNode("party member almost full health", new TriggerNode("party member almost full health",
NextAction::array(0, new NextAction("wild growth on party", ACTION_LIGHT_HEAL + 0.3f), { NextAction("wild growth on party", ACTION_LIGHT_HEAL + 0.3f),
new NextAction("rejuvenation on party", ACTION_LIGHT_HEAL + 0.2f), NextAction("rejuvenation on party", ACTION_LIGHT_HEAL + 0.2f),
new NextAction("regrowth on party", ACTION_LIGHT_HEAL + 0.1f), nullptr))); NextAction("regrowth on party", ACTION_LIGHT_HEAL + 0.1f) }));
triggers.push_back( triggers.push_back(
new TriggerNode("medium mana", NextAction::array(0, new NextAction("innervate", ACTION_HIGH + 5), nullptr))); new TriggerNode("medium mana", { NextAction("innervate", ACTION_HIGH + 5) }));
triggers.push_back(new TriggerNode("enemy too close for spell", triggers.push_back(new TriggerNode("enemy too close for spell",
NextAction::array(0, new NextAction("flee", ACTION_MOVE + 9), nullptr))); { NextAction("flee", ACTION_MOVE + 9) }));
} }

View File

@@ -9,16 +9,24 @@
MeleeDruidStrategy::MeleeDruidStrategy(PlayerbotAI* botAI) : CombatStrategy(botAI) {} MeleeDruidStrategy::MeleeDruidStrategy(PlayerbotAI* botAI) : CombatStrategy(botAI) {}
NextAction** MeleeDruidStrategy::getDefaultActions() std::vector<NextAction> MeleeDruidStrategy::getDefaultActions()
{ {
return NextAction::array(0, new NextAction("faerie fire", ACTION_DEFAULT + 0.1f), return {
new NextAction("melee", ACTION_DEFAULT), nullptr); NextAction("faerie fire", ACTION_DEFAULT + 0.1f),
NextAction("melee", ACTION_DEFAULT)
};
} }
void MeleeDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void MeleeDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode( triggers.push_back(
"omen of clarity", NextAction::array(0, new NextAction("omen of clarity", ACTION_HIGH + 9), nullptr))); new TriggerNode(
"omen of clarity",
{
NextAction("omen of clarity", ACTION_HIGH + 9)
}
)
);
CombatStrategy::InitTriggers(triggers); CombatStrategy::InitTriggers(triggers);
} }

View File

@@ -15,7 +15,7 @@ public:
void InitTriggers(std::vector<TriggerNode*>& triggers) override; void InitTriggers(std::vector<TriggerNode*>& triggers) override;
std::string const getName() override { return "melee"; } std::string const getName() override { return "melee"; }
NextAction** getDefaultActions() override; std::vector<NextAction> getDefaultActions() override;
}; };
#endif #endif

View File

@@ -29,90 +29,112 @@ public:
private: private:
static ActionNode* cat_form([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* cat_form([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("cat form", return new ActionNode(
/*P*/ nullptr, "cat form",
/*A*/ nullptr, /*P*/ {},
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* mangle_cat([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* mangle_cat([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("mangle (cat)", return new ActionNode(
/*P*/ nullptr, "mangle (cat)",
/*A*/ nullptr, /*P*/ {},
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* shred([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* shred([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("shred", return new ActionNode(
/*P*/ nullptr, "shred",
/*A*/ NextAction::array(0, new NextAction("claw"), nullptr), /*P*/ {},
/*C*/ nullptr); /*A*/ { NextAction("claw") },
/*C*/ {}
);
} }
static ActionNode* rake([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* rake([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("rake", return new ActionNode(
/*P*/ nullptr, "rake",
/*A*/ nullptr, /*P*/ {},
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* rip([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* rip([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("rip", return new ActionNode(
/*P*/ nullptr, "rip",
/*A*/ nullptr, /*P*/ {},
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* ferocious_bite([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* ferocious_bite([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("ferocious bite", return new ActionNode(
/*P*/ nullptr, "ferocious bite",
/*A*/ NextAction::array(0, new NextAction("rip"), nullptr), /*P*/ {},
/*C*/ nullptr); /*A*/ { NextAction("rip") },
/*C*/ {}
);
} }
static ActionNode* savage_roar([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* savage_roar([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("savage roar", return new ActionNode(
/*P*/ nullptr, "savage roar",
/*A*/ nullptr, /*P*/ {},
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* faerie_fire_feral([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* faerie_fire_feral([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("faerie fire (feral)", return new ActionNode(
/*P*/ nullptr, "faerie fire (feral)",
/*A*/ nullptr, /*P*/ {},
/*C*/ nullptr); /*A*/ {},
/*C*/ {}
);
} }
static ActionNode* healing_touch_on_party([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* healing_touch_on_party([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("healing touch on party", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr), "healing touch on party",
/*A*/ nullptr, /*P*/ { NextAction("caster form") },
/*C*/ NextAction::array(0, new NextAction("cat form"), nullptr)); /*A*/ {},
/*C*/ { NextAction("cat form") }
);
} }
static ActionNode* regrowth_on_party([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* regrowth_on_party([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("regrowth on party", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr), "regrowth on party",
/*A*/ nullptr, /*P*/ { NextAction("caster form") },
/*C*/ NextAction::array(0, new NextAction("cat form"), nullptr)); /*A*/ {},
/*C*/ { NextAction("cat form") }
);
} }
static ActionNode* rejuvenation_on_party([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* rejuvenation_on_party([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("rejuvenation on party", return new ActionNode(
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr), "rejuvenation on party",
/*A*/ nullptr, /*P*/ { NextAction("caster form") },
/*C*/ NextAction::array(0, new NextAction("cat form"), nullptr)); /*A*/ {},
/*C*/ { NextAction("cat form") }
);
} }
}; };
@@ -121,12 +143,15 @@ OffhealDruidCatStrategy::OffhealDruidCatStrategy(PlayerbotAI* botAI) : FeralDrui
actionNodeFactories.Add(new OffhealDruidCatStrategyActionNodeFactory()); actionNodeFactories.Add(new OffhealDruidCatStrategyActionNodeFactory());
} }
NextAction** OffhealDruidCatStrategy::getDefaultActions() std::vector<NextAction> OffhealDruidCatStrategy::getDefaultActions()
{ {
return NextAction::array(0, new NextAction("mangle (cat)", ACTION_DEFAULT + 0.5f), return {
new NextAction("shred", ACTION_DEFAULT + 0.4f), NextAction("mangle (cat)", ACTION_DEFAULT + 0.5f),
new NextAction("rake", ACTION_DEFAULT + 0.3f), new NextAction("melee", ACTION_DEFAULT), NextAction("shred", ACTION_DEFAULT + 0.4f),
new NextAction("cat form", ACTION_DEFAULT - 0.1f), nullptr); NextAction("rake", ACTION_DEFAULT + 0.3f),
NextAction("melee", ACTION_DEFAULT),
NextAction("cat form", ACTION_DEFAULT - 0.1f)
};
} }
void OffhealDruidCatStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void OffhealDruidCatStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
@@ -134,46 +159,149 @@ void OffhealDruidCatStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
FeralDruidStrategy::InitTriggers(triggers); FeralDruidStrategy::InitTriggers(triggers);
triggers.push_back( triggers.push_back(
new TriggerNode("cat form", NextAction::array(0, new NextAction("cat form", ACTION_HIGH + 8), nullptr))); new TriggerNode(
triggers.push_back( "cat form",
new TriggerNode("savage roar", NextAction::array(0, new NextAction("savage roar", ACTION_HIGH + 7), nullptr))); {
triggers.push_back(new TriggerNode("combo points available", NextAction("cat form", ACTION_HIGH + 8)
NextAction::array(0, new NextAction("rip", ACTION_HIGH + 6), nullptr))); }
triggers.push_back(new TriggerNode( )
"ferocious bite time", NextAction::array(0, new NextAction("ferocious bite", ACTION_HIGH + 5), nullptr))); );
triggers.push_back( triggers.push_back(
new TriggerNode("target with combo points almost dead", new TriggerNode(
NextAction::array(0, new NextAction("ferocious bite", ACTION_HIGH + 4), nullptr))); "savage roar",
triggers.push_back(new TriggerNode("mangle (cat)", {
NextAction::array(0, new NextAction("mangle (cat)", ACTION_HIGH + 3), nullptr))); NextAction("savage roar", ACTION_HIGH + 7)
triggers.push_back(new TriggerNode("rake", NextAction::array(0, new NextAction("rake", ACTION_HIGH + 2), nullptr))); }
triggers.push_back(new TriggerNode("almost full energy available", )
NextAction::array(0, new NextAction("shred", ACTION_DEFAULT + 0.4f), nullptr))); );
triggers.push_back(new TriggerNode("combo points not full", triggers.push_back(
NextAction::array(0, new NextAction("shred", ACTION_DEFAULT + 0.4f), nullptr))); new TriggerNode(
triggers.push_back(new TriggerNode( "combo points available",
"faerie fire (feral)", NextAction::array(0, new NextAction("faerie fire (feral)", ACTION_NORMAL), nullptr))); {
triggers.push_back(new TriggerNode("enemy out of melee", NextAction("rip", ACTION_HIGH + 6)
NextAction::array(0, new NextAction("feral charge - cat", ACTION_HIGH + 9), }
new NextAction("dash", ACTION_HIGH + 8), nullptr))); )
triggers.push_back( );
new TriggerNode("medium aoe", NextAction::array(0, new NextAction("swipe (cat)", ACTION_HIGH + 3), nullptr))); triggers.push_back(
triggers.push_back(new TriggerNode( new TriggerNode(
"low energy", NextAction::array(0, new NextAction("tiger's fury", ACTION_NORMAL + 1), nullptr))); "ferocious bite time",
{
triggers.push_back(new TriggerNode( NextAction("ferocious bite", ACTION_HIGH + 5)
"party member critical health", }
NextAction::array(0, new NextAction("regrowth on party", ACTION_CRITICAL_HEAL + 6), )
new NextAction("healing touch on party", ACTION_CRITICAL_HEAL + 5), nullptr))); );
triggers.push_back(new TriggerNode( triggers.push_back(
"party member low health", new TriggerNode(
NextAction::array(0, new NextAction("healing touch on party", ACTION_MEDIUM_HEAL + 5), nullptr))); "target with combo points almost dead",
triggers.push_back( {
new TriggerNode("party member medium health", NextAction("ferocious bite", ACTION_HIGH + 4)
NextAction::array(0, new NextAction("rejuvenation on party", ACTION_LIGHT_HEAL + 8), nullptr))); }
triggers.push_back(new TriggerNode( )
"party member to heal out of spell range", );
NextAction::array(0, new NextAction("reach party member to heal", ACTION_EMERGENCY + 3), nullptr))); triggers.push_back(
triggers.push_back( new TriggerNode(
new TriggerNode("low mana", NextAction::array(0, new NextAction("innervate", ACTION_HIGH + 4), nullptr))); "mangle (cat)",
{
NextAction("mangle (cat)", ACTION_HIGH + 3)
}
)
);
triggers.push_back(
new TriggerNode(
"rake",
{
NextAction("rake", ACTION_HIGH + 2)
}
)
);
triggers.push_back(
new TriggerNode(
"almost full energy available",
{
NextAction("shred", ACTION_DEFAULT + 0.4f)
}
)
);
triggers.push_back(
new TriggerNode(
"combo points not full",
{
NextAction("shred", ACTION_DEFAULT + 0.4f)
}
)
);
triggers.push_back(
new TriggerNode(
"faerie fire (feral)",
{
NextAction("faerie fire (feral)", ACTION_NORMAL)
}
)
);
triggers.push_back(
new TriggerNode(
"enemy out of melee",
{
NextAction("feral charge - cat", ACTION_HIGH + 9),
NextAction("dash", ACTION_HIGH + 8)
}
)
);
triggers.push_back(
new TriggerNode(
"medium aoe",
{
NextAction("swipe (cat)", ACTION_HIGH + 3)
}
)
);
triggers.push_back(
new TriggerNode(
"low energy",
{
NextAction("tiger's fury", ACTION_NORMAL + 1)
}
)
);
triggers.push_back(
new TriggerNode(
"party member critical health",
{
NextAction("regrowth on party", ACTION_CRITICAL_HEAL + 6),
NextAction("healing touch on party", ACTION_CRITICAL_HEAL + 5)
}
)
);
triggers.push_back(
new TriggerNode(
"party member low health",
{
NextAction("healing touch on party", ACTION_MEDIUM_HEAL + 5)
}
)
);
triggers.push_back(
new TriggerNode(
"party member medium health",
{
NextAction("rejuvenation on party", ACTION_LIGHT_HEAL + 8)
}
)
);
triggers.push_back(
new TriggerNode(
"party member to heal out of spell range",
{
NextAction("reach party member to heal", ACTION_EMERGENCY + 3)
}
)
);
triggers.push_back(
new TriggerNode(
"low mana",
{
NextAction("innervate", ACTION_HIGH + 4)
}
)
);
} }

View File

@@ -17,7 +17,7 @@
void InitTriggers(std::vector<TriggerNode*>& triggers) override; void InitTriggers(std::vector<TriggerNode*>& triggers) override;
std::string const getName() override { return "offheal"; } std::string const getName() override { return "offheal"; }
NextAction** getDefaultActions() override; std::vector<NextAction> getDefaultActions() override;
uint32 GetType() const override uint32 GetType() const override
{ {
return STRATEGY_TYPE_COMBAT | STRATEGY_TYPE_DPS | STRATEGY_TYPE_HEAL | STRATEGY_TYPE_MELEE; return STRATEGY_TYPE_COMBAT | STRATEGY_TYPE_DPS | STRATEGY_TYPE_HEAL | STRATEGY_TYPE_MELEE;

View File

@@ -7,9 +7,9 @@ void WotlkDungeonANStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
// TODO: Add CC trigger while web wraps are casting? // TODO: Add CC trigger while web wraps are casting?
// TODO: Bring healer closer than ranged dps to avoid fixates? // TODO: Bring healer closer than ranged dps to avoid fixates?
triggers.push_back(new TriggerNode("krik'thir web wrap", triggers.push_back(new TriggerNode("krik'thir web wrap",
NextAction::array(0, new NextAction("attack web wrap", ACTION_RAID + 5), nullptr))); { NextAction("attack web wrap", ACTION_RAID + 5) }));
triggers.push_back(new TriggerNode("krik'thir watchers", triggers.push_back(new TriggerNode("krik'thir watchers",
NextAction::array(0, new NextAction("krik'thir priority", ACTION_RAID + 4), nullptr))); { NextAction("krik'thir priority", ACTION_RAID + 4) }));
// Hadronox // Hadronox
// The core AC triggers are very buggy with this boss, but default strat seems to play correctly // The core AC triggers are very buggy with this boss, but default strat seems to play correctly
@@ -19,9 +19,9 @@ void WotlkDungeonANStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
// and cast time is instant so no way to check currently casting location. // and cast time is instant so no way to check currently casting location.
// May need to hook boss AI.. might be able to just heal through it for now. // May need to hook boss AI.. might be able to just heal through it for now.
// triggers.push_back(new TriggerNode("anub'arak impale", // triggers.push_back(new TriggerNode("anub'arak impale",
// NextAction::array(0, new NextAction("TODO", ACTION_MOVE + 5), nullptr))); // { NextAction("TODO", ACTION_MOVE + 5) }));
triggers.push_back(new TriggerNode("anub'arak pound", triggers.push_back(new TriggerNode("anub'arak pound",
NextAction::array(0, new NextAction("dodge pound", ACTION_MOVE + 5), nullptr))); { NextAction("dodge pound", ACTION_MOVE + 5) }));
} }
void WotlkDungeonANStrategy::InitMultipliers(std::vector<Multiplier*> &multipliers) void WotlkDungeonANStrategy::InitMultipliers(std::vector<Multiplier*> &multipliers)

View File

@@ -8,12 +8,12 @@ void WotlkDungeonCoSStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
// Salramm the Fleshcrafter // Salramm the Fleshcrafter
triggers.push_back(new TriggerNode("explode ghoul", triggers.push_back(new TriggerNode("explode ghoul",
NextAction::array(0, new NextAction("explode ghoul spread", ACTION_MOVE + 5), nullptr))); { NextAction("explode ghoul spread", ACTION_MOVE + 5) }));
// Chrono-Lord Epoch // Chrono-Lord Epoch
// Not sure if this actually works, I think I've seen him charge melee characters..? // Not sure if this actually works, I think I've seen him charge melee characters..?
triggers.push_back(new TriggerNode("epoch ranged", triggers.push_back(new TriggerNode("epoch ranged",
NextAction::array(0, new NextAction("epoch stack", ACTION_MOVE + 5), nullptr))); { NextAction("epoch stack", ACTION_MOVE + 5) }));
// Mal'Ganis // Mal'Ganis

View File

@@ -5,32 +5,32 @@ void WotlkDungeonDTKStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
{ {
// Trollgore // Trollgore
triggers.push_back(new TriggerNode("corpse explode", triggers.push_back(new TriggerNode("corpse explode",
NextAction::array(0, new NextAction("corpse explode spread", ACTION_MOVE + 5), nullptr))); { NextAction("corpse explode spread", ACTION_MOVE + 5) }));
// Novos the Summoner // Novos the Summoner
// TODO: Can be improved - it's a pretty easy fight but complex to program, revisit if needed // TODO: Can be improved - it's a pretty easy fight but complex to program, revisit if needed
triggers.push_back(new TriggerNode("arcane field", triggers.push_back(new TriggerNode("arcane field",
NextAction::array(0, new NextAction("avoid arcane field", ACTION_MOVE + 5), nullptr))); { NextAction("avoid arcane field", ACTION_MOVE + 5) }));
triggers.push_back(new TriggerNode("arcane field", triggers.push_back(new TriggerNode("arcane field",
NextAction::array(0, new NextAction("novos positioning", ACTION_MOVE + 4), nullptr))); { NextAction("novos positioning", ACTION_MOVE + 4) }));
triggers.push_back(new TriggerNode("arcane field", triggers.push_back(new TriggerNode("arcane field",
NextAction::array(0, new NextAction("novos target priority", ACTION_NORMAL + 1), nullptr))); { NextAction("novos target priority", ACTION_NORMAL + 1) }));
// King Dred // King Dred
// TODO: Fear ward / tremor totem, or general anti-fear strat development // TODO: Fear ward / tremor totem, or general anti-fear strat development
//The Prophet Tharon'ja //The Prophet Tharon'ja
triggers.push_back(new TriggerNode("gift of tharon'ja", triggers.push_back(new TriggerNode("gift of tharon'ja",
NextAction::array(0, new NextAction("touch of life", ACTION_NORMAL + 5), nullptr))); { NextAction("touch of life", ACTION_NORMAL + 5) }));
triggers.push_back(new TriggerNode("gift of tharon'ja", triggers.push_back(new TriggerNode("gift of tharon'ja",
NextAction::array(0, new NextAction("bone armor", ACTION_NORMAL + 4), nullptr))); { NextAction("bone armor", ACTION_NORMAL + 4) }));
// Run ranged chars (who would normally stand at range) into melee, to dps in skeleton form // Run ranged chars (who would normally stand at range) into melee, to dps in skeleton form
triggers.push_back(new TriggerNode("tharon'ja out of melee", triggers.push_back(new TriggerNode("tharon'ja out of melee",
NextAction::array(0, new NextAction("reach melee", ACTION_NORMAL + 3), nullptr))); { NextAction("reach melee", ACTION_NORMAL + 3) }));
triggers.push_back(new TriggerNode("gift of tharon'ja", triggers.push_back(new TriggerNode("gift of tharon'ja",
NextAction::array(0, new NextAction("taunt", ACTION_NORMAL + 2), nullptr))); { NextAction("taunt", ACTION_NORMAL + 2) }));
triggers.push_back(new TriggerNode("gift of tharon'ja", triggers.push_back(new TriggerNode("gift of tharon'ja",
NextAction::array(0, new NextAction("slaying strike", ACTION_NORMAL + 2), nullptr))); { NextAction("slaying strike", ACTION_NORMAL + 2) }));
} }
void WotlkDungeonDTKStrategy::InitMultipliers(std::vector<Multiplier*> &multipliers) void WotlkDungeonDTKStrategy::InitMultipliers(std::vector<Multiplier*> &multipliers)

View File

@@ -4,17 +4,16 @@
void WotlkDungeonFoSStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void WotlkDungeonFoSStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode("move from bronjahm", triggers.push_back(new TriggerNode("move from bronjahm",
NextAction::array(0, new NextAction("move from bronjahm", ACTION_MOVE + 5), nullptr))); { NextAction("move from bronjahm", ACTION_MOVE + 5) }));
triggers.push_back(new TriggerNode("switch to soul fragment", triggers.push_back(new TriggerNode("switch to soul fragment",
NextAction::array(0, new NextAction("attack corrupted soul fragment", ACTION_RAID + 2), nullptr))); { NextAction("attack corrupted soul fragment", ACTION_RAID + 2) }));
triggers.push_back(new TriggerNode("bronjahm position", triggers.push_back(new TriggerNode("bronjahm position",
NextAction::array(0, new NextAction("bronjahm group position", ACTION_RAID + 1), nullptr))); { NextAction("bronjahm group position", ACTION_RAID + 1) }));
triggers.push_back(new TriggerNode("devourer of souls", triggers.push_back(new TriggerNode("devourer of souls",
NextAction::array(0, new NextAction("devourer of souls", ACTION_RAID + 1), nullptr))); { NextAction("devourer of souls", ACTION_RAID + 1) }));
} }
void WotlkDungeonFoSStrategy::InitMultipliers(std::vector<Multiplier*>& multipliers) void WotlkDungeonFoSStrategy::InitMultipliers(std::vector<Multiplier*>& multipliers)
{ {
multipliers.push_back(new BronjahmMultiplier(botAI)); multipliers.push_back(new BronjahmMultiplier(botAI));
//multipliers.push_back(new AttackFragmentMultiplier(botAI));
} }

View File

@@ -11,13 +11,13 @@ void WotlkDungeonGDStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
// TODO: Might need to add target priority for heroic on the snakes or to burn down boss. // TODO: Might need to add target priority for heroic on the snakes or to burn down boss.
// Will re-test in heroic, decent dps groups should be able to blast him down with no funky strats. // Will re-test in heroic, decent dps groups should be able to blast him down with no funky strats.
triggers.push_back(new TriggerNode("poison nova", triggers.push_back(new TriggerNode("poison nova",
NextAction::array(0, new NextAction("avoid poison nova", ACTION_RAID + 5), nullptr))); { NextAction("avoid poison nova", ACTION_RAID + 5) }));
triggers.push_back(new TriggerNode("snake wrap", triggers.push_back(new TriggerNode("snake wrap",
NextAction::array(0, new NextAction("attack snake wrap", ACTION_RAID + 4), nullptr))); { NextAction("attack snake wrap", ACTION_RAID + 4) }));
// Gal'darah // Gal'darah
triggers.push_back(new TriggerNode("whirling slash", triggers.push_back(new TriggerNode("whirling slash",
NextAction::array(0, new NextAction("avoid whirling slash", ACTION_RAID + 5), nullptr))); { NextAction("avoid whirling slash", ACTION_RAID + 5) }));
// Eck the Ferocious (Heroic only) // Eck the Ferocious (Heroic only)
} }

View File

@@ -5,30 +5,30 @@ void WotlkDungeonHoLStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
{ {
// General Bjarngrim // General Bjarngrim
triggers.push_back(new TriggerNode("stormforged lieutenant", triggers.push_back(new TriggerNode("stormforged lieutenant",
NextAction::array(0, new NextAction("bjarngrim target", ACTION_RAID + 5), nullptr))); { NextAction("bjarngrim target", ACTION_RAID + 5) }));
triggers.push_back(new TriggerNode("whirlwind", triggers.push_back(new TriggerNode("whirlwind",
NextAction::array(0, new NextAction("avoid whirlwind", ACTION_RAID + 4), nullptr))); { NextAction("avoid whirlwind", ACTION_RAID + 4) }));
// Volkhan // Volkhan
triggers.push_back(new TriggerNode("volkhan", triggers.push_back(new TriggerNode("volkhan",
NextAction::array(0, new NextAction("volkhan target", ACTION_RAID + 5), nullptr))); { NextAction("volkhan target", ACTION_RAID + 5) }));
// Ionar // Ionar
triggers.push_back(new TriggerNode("ionar disperse", triggers.push_back(new TriggerNode("ionar disperse",
NextAction::array(0, new NextAction("disperse position", ACTION_MOVE + 5), nullptr))); { NextAction("disperse position", ACTION_MOVE + 5) }));
triggers.push_back(new TriggerNode("ionar tank aggro", triggers.push_back(new TriggerNode("ionar tank aggro",
NextAction::array(0, new NextAction("ionar tank position", ACTION_MOVE + 4), nullptr))); { NextAction("ionar tank position", ACTION_MOVE + 4) }));
triggers.push_back(new TriggerNode("static overload", triggers.push_back(new TriggerNode("static overload",
NextAction::array(0, new NextAction("static overload spread", ACTION_MOVE + 3), nullptr))); { NextAction("static overload spread", ACTION_MOVE + 3) }));
// TODO: Targeted player can dodge the ball, but a single player soaking it isn't too bad to heal // TODO: Targeted player can dodge the ball, but a single player soaking it isn't too bad to heal
triggers.push_back(new TriggerNode("ball lightning", triggers.push_back(new TriggerNode("ball lightning",
NextAction::array(0, new NextAction("ball lightning spread", ACTION_MOVE + 2), nullptr))); { NextAction("ball lightning spread", ACTION_MOVE + 2) }));
// Loken // Loken
triggers.push_back(new TriggerNode("lightning nova", triggers.push_back(new TriggerNode("lightning nova",
NextAction::array(0, new NextAction("avoid lightning nova", ACTION_MOVE + 5), nullptr))); { NextAction("avoid lightning nova", ACTION_MOVE + 5) }));
triggers.push_back(new TriggerNode("loken ranged", triggers.push_back(new TriggerNode("loken ranged",
NextAction::array(0, new NextAction("loken stack", ACTION_MOVE + 4), nullptr))); { NextAction("loken stack", ACTION_MOVE + 4) }));
} }
void WotlkDungeonHoLStrategy::InitMultipliers(std::vector<Multiplier*> &multipliers) void WotlkDungeonHoLStrategy::InitMultipliers(std::vector<Multiplier*> &multipliers)

View File

@@ -9,7 +9,7 @@ void WotlkDungeonHoSStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
// Krystallus // Krystallus
// TODO: I think bots need to dismiss pets on this, or they nuke players they are standing close to // TODO: I think bots need to dismiss pets on this, or they nuke players they are standing close to
triggers.push_back(new TriggerNode("ground slam", triggers.push_back(new TriggerNode("ground slam",
NextAction::array(0, new NextAction("shatter spread", ACTION_RAID + 5), nullptr))); { NextAction("shatter spread", ACTION_RAID + 5) }));
// Tribunal of Ages // Tribunal of Ages
// Seems fine, maybe add focus targeting strat if needed on heroic. // Seems fine, maybe add focus targeting strat if needed on heroic.
@@ -19,7 +19,7 @@ void WotlkDungeonHoSStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
// Sjonnir The Ironshaper // Sjonnir The Ironshaper
// Possibly tank in place in the middle of the room, assign a dps to adds? // Possibly tank in place in the middle of the room, assign a dps to adds?
triggers.push_back(new TriggerNode("lightning ring", triggers.push_back(new TriggerNode("lightning ring",
NextAction::array(0, new NextAction("avoid lightning ring", ACTION_RAID + 5), nullptr))); { NextAction("avoid lightning ring", ACTION_RAID + 5) }));
} }
void WotlkDungeonHoSStrategy::InitMultipliers(std::vector<Multiplier*> &multipliers) void WotlkDungeonHoSStrategy::InitMultipliers(std::vector<Multiplier*> &multipliers)

View File

@@ -7,39 +7,39 @@ void WotlkDungeonNexStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
// or // or
// Alliance Commander (Horde N)/Commander Stoutbeard (Horde H) // Alliance Commander (Horde N)/Commander Stoutbeard (Horde H)
triggers.push_back(new TriggerNode("faction commander whirlwind", triggers.push_back(new TriggerNode("faction commander whirlwind",
NextAction::array(0, new NextAction("move from whirlwind", ACTION_MOVE + 5), nullptr))); { NextAction("move from whirlwind", ACTION_MOVE + 5) }));
// TODO: Handle fear? (tremor totems, fear ward etc.) // TODO: Handle fear? (tremor totems, fear ward etc.)
// Grand Magus Telestra // Grand Magus Telestra
triggers.push_back(new TriggerNode("telestra firebomb", triggers.push_back(new TriggerNode("telestra firebomb",
NextAction::array(0, new NextAction("firebomb spread", ACTION_MOVE + 5), nullptr))); { NextAction("firebomb spread", ACTION_MOVE + 5) }));
triggers.push_back(new TriggerNode("telestra split phase", triggers.push_back(new TriggerNode("telestra split phase",
NextAction::array(0, new NextAction("telestra split target", ACTION_RAID + 1), nullptr))); { NextAction("telestra split target", ACTION_RAID + 1) }));
// TODO: Add priority interrupt on the frost split's Blizzard casts // TODO: Add priority interrupt on the frost split's Blizzard casts
// Anomalus // Anomalus
triggers.push_back(new TriggerNode("chaotic rift", triggers.push_back(new TriggerNode("chaotic rift",
NextAction::array(0, new NextAction("chaotic rift target", ACTION_RAID + 1), nullptr))); { NextAction("chaotic rift target", ACTION_RAID + 1) }));
// Ormorok the Tree-Shaper // Ormorok the Tree-Shaper
// Tank trigger to stack inside boss. Can also add return action to prevent boss repositioning // Tank trigger to stack inside boss. Can also add return action to prevent boss repositioning
// if it becomes too much of a problem. He usually dies before he's up against a wall though // if it becomes too much of a problem. He usually dies before he's up against a wall though
triggers.push_back(new TriggerNode("ormorok spikes", triggers.push_back(new TriggerNode("ormorok spikes",
NextAction::array(0, new NextAction("dodge spikes", ACTION_MOVE + 5), nullptr))); { NextAction("dodge spikes", ACTION_MOVE + 5) }));
// Non-tank trigger to stack. Avoiding the spikes at range is.. harder than it seems. // Non-tank trigger to stack. Avoiding the spikes at range is.. harder than it seems.
// TODO: This turns hunters into melee marshmallows, have not come up with a better solution yet // TODO: This turns hunters into melee marshmallows, have not come up with a better solution yet
triggers.push_back(new TriggerNode("ormorok stack", triggers.push_back(new TriggerNode("ormorok stack",
NextAction::array(0, new NextAction("dodge spikes", ACTION_MOVE + 5), nullptr))); { NextAction("dodge spikes", ACTION_MOVE + 5) }));
// TODO: Add handling for spell reflect... best to spam low level/weak spells but don't want // TODO: Add handling for spell reflect... best to spam low level/weak spells but don't want
// to hardcode spells per class, might be difficult to dynamically generate this. // to hardcode spells per class, might be difficult to dynamically generate this.
// Will revisit if I find my altbots killing themselves in heroic, just heal through it for now // Will revisit if I find my altbots killing themselves in heroic, just heal through it for now
// Keristrasza // Keristrasza
triggers.push_back(new TriggerNode("intense cold", triggers.push_back(new TriggerNode("intense cold",
NextAction::array(0, new NextAction("intense cold jump", ACTION_MOVE + 5), nullptr))); { NextAction("intense cold jump", ACTION_MOVE + 5) }));
// Flank dragon positioning // Flank dragon positioning
triggers.push_back(new TriggerNode("keristrasza positioning", triggers.push_back(new TriggerNode("keristrasza positioning",
NextAction::array(0, new NextAction("rear flank", ACTION_MOVE + 4), nullptr))); { NextAction("rear flank", ACTION_MOVE + 4) }));
// TODO: Add frost resist aura for paladins? // TODO: Add frost resist aura for paladins?
} }

View File

@@ -6,28 +6,28 @@ void WotlkDungeonOccStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
// Drakos the Interrogator // Drakos the Interrogator
// TODO: May need work, TBA. // TODO: May need work, TBA.
triggers.push_back(new TriggerNode("unstable sphere", triggers.push_back(new TriggerNode("unstable sphere",
NextAction::array(0, new NextAction("avoid unstable sphere", ACTION_MOVE + 5), nullptr))); { NextAction("avoid unstable sphere", ACTION_MOVE + 5) }));
// DRAKES // DRAKES
triggers.push_back(new TriggerNode("drake mount", triggers.push_back(new TriggerNode("drake mount",
NextAction::array(0, new NextAction("mount drake", ACTION_RAID + 5), nullptr))); { NextAction("mount drake", ACTION_RAID + 5) }));
triggers.push_back(new TriggerNode("drake dismount", triggers.push_back(new TriggerNode("drake dismount",
NextAction::array(0, new NextAction("dismount drake", ACTION_RAID + 5), nullptr))); { NextAction("dismount drake", ACTION_RAID + 5) }));
triggers.push_back(new TriggerNode("group flying", triggers.push_back(new TriggerNode("group flying",
NextAction::array(0, new NextAction("occ fly drake", ACTION_NORMAL + 1), nullptr))); { NextAction("occ fly drake", ACTION_NORMAL + 1) }));
triggers.push_back(new TriggerNode("drake combat", triggers.push_back(new TriggerNode("drake combat",
NextAction::array(0, new NextAction("occ drake attack", ACTION_NORMAL + 5), nullptr))); { NextAction("occ drake attack", ACTION_NORMAL + 5) }));
// Varos Cloudstrider // Varos Cloudstrider
// Seems to be no way to identify the marked cores, may need to hook boss AI.. // Seems to be no way to identify the marked cores, may need to hook boss AI..
// triggers.push_back(new TriggerNode("varos cloudstrider", // triggers.push_back(new TriggerNode("varos cloudstrider",
// NextAction::array(0, new NextAction("avoid energize cores", ACTION_RAID + 5), nullptr))); // { NextAction("avoid energize cores", ACTION_RAID + 5) }));
// Mage-Lord Urom // Mage-Lord Urom
triggers.push_back(new TriggerNode("arcane explosion", triggers.push_back(new TriggerNode("arcane explosion",
NextAction::array(0, new NextAction("avoid arcane explosion", ACTION_MOVE + 5), nullptr))); { NextAction("avoid arcane explosion", ACTION_MOVE + 5) }));
triggers.push_back(new TriggerNode("time bomb", triggers.push_back(new TriggerNode("time bomb",
NextAction::array(0, new NextAction("time bomb spread", ACTION_MOVE + 4), nullptr))); { NextAction("time bomb spread", ACTION_MOVE + 4) }));
// Ley-Guardian Eregos // Ley-Guardian Eregos
} }

View File

@@ -5,7 +5,7 @@ void WotlkDungeonOKStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
{ {
// Elder Nadox // Elder Nadox
triggers.push_back(new TriggerNode("nadox guardian", triggers.push_back(new TriggerNode("nadox guardian",
NextAction::array(0, new NextAction("attack nadox guardian", ACTION_RAID + 5), nullptr))); { NextAction("attack nadox guardian", ACTION_RAID + 5) }));
// Prince Taldaram // Prince Taldaram
// Flame Orb spawns in melee, doesn't have a clear direction until it starts moving. // Flame Orb spawns in melee, doesn't have a clear direction until it starts moving.
@@ -14,13 +14,13 @@ void WotlkDungeonOKStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
// Jedoga Shadowseeker // Jedoga Shadowseeker
triggers.push_back(new TriggerNode("jedoga volunteer", triggers.push_back(new TriggerNode("jedoga volunteer",
NextAction::array(0, new NextAction("attack jedoga volunteer", ACTION_RAID + 5), nullptr))); { NextAction("attack jedoga volunteer", ACTION_RAID + 5) }));
// Herald Volazj // Herald Volazj
// Trash mobs before him have a big telegraphed shadow crash spell, // Trash mobs before him have a big telegraphed shadow crash spell,
// this can be avoided and is intended to be dodged // this can be avoided and is intended to be dodged
triggers.push_back(new TriggerNode("shadow crash", triggers.push_back(new TriggerNode("shadow crash",
NextAction::array(0, new NextAction("avoid shadow crash", ACTION_MOVE + 5), nullptr))); { NextAction("avoid shadow crash", ACTION_MOVE + 5) }));
// Volazj is not implemented properly in AC, insanity phase does nothing. // Volazj is not implemented properly in AC, insanity phase does nothing.
// Amanitar (Heroic Only) // Amanitar (Heroic Only)

View File

@@ -4,14 +4,13 @@
void WotlkDungeonPoSStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void WotlkDungeonPoSStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode("ick and krick", triggers.push_back(new TriggerNode("ick and krick",
NextAction::array(0, new NextAction("ick and krick", ACTION_RAID + 5), nullptr))); { NextAction("ick and krick", ACTION_RAID + 5) }));
triggers.push_back(new TriggerNode("tyrannus", triggers.push_back(new TriggerNode("tyrannus",
NextAction::array(0, new NextAction("tyrannus", ACTION_RAID + 5), nullptr))); { NextAction("tyrannus", ACTION_RAID + 5) }));
} }
void WotlkDungeonPoSStrategy::InitMultipliers(std::vector<Multiplier*>& multipliers) void WotlkDungeonPoSStrategy::InitMultipliers(std::vector<Multiplier*>& multipliers)
{ {
multipliers.push_back(new IckAndKrickMultiplier(botAI)); multipliers.push_back(new IckAndKrickMultiplier(botAI));
//multipliers.push_back(new AttackFragmentMultiplier(botAI));
} }

View File

@@ -4,19 +4,18 @@
void WotlkDungeonToCStrategy::InitTriggers(std::vector<TriggerNode*> &triggers) void WotlkDungeonToCStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
{ {
triggers.push_back(new TriggerNode("toc lance", triggers.push_back(new TriggerNode("toc lance",
NextAction::array(0, new NextAction("toc lance", ACTION_RAID + 5), nullptr))); { NextAction("toc lance", ACTION_RAID + 5) }));
triggers.push_back(new TriggerNode("toc ue lance", triggers.push_back(new TriggerNode("toc ue lance",
NextAction::array(0, new NextAction("toc ue lance", ACTION_RAID + 2), nullptr))); { NextAction("toc ue lance", ACTION_RAID + 2) }));
triggers.push_back(new TriggerNode("toc mount near", triggers.push_back(new TriggerNode("toc mount near",
NextAction::array(0, new NextAction("toc mount", ACTION_RAID + 4), nullptr))); { NextAction("toc mount", ACTION_RAID + 4) }));
triggers.push_back(new TriggerNode("toc mounted", triggers.push_back(new TriggerNode("toc mounted",
NextAction::array(0, new NextAction("toc mounted", ACTION_RAID + 6), nullptr))); { NextAction("toc mounted", ACTION_RAID + 6) }));
triggers.push_back(new TriggerNode("toc eadric", triggers.push_back(new TriggerNode("toc eadric",
NextAction::array(0, new NextAction("toc eadric", ACTION_RAID + 3), nullptr))); { NextAction("toc eadric", ACTION_RAID + 3) }));
} }
void WotlkDungeonToCStrategy::InitMultipliers(std::vector<Multiplier*> &multipliers) void WotlkDungeonToCStrategy::InitMultipliers(std::vector<Multiplier*> &multipliers)
{ {
//multipliers.push_back(new toc...); if needed in the future
} }

View File

@@ -5,32 +5,32 @@ void WotlkDungeonUKStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
{ {
// Prince Keleseth // Prince Keleseth
triggers.push_back(new TriggerNode("keleseth frost tomb", triggers.push_back(new TriggerNode("keleseth frost tomb",
NextAction::array(0, new NextAction("attack frost tomb", ACTION_RAID + 1), nullptr))); { NextAction("attack frost tomb", ACTION_RAID + 1) }));
// Skarvald the Constructor & Dalronn the Controller // Skarvald the Constructor & Dalronn the Controller
triggers.push_back(new TriggerNode("dalronn priority", triggers.push_back(new TriggerNode("dalronn priority",
NextAction::array(0, new NextAction("attack dalronn", ACTION_RAID + 1), nullptr))); { NextAction("attack dalronn", ACTION_RAID + 1) }));
// Ingvar the Plunderer // Ingvar the Plunderer
// Doesn't work yet, this action doesn't get processed until the existing cast finishes // Doesn't work yet, this action doesn't get processed until the existing cast finishes
// triggers.push_back(new TriggerNode("ingvar staggering roar", // triggers.push_back(new TriggerNode("ingvar staggering roar",
// NextAction::array(0, new NextAction("ingvar stop casting", ACTION_RAID + 1), nullptr))); // { NextAction("ingvar stop casting", ACTION_RAID + 1) }));
// No easy way to check LoS here, the pillars do not seem to count as gameobjects. // No easy way to check LoS here, the pillars do not seem to count as gameobjects.
// Not implemented for now, unsure if this is needed as a good group can probably burst through the boss // Not implemented for now, unsure if this is needed as a good group can probably burst through the boss
// and just eat the debuff. // and just eat the debuff.
// triggers.push_back(new TriggerNode("ingvar dreadful roar", // triggers.push_back(new TriggerNode("ingvar dreadful roar",
// NextAction::array(0, new NextAction("ingvar hide los", ACTION_RAID + 1), nullptr))); // { NextAction("ingvar hide los", ACTION_RAID + 1) }));
triggers.push_back(new TriggerNode("ingvar smash tank", triggers.push_back(new TriggerNode("ingvar smash tank",
NextAction::array(0, new NextAction("ingvar dodge smash", ACTION_MOVE + 5), nullptr))); { NextAction("ingvar dodge smash", ACTION_MOVE + 5) }));
triggers.push_back(new TriggerNode("ingvar smash tank return", triggers.push_back(new TriggerNode("ingvar smash tank return",
NextAction::array(0, new NextAction("ingvar smash return", ACTION_MOVE + 5), nullptr))); { NextAction("ingvar smash return", ACTION_MOVE + 5) }));
// Buggy... if not behind target, ai can get stuck running towards and away from target. // Buggy... if not behind target, ai can get stuck running towards and away from target.
// I think for ranged chars, a custom action should be added that doesn't attempt to run into melee. // I think for ranged chars, a custom action should be added that doesn't attempt to run into melee.
// This is a bandaid for now, needs to be improved. // This is a bandaid for now, needs to be improved.
triggers.push_back(new TriggerNode("not behind ingvar", triggers.push_back(new TriggerNode("not behind ingvar",
NextAction::array(0, new NextAction("set behind", ACTION_MOVE + 1), nullptr))); { NextAction("set behind", ACTION_MOVE + 1) }));
} }

View File

@@ -10,14 +10,14 @@ void WotlkDungeonUPStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
// Skadi the Ruthless // Skadi the Ruthless
// TODO: Harpoons launchable via GameObject. For now players should do them // TODO: Harpoons launchable via GameObject. For now players should do them
triggers.push_back(new TriggerNode("freezing cloud", triggers.push_back(new TriggerNode("freezing cloud",
NextAction::array(0, new NextAction("avoid freezing cloud", ACTION_RAID + 5), nullptr))); { NextAction("avoid freezing cloud", ACTION_RAID + 5) }));
triggers.push_back(new TriggerNode("skadi whirlwind", triggers.push_back(new TriggerNode("skadi whirlwind",
NextAction::array(0, new NextAction("avoid skadi whirlwind", ACTION_RAID + 4), nullptr))); { NextAction("avoid skadi whirlwind", ACTION_RAID + 4) }));
// King Ymiron // King Ymiron
// May need to avoid orb.. unclear if the generic avoid AoE does this well // May need to avoid orb.. unclear if the generic avoid AoE does this well
triggers.push_back(new TriggerNode("ymiron bane", triggers.push_back(new TriggerNode("ymiron bane",
NextAction::array(0, new NextAction("stop attack", ACTION_RAID + 5), nullptr))); { NextAction("stop attack", ACTION_RAID + 5) }));
} }
void WotlkDungeonUPStrategy::InitMultipliers(std::vector<Multiplier*> &multipliers) void WotlkDungeonUPStrategy::InitMultipliers(std::vector<Multiplier*> &multipliers)

View File

@@ -6,14 +6,14 @@ void WotlkDungeonVHStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
// Erekem // Erekem
// This boss has many purgable buffs, purging/dispels could be merged into generic strats though // This boss has many purgable buffs, purging/dispels could be merged into generic strats though
triggers.push_back(new TriggerNode("erekem target", triggers.push_back(new TriggerNode("erekem target",
NextAction::array(0, new NextAction("attack erekem", ACTION_RAID + 1), nullptr))); { NextAction("attack erekem", ACTION_RAID + 1) }));
// Moragg // Moragg
// TODO: This guy has Optic Link which may require moving, add if needed // TODO: This guy has Optic Link which may require moving, add if needed
// Ichoron // Ichoron
triggers.push_back(new TriggerNode("ichoron target", triggers.push_back(new TriggerNode("ichoron target",
NextAction::array(0, new NextAction("attack ichor globule", ACTION_RAID + 1), nullptr))); { NextAction("attack ichor globule", ACTION_RAID + 1) }));
// Xevozz // Xevozz
// TODO: Revisit in heroics, waypoints back and forth on stairs. Need to test with double beacon spawn // TODO: Revisit in heroics, waypoints back and forth on stairs. Need to test with double beacon spawn
@@ -23,13 +23,13 @@ void WotlkDungeonVHStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
// Zuramat the Obliterator // Zuramat the Obliterator
triggers.push_back(new TriggerNode("shroud of darkness", triggers.push_back(new TriggerNode("shroud of darkness",
NextAction::array(0, new NextAction("stop attack", ACTION_HIGH + 5), nullptr))); { NextAction("stop attack", ACTION_HIGH + 5) }));
triggers.push_back(new TriggerNode("void shift", triggers.push_back(new TriggerNode("void shift",
NextAction::array(0, new NextAction("attack void sentry", ACTION_RAID + 1), nullptr))); { NextAction("attack void sentry", ACTION_RAID + 1) }));
// Cyanigosa // Cyanigosa
triggers.push_back(new TriggerNode("cyanigosa positioning", triggers.push_back(new TriggerNode("cyanigosa positioning",
NextAction::array(0, new NextAction("rear flank", ACTION_MOVE + 5), nullptr))); { NextAction("rear flank", ACTION_MOVE + 5) }));
} }
void WotlkDungeonVHStrategy::InitMultipliers(std::vector<Multiplier*> &multipliers) void WotlkDungeonVHStrategy::InitMultipliers(std::vector<Multiplier*> &multipliers)

View File

@@ -10,5 +10,5 @@
void AttackEnemyPlayersStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void AttackEnemyPlayersStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode("enemy player near", triggers.push_back(new TriggerNode("enemy player near",
NextAction::array(0, new NextAction("attack enemy player", 55.0f), nullptr))); { NextAction("attack enemy player", 55.0f) }));
} }

View File

@@ -9,83 +9,79 @@
void BGStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void BGStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("bg join", relevance), nullptr))); triggers.push_back(new TriggerNode("often", { NextAction("bg join", relevance)}));
triggers.push_back(new TriggerNode("bg invite active", NextAction::array(0, new NextAction("bg status check", relevance), nullptr))); triggers.push_back(new TriggerNode("bg invite active", { NextAction("bg status check", relevance)}));
triggers.push_back(new TriggerNode("timer", NextAction::array(0, new NextAction("bg strategy check", relevance), nullptr))); triggers.push_back(new TriggerNode("timer", { NextAction("bg strategy check", relevance)}));
} }
BGStrategy::BGStrategy(PlayerbotAI* botAI) : PassTroughStrategy(botAI) {} BGStrategy::BGStrategy(PlayerbotAI* botAI) : PassTroughStrategy(botAI) {}
void BattlegroundStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void BattlegroundStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode("bg waiting", NextAction::array(0, new NextAction("bg move to start", ACTION_BG), nullptr))); triggers.push_back(new TriggerNode("bg waiting", { NextAction("bg move to start", ACTION_BG)}));
triggers.push_back(new TriggerNode("bg active", NextAction::array(0, new NextAction("bg move to objective", ACTION_BG), nullptr))); triggers.push_back(new TriggerNode("bg active", { NextAction("bg move to objective", ACTION_BG)}));
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("bg check objective", ACTION_BG + 1), nullptr))); triggers.push_back(new TriggerNode("often", { NextAction("bg check objective", ACTION_BG + 1)}));
triggers.push_back(new TriggerNode("dead", NextAction::array(0, new NextAction("bg reset objective force", ACTION_EMERGENCY), nullptr))); triggers.push_back(new TriggerNode("dead", { NextAction("bg reset objective force", ACTION_EMERGENCY)}));
// triggers.push_back(new TriggerNode("enemy flagcarrier near", NextAction::array(0, new NextAction("attack enemy
// flag carrier", 80.0f), nullptr))); triggers.push_back(new TriggerNode("team flagcarrier near",
// NextAction::array(0, new NextAction("bg protect fc", 40.0f), nullptr))); triggers.push_back(new
// TriggerNode("player has flag", NextAction::array(0, new NextAction("bg move to objective", 90.0f), nullptr)));
} }
void WarsongStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void WarsongStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode("bg active", NextAction::array(0, new NextAction("bg check flag", ACTION_EMERGENCY ), nullptr))); triggers.push_back(new TriggerNode("bg active", { NextAction("bg check flag", ACTION_EMERGENCY )}));
triggers.push_back(new TriggerNode("enemy flagcarrier near", NextAction::array(0, new NextAction("attack enemy flag carrier", ACTION_RAID + 1.0f), nullptr))); triggers.push_back(new TriggerNode("enemy flagcarrier near", { NextAction("attack enemy flag carrier", ACTION_RAID + 1.0f)}));
triggers.push_back(new TriggerNode("team flagcarrier near", NextAction::array(0, new NextAction("bg protect fc", ACTION_RAID), nullptr))); triggers.push_back(new TriggerNode("team flagcarrier near", { NextAction("bg protect fc", ACTION_RAID)}));
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("bg use buff", ACTION_BG), nullptr))); triggers.push_back(new TriggerNode("often", { NextAction("bg use buff", ACTION_BG)}));
triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("bg use buff", ACTION_MOVE), nullptr))); triggers.push_back(new TriggerNode("low health", { NextAction("bg use buff", ACTION_MOVE)}));
triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("bg use buff", ACTION_MOVE), nullptr))); triggers.push_back(new TriggerNode("low mana", { NextAction("bg use buff", ACTION_MOVE)}));
triggers.push_back(new TriggerNode("player has flag", NextAction::array(0, new NextAction("bg move to objective", ACTION_EMERGENCY), nullptr))); triggers.push_back(new TriggerNode("player has flag", { NextAction("bg move to objective", ACTION_EMERGENCY)}));
triggers.push_back(new TriggerNode("timer bg", NextAction::array(0, new NextAction("bg reset objective force", ACTION_EMERGENCY), nullptr))); triggers.push_back(new TriggerNode("timer bg", { NextAction("bg reset objective force", ACTION_EMERGENCY)}));
} }
void AlteracStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void AlteracStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode("alliance no snowfall gy", NextAction::array(0, new NextAction("bg move to objective", ACTION_EMERGENCY), nullptr))); triggers.push_back(new TriggerNode("alliance no snowfall gy", { NextAction("bg move to objective", ACTION_EMERGENCY)}));
triggers.push_back(new TriggerNode("timer bg", NextAction::array(0, new NextAction("bg reset objective force", ACTION_EMERGENCY), nullptr))); triggers.push_back(new TriggerNode("timer bg", { NextAction("bg reset objective force", ACTION_EMERGENCY)}));
} }
void ArathiStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void ArathiStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode("bg active", NextAction::array(0, new NextAction("bg check flag", ACTION_EMERGENCY), nullptr))); triggers.push_back(new TriggerNode("bg active", { NextAction("bg check flag", ACTION_EMERGENCY)}));
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("bg use buff", ACTION_BG), nullptr))); triggers.push_back(new TriggerNode("often", { NextAction("bg use buff", ACTION_BG)}));
triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("bg use buff", ACTION_MOVE), nullptr))); triggers.push_back(new TriggerNode("low health", { NextAction("bg use buff", ACTION_MOVE)}));
triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("bg use buff", ACTION_MOVE), nullptr))); triggers.push_back(new TriggerNode("low mana", { NextAction("bg use buff", ACTION_MOVE)}));
} }
void EyeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void EyeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode("bg active", NextAction::array(0, new NextAction("bg check flag", ACTION_EMERGENCY), nullptr))); triggers.push_back(new TriggerNode("bg active", { NextAction("bg check flag", ACTION_EMERGENCY)}));
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("bg use buff", ACTION_BG), nullptr))); triggers.push_back(new TriggerNode("often", { NextAction("bg use buff", ACTION_BG)}));
triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("bg use buff", ACTION_MOVE), nullptr))); triggers.push_back(new TriggerNode("low health", { NextAction("bg use buff", ACTION_MOVE)}));
triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("bg use buff", ACTION_MOVE), nullptr))); triggers.push_back(new TriggerNode("low mana", { NextAction("bg use buff", ACTION_MOVE)}));
triggers.push_back(new TriggerNode("enemy flagcarrier near", NextAction::array(0, new NextAction("attack enemy flag carrier", ACTION_RAID), nullptr))); triggers.push_back(new TriggerNode("enemy flagcarrier near", { NextAction("attack enemy flag carrier", ACTION_RAID)}));
triggers.push_back(new TriggerNode("player has flag",NextAction::array(0, new NextAction("bg move to objective", ACTION_EMERGENCY), nullptr))); triggers.push_back(new TriggerNode("player has flag",{ NextAction("bg move to objective", ACTION_EMERGENCY)}));
} }
//TODO: Do Priorities //TODO: Do Priorities
void IsleStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void IsleStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode("bg active", NextAction::array(0, new NextAction("bg check flag", ACTION_MOVE), nullptr))); triggers.push_back(new TriggerNode("bg active", { NextAction("bg check flag", ACTION_MOVE)}));
triggers.push_back(new TriggerNode("timer", NextAction::array(0, new NextAction("enter vehicle", ACTION_MOVE + 8.0f), nullptr))); triggers.push_back(new TriggerNode("timer", { NextAction("enter vehicle", ACTION_MOVE + 8.0f)}));
triggers.push_back(new TriggerNode("random", NextAction::array(0, new NextAction("leave vehicle", ACTION_MOVE + 7.0f), nullptr))); triggers.push_back(new TriggerNode("random", { NextAction("leave vehicle", ACTION_MOVE + 7.0f)}));
triggers.push_back(new TriggerNode("in vehicle", NextAction::array(0, new NextAction("hurl boulder", ACTION_MOVE + 9.0f), nullptr))); triggers.push_back(new TriggerNode("in vehicle", { NextAction("hurl boulder", ACTION_MOVE + 9.0f)}));
triggers.push_back(new TriggerNode("in vehicle", NextAction::array(0, new NextAction("fire cannon", ACTION_MOVE + 9.0f), nullptr))); triggers.push_back(new TriggerNode("in vehicle", { NextAction("fire cannon", ACTION_MOVE + 9.0f)}));
triggers.push_back(new TriggerNode("in vehicle", NextAction::array(0, new NextAction("napalm", ACTION_MOVE + 9.0f), nullptr))); triggers.push_back(new TriggerNode("in vehicle", { NextAction("napalm", ACTION_MOVE + 9.0f)}));
triggers.push_back(new TriggerNode("enemy is close", NextAction::array(0, new NextAction("steam blast", ACTION_MOVE + 9.0f), nullptr))); triggers.push_back(new TriggerNode("enemy is close", { NextAction("steam blast", ACTION_MOVE + 9.0f)}));
triggers.push_back(new TriggerNode("in vehicle", NextAction::array(0, new NextAction("ram", ACTION_MOVE + 9.0f), nullptr))); triggers.push_back(new TriggerNode("in vehicle", { NextAction("ram", ACTION_MOVE + 9.0f)}));
triggers.push_back(new TriggerNode("enemy is close", NextAction::array(0, new NextAction("ram", ACTION_MOVE + 9.1f), nullptr))); triggers.push_back(new TriggerNode("enemy is close", { NextAction("ram", ACTION_MOVE + 9.1f)}));
triggers.push_back(new TriggerNode("enemy out of melee", NextAction::array(0, new NextAction("steam rush", ACTION_MOVE + 9.2f), nullptr))); triggers.push_back(new TriggerNode("enemy out of melee", { NextAction("steam rush", ACTION_MOVE + 9.2f)}));
triggers.push_back(new TriggerNode("in vehicle", NextAction::array(0, new NextAction("incendiary rocket", ACTION_MOVE + 9.0f), nullptr))); triggers.push_back(new TriggerNode("in vehicle", { NextAction("incendiary rocket", ACTION_MOVE + 9.0f)}));
triggers.push_back(new TriggerNode("in vehicle", NextAction::array(0, new NextAction("rocket blast", ACTION_MOVE + 9.0f), nullptr))); triggers.push_back(new TriggerNode("in vehicle", { NextAction("rocket blast", ACTION_MOVE + 9.0f)}));
// this is bugged: it doesn't work, and stops glaive throw working (which is needed to take down gate) // this is bugged: it doesn't work, and stops glaive throw working (which is needed to take down gate)
// triggers.push_back(new TriggerNode("in vehicle", NextAction::array(0, new NextAction("blade salvo", ACTION_MOVE + 9.0f), nullptr))); // triggers.push_back(new TriggerNode("in vehicle", { NextAction("blade salvo", ACTION_MOVE + 9.0f)}));
triggers.push_back(new TriggerNode("in vehicle", NextAction::array(0, new NextAction("glaive throw", ACTION_MOVE + 9.0f), nullptr))); triggers.push_back(new TriggerNode("in vehicle", { NextAction("glaive throw", ACTION_MOVE + 9.0f)}));
} }
void ArenaStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void ArenaStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back( triggers.push_back(
new TriggerNode("no possible targets", NextAction::array(0, new NextAction("arena tactics", ACTION_BG), nullptr))); new TriggerNode("no possible targets", { NextAction("arena tactics", ACTION_BG)}));
} }

View File

@@ -16,9 +16,9 @@ private:
static ActionNode* tank_attack_chat_shortcut(PlayerbotAI* botAI) static ActionNode* tank_attack_chat_shortcut(PlayerbotAI* botAI)
{ {
return new ActionNode("tank attack chat shortcut", return new ActionNode("tank attack chat shortcut",
/*P*/ nullptr, /*P*/ {},
/*A*/ nullptr, /*A*/ {},
/*C*/ NextAction::array(0, new NextAction("attack my target", 100.0f), nullptr)); /*C*/ { NextAction("attack my target", 100.0f) });
} }
}; };
@@ -26,86 +26,86 @@ void ChatCommandHandlerStrategy::InitTriggers(std::vector<TriggerNode*>& trigger
{ {
PassTroughStrategy::InitTriggers(triggers); PassTroughStrategy::InitTriggers(triggers);
triggers.push_back(new TriggerNode("rep", NextAction::array(0, new NextAction("reputation", relevance), nullptr))); triggers.push_back(new TriggerNode("rep", { NextAction("reputation", relevance) }));
triggers.push_back(new TriggerNode("q", NextAction::array(0, new NextAction("query quest", relevance), triggers.push_back(new TriggerNode("q", { NextAction("query quest", relevance),
new NextAction("query item usage", relevance), nullptr))); NextAction("query item usage", relevance) }));
triggers.push_back(new TriggerNode("add all loot", NextAction::array(0, new NextAction("add all loot", relevance), triggers.push_back(new TriggerNode("add all loot", { NextAction("add all loot", relevance),
new NextAction("loot", relevance), nullptr))); NextAction("loot", relevance) }));
triggers.push_back(new TriggerNode("u", NextAction::array(0, new NextAction("use", relevance), nullptr))); triggers.push_back(new TriggerNode("u", { NextAction("use", relevance) }));
triggers.push_back(new TriggerNode("c", NextAction::array(0, new NextAction("item count", relevance), nullptr))); triggers.push_back(new TriggerNode("c", { NextAction("item count", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("items", NextAction::array(0, new NextAction("item count", relevance), nullptr))); new TriggerNode("items", { NextAction("item count", relevance) }));
triggers.push_back(new TriggerNode("inv", NextAction::array(0, new NextAction("item count", relevance), nullptr))); triggers.push_back(new TriggerNode("inv", { NextAction("item count", relevance) }));
triggers.push_back(new TriggerNode("e", NextAction::array(0, new NextAction("equip", relevance), nullptr))); triggers.push_back(new TriggerNode("e", { NextAction("equip", relevance) }));
triggers.push_back(new TriggerNode("ue", NextAction::array(0, new NextAction("unequip", relevance), nullptr))); triggers.push_back(new TriggerNode("ue", { NextAction("unequip", relevance) }));
triggers.push_back(new TriggerNode("t", NextAction::array(0, new NextAction("trade", relevance), nullptr))); triggers.push_back(new TriggerNode("t", { NextAction("trade", relevance) }));
triggers.push_back(new TriggerNode("nt", NextAction::array(0, new NextAction("trade", relevance), nullptr))); triggers.push_back(new TriggerNode("nt", { NextAction("trade", relevance) }));
triggers.push_back(new TriggerNode("s", NextAction::array(0, new NextAction("sell", relevance), nullptr))); triggers.push_back(new TriggerNode("s", { NextAction("sell", relevance) }));
triggers.push_back(new TriggerNode("b", NextAction::array(0, new NextAction("buy", relevance), nullptr))); triggers.push_back(new TriggerNode("b", { NextAction("buy", relevance) }));
triggers.push_back(new TriggerNode("r", NextAction::array(0, new NextAction("reward", relevance), nullptr))); triggers.push_back(new TriggerNode("r", { NextAction("reward", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("attack", NextAction::array(0, new NextAction("attack my target", relevance), nullptr))); new TriggerNode("attack", { NextAction("attack my target", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("accept", NextAction::array(0, new NextAction("accept quest", relevance), nullptr))); new TriggerNode("accept", { NextAction("accept quest", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("follow", NextAction::array(0, new NextAction("follow chat shortcut", relevance), nullptr))); new TriggerNode("follow", { NextAction("follow chat shortcut", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("stay", NextAction::array(0, new NextAction("stay chat shortcut", relevance), nullptr))); new TriggerNode("stay", { NextAction("stay chat shortcut", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("move from group", NextAction::array(0, new NextAction("move from group chat shortcut", relevance), nullptr))); new TriggerNode("move from group", { NextAction("move from group chat shortcut", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("flee", NextAction::array(0, new NextAction("flee chat shortcut", relevance), nullptr))); new TriggerNode("flee", { NextAction("flee chat shortcut", relevance) }));
triggers.push_back(new TriggerNode( triggers.push_back(new TriggerNode(
"tank attack", NextAction::array(0, new NextAction("tank attack chat shortcut", relevance), nullptr))); "tank attack", { NextAction("tank attack chat shortcut", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("grind", NextAction::array(0, new NextAction("grind chat shortcut", relevance), nullptr))); new TriggerNode("grind", { NextAction("grind chat shortcut", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("talk", NextAction::array(0, new NextAction("gossip hello", relevance), new TriggerNode("talk", { NextAction("gossip hello", relevance),
new NextAction("talk to quest giver", relevance), nullptr))); NextAction("talk to quest giver", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("enter vehicle", NextAction::array(0, new NextAction("enter vehicle", relevance), nullptr))); new TriggerNode("enter vehicle", { NextAction("enter vehicle", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("leave vehicle", NextAction::array(0, new NextAction("leave vehicle", relevance), nullptr))); new TriggerNode("leave vehicle", { NextAction("leave vehicle", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("cast", NextAction::array(0, new NextAction("cast custom spell", relevance), nullptr))); new TriggerNode("cast", { NextAction("cast custom spell", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("castnc", NextAction::array(0, new NextAction("cast custom nc spell", relevance), nullptr))); new TriggerNode("castnc", { NextAction("cast custom nc spell", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("revive", NextAction::array(0, new NextAction("spirit healer", relevance), nullptr))); new TriggerNode("revive", { NextAction("spirit healer", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("runaway", NextAction::array(0, new NextAction("runaway chat shortcut", relevance), nullptr))); new TriggerNode("runaway", { NextAction("runaway chat shortcut", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("warning", NextAction::array(0, new NextAction("runaway chat shortcut", relevance), nullptr))); new TriggerNode("warning", { NextAction("runaway chat shortcut", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("max dps", NextAction::array(0, new NextAction("max dps chat shortcut", relevance), nullptr))); new TriggerNode("max dps", { NextAction("max dps chat shortcut", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("attackers", NextAction::array(0, new NextAction("tell attackers", relevance), nullptr))); new TriggerNode("attackers", { NextAction("tell attackers", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("target", NextAction::array(0, new NextAction("tell target", relevance), nullptr))); new TriggerNode("target", { NextAction("tell target", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("ready", NextAction::array(0, new NextAction("ready check", relevance), nullptr))); new TriggerNode("ready", { NextAction("ready check", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("bwl", NextAction::array(0, new NextAction("bwl chat shortcut", relevance), NULL))); new TriggerNode("bwl", { NextAction("bwl chat shortcut", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("dps", NextAction::array(0, new NextAction("tell estimated dps", relevance), NULL))); new TriggerNode("dps", { NextAction("tell estimated dps", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("disperse", NextAction::array(0, new NextAction("disperse set", relevance), NULL))); new TriggerNode("disperse", { NextAction("disperse set", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("open items", NextAction::array(0, new NextAction("open items", relevance), nullptr))); new TriggerNode("open items", { NextAction("open items", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("qi", NextAction::array(0, new NextAction("query item usage", relevance), nullptr))); new TriggerNode("qi", { NextAction("query item usage", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("unlock items", NextAction::array(0, new NextAction("unlock items", relevance), nullptr))); new TriggerNode("unlock items", { NextAction("unlock items", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("unlock traded item", NextAction::array(0, new NextAction("unlock traded item", relevance), nullptr))); new TriggerNode("unlock traded item", { NextAction("unlock traded item", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("wipe", NextAction::array(0, new NextAction("wipe", relevance), nullptr))); new TriggerNode("wipe", { NextAction("wipe", relevance) }));
triggers.push_back(new TriggerNode("tame", NextAction::array(0, new NextAction("tame", relevance), nullptr))); triggers.push_back(new TriggerNode("tame", { NextAction("tame", relevance) }));
triggers.push_back(new TriggerNode("glyphs", NextAction::array(0, new NextAction("glyphs", relevance), nullptr))); // Added for custom Glyphs triggers.push_back(new TriggerNode("glyphs", { NextAction("glyphs", relevance) })); // Added for custom Glyphs
triggers.push_back(new TriggerNode("glyph equip", NextAction::array(0, new NextAction("glyph equip", relevance), nullptr))); // Added for custom Glyphs triggers.push_back(new TriggerNode("glyph equip", { NextAction("glyph equip", relevance) })); // Added for custom Glyphs
triggers.push_back(new TriggerNode("pet", NextAction::array(0, new NextAction("pet", relevance), nullptr))); triggers.push_back(new TriggerNode("pet", { NextAction("pet", relevance) }));
triggers.push_back(new TriggerNode("pet attack", NextAction::array(0, new NextAction("pet attack", relevance), nullptr))); triggers.push_back(new TriggerNode("pet attack", { NextAction("pet attack", relevance) }));
triggers.push_back(new TriggerNode("roll", NextAction::array(0, new NextAction("roll", relevance), nullptr))); triggers.push_back(new TriggerNode("roll", { NextAction("roll", relevance) }));
} }
ChatCommandHandlerStrategy::ChatCommandHandlerStrategy(PlayerbotAI* botAI) : PassTroughStrategy(botAI) ChatCommandHandlerStrategy::ChatCommandHandlerStrategy(PlayerbotAI* botAI) : PassTroughStrategy(botAI)

View File

@@ -10,70 +10,59 @@
void CombatStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void CombatStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode("enemy out of spell", triggers.push_back(
NextAction::array(0, new NextAction("reach spell", ACTION_HIGH), nullptr))); new TriggerNode(
"enemy out of spell",
{
NextAction("reach spell", ACTION_HIGH)
}
)
);
// drop target relevance 99 (lower than Worldpacket triggers) // drop target relevance 99 (lower than Worldpacket triggers)
triggers.push_back( triggers.push_back(
new TriggerNode("invalid target", NextAction::array(0, new NextAction("drop target", 99), nullptr))); new TriggerNode(
"invalid target",
{
NextAction("drop target", 99)
}
)
);
triggers.push_back( triggers.push_back(
new TriggerNode("mounted", NextAction::array(0, new NextAction("check mount state", 54), nullptr))); new TriggerNode(
// triggers.push_back(new TriggerNode("out of react range", NextAction::array(0, new NextAction("flee to master", "mounted",
// 55), nullptr))); {
triggers.push_back(new TriggerNode("combat stuck", NextAction::array(0, new NextAction("reset", 1.0f), nullptr))); NextAction("check mount state", 54)
triggers.push_back(new TriggerNode("not facing target", }
NextAction::array(0, new NextAction("set facing", ACTION_MOVE + 7), nullptr))); )
// triggers.push_back(new TriggerNode("pet attack", NextAction::array(0, new NextAction("pet attack", 40.0f), nullptr))); );
triggers.push_back(
new TriggerNode(
"combat stuck",
{
NextAction("reset", 1.0f)
}
)
);
triggers.push_back(
new TriggerNode(
"not facing target",
{
NextAction("set facing", ACTION_MOVE + 7)
}
)
);
// The pet-attack trigger is commented out because it was forcing the bot's pet to attack, overriding stay and follow commands. // The pet-attack trigger is commented out because it was forcing the bot's pet to attack, overriding stay and follow commands.
// Pets will automatically attack the bot's enemy if they are in "defensive" or "aggressive" // Pets will automatically attack the bot's enemy if they are in "defensive" or "aggressive"
// stance, or if the master issues an attack command. // stance, or if the master issues an attack command.
// triggers.push_back(new TriggerNode("combat long stuck", NextAction::array(0, new NextAction("hearthstone", 0.9f),
// new NextAction("repop", 0.8f), nullptr)));
} }
AvoidAoeStrategy::AvoidAoeStrategy(PlayerbotAI* botAI) : Strategy(botAI) {} AvoidAoeStrategy::AvoidAoeStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
// class AvoidAoeStrategyMultiplier : public Multiplier std::vector<NextAction> AvoidAoeStrategy::getDefaultActions()
// {
// public:
// AvoidAoeStrategyMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "run away on area debuff") {}
// public:
// virtual float GetValue(Action* action);
// private:
// };
// float AvoidAoeStrategyMultiplier::GetValue(Action* action)
// {
// if (!action)
// return 1.0f;
// std::string name = action->getName();
// if (name == "follow" || name == "co" || name == "nc" || name == "drop target")
// return 1.0f;
// uint32 spellId = AI_VALUE2(uint32, "spell id", name);
// const SpellInfo* const pSpellInfo = sSpellMgr->GetSpellInfo(spellId);
// if (!pSpellInfo) return 1.0f;
// if (spellId && pSpellInfo->Targets & TARGET_FLAG_DEST_LOCATION)
// return 1.0f;
// else if (spellId && pSpellInfo->Targets & TARGET_FLAG_SOURCE_LOCATION)
// return 1.0f;
// uint32 castTime = pSpellInfo->CalcCastTime(bot);
// if (AI_VALUE2(bool, "has area debuff", "self target") && spellId && castTime > 0)
// {
// return 0.0f;
// }
// return 1.0f;
// }
NextAction** AvoidAoeStrategy::getDefaultActions()
{ {
return NextAction::array(0, new NextAction("avoid aoe", ACTION_EMERGENCY), nullptr); return {
NextAction("avoid aoe", ACTION_EMERGENCY)
};
} }
void AvoidAoeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void AvoidAoeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
@@ -82,21 +71,24 @@ void AvoidAoeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
void AvoidAoeStrategy::InitMultipliers(std::vector<Multiplier*>& multipliers) void AvoidAoeStrategy::InitMultipliers(std::vector<Multiplier*>& multipliers)
{ {
// multipliers.push_back(new AvoidAoeStrategyMultiplier(botAI));
} }
TankFaceStrategy::TankFaceStrategy(PlayerbotAI* botAI) : Strategy(botAI) {} TankFaceStrategy::TankFaceStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
NextAction** TankFaceStrategy::getDefaultActions() std::vector<NextAction> TankFaceStrategy::getDefaultActions()
{ {
return NextAction::array(0, new NextAction("tank face", ACTION_MOVE), nullptr); return {
NextAction("tank face", ACTION_MOVE)
};
} }
void TankFaceStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void TankFaceStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
} }
NextAction** CombatFormationStrategy::getDefaultActions() std::vector<NextAction> CombatFormationStrategy::getDefaultActions()
{ {
return NextAction::array(0, new NextAction("combat formation move", ACTION_NORMAL), nullptr); return {
NextAction("combat formation move", ACTION_NORMAL)
};
} }

View File

@@ -24,7 +24,7 @@ class AvoidAoeStrategy : public Strategy
public: public:
explicit AvoidAoeStrategy(PlayerbotAI* ai); explicit AvoidAoeStrategy(PlayerbotAI* ai);
const std::string getName() override { return "avoid aoe"; } const std::string getName() override { return "avoid aoe"; }
NextAction** getDefaultActions() override; std::vector<NextAction> getDefaultActions() override;
void InitMultipliers(std::vector<Multiplier*>& multipliers) override; void InitMultipliers(std::vector<Multiplier*>& multipliers) override;
void InitTriggers(std::vector<TriggerNode*>& triggers) override; void InitTriggers(std::vector<TriggerNode*>& triggers) override;
}; };
@@ -34,7 +34,7 @@ class TankFaceStrategy : public Strategy
public: public:
explicit TankFaceStrategy(PlayerbotAI* ai); explicit TankFaceStrategy(PlayerbotAI* ai);
const std::string getName() override { return "tank face"; } const std::string getName() override { return "tank face"; }
NextAction** getDefaultActions() override; std::vector<NextAction> getDefaultActions() override;
void InitTriggers(std::vector<TriggerNode*>& triggers) override; void InitTriggers(std::vector<TriggerNode*>& triggers) override;
}; };
@@ -43,7 +43,7 @@ class CombatFormationStrategy : public Strategy
public: public:
CombatFormationStrategy(PlayerbotAI* ai) : Strategy(ai) {} CombatFormationStrategy(PlayerbotAI* ai) : Strategy(ai) {}
const std::string getName() override { return "formation"; } const std::string getName() override { return "formation"; }
NextAction** getDefaultActions() override; std::vector<NextAction> getDefaultActions() override;
}; };
#endif #endif

View File

@@ -12,21 +12,21 @@ void DeadStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
PassTroughStrategy::InitTriggers(triggers); PassTroughStrategy::InitTriggers(triggers);
triggers.push_back( triggers.push_back(
new TriggerNode("often", NextAction::array(0, new NextAction("auto release", relevance), nullptr))); new TriggerNode("often", { NextAction("auto release", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("bg active", NextAction::array(0, new NextAction("auto release", relevance), nullptr))); new TriggerNode("bg active", { NextAction("auto release", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("dead", NextAction::array(0, new NextAction("find corpse", relevance), nullptr))); new TriggerNode("dead", { NextAction("find corpse", relevance) }));
triggers.push_back(new TriggerNode( triggers.push_back(new TriggerNode(
"corpse near", NextAction::array(0, new NextAction("revive from corpse", relevance - 1.0f), nullptr))); "corpse near", { NextAction("revive from corpse", relevance - 1.0f) }));
triggers.push_back(new TriggerNode("resurrect request", triggers.push_back(new TriggerNode("resurrect request",
NextAction::array(0, new NextAction("accept resurrect", relevance), nullptr))); { NextAction("accept resurrect", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("falling far", NextAction::array(0, new NextAction("repop", relevance + 1.f), nullptr))); new TriggerNode("falling far", { NextAction("repop", relevance + 1.f) }));
triggers.push_back( triggers.push_back(
new TriggerNode("location stuck", NextAction::array(0, new NextAction("repop", relevance + 1), nullptr))); new TriggerNode("location stuck", { NextAction("repop", relevance + 1) }));
triggers.push_back(new TriggerNode( triggers.push_back(new TriggerNode(
"can self resurrect", NextAction::array(0, new NextAction("self resurrect", relevance + 2.0f), nullptr))); "can self resurrect", { NextAction("self resurrect", relevance + 2.0f) }));
} }
DeadStrategy::DeadStrategy(PlayerbotAI* botAI) : PassTroughStrategy(botAI) {} DeadStrategy::DeadStrategy(PlayerbotAI* botAI) : PassTroughStrategy(botAI) {}

View File

@@ -10,11 +10,11 @@
void DpsAssistStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void DpsAssistStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back( triggers.push_back(
new TriggerNode("not dps target active", NextAction::array(0, new NextAction("dps assist", 50.0f), nullptr))); new TriggerNode("not dps target active", { NextAction("dps assist", 50.0f) }));
} }
void DpsAoeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void DpsAoeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back( triggers.push_back(
new TriggerNode("not dps aoe target active", NextAction::array(0, new NextAction("dps aoe", 50.0f), nullptr))); new TriggerNode("not dps aoe target active", { NextAction("dps aoe", 50.0f) }));
} }

View File

@@ -12,9 +12,9 @@ void DuelStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
PassTroughStrategy::InitTriggers(triggers); PassTroughStrategy::InitTriggers(triggers);
triggers.push_back( triggers.push_back(
new TriggerNode("duel requested", NextAction::array(0, new NextAction("accept duel", relevance), nullptr))); new TriggerNode("duel requested", { NextAction("accept duel", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("no attackers", NextAction::array(0, new NextAction("attack duel opponent", 70.0f), nullptr))); new TriggerNode("no attackers", { NextAction("attack duel opponent", 70.0f) }));
} }
DuelStrategy::DuelStrategy(PlayerbotAI* botAI) : PassTroughStrategy(botAI) {} DuelStrategy::DuelStrategy(PlayerbotAI* botAI) : PassTroughStrategy(botAI) {}

View File

@@ -11,25 +11,25 @@ void EmoteStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
if (sPlayerbotAIConfig->randomBotEmote) if (sPlayerbotAIConfig->randomBotEmote)
{ {
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("talk", 1.0f), nullptr))); triggers.push_back(new TriggerNode("often", { NextAction("talk", 1.0f) }));
triggers.push_back(new TriggerNode("seldom", NextAction::array(0, new NextAction("emote", 1.0f), nullptr))); triggers.push_back(new TriggerNode("seldom", { NextAction("emote", 1.0f) }));
triggers.push_back( triggers.push_back(
new TriggerNode("receive text emote", NextAction::array(0, new NextAction("emote", 10.0f), nullptr))); new TriggerNode("receive text emote", { NextAction("emote", 10.0f) }));
triggers.push_back( triggers.push_back(
new TriggerNode("receive emote", NextAction::array(0, new NextAction("emote", 10.0f), nullptr))); new TriggerNode("receive emote", { NextAction("emote", 10.0f) }));
} }
if (sPlayerbotAIConfig->randomBotTalk) if (sPlayerbotAIConfig->randomBotTalk)
{ {
triggers.push_back(new TriggerNode( triggers.push_back(new TriggerNode(
"often", "often",
NextAction::array(0, new NextAction("suggest what to do", 10.0f), new NextAction("suggest dungeon", 3.0f), { NextAction("suggest what to do", 10.0f), NextAction("suggest dungeon", 3.0f),
new NextAction("suggest trade", 3.0f), nullptr))); NextAction("suggest trade", 3.0f) }));
} }
if (sPlayerbotAIConfig->enableGreet) if (sPlayerbotAIConfig->enableGreet)
triggers.push_back( triggers.push_back(
new TriggerNode("new player nearby", NextAction::array(0, new NextAction("greet", 1.0f), nullptr))); new TriggerNode("new player nearby", { NextAction("greet", 1.0f) }));
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("rpg mount anim", 1.0f), nullptr))); triggers.push_back(new TriggerNode("often", { NextAction("rpg mount anim", 1.0f) }));
} }

View File

@@ -10,15 +10,15 @@
void FleeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void FleeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back( triggers.push_back(
new TriggerNode("panic", NextAction::array(0, new NextAction("flee", ACTION_EMERGENCY + 9), nullptr))); new TriggerNode("panic", { NextAction("flee", ACTION_EMERGENCY + 9) }));
triggers.push_back( triggers.push_back(
new TriggerNode("outnumbered", NextAction::array(0, new NextAction("flee", ACTION_EMERGENCY + 9), nullptr))); new TriggerNode("outnumbered", { NextAction("flee", ACTION_EMERGENCY + 9) }));
triggers.push_back( triggers.push_back(
new TriggerNode("critical health", NextAction::array(0, new NextAction("flee", ACTION_MEDIUM_HEAL), nullptr))); new TriggerNode("critical health", { NextAction("flee", ACTION_MEDIUM_HEAL) }));
} }
void FleeFromAddsStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void FleeFromAddsStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back( triggers.push_back(
new TriggerNode("has nearest adds", NextAction::array(0, new NextAction("runaway", 50.0f), nullptr))); new TriggerNode("has nearest adds", { NextAction("runaway", 50.0f) }));
} }

View File

@@ -7,13 +7,13 @@
#include "Playerbots.h" #include "Playerbots.h"
NextAction** FollowMasterStrategy::getDefaultActions() std::vector<NextAction> FollowMasterStrategy::getDefaultActions()
{ {
return NextAction::array(0, new NextAction("follow", 1.0f), nullptr); return {
NextAction("follow", 1.0f)
};
} }
void FollowMasterStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void FollowMasterStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
// triggers.push_back(new TriggerNode("out of react range", NextAction::array(0, new NextAction("flee to master",
// ACTION_HIGH), nullptr)));
} }

View File

@@ -16,7 +16,7 @@ public:
FollowMasterStrategy(PlayerbotAI* botAI) : NonCombatStrategy(botAI) {} FollowMasterStrategy(PlayerbotAI* botAI) : NonCombatStrategy(botAI) {}
std::string const getName() override { return "follow"; } std::string const getName() override { return "follow"; }
NextAction** getDefaultActions() override; std::vector<NextAction> getDefaultActions() override;
void InitTriggers(std::vector<TriggerNode*>& triggers) override; void InitTriggers(std::vector<TriggerNode*>& triggers) override;
}; };

View File

@@ -7,22 +7,35 @@
#include "Playerbots.h" #include "Playerbots.h"
NextAction** GrindingStrategy::getDefaultActions() std::vector<NextAction> GrindingStrategy::getDefaultActions()
{ {
return NextAction::array(0, return {
new NextAction("drink", 4.2f), NextAction("drink", 4.2f),
new NextAction("food", 4.1f), NextAction("food", 4.1f),
nullptr); };
} }
void GrindingStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void GrindingStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
// reduce lower than loot // reduce lower than loot
triggers.push_back( triggers.push_back(
new TriggerNode("no target", NextAction::array(0, new NextAction("attack anything", 4.0f), nullptr))); new TriggerNode(
"no target",
{
NextAction("attack anything", 4.0f)
}
)
);
} }
void MoveRandomStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void MoveRandomStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("move random", 1.5f), NULL))); triggers.push_back(
new TriggerNode(
"often",
{
NextAction("move random", 1.5f)
}
)
);
} }

View File

@@ -17,7 +17,7 @@ public:
std::string const getName() override { return "grind"; } std::string const getName() override { return "grind"; }
uint32 GetType() const override { return STRATEGY_TYPE_DPS; } uint32 GetType() const override { return STRATEGY_TYPE_DPS; }
NextAction** getDefaultActions() override; std::vector<NextAction> getDefaultActions() override;
void InitTriggers(std::vector<TriggerNode*>& triggers) override; void InitTriggers(std::vector<TriggerNode*>& triggers) override;
}; };

View File

@@ -9,8 +9,8 @@
void GroupStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void GroupStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("invite nearby", 4.0f), nullptr))); triggers.push_back(new TriggerNode("often", { NextAction("invite nearby", 4.0f) }));
triggers.push_back(new TriggerNode("random", NextAction::array(0, new NextAction("invite guild", 4.0f), nullptr))); triggers.push_back(new TriggerNode("random", { NextAction("invite guild", 4.0f) }));
triggers.push_back(new TriggerNode("random", NextAction::array(0, new NextAction("leave far away", 4.0f), nullptr))); triggers.push_back(new TriggerNode("random", { NextAction("leave far away", 4.0f) }));
triggers.push_back(new TriggerNode("seldom", NextAction::array(0, new NextAction("reset instances", 1.0f), nullptr))); triggers.push_back(new TriggerNode("seldom", { NextAction("reset instances", 1.0f) }));
} }

View File

@@ -7,6 +7,11 @@
#include "Playerbots.h" #include "Playerbots.h"
NextAction** GuardStrategy::getDefaultActions() { return NextAction::array(0, new NextAction("guard", 4.0f), nullptr); } std::vector<NextAction> GuardStrategy::getDefaultActions()
{
return {
NextAction("guard", 4.0f)
};
}
void GuardStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) {} void GuardStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) {}

View File

@@ -16,7 +16,7 @@ public:
GuardStrategy(PlayerbotAI* botAI) : NonCombatStrategy(botAI) {} GuardStrategy(PlayerbotAI* botAI) : NonCombatStrategy(botAI) {}
std::string const getName() override { return "guard"; } std::string const getName() override { return "guard"; }
NextAction** getDefaultActions() override; std::vector<NextAction> getDefaultActions() override;
void InitTriggers(std::vector<TriggerNode*>& triggers) override; void InitTriggers(std::vector<TriggerNode*>& triggers) override;
}; };

View File

@@ -10,13 +10,13 @@
void GuildStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void GuildStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back( triggers.push_back(
new TriggerNode("often", NextAction::array(0, new NextAction("offer petition nearby", 4.0f), nullptr))); new TriggerNode("often", { NextAction("offer petition nearby", 4.0f) }));
triggers.push_back( triggers.push_back(
new TriggerNode("often", NextAction::array(0, new NextAction("guild manage nearby", 4.0f), nullptr))); new TriggerNode("often", { NextAction("guild manage nearby", 4.0f) }));
triggers.push_back( triggers.push_back(
new TriggerNode("petition signed", NextAction::array(0, new NextAction("turn in petition", 10.0f), nullptr))); new TriggerNode("petition signed", { NextAction("turn in petition", 10.0f) }));
triggers.push_back( triggers.push_back(
new TriggerNode("buy tabard", NextAction::array(0, new NextAction("buy tabard", 10.0f), nullptr))); new TriggerNode("buy tabard", { NextAction("buy tabard", 10.0f) }));
triggers.push_back( triggers.push_back(
new TriggerNode("leave large guild", NextAction::array(0, new NextAction("guild leave", 4.0f), nullptr))); new TriggerNode("leave large guild", { NextAction("guild leave", 4.0f) }));
} }

View File

@@ -11,5 +11,5 @@ KiteStrategy::KiteStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
void KiteStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void KiteStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode("has aggro", NextAction::array(0, new NextAction("runaway", 51.0f), nullptr))); triggers.push_back(new TriggerNode("has aggro", { NextAction("runaway", 51.0f) }));
} }

View File

@@ -9,11 +9,11 @@
void LfgStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void LfgStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode("random", NextAction::array(0, new NextAction("lfg join", relevance), nullptr))); triggers.push_back(new TriggerNode("random", { NextAction("lfg join", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("seldom", NextAction::array(0, new NextAction("lfg leave", relevance), nullptr))); new TriggerNode("seldom", { NextAction("lfg leave", relevance) }));
triggers.push_back(new TriggerNode( triggers.push_back(new TriggerNode(
"unknown dungeon", NextAction::array(0, new NextAction("give leader in dungeon", relevance), nullptr))); "unknown dungeon", { NextAction("give leader in dungeon", relevance) }));
} }
LfgStrategy::LfgStrategy(PlayerbotAI* botAI) : PassTroughStrategy(botAI) {} LfgStrategy::LfgStrategy(PlayerbotAI* botAI) : PassTroughStrategy(botAI) {}

View File

@@ -9,29 +9,29 @@
void LootNonCombatStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void LootNonCombatStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode("loot available", NextAction::array(0, new NextAction("loot", 6.0f), nullptr))); triggers.push_back(new TriggerNode("loot available", { NextAction("loot", 6.0f) }));
triggers.push_back( triggers.push_back(
new TriggerNode("far from loot target", NextAction::array(0, new NextAction("move to loot", 7.0f), nullptr))); new TriggerNode("far from loot target", { NextAction("move to loot", 7.0f) }));
triggers.push_back(new TriggerNode("can loot", NextAction::array(0, new NextAction("open loot", 8.0f), nullptr))); triggers.push_back(new TriggerNode("can loot", { NextAction("open loot", 8.0f) }));
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("add all loot", 5.0f), nullptr))); triggers.push_back(new TriggerNode("often", { NextAction("add all loot", 5.0f) }));
} }
void GatherStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void GatherStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back( triggers.push_back(
new TriggerNode("timer", NextAction::array(0, new NextAction("add gathering loot", 5.0f), nullptr))); new TriggerNode("timer", { NextAction("add gathering loot", 5.0f) }));
} }
void RevealStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void RevealStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back( triggers.push_back(
new TriggerNode("often", NextAction::array(0, new NextAction("reveal gathering item", 50.0f), nullptr))); new TriggerNode("often", { NextAction("reveal gathering item", 50.0f) }));
} }
void UseBobberStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void UseBobberStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back( triggers.push_back(
new TriggerNode("can use fishing bobber", NextAction::array(0, new NextAction("use fishing bobber", 20.0f), nullptr))); new TriggerNode("can use fishing bobber", { NextAction("use fishing bobber", 20.0f) }));
triggers.push_back( triggers.push_back(
new TriggerNode("random", NextAction::array(0, new NextAction("remove bobber strategy", 20.0f), nullptr))); new TriggerNode("random", { NextAction("remove bobber strategy", 20.0f) }));
} }

View File

@@ -7,17 +7,72 @@
#include "Playerbots.h" #include "Playerbots.h"
NextAction** MaintenanceStrategy::getDefaultActions() { return nullptr; } std::vector<NextAction> MaintenanceStrategy::getDefaultActions() { return {}; }
void MaintenanceStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void MaintenanceStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode("random", NextAction::array(0, new NextAction("clean quest log", 6.0f), nullptr))); triggers.push_back(
triggers.push_back(new TriggerNode("random", NextAction::array(0, new NextAction("use random recipe", 1.0f), nullptr))); new TriggerNode(
triggers.push_back(new TriggerNode("random", NextAction::array(0, new NextAction("disenchant random item", 1.0f), nullptr))); "random",
triggers.push_back(new TriggerNode("random", NextAction::array(0, new NextAction("enchant random item", 1.0f), nullptr))); {
triggers.push_back(new TriggerNode("random", NextAction::array(0, new NextAction("smart destroy item", 1.0f), nullptr))); NextAction("clean quest log", 6.0f)
triggers.push_back(new TriggerNode("move stuck", NextAction::array(0, new NextAction("reset", 1.0f), nullptr))); }
// triggers.push_back(new TriggerNode("move long stuck", NextAction::array(0, new NextAction("hearthstone", 0.9f), new NextAction("repop", 0.8f), nullptr))); )
triggers.push_back(new TriggerNode("random", NextAction::array(0, new NextAction("use random quest item", 0.9f), nullptr))); );
triggers.push_back(new TriggerNode("random", NextAction::array(0, new NextAction("auto share quest", 0.9f), nullptr))); triggers.push_back(
new TriggerNode(
"random",
{
NextAction("use random recipe", 1.0f)
}
)
);
triggers.push_back(
new TriggerNode(
"random",
{
NextAction("disenchant random item", 1.0f)
}
)
);
triggers.push_back(
new TriggerNode(
"random",
{
NextAction("enchant random item", 1.0f)
}
)
);
triggers.push_back(
new TriggerNode(
"random",
{
NextAction("smart destroy item", 1.0f)
}
)
);
triggers.push_back(
new TriggerNode(
"move stuck",
{
NextAction("reset", 1.0f)
}
)
);
triggers.push_back(
new TriggerNode(
"random",
{
NextAction("use random quest item", 0.9f)
}
)
);
triggers.push_back(
new TriggerNode(
"random",
{
NextAction("auto share quest", 0.9f)
}
)
);
} }

View File

@@ -17,7 +17,7 @@ public:
std::string const getName() override { return "maintenance"; } std::string const getName() override { return "maintenance"; }
uint32 GetType() const override { return STRATEGY_TYPE_NONCOMBAT; } uint32 GetType() const override { return STRATEGY_TYPE_NONCOMBAT; }
NextAction** getDefaultActions() override; std::vector<NextAction> getDefaultActions() override;
void InitTriggers(std::vector<TriggerNode*>& triggers) override; void InitTriggers(std::vector<TriggerNode*>& triggers) override;
}; };

View File

@@ -10,5 +10,5 @@
void MarkRtiStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void MarkRtiStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back( triggers.push_back(
new TriggerNode("no rti target", NextAction::array(0, new NextAction("mark rti", ACTION_NORMAL), nullptr))); new TriggerNode("no rti target", { NextAction("mark rti", ACTION_NORMAL) }));
} }

View File

@@ -11,12 +11,8 @@ void MeleeCombatStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
CombatStrategy::InitTriggers(triggers); CombatStrategy::InitTriggers(triggers);
// triggers.push_back(new TriggerNode("not facing target", NextAction::array(0, new NextAction("set facing",
// ACTION_MOVE + 7), nullptr)));
triggers.push_back(new TriggerNode( triggers.push_back(new TriggerNode(
"enemy out of melee", NextAction::array(0, new NextAction("reach melee", ACTION_HIGH + 1), nullptr))); "enemy out of melee", { NextAction("reach melee", ACTION_HIGH + 1) }));
// triggers.push_back(new TriggerNode("enemy too close for melee", NextAction::array(0, new NextAction("move out of
// enemy contact", ACTION_NORMAL + 8), nullptr)));
} }
void SetBehindCombatStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void SetBehindCombatStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
@@ -24,5 +20,5 @@ void SetBehindCombatStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
CombatStrategy::InitTriggers(triggers); CombatStrategy::InitTriggers(triggers);
triggers.push_back(new TriggerNode("not behind target", triggers.push_back(new TriggerNode("not behind target",
NextAction::array(0, new NextAction("set behind", ACTION_MOVE + 7), nullptr))); { NextAction("set behind", ACTION_MOVE + 7) }));
} }

View File

@@ -7,9 +7,11 @@
#include "PassiveMultiplier.h" #include "PassiveMultiplier.h"
#include "Playerbots.h" #include "Playerbots.h"
NextAction** MoveFromGroupStrategy::getDefaultActions() std::vector<NextAction> MoveFromGroupStrategy::getDefaultActions()
{ {
return NextAction::array(0, new NextAction("move from group", 1.0f), nullptr); return {
NextAction("move from group", 1.0f)
};
} }
void MoveFromGroupStrategy::InitMultipliers(std::vector<Multiplier*>& multipliers) void MoveFromGroupStrategy::InitMultipliers(std::vector<Multiplier*>& multipliers)

View File

@@ -16,7 +16,7 @@ public:
MoveFromGroupStrategy(PlayerbotAI* botAI) : Strategy(botAI) {} MoveFromGroupStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
std::string const getName() override { return "move from group"; } std::string const getName() override { return "move from group"; }
NextAction** getDefaultActions() override; std::vector<NextAction> getDefaultActions() override;
void InitMultipliers(std::vector<Multiplier*>& multipliers) override; void InitMultipliers(std::vector<Multiplier*>& multipliers) override;
}; };

View File

@@ -9,41 +9,57 @@
void NonCombatStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void NonCombatStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode("random", NextAction::array(0, new NextAction("clean quest log", 1.0f), nullptr))); triggers.push_back(new TriggerNode("random", { NextAction("clean quest log", 1.0f) }));
triggers.push_back(new TriggerNode("timer", NextAction::array(0, new NextAction("check mount state", 1.0f), triggers.push_back(new TriggerNode("timer", { NextAction("check mount state", 1.0f) }));
// new NextAction("check values", 1.0f),
nullptr)));
// triggers.push_back(new TriggerNode("near dark portal", NextAction::array(0, new NextAction("move to dark portal", 1.0f), nullptr)));
// triggers.push_back(new TriggerNode("at dark portal azeroth", NextAction::array(0, new NextAction("use dark portal azeroth", 1.0f), nullptr)));
// triggers.push_back(new TriggerNode("at dark portal outland", NextAction::array(0, new NextAction("move from dark portal", 1.0f), nullptr)));
// triggers.push_back(new TriggerNode("vehicle near", NextAction::array(0, new NextAction("enter vehicle", 10.0f), nullptr)));
} }
void CollisionStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void CollisionStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back( triggers.push_back(
new TriggerNode("collision", NextAction::array(0, new NextAction("move out of collision", 2.0f), nullptr))); new TriggerNode("collision", { NextAction("move out of collision", 2.0f) }));
} }
void MountStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void MountStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
/*triggers.push_back(new TriggerNode("no possible targets", NextAction::array(0, new NextAction("mount", 1.0f),
nullptr))); triggers.push_back(new TriggerNode("no rpg target", NextAction::array(0, new NextAction("mount", 1.0f),
nullptr)));*/
/*triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("mount", 4.0f), nullptr)));*/
} }
void WorldBuffStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void WorldBuffStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode("need world buff", NextAction::array(0, new NextAction("world buff", 1.0f), nullptr))); triggers.push_back(
new TriggerNode(
"need world buff",
{
NextAction("world buff", 1.0f)
}
)
);
} }
void MasterFishingStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void MasterFishingStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode("very often", NextAction::array(0, new NextAction("move near water" , 10.0f), nullptr))); triggers.push_back(
new TriggerNode(
triggers.push_back(new TriggerNode("very often", NextAction::array(0, new NextAction("go fishing" , 10.0f), nullptr))); "very often",
{
triggers.push_back(new TriggerNode("random", NextAction::array(0, new NextAction("end master fishing", 12.0f), NextAction("move near water" , 10.0f)
new NextAction("equip upgrades", 6.0f), nullptr))); }
)
);
triggers.push_back(
new TriggerNode(
"very often",
{
NextAction("go fishing" , 10.0f)
}
)
);
triggers.push_back(
new TriggerNode(
"random",
{
NextAction("end master fishing", 12.0f),
NextAction("equip upgrades", 6.0f)
}
)
);
} }

View File

@@ -11,5 +11,5 @@ void PassTroughStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
for (std::vector<std::string>::iterator i = supported.begin(); i != supported.end(); i++) for (std::vector<std::string>::iterator i = supported.begin(); i != supported.end(); i++)
triggers.push_back( triggers.push_back(
new TriggerNode(i->c_str(), NextAction::array(0, new NextAction(i->c_str(), relevance), nullptr))); new TriggerNode(i->c_str(), { NextAction(i->c_str(), relevance) }));
} }

View File

@@ -31,10 +31,13 @@ float MagePullMultiplier::GetValue(Action* action)
return PassiveMultiplier::GetValue(action); return PassiveMultiplier::GetValue(action);
} }
NextAction** PullStrategy::getDefaultActions() std::vector<NextAction> PullStrategy::getDefaultActions()
{ {
return NextAction::array(0, new NextAction(action, 105.0f), new NextAction("follow", 104.0f), return {
new NextAction("end pull", 103.0f), nullptr); NextAction(action, 105.0f),
NextAction("follow", 104.0f),
NextAction("end pull", 103.0f),
};
} }
void PullStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) { CombatStrategy::InitTriggers(triggers); } void PullStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) { CombatStrategy::InitTriggers(triggers); }
@@ -50,5 +53,11 @@ void PossibleAddsStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
Strategy::InitTriggers(triggers); Strategy::InitTriggers(triggers);
triggers.push_back( triggers.push_back(
new TriggerNode("possible adds", NextAction::array(0, new NextAction("flee with pet", 60), nullptr))); new TriggerNode(
"possible adds",
{
NextAction("flee with pet", 60)
}
)
);
} }

View File

@@ -18,7 +18,7 @@ public:
void InitTriggers(std::vector<TriggerNode*>& triggers) override; void InitTriggers(std::vector<TriggerNode*>& triggers) override;
void InitMultipliers(std::vector<Multiplier*>& multipliers) override; void InitMultipliers(std::vector<Multiplier*>& multipliers) override;
std::string const getName() override { return "pull"; } std::string const getName() override { return "pull"; }
NextAction** getDefaultActions() override; std::vector<NextAction> getDefaultActions() override;
private: private:
std::string const action; std::string const action;

View File

@@ -14,7 +14,7 @@ void QuestStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
PassTroughStrategy::InitTriggers(triggers); PassTroughStrategy::InitTriggers(triggers);
triggers.push_back( triggers.push_back(
new TriggerNode("quest share", NextAction::array(0, new NextAction("accept quest share", relevance), nullptr))); new TriggerNode("quest share", { NextAction("accept quest share", relevance) }));
} }
void DefaultQuestStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void DefaultQuestStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
@@ -22,11 +22,11 @@ void DefaultQuestStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
QuestStrategy::InitTriggers(triggers); QuestStrategy::InitTriggers(triggers);
triggers.push_back(new TriggerNode( triggers.push_back(new TriggerNode(
"use game object", NextAction::array(0, new NextAction("talk to quest giver", relevance), nullptr))); "use game object", { NextAction("talk to quest giver", relevance) }));
triggers.push_back(new TriggerNode( triggers.push_back(new TriggerNode(
"gossip hello", NextAction::array(0, new NextAction("talk to quest giver", relevance), nullptr))); "gossip hello", { NextAction("talk to quest giver", relevance) }));
triggers.push_back(new TriggerNode( triggers.push_back(new TriggerNode(
"complete quest", NextAction::array(0, new NextAction("talk to quest giver", relevance), nullptr))); "complete quest", { NextAction("talk to quest giver", relevance) }));
} }
DefaultQuestStrategy::DefaultQuestStrategy(PlayerbotAI* botAI) : QuestStrategy(botAI) {} DefaultQuestStrategy::DefaultQuestStrategy(PlayerbotAI* botAI) : QuestStrategy(botAI) {}
@@ -36,14 +36,14 @@ void AcceptAllQuestsStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
QuestStrategy::InitTriggers(triggers); QuestStrategy::InitTriggers(triggers);
triggers.push_back( triggers.push_back(
new TriggerNode("use game object", NextAction::array(0, new NextAction("talk to quest giver", relevance), new TriggerNode("use game object", { NextAction("talk to quest giver", relevance),
new NextAction("accept all quests", relevance), nullptr))); NextAction("accept all quests", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("gossip hello", NextAction::array(0, new NextAction("talk to quest giver", relevance), new TriggerNode("gossip hello", { NextAction("talk to quest giver", relevance),
new NextAction("accept all quests", relevance), nullptr))); NextAction("accept all quests", relevance) }));
triggers.push_back( triggers.push_back(
new TriggerNode("complete quest", NextAction::array(0, new NextAction("talk to quest giver", relevance), new TriggerNode("complete quest", { NextAction("talk to quest giver", relevance),
new NextAction("accept all quests", relevance), nullptr))); NextAction("accept all quests", relevance) }));
} }
AcceptAllQuestsStrategy::AcceptAllQuestsStrategy(PlayerbotAI* botAI) : QuestStrategy(botAI) {} AcceptAllQuestsStrategy::AcceptAllQuestsStrategy(PlayerbotAI* botAI) : QuestStrategy(botAI) {}

View File

@@ -16,26 +16,25 @@ private:
static ActionNode* lifeblood(PlayerbotAI* botAI) static ActionNode* lifeblood(PlayerbotAI* botAI)
{ {
return new ActionNode("lifeblood", return new ActionNode("lifeblood",
/*P*/ nullptr, /*P*/ {},
/*A*/ NextAction::array(0, new NextAction("gift of the naaru"), nullptr), /*A*/ { NextAction("gift of the naaru") },
/*C*/ nullptr); /*C*/ {});
} }
}; };
void RacialsStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void RacialsStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back( triggers.push_back(
new TriggerNode("low health", NextAction::array(0, new NextAction("lifeblood", ACTION_NORMAL + 5), nullptr))); new TriggerNode("low health", { NextAction("lifeblood", ACTION_NORMAL + 5) }));
triggers.push_back( triggers.push_back(
new TriggerNode("medium aoe", NextAction::array(0, new NextAction("war stomp", ACTION_NORMAL + 5), nullptr))); new TriggerNode("medium aoe", { NextAction("war stomp", ACTION_NORMAL + 5) }));
triggers.push_back(new TriggerNode( triggers.push_back(new TriggerNode(
"low mana", NextAction::array(0, new NextAction("arcane torrent", ACTION_NORMAL + 5), nullptr))); "low mana", { NextAction("arcane torrent", ACTION_NORMAL + 5) }));
triggers.push_back(new TriggerNode( triggers.push_back(new TriggerNode(
"generic boost", NextAction::array(0, new NextAction("blood fury", ACTION_NORMAL + 5), "generic boost", { NextAction("blood fury", ACTION_NORMAL + 5),
new NextAction("berserking", ACTION_NORMAL + 5), NextAction("berserking", ACTION_NORMAL + 5),
new NextAction("use trinket", ACTION_NORMAL + 4), NextAction("use trinket", ACTION_NORMAL + 4) }));
nullptr)));
} }

View File

@@ -12,7 +12,5 @@ void RangedCombatStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
CombatStrategy::InitTriggers(triggers); CombatStrategy::InitTriggers(triggers);
triggers.push_back(new TriggerNode("enemy too close for spell", triggers.push_back(new TriggerNode("enemy too close for spell",
NextAction::array(0, new NextAction("flee", ACTION_MOVE + 4), nullptr))); { NextAction("flee", ACTION_MOVE + 4) }));
// triggers.push_back(new TriggerNode("not facing target", NextAction::array(0, new NextAction("set facing",
// ACTION_MOVE + 7), nullptr)));
} }

View File

@@ -9,6 +9,6 @@
void ReturnStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void ReturnStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode("return", NextAction::array(0, new NextAction("set return position", 1.5f), triggers.push_back(new TriggerNode("return", { NextAction("set return position", 1.5f),
new NextAction("return", 1.0f), nullptr))); NextAction("return", 1.0f), }));
} }

View File

@@ -24,51 +24,145 @@ float RpgActionMultiplier::GetValue(Action* action)
RpgStrategy::RpgStrategy(PlayerbotAI* botAI) : Strategy(botAI) {} RpgStrategy::RpgStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
NextAction** RpgStrategy::getDefaultActions() { return NextAction::array(0, new NextAction("rpg", 1.0f), nullptr); } std::vector<NextAction> RpgStrategy::getDefaultActions()
{
return {
NextAction("rpg", 1.0f)
};
}
void RpgStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void RpgStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back( triggers.push_back(
new TriggerNode("no rpg target", NextAction::array(0, new NextAction("choose rpg target", 5.0f), nullptr))); new TriggerNode(
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("move random", 1.10f), NULL))); "no rpg target",
triggers.push_back(new TriggerNode("far from rpg target", {
NextAction::array(0, new NextAction("move to rpg target", 5.0f), nullptr))); NextAction("choose rpg target", 5.0f)
}
)
);
triggers.push_back(
new TriggerNode(
"often",
{
NextAction("move random", 1.10f)
}
)
);
triggers.push_back(
new TriggerNode(
"far from rpg target",
{
NextAction("move to rpg target", 5.0f)
}
)
);
// Sub actions // Sub actions
triggers.push_back(new TriggerNode("rpg", NextAction::array(0, new NextAction("rpg stay", 1.101f), nullptr)));
triggers.push_back(new TriggerNode("rpg", NextAction::array(0, new NextAction("rpg work", 1.101f), nullptr)));
triggers.push_back(new TriggerNode("rpg", NextAction::array(0, new NextAction("rpg emote", 1.101f), nullptr)));
triggers.push_back( triggers.push_back(
new TriggerNode("has rpg target", NextAction::array(0, new NextAction("rpg cancel", 1.101f), nullptr))); new TriggerNode(
// triggers.push_back(new TriggerNode("rpg taxi", NextAction::array(0, new NextAction("rpg taxi", 1.005f), "rpg",
// nullptr))); {
NextAction("rpg stay", 1.101f)
}
)
);
triggers.push_back( triggers.push_back(
new TriggerNode("rpg discover", NextAction::array(0, new NextAction("rpg discover", 1.210f), nullptr))); new TriggerNode(
"rpg",
{
NextAction("rpg work", 1.101f)
}
)
);
triggers.push_back( triggers.push_back(
new TriggerNode("rpg start quest", NextAction::array(0, new NextAction("rpg start quest", 1.180f), nullptr))); new TriggerNode(
"rpg",
{
NextAction("rpg emote", 1.101f)
}
)
);
triggers.push_back( triggers.push_back(
new TriggerNode("rpg end quest", NextAction::array(0, new NextAction("rpg end quest", 1.190f), nullptr))); new TriggerNode(
triggers.push_back(new TriggerNode("rpg buy", NextAction::array(0, new NextAction("rpg buy", 1.130f), nullptr))); "has rpg target",
// triggers.push_back(new TriggerNode("rpg sell", NextAction::array(0, new NextAction("rpg sell", 1.100f), {
// nullptr))); NextAction("rpg cancel", 1.101f)
}
)
);
triggers.push_back( triggers.push_back(
new TriggerNode("rpg repair", NextAction::array(0, new NextAction("rpg repair", 1.195f), nullptr))); new TriggerNode(
// triggers.push_back(new TriggerNode("rpg train", NextAction::array(0, new NextAction("rpg train", 1.080f), "rpg discover",
// nullptr))); {
triggers.push_back(new TriggerNode("rpg heal", NextAction::array(0, new NextAction("rpg heal", 1.125f), nullptr))); NextAction("rpg discover", 1.210f)
}
)
);
triggers.push_back( triggers.push_back(
new TriggerNode("rpg home bind", NextAction::array(0, new NextAction("rpg home bind", 1.160f), nullptr))); new TriggerNode(
// triggers.push_back(new TriggerNode("rpg queue bg", NextAction::array(0, new NextAction("rpg queue bg", 1.085f), "rpg start quest",
// nullptr))); {
NextAction("rpg start quest", 1.180f)
}
)
);
triggers.push_back( triggers.push_back(
new TriggerNode("rpg buy petition", NextAction::array(0, new NextAction("rpg buy petition", 1.140f), nullptr))); new TriggerNode(
triggers.push_back(new TriggerNode("rpg use", NextAction::array(0, new NextAction("rpg use", 1.102f), nullptr))); "rpg end quest",
// triggers.push_back(new TriggerNode("rpg spell", NextAction::array(0, new NextAction("rpg spell", 1.001f), {
// nullptr))); triggers.push_back(new TriggerNode("rpg craft", NextAction::array(0, new NextAction("rpg NextAction("rpg end quest", 1.190f)
// craft", 1.001f), nullptr))); }
// triggers.push_back(new TriggerNode("rpg trade useful", NextAction::array(0, new NextAction("rpg trade )
// useful", 1.030f), nullptr))); triggers.push_back(new TriggerNode("rpg duel", NextAction::array(0, new );
// NextAction("rpg duel", 1.010f), nullptr))); triggers.push_back(
new TriggerNode(
"rpg buy",
{
NextAction("rpg buy", 1.130f)
}
)
);
triggers.push_back(
new TriggerNode(
"rpg repair",
{
NextAction("rpg repair", 1.195f)
}
)
);
triggers.push_back(
new TriggerNode(
"rpg heal",
{
NextAction("rpg heal", 1.125f)
}
)
);
triggers.push_back(
new TriggerNode(
"rpg home bind",
{
NextAction("rpg home bind", 1.160f)
}
)
);
triggers.push_back(
new TriggerNode(
"rpg buy petition",
{
NextAction("rpg buy petition", 1.140f)
}
)
);
triggers.push_back(
new TriggerNode(
"rpg use",
{
NextAction("rpg use", 1.102f)
}
)
);
} }
void RpgStrategy::InitMultipliers(std::vector<Multiplier*>& multipliers) void RpgStrategy::InitMultipliers(std::vector<Multiplier*>& multipliers)

View File

@@ -24,7 +24,7 @@ public:
RpgStrategy(PlayerbotAI* botAI); RpgStrategy(PlayerbotAI* botAI);
std::string const getName() override { return "rpg"; } std::string const getName() override { return "rpg"; }
NextAction** getDefaultActions() override; std::vector<NextAction> getDefaultActions() override;
void InitTriggers(std::vector<TriggerNode*>& triggers) override; void InitTriggers(std::vector<TriggerNode*>& triggers) override;
void InitMultipliers(std::vector<Multiplier*>& multipliers) override; void InitMultipliers(std::vector<Multiplier*>& multipliers) override;
}; };

View File

@@ -10,5 +10,5 @@
void RunawayStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void RunawayStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back( triggers.push_back(
new TriggerNode("enemy too close for spell", NextAction::array(0, new NextAction("runaway", 50.0f), nullptr))); new TriggerNode("enemy too close for spell", { NextAction("runaway", 50.0f) }));
} }

View File

@@ -10,11 +10,11 @@
void SayStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void SayStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode("critical health", triggers.push_back(new TriggerNode("critical health",
NextAction::array(0, new NextAction("say::critical health", 99.0f), nullptr))); { NextAction("say::critical health", 99.0f) }));
triggers.push_back( triggers.push_back(
new TriggerNode("low health", NextAction::array(0, new NextAction("say::low health", 99.0f), nullptr))); new TriggerNode("low health", { NextAction("say::low health", 99.0f) }));
triggers.push_back( triggers.push_back(
new TriggerNode("low mana", NextAction::array(0, new NextAction("say::low mana", 99.0f), nullptr))); new TriggerNode("low mana", { NextAction("say::low mana", 99.0f) }));
triggers.push_back(new TriggerNode("tank aoe", NextAction::array(0, new NextAction("say::taunt", 99.0f), nullptr))); triggers.push_back(new TriggerNode("tank aoe", { NextAction("say::taunt", 99.0f) }));
triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("say::aoe", 99.0f), nullptr))); triggers.push_back(new TriggerNode("medium aoe", { NextAction("say::aoe", 99.0f) }));
} }

View File

@@ -9,14 +9,31 @@
void StayStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void StayStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode( triggers.push_back(
new TriggerNode(
"return to stay position", "return to stay position",
NextAction::array(0, new NextAction("return to stay position", ACTION_MOVE), nullptr))); {
NextAction("return to stay position", ACTION_MOVE)
}
)
);
} }
NextAction** StayStrategy::getDefaultActions() { return NextAction::array(0, new NextAction("stay", 1.0f), nullptr); } std::vector<NextAction> StayStrategy::getDefaultActions()
{
return {
NextAction("stay", 1.0f)
};
}
void SitStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void SitStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode("sit", NextAction::array(0, new NextAction("sit", 1.5f), nullptr))); triggers.push_back(
new TriggerNode(
"sit",
{
NextAction("sit", 1.5f)
}
)
);
} }

View File

@@ -17,7 +17,7 @@ public:
std::string const getName() override { return "stay"; } std::string const getName() override { return "stay"; }
void InitTriggers(std::vector<TriggerNode*>& triggers) override; void InitTriggers(std::vector<TriggerNode*>& triggers) override;
NextAction** getDefaultActions() override; std::vector<NextAction> getDefaultActions() override;
}; };
class SitStrategy : public NonCombatStrategy class SitStrategy : public NonCombatStrategy

View File

@@ -10,5 +10,5 @@
void TankAssistStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void TankAssistStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back( triggers.push_back(
new TriggerNode("tank assist", NextAction::array(0, new NextAction("tank assist", 50.0f), nullptr))); new TriggerNode("tank assist", { NextAction("tank assist", 50.0f) }));
} }

Some files were not shown because too many files have changed in this diff Show More