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);
if (strat->getDefaultActions())
for (uint32 i = 0; i < NextAction::size(strat->getDefaultActions()); i++)
{
NextAction* nextAction = strat->getDefaultActions()[i];
const std::vector<NextAction> defaultActions = strat->getDefaultActions();
if (defaultActions.size() > 0)
{
for (NextAction nextAction : defaultActions)
{
std::ostringstream aout;
aout << nextAction->getRelevance() << "," << nextAction->getName()
aout << nextAction.getRelevance() << "," << nextAction.getName()
<< ",,S:" << stratName;
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);
}
}
std::vector<TriggerNode*> triggers;
strat->InitTriggers(triggers);
for (auto& triggerNode : triggers)
{
// out << " TN:" << triggerNode->getName();
for (TriggerNode*& triggerNode : triggers)
{
if (Trigger* trigger = con->GetTrigger(triggerNode->getName()))
{
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;
aout << nextAction->getRelevance() << "," << nextAction->getName()
aout << nextAction.getRelevance() << "," << nextAction.getName()
<< "," << triggerNode->getName() << "," << stratName;
if (actions.find(aout.str().c_str()) != actions.end())

View File

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

View File

@@ -42,9 +42,6 @@ protected:
// TRIGGERS
//
#define NEXT_TRIGGERS(name, relevance) \
virtual NextAction* getNextAction() { return new NextAction(name, relevance); }
#define BEGIN_TRIGGER(clazz, super) \
class clazz : public super \
{ \
@@ -78,14 +75,6 @@ protected:
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) \
class clazz : public DebuffTrigger \
{ \
@@ -296,14 +285,6 @@ protected:
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) \
class clazz : public HealPartyMemberAction \
{ \
@@ -404,14 +385,6 @@ protected:
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) \
class clazz : public CastSpellOnEnemyHealerAction \
{ \
@@ -440,10 +413,6 @@ protected:
clazz(PlayerbotAI* botAI) : CastProtectSpellAction(botAI, spell) {} \
}
#define END_RANGED_SPELL_ACTION() \
} \
;
#define BEGIN_SPELL_ACTION(clazz, name) \
class clazz : public CastSpellAction \
{ \
@@ -472,42 +441,4 @@ protected:
public: \
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

View File

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

View File

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

View File

@@ -90,7 +90,7 @@ public:
bool testMode;
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);
void Reset();
void ProcessTriggers(bool minimal);

View File

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

View File

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

View File

@@ -3,8 +3,7 @@
* and/or modify it under version 3 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_TRIGGER_H
#define _PLAYERBOT_TRIGGER_H
#pragma once
#include "Action.h"
#include "Common.h"
@@ -15,7 +14,11 @@ class Unit;
class Trigger : public AiNamedObject
{
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() {}
@@ -23,7 +26,7 @@ public:
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 bool IsActive() { return false; }
virtual NextAction** getHandlers() { return nullptr; }
virtual std::vector<NextAction> getHandlers() { return {}; }
void Update() {}
virtual void Reset() {}
virtual Unit* GetTarget();
@@ -33,32 +36,49 @@ public:
bool needCheck(uint32 now);
protected:
int32 checkInterval;
uint32 lastCheckTime;
int32_t checkInterval;
uint32_t lastCheckTime;
};
class TriggerNode
{
public:
TriggerNode(std::string const name, NextAction** handlers = nullptr)
: trigger(nullptr), handlers(handlers), name(name)
{
} // reorder args - whipowill
virtual ~TriggerNode() { NextAction::destroy(handlers); }
TriggerNode(
const std::string& name,
std::vector<NextAction> handlers = {}
) :
trigger(nullptr),
handlers(std::move(handlers)),
name(name)
{}
Trigger* getTrigger() { return 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:
Trigger* trigger;
NextAction** handlers;
std::string const name;
std::vector<NextAction> handlers;
const std::string name;
};
#endif

View File

@@ -78,20 +78,17 @@ float ChooseRpgTargetAction::getMaxRelevance(GuidPosition guidP)
if (!trigger->IsActive())
continue;
NextAction** nextActions = triggerNode->getHandlers();
std::vector<NextAction> nextActions = triggerNode->getHandlers();
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))
isRpg = true;
}
NextAction::destroy(nextActions);
if (isRpg)
{

View File

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

View File

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

View File

@@ -68,17 +68,15 @@ bool RpgAction::SetNextRpgAction()
triggerNode->setTrigger(trigger);
NextAction** nextActions = triggerNode->getHandlers();
std::vector<NextAction> nextActions = triggerNode->getHandlers();
Trigger* trigger = triggerNode->getTrigger();
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;
if (!isChecked && !trigger->IsActive())
@@ -86,14 +84,13 @@ bool RpgAction::SetNextRpgAction()
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())
continue;
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:
BloodDKStrategyActionNodeFactory()
{
// creators["melee"] = &melee;
// creators["blood strike"] = &blood_strike;
creators["rune strike"] = &rune_strike;
creators["heart strike"] = &heart_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["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["taunt spell"] = &dark_command;
}
@@ -38,39 +23,61 @@ public:
private:
static ActionNode* rune_strike([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("rune strike",
/*P*/ NextAction::array(0, new NextAction("frost presence"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
return new ActionNode(
"rune strike",
{
NextAction("frost presence")
},
/*A*/ {},
/*C*/ {}
);
}
static ActionNode* icy_touch([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("icy touch",
/*P*/ NextAction::array(0, new NextAction("frost presence"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
return new ActionNode(
"icy touch",
{
NextAction("frost presence")
},
/*A*/ {},
/*C*/ {}
);
}
static ActionNode* heart_strike([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("heart strike",
/*P*/ NextAction::array(0, new NextAction("frost presence"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
return new ActionNode(
"heart strike",
{
NextAction("frost presence")
},
/*A*/ {},
/*C*/ {}
);
}
static ActionNode* death_strike([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("death strike",
/*P*/ NextAction::array(0, new NextAction("frost presence"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
return new ActionNode(
"death strike",
{
NextAction("frost presence")
},
/*A*/ {},
/*C*/ {}
);
}
static ActionNode* dark_command([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("dark command",
/*P*/ NextAction::array(0, new NextAction("frost presence"), NULL),
/*A*/ NextAction::array(0, new NextAction("death grip"), NULL),
/*C*/ NULL);
return new ActionNode(
"dark command",
{
NextAction("frost presence")
},
/*A*/ {
NextAction("death grip")
},
/*C*/ {}
);
}
};
@@ -79,33 +86,80 @@ BloodDKStrategy::BloodDKStrategy(PlayerbotAI* botAI) : GenericDKStrategy(botAI)
actionNodeFactories.Add(new BloodDKStrategyActionNodeFactory());
}
NextAction** BloodDKStrategy::getDefaultActions()
std::vector<NextAction> BloodDKStrategy::getDefaultActions()
{
return NextAction::array(
0, new NextAction("rune strike", ACTION_DEFAULT + 0.8f), new NextAction("icy touch", ACTION_DEFAULT + 0.7f),
new NextAction("heart strike", ACTION_DEFAULT + 0.6f), new NextAction("blood strike", ACTION_DEFAULT + 0.5f),
new NextAction("dancing rune weapon", ACTION_DEFAULT + 0.4f),
new NextAction("death coil", ACTION_DEFAULT + 0.3f), new NextAction("plague strike", ACTION_DEFAULT + 0.2f),
new NextAction("horn of winter", ACTION_DEFAULT + 0.1f), new NextAction("melee", ACTION_DEFAULT), NULL);
return {
NextAction("rune strike", ACTION_DEFAULT + 0.8f),
NextAction("icy touch", ACTION_DEFAULT + 0.7f),
NextAction("heart strike", ACTION_DEFAULT + 0.6f),
NextAction("blood strike", ACTION_DEFAULT + 0.5f),
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)
{
GenericDKStrategy::InitTriggers(triggers);
triggers.push_back(new TriggerNode(
"rune strike", NextAction::array(0, new NextAction("rune strike", ACTION_NORMAL + 3), nullptr)));
triggers.push_back(
new TriggerNode("blood tap", NextAction::array(0, new NextAction("blood tap", ACTION_HIGH + 5), nullptr)));
new TriggerNode(
"rune strike",
{
NextAction("rune strike", ACTION_NORMAL + 3)
}
)
);
triggers.push_back(
new TriggerNode("lose aggro", NextAction::array(0, new NextAction("dark command", ACTION_HIGH + 3), nullptr)));
new TriggerNode(
"blood tap",
{
NextAction("blood tap", ACTION_HIGH + 5)
}
)
);
triggers.push_back(
new TriggerNode("low health", NextAction::array(0, new NextAction("army of the dead", ACTION_HIGH + 4),
new NextAction("death strike", ACTION_HIGH + 3), nullptr)));
new TriggerNode(
"lose aggro",
{
NextAction("dark command", ACTION_HIGH + 3)
}
)
);
triggers.push_back(
new TriggerNode("critical health", NextAction::array(0, new NextAction("vampiric blood", ACTION_HIGH + 5), nullptr)));
new TriggerNode(
"low health",
{
NextAction("army of the dead", ACTION_HIGH + 4),
NextAction("death strike", ACTION_HIGH + 3)
}
)
);
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 + 2), nullptr)));
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;
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; }
};

View File

@@ -11,39 +11,40 @@
#include "SpellInfo.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());
}
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());
}
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());
}
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());
}
bool CastRaiseDeadAction::Execute(Event event)
{
bool result = CastBuffSpellAction::Execute(event);
const bool result = CastBuffSpellAction::Execute(event);
if (!result)
{
return false;
}
uint32 spellId = AI_VALUE2(uint32, "spell id", spell);
// SpellInfo const *spellInfo = sSpellMgr->GetSpellInfo(spellId);
const uint32_t spellId = AI_VALUE2(uint32_t, "spell id", spell);
bot->AddSpellCooldown(spellId, 0, 3 * 60 * 1000);
return true;
}

View File

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

View File

@@ -16,66 +16,68 @@ public:
creators["obliterate"] = &obliterate;
creators["howling blast"] = &howling_blast;
creators["frost strike"] = &frost_strike;
// creators["chains of ice"] = &chains_of_ice;
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["improved icy talons"] = &improved_icy_talons;
}
private:
static ActionNode* icy_touch([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("icy touch",
/*P*/ NextAction::array(0, new NextAction("blood presence"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
return new ActionNode(
"icy touch",
/*P*/ { NextAction("blood presence") },
/*A*/ {},
/*C*/ {}
);
}
static ActionNode* obliterate([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("obliterate",
/*P*/ NextAction::array(0, new NextAction("blood presence"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
return new ActionNode(
"obliterate",
/*P*/ { NextAction("blood presence") },
/*A*/ {},
/*C*/ {}
);
}
static ActionNode* rune_strike([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("rune strike",
/*P*/ NextAction::array(0, new NextAction("blood presence"), nullptr),
/*A*/ NextAction::array(0, new NextAction("melee"), nullptr),
/*C*/ nullptr);
return new ActionNode(
"rune strike",
/*P*/ { NextAction("blood presence") },
/*A*/ { NextAction("melee") },
/*C*/ {}
);
}
static ActionNode* frost_strike([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("frost strike",
/*P*/ NextAction::array(0, new NextAction("blood presence"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
return new ActionNode(
"frost strike",
/*P*/ { NextAction("blood presence") },
/*A*/ {},
/*C*/ {}
);
}
static ActionNode* howling_blast([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("howling blast",
/*P*/ NextAction::array(0, new NextAction("blood presence"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
return new ActionNode(
"howling blast",
/*P*/ { NextAction("blood presence") },
/*A*/ {},
/*C*/ {}
);
}
static ActionNode* unbreakable_armor([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("unbreakable armor",
/*P*/ NextAction::array(0, new NextAction("blood tap"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
return new ActionNode(
"unbreakable armor",
/*P*/ { NextAction("blood tap") },
/*A*/ {},
/*C*/ {}
);
}
};
@@ -84,41 +86,84 @@ FrostDKStrategy::FrostDKStrategy(PlayerbotAI* botAI) : GenericDKStrategy(botAI)
actionNodeFactories.Add(new FrostDKStrategyActionNodeFactory());
}
NextAction** FrostDKStrategy::getDefaultActions()
std::vector<NextAction> FrostDKStrategy::getDefaultActions()
{
return NextAction::array(
0, new NextAction("obliterate", ACTION_DEFAULT + 0.7f),
new NextAction("frost strike", ACTION_DEFAULT + 0.4f),
new NextAction("empower rune weapon", ACTION_DEFAULT + 0.3f),
new NextAction("horn of winter", ACTION_DEFAULT + 0.1f), new NextAction("melee", ACTION_DEFAULT), NULL);
return {
NextAction("obliterate", ACTION_DEFAULT + 0.7f),
NextAction("frost strike", ACTION_DEFAULT + 0.4f),
NextAction("empower rune weapon", ACTION_DEFAULT + 0.3f),
NextAction("horn of winter", ACTION_DEFAULT + 0.1f),
NextAction("melee", ACTION_DEFAULT)
};
}
void FrostDKStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{
GenericDKStrategy::InitTriggers(triggers);
triggers.push_back(new TriggerNode(
"unbreakable armor", NextAction::array(0, new NextAction("unbreakable armor", ACTION_DEFAULT + 0.6f), nullptr)));
triggers.push_back(new TriggerNode(
"freezing fog", NextAction::array(0, new NextAction("howling blast", ACTION_DEFAULT + 0.5f), nullptr)));
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(
new TriggerNode(
"unbreakable armor",
{
NextAction("unbreakable armor", ACTION_DEFAULT + 0.6f)
}
)
);
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 + 2), nullptr)));
// triggers.push_back(new TriggerNode("empower rune weapon", NextAction::array(0, new NextAction("empower rune
// weapon", ACTION_NORMAL + 4), nullptr)));
new TriggerNode(
"freezing fog",
{
NextAction("howling blast", ACTION_DEFAULT + 0.5f)
}
)
);
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)
{
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;
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; }
};

View File

@@ -20,17 +20,17 @@ private:
static ActionNode* bone_shield([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("bone shield",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ {},
/*A*/ {},
/*C*/ {});
}
static ActionNode* horn_of_winter([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("horn of winter",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ {},
/*A*/ {},
/*C*/ {});
}
};
@@ -44,19 +44,18 @@ void GenericDKNonCombatStrategy::InitTriggers(std::vector<TriggerNode*>& trigger
NonCombatStrategy::InitTriggers(triggers);
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(
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(
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(
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(
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)
{
// 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)
{
return new ActionNode("death coil",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ {},
/*A*/ {},
/*C*/ {});
}
static ActionNode* death_grip([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("death grip",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("icy touch"), nullptr),
/*C*/ nullptr);
/*P*/ {},
/*A*/ { NextAction("icy touch") },
/*C*/ {});
}
static ActionNode* plague_strike([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("plague strike",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ {},
/*A*/ {},
/*C*/ {});
}
static ActionNode* icy_touch([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("icy touch",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ {},
/*A*/ {},
/*C*/ {});
}
static ActionNode* heart_strike([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("heart strike",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ {},
/*A*/ {},
/*C*/ {});
}
static ActionNode* pestilence([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("pestilence",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ {},
/*A*/ {},
/*C*/ {});
}
static ActionNode* horn_of_winter([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("horn of winter",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ {},
/*A*/ {},
/*C*/ {});
}
static ActionNode* bone_shield([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("bone shield",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ {},
/*A*/ {},
/*C*/ {});
}
static ActionNode* killing_machine([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("killing machine",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("improved icy talons"), nullptr),
/*C*/ nullptr);
/*P*/ {},
/*A*/ { NextAction("improved icy talons") },
/*C*/ {});
}
static ActionNode* corpse_explosion([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("corpse explosion",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ {},
/*A*/ {},
/*C*/ {});
}
static ActionNode* death_and_decay([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("death and decay",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ {},
/*A*/ {},
/*C*/ {});
}
static ActionNode* anti_magic_zone([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("anti magic zone",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("anti magic shell"), nullptr),
/*C*/ nullptr);
/*P*/ {},
/*A*/ { NextAction("anti magic shell") },
/*C*/ {});
}
static ActionNode* icebound_fortitude([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("icebound fortitude",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ {},
/*A*/ {},
/*C*/ {});
}
};
@@ -165,36 +165,29 @@ void GenericDKStrategy::InitTriggers(std::vector<TriggerNode*>& 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(
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(
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(
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("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(
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(
"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",
NextAction::array(0, new NextAction("death pact", ACTION_HIGH + 5), nullptr)));
{ NextAction("death pact", ACTION_HIGH + 5) }));
triggers.push_back(
new TriggerNode("low health", NextAction::array(0, new NextAction("icebound fortitude", ACTION_HIGH + 5),
new NextAction("rune tap", ACTION_HIGH + 4), nullptr)));
new TriggerNode("low health", { NextAction("icebound fortitude", ACTION_HIGH + 5),
NextAction("rune tap", ACTION_HIGH + 4) }));
triggers.push_back(
new TriggerNode("medium aoe", NextAction::array(0, new NextAction("death and decay", ACTION_HIGH + 9),
new NextAction("pestilence", ACTION_NORMAL + 4),
new NextAction("blood boil", ACTION_NORMAL + 3), nullptr)));
// triggers.push_back(new TriggerNode("light aoe", NextAction::array(0,
// new NextAction("pestilence", ACTION_NORMAL + 4),
// nullptr)));
new TriggerNode("medium aoe", { NextAction("death and decay", ACTION_HIGH + 9),
NextAction("pestilence", ACTION_NORMAL + 4),
NextAction("blood boil", ACTION_NORMAL + 3) }));
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.
*/
@@ -11,21 +11,8 @@ class UnholyDKStrategyActionNodeFactory : public NamedObjectFactory<ActionNode>
public:
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["unholy blight"] = &unholy_blight;
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["corpse explosion"] = &corpse_explosion;
creators["icy touch"] = &icy_touch;
@@ -34,39 +21,49 @@ public:
private:
static ActionNode* death_strike([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("death strike",
/*P*/ NextAction::array(0, new NextAction("blood presence"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
return new ActionNode(
"death strike",
/*P*/ { NextAction("blood presence") },
/*A*/ {},
/*C*/ {}
);
}
static ActionNode* ghoul_frenzy([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("ghoul frenzy",
/*P*/ NextAction::array(0, new NextAction("blood presence"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
return new ActionNode(
"ghoul frenzy",
/*P*/ { NextAction("blood presence") },
/*A*/ {},
/*C*/ {}
);
}
static ActionNode* corpse_explosion([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("corpse explosion",
/*P*/ NextAction::array(0, new NextAction("blood presence"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
return new ActionNode(
"corpse explosion",
/*P*/ { NextAction("blood presence") },
/*A*/ {},
/*C*/ {}
);
}
static ActionNode* scourge_strike([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("scourge strike",
/*P*/ NextAction::array(0, new NextAction("blood presence"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
return new ActionNode(
"scourge strike",
/*P*/ { NextAction("blood presence") },
/*A*/ {},
/*C*/ {}
);
}
static ActionNode* icy_touch([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("icy touch",
/*P*/ NextAction::array(0, new NextAction("blood presence"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
return new ActionNode(
"icy touch",
/*P*/ { NextAction("blood presence") },
/*A*/ {},
/*C*/ {}
);
}
};
@@ -75,69 +72,121 @@ UnholyDKStrategy::UnholyDKStrategy(PlayerbotAI* botAI) : GenericDKStrategy(botAI
actionNodeFactories.Add(new UnholyDKStrategyActionNodeFactory());
}
NextAction** UnholyDKStrategy::getDefaultActions()
std::vector<NextAction> UnholyDKStrategy::getDefaultActions()
{
return NextAction::array(
0, new NextAction("death and decay", ACTION_HIGH + 5),
new NextAction("summon gargoyle", ACTION_DEFAULT + 0.4f),
// new NextAction("empower rune weapon", ACTION_DEFAULT + 0.3f),
new NextAction("horn of winter", ACTION_DEFAULT + 0.2f),
new NextAction("death coil", ACTION_DEFAULT + 0.1f),
new NextAction("melee", ACTION_DEFAULT), nullptr);
return {
NextAction("death and decay", ACTION_HIGH + 5),
NextAction("summon gargoyle", ACTION_DEFAULT + 0.4f),
NextAction("horn of winter", ACTION_DEFAULT + 0.2f),
NextAction("death coil", ACTION_DEFAULT + 0.1f),
NextAction("melee", ACTION_DEFAULT)
};
}
void UnholyDKStrategy::InitTriggers(std::vector<TriggerNode*>& 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(
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(
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(
new TriggerNode("no rune", NextAction::array(0, new NextAction("empower rune weapon", ACTION_HIGH + 1), nullptr)));
// triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction(, ACTION_NORMAL + 2), nullptr)));
triggers.push_back(new TriggerNode(
"army of the dead", NextAction::array(0, new NextAction("army of the dead", ACTION_HIGH + 6), nullptr)));
new TriggerNode(
"high frost rune",
{
NextAction("icy touch", ACTION_NORMAL + 3)
}
)
);
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)
{
triggers.push_back(new TriggerNode(
"loot available", NextAction::array(0, new NextAction("corpse explosion", ACTION_NORMAL + 1), nullptr)));
triggers.push_back(new TriggerNode(
"medium aoe", NextAction::array(0, new NextAction("death and decay", ACTION_NORMAL + 3),
new NextAction("corpse explosion", ACTION_NORMAL + 3), nullptr)));
triggers.push_back(
new TriggerNode(
"loot available",
{
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;
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; }
};

View File

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

View File

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

View File

@@ -28,90 +28,112 @@ public:
private:
static ActionNode* faerie_fire_feral([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("faerie fire (feral)",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ nullptr);
return new ActionNode(
"faerie fire (feral)",
/*P*/ {},
/*A*/ {},
/*C*/ {}
);
}
static ActionNode* melee([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("melee",
/*P*/ NextAction::array(0, new NextAction("feral charge - cat"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
return new ActionNode(
"melee",
/*P*/ { NextAction("feral charge - cat") },
/*A*/ {},
/*C*/ {}
);
}
static ActionNode* feral_charge_cat([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("feral charge - cat",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("reach melee"), nullptr),
/*C*/ nullptr);
return new ActionNode(
"feral charge - cat",
/*P*/ {},
/*A*/ { NextAction("reach melee") },
/*C*/ {}
);
}
static ActionNode* cat_form([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("cat form",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
return new ActionNode(
"cat form",
/*P*/ { NextAction("caster form") },
/*A*/ {},
/*C*/ {}
);
}
static ActionNode* claw([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("claw",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("melee"), nullptr),
/*C*/ nullptr);
return new ActionNode(
"claw",
/*P*/ {},
/*A*/ { NextAction("melee") },
/*C*/ {}
);
}
static ActionNode* mangle_cat([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("mangle (cat)",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ nullptr);
return new ActionNode(
"mangle (cat)",
/*P*/ {},
/*A*/ {},
/*C*/ {}
);
}
static ActionNode* rake([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("rake",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ nullptr);
return new ActionNode(
"rake",
/*P*/ {},
/*A*/ {},
/*C*/ {}
);
}
static ActionNode* ferocious_bite([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("ferocious bite",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("rip"), nullptr),
/*C*/ nullptr);
return new ActionNode(
"ferocious bite",
/*P*/ {},
/*A*/ { NextAction("rip") },
/*C*/ {}
);
}
static ActionNode* rip([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("rip",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ nullptr);
return new ActionNode(
"rip",
/*P*/ {},
/*A*/ {},
/*C*/ {}
);
}
static ActionNode* pounce([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("pounce",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("ravage"), nullptr),
/*C*/ nullptr);
return new ActionNode(
"pounce",
/*P*/ {},
/*A*/ { NextAction("ravage") },
/*C*/ {}
);
}
static ActionNode* ravage([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("ravage",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("shred"), nullptr),
/*C*/ nullptr);
return new ActionNode(
"ravage",
/*P*/ {},
/*A*/ { NextAction("shred") },
/*C*/ {}
);
}
};
@@ -120,9 +142,11 @@ CatDpsDruidStrategy::CatDpsDruidStrategy(PlayerbotAI* botAI) : FeralDruidStrateg
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)
@@ -130,50 +154,161 @@ void CatDpsDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
FeralDruidStrategy::InitTriggers(triggers);
// 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(
new TriggerNode("faerie fire (feral)",
NextAction::array(0, new NextAction("faerie fire (feral)", ACTION_DEFAULT + 0.0f), nullptr)));
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(
"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
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(
new TriggerNode("savage roar", NextAction::array(0, new NextAction("savage roar", ACTION_HIGH + 7), nullptr)));
triggers.push_back(new TriggerNode("combo points available",
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)));
new TriggerNode(
"savage roar", {
NextAction("savage roar", ACTION_HIGH + 7)
}
)
);
triggers.push_back(
new TriggerNode("target with combo points almost dead",
NextAction::array(0, new NextAction("ferocious bite", ACTION_HIGH + 4), nullptr)));
triggers.push_back(new TriggerNode("mangle (cat)",
NextAction::array(0, new NextAction("mangle (cat)", ACTION_HIGH + 3), nullptr)));
triggers.push_back(new TriggerNode("rake", NextAction::array(0, new NextAction("rake", ACTION_HIGH + 2), nullptr)));
new TriggerNode(
"combo points available",
{
NextAction("rip", ACTION_HIGH + 6)
}
)
);
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
triggers.push_back(
new TriggerNode("medium aoe", NextAction::array(0, new NextAction("swipe (cat)", ACTION_HIGH + 3), nullptr)));
triggers.push_back(new TriggerNode(
"light aoe", NextAction::array(0, new NextAction("rake on attacker", ACTION_HIGH + 2), nullptr)));
// Reach target
triggers.push_back(new TriggerNode(
"enemy out of melee", NextAction::array(0, new NextAction("feral charge - cat", ACTION_HIGH + 9), nullptr)));
new TriggerNode(
"medium aoe",
{
NextAction("swipe (cat)", ACTION_HIGH + 3)
}
)
);
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) {}

View File

@@ -18,7 +18,7 @@ public:
public:
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
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; }
};

View File

@@ -11,15 +11,15 @@
#include "AoeValues.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());
}
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());
}
@@ -60,15 +60,15 @@ bool CastStarfallAction::isUseful()
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());
}
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());
}

View File

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

View File

@@ -17,9 +17,9 @@ bool CastBearFormAction::isUseful()
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());
}

View File

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

View File

@@ -26,65 +26,65 @@ private:
static ActionNode* survival_instincts([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("survival instincts",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("barkskin"), nullptr),
/*C*/ nullptr);
/*P*/ {},
/*A*/ { NextAction("barkskin") },
/*C*/ {});
}
static ActionNode* thorns([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("thorns",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ { NextAction("caster form") },
/*A*/ {},
/*C*/ {});
}
static ActionNode* omen_of_clarity([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("omen of clarity",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ { NextAction("caster form") },
/*A*/ {},
/*C*/ {});
}
static ActionNode* cure_poison([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("cure poison",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ { NextAction("caster form") },
/*A*/ {},
/*C*/ {});
}
static ActionNode* cure_poison_on_party([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("cure poison on party",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ { NextAction("caster form") },
/*A*/ {},
/*C*/ {});
}
static ActionNode* abolish_poison([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("abolish poison",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ { NextAction("caster form") },
/*A*/ {},
/*C*/ {});
}
static ActionNode* abolish_poison_on_party([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("abolish poison on party",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ { NextAction("caster form") },
/*A*/ {},
/*C*/ {});
}
static ActionNode* prowl([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("prowl",
/*P*/ NextAction::array(0, new NextAction("cat form"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ { NextAction("cat form") },
/*A*/ {},
/*C*/ {});
}
};
@@ -98,20 +98,16 @@ void FeralDruidStrategy::InitTriggers(std::vector<TriggerNode*>& 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(
"enemy out of melee", NextAction::array(0, new NextAction("reach melee", ACTION_HIGH + 1), nullptr)));
// triggers.push_back(new TriggerNode("enemy too close for melee", NextAction::array(0, new NextAction("move out of
// enemy contact", ACTION_NORMAL + 8), nullptr)));
"enemy out of melee", { NextAction("reach melee", ACTION_HIGH + 1) }));
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(
"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",
NextAction::array(0, new NextAction("dash", ACTION_EMERGENCY + 2), nullptr)));
{ NextAction("dash", ACTION_EMERGENCY + 2) }));
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(
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)
{
return new ActionNode("regrowth",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr),
/*A*/ NextAction::array(0, new NextAction("healing touch"), nullptr),
/*C*/ NextAction::array(0, new NextAction("melee", 10.0f), nullptr));
/*P*/ { NextAction("caster form") },
/*A*/ { NextAction("healing touch") },
/*C*/ { NextAction("melee", 10.0f) });
}
static ActionNode* rejuvenation([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("rejuvenation",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ { NextAction("caster form") },
/*A*/ {},
/*C*/ {});
}
static ActionNode* healing_touch([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("healing touch",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ { NextAction("caster form") },
/*A*/ {},
/*C*/ {});
}
static ActionNode* regrowth_on_party([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("regrowth on party",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr),
/*A*/ NextAction::array(0, new NextAction("healing touch on party"), nullptr),
/*C*/ NextAction::array(0, new NextAction("melee", 10.0f), nullptr));
/*P*/ { NextAction("caster form") },
/*A*/ { NextAction("healing touch on party") },
/*C*/ { NextAction("melee", 10.0f) });
}
static ActionNode* rejuvenation_on_party([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("rejuvenation on party",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ { NextAction("caster form") },
/*A*/ {},
/*C*/ {});
}
static ActionNode* healing_touch_on_party([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("healing touch on party",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ { NextAction("caster form") },
/*A*/ {},
/*C*/ {});
}
};

View File

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

View File

@@ -27,73 +27,73 @@ private:
static ActionNode* melee([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("melee",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ {},
/*A*/ {},
/*C*/ {});
}
static ActionNode* caster_form([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("caster form",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ {},
/*A*/ {},
/*C*/ {});
}
static ActionNode* cure_poison([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("cure poison",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ {},
/*A*/ {},
/*C*/ {});
}
static ActionNode* cure_poison_on_party([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("cure poison on party",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ {},
/*A*/ {},
/*C*/ {});
}
static ActionNode* abolish_poison([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("abolish poison",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ {},
/*A*/ {},
/*C*/ {});
}
static ActionNode* abolish_poison_on_party([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("abolish poison on party",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ {},
/*A*/ {},
/*C*/ {});
}
static ActionNode* rebirth([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("rebirth",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ {},
/*A*/ {},
/*C*/ {});
}
static ActionNode* entangling_roots_on_cc([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("entangling roots on cc",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ { NextAction("caster form") },
/*A*/ {},
/*C*/ {});
}
static ActionNode* innervate([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("innervate",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("mana potion"), nullptr),
/*C*/ nullptr);
/*P*/ {},
/*A*/ { NextAction("mana potion") },
/*C*/ {});
}
};
@@ -107,70 +107,52 @@ void GenericDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
CombatStrategy::InitTriggers(triggers);
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",
NextAction::array(0, new NextAction("rebirth", ACTION_HIGH + 9), NULL)));
{ NextAction("rebirth", ACTION_HIGH + 9) }));
triggers.push_back(new TriggerNode("being attacked",
NextAction::array(0, new NextAction("nature's grasp", ACTION_HIGH + 1), nullptr)));
triggers.push_back(new TriggerNode("new pet", NextAction::array(0, new NextAction("set pet stance", 60.0f), nullptr)));
{ NextAction("nature's grasp", ACTION_HIGH + 1) }));
triggers.push_back(new TriggerNode("new pet", { NextAction("set pet stance", 60.0f) }));
}
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(
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(
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)
{
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)
{
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(
"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(
"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)
{
triggers.push_back(
new TriggerNode("healer should attack",
NextAction::array(0,
new NextAction("cancel tree form", ACTION_DEFAULT + 0.3f),
new NextAction("moonfire", ACTION_DEFAULT + 0.2f),
new NextAction("wrath", ACTION_DEFAULT + 0.1f),
new NextAction("starfire", ACTION_DEFAULT),
nullptr)));
{
NextAction("cancel tree form", ACTION_DEFAULT + 0.3f),
NextAction("moonfire", ACTION_DEFAULT + 0.2f),
NextAction("wrath", ACTION_DEFAULT + 0.1f),
NextAction("starfire", ACTION_DEFAULT),
}));
// 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:
HealDruidStrategyActionNodeFactory() {
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:
static ActionNode* nourtish_on_party([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("nourish on party",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("healing touch on party"), nullptr),
/*C*/ nullptr);
/*P*/ {},
/*A*/ { NextAction("healing touch on party") },
/*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)
@@ -57,73 +33,69 @@ void HealDruidStrategy::InitTriggers(std::vector<TriggerNode*>& 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(
"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
triggers.push_back(
new TriggerNode("party member critical health",
NextAction::array(0,
new NextAction("tree form", ACTION_CRITICAL_HEAL + 4.1f),
new NextAction("swiftmend on party", ACTION_CRITICAL_HEAL + 4),
new NextAction("regrowth on party", ACTION_CRITICAL_HEAL + 3),
new NextAction("wild growth on party", ACTION_CRITICAL_HEAL + 2),
new NextAction("nourish on party", ACTION_CRITICAL_HEAL + 1),
// new NextAction("healing touch on party", ACTION_CRITICAL_HEAL + 0),
nullptr)));
{
NextAction("tree form", ACTION_CRITICAL_HEAL + 4.1f),
NextAction("swiftmend on party", ACTION_CRITICAL_HEAL + 4),
NextAction("regrowth on party", ACTION_CRITICAL_HEAL + 3),
NextAction("wild growth on party", ACTION_CRITICAL_HEAL + 2),
NextAction("nourish on party", ACTION_CRITICAL_HEAL + 1),
}));
triggers.push_back(
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(
"group heal setting",
NextAction::array(0,
new NextAction("tree form", ACTION_MEDIUM_HEAL + 2.3f),
new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 2.2f),
new NextAction("rejuvenation on not full", ACTION_MEDIUM_HEAL + 2.1f),
nullptr)));
{
NextAction("tree form", ACTION_MEDIUM_HEAL + 2.3f),
NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 2.2f),
NextAction("rejuvenation on not full", ACTION_MEDIUM_HEAL + 2.1f),
}));
triggers.push_back(
new TriggerNode("medium group heal setting",
NextAction::array(0,
new NextAction("tree form", ACTION_CRITICAL_HEAL + 0.6f),
new NextAction("tranquility", ACTION_CRITICAL_HEAL + 0.5f), nullptr)));
{
NextAction("tree form", ACTION_CRITICAL_HEAL + 0.6f),
NextAction("tranquility", ACTION_CRITICAL_HEAL + 0.5f) }));
// LOW
triggers.push_back(
new TriggerNode("party member low health",
NextAction::array(0, new NextAction("tree form", ACTION_MEDIUM_HEAL + 1.5f),
new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 1.4f),
new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 1.3f),
new NextAction("swiftmend on party", ACTION_MEDIUM_HEAL + 1.2),
new NextAction("nourish on party", ACTION_MEDIUM_HEAL + 1.1f),
nullptr)));
{ NextAction("tree form", ACTION_MEDIUM_HEAL + 1.5f),
NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 1.4f),
NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 1.3f),
NextAction("swiftmend on party", ACTION_MEDIUM_HEAL + 1.2),
NextAction("nourish on party", ACTION_MEDIUM_HEAL + 1.1f),
}));
// MEDIUM
triggers.push_back(
new TriggerNode("party member medium health",
NextAction::array(0,
new NextAction("tree form", ACTION_MEDIUM_HEAL + 0.5f),
new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 0.4f),
new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 0.3f),
new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 0.2f),
new NextAction("nourish on party", ACTION_MEDIUM_HEAL + 0.1f), nullptr)));
{
NextAction("tree form", ACTION_MEDIUM_HEAL + 0.5f),
NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 0.4f),
NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 0.3f),
NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 0.2f),
NextAction("nourish on party", ACTION_MEDIUM_HEAL + 0.1f) }));
// almost full
triggers.push_back(
new TriggerNode("party member almost full health",
NextAction::array(0, new NextAction("wild growth on party", ACTION_LIGHT_HEAL + 0.3f),
new NextAction("rejuvenation on party", ACTION_LIGHT_HEAL + 0.2f),
new NextAction("regrowth on party", ACTION_LIGHT_HEAL + 0.1f), nullptr)));
{ NextAction("wild growth on party", ACTION_LIGHT_HEAL + 0.3f),
NextAction("rejuvenation on party", ACTION_LIGHT_HEAL + 0.2f),
NextAction("regrowth on party", ACTION_LIGHT_HEAL + 0.1f) }));
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",
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) {}
NextAction** MeleeDruidStrategy::getDefaultActions()
std::vector<NextAction> MeleeDruidStrategy::getDefaultActions()
{
return NextAction::array(0, new NextAction("faerie fire", ACTION_DEFAULT + 0.1f),
new NextAction("melee", ACTION_DEFAULT), nullptr);
return {
NextAction("faerie fire", ACTION_DEFAULT + 0.1f),
NextAction("melee", ACTION_DEFAULT)
};
}
void MeleeDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{
triggers.push_back(new TriggerNode(
"omen of clarity", NextAction::array(0, new NextAction("omen of clarity", ACTION_HIGH + 9), nullptr)));
triggers.push_back(
new TriggerNode(
"omen of clarity",
{
NextAction("omen of clarity", ACTION_HIGH + 9)
}
)
);
CombatStrategy::InitTriggers(triggers);
}

View File

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

View File

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

View File

@@ -17,7 +17,7 @@
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
std::string const getName() override { return "offheal"; }
NextAction** getDefaultActions() override;
std::vector<NextAction> getDefaultActions() override;
uint32 GetType() const override
{
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: Bring healer closer than ranged dps to avoid fixates?
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",
NextAction::array(0, new NextAction("krik'thir priority", ACTION_RAID + 4), nullptr)));
{ NextAction("krik'thir priority", ACTION_RAID + 4) }));
// Hadronox
// 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.
// May need to hook boss AI.. might be able to just heal through it for now.
// 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",
NextAction::array(0, new NextAction("dodge pound", ACTION_MOVE + 5), nullptr)));
{ NextAction("dodge pound", ACTION_MOVE + 5) }));
}
void WotlkDungeonANStrategy::InitMultipliers(std::vector<Multiplier*> &multipliers)

View File

@@ -8,12 +8,12 @@ void WotlkDungeonCoSStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
// Salramm the Fleshcrafter
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
// Not sure if this actually works, I think I've seen him charge melee characters..?
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

View File

@@ -5,32 +5,32 @@ void WotlkDungeonDTKStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
{
// Trollgore
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
// TODO: Can be improved - it's a pretty easy fight but complex to program, revisit if needed
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",
NextAction::array(0, new NextAction("novos positioning", ACTION_MOVE + 4), nullptr)));
{ NextAction("novos positioning", ACTION_MOVE + 4) }));
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
// TODO: Fear ward / tremor totem, or general anti-fear strat development
//The Prophet 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",
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
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",
NextAction::array(0, new NextAction("taunt", ACTION_NORMAL + 2), nullptr)));
{ NextAction("taunt", ACTION_NORMAL + 2) }));
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)

View File

@@ -4,17 +4,16 @@
void WotlkDungeonFoSStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{
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",
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",
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",
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)
{
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.
// 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",
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",
NextAction::array(0, new NextAction("attack snake wrap", ACTION_RAID + 4), nullptr)));
{ NextAction("attack snake wrap", ACTION_RAID + 4) }));
// Gal'darah
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)
}

View File

@@ -5,30 +5,30 @@ void WotlkDungeonHoLStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
{
// General Bjarngrim
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",
NextAction::array(0, new NextAction("avoid whirlwind", ACTION_RAID + 4), nullptr)));
{ NextAction("avoid whirlwind", ACTION_RAID + 4) }));
// 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
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",
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",
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
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
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",
NextAction::array(0, new NextAction("loken stack", ACTION_MOVE + 4), nullptr)));
{ NextAction("loken stack", ACTION_MOVE + 4) }));
}
void WotlkDungeonHoLStrategy::InitMultipliers(std::vector<Multiplier*> &multipliers)

View File

@@ -9,7 +9,7 @@ void WotlkDungeonHoSStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
// Krystallus
// 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",
NextAction::array(0, new NextAction("shatter spread", ACTION_RAID + 5), nullptr)));
{ NextAction("shatter spread", ACTION_RAID + 5) }));
// Tribunal of Ages
// 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
// Possibly tank in place in the middle of the room, assign a dps to adds?
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)

View File

@@ -7,39 +7,39 @@ void WotlkDungeonNexStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
// or
// Alliance Commander (Horde N)/Commander Stoutbeard (Horde H)
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.)
// Grand Magus Telestra
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",
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
// Anomalus
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
// 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
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.
// TODO: This turns hunters into melee marshmallows, have not come up with a better solution yet
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
// 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
// Keristrasza
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
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?
}

View File

@@ -6,28 +6,28 @@ void WotlkDungeonOccStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
// Drakos the Interrogator
// TODO: May need work, TBA.
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
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",
NextAction::array(0, new NextAction("dismount drake", ACTION_RAID + 5), nullptr)));
{ NextAction("dismount drake", ACTION_RAID + 5) }));
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",
NextAction::array(0, new NextAction("occ drake attack", ACTION_NORMAL + 5), nullptr)));
{ NextAction("occ drake attack", ACTION_NORMAL + 5) }));
// Varos Cloudstrider
// Seems to be no way to identify the marked cores, may need to hook boss AI..
// 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
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",
NextAction::array(0, new NextAction("time bomb spread", ACTION_MOVE + 4), nullptr)));
{ NextAction("time bomb spread", ACTION_MOVE + 4) }));
// Ley-Guardian Eregos
}

View File

@@ -5,7 +5,7 @@ void WotlkDungeonOKStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
{
// Elder Nadox
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
// 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
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
// Trash mobs before him have a big telegraphed shadow crash spell,
// this can be avoided and is intended to be dodged
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.
// Amanitar (Heroic Only)

View File

@@ -4,14 +4,13 @@
void WotlkDungeonPoSStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{
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",
NextAction::array(0, new NextAction("tyrannus", ACTION_RAID + 5), nullptr)));
{ NextAction("tyrannus", ACTION_RAID + 5) }));
}
void WotlkDungeonPoSStrategy::InitMultipliers(std::vector<Multiplier*>& multipliers)
{
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)
{
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",
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",
NextAction::array(0, new NextAction("toc mount", ACTION_RAID + 4), nullptr)));
{ NextAction("toc mount", ACTION_RAID + 4) }));
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",
NextAction::array(0, new NextAction("toc eadric", ACTION_RAID + 3), nullptr)));
{ NextAction("toc eadric", ACTION_RAID + 3) }));
}
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
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
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
// Doesn't work yet, this action doesn't get processed until the existing cast finishes
// 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.
// Not implemented for now, unsure if this is needed as a good group can probably burst through the boss
// and just eat the debuff.
// 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",
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",
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.
// 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.
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
// TODO: Harpoons launchable via GameObject. For now players should do them
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",
NextAction::array(0, new NextAction("avoid skadi whirlwind", ACTION_RAID + 4), nullptr)));
{ NextAction("avoid skadi whirlwind", ACTION_RAID + 4) }));
// King Ymiron
// May need to avoid orb.. unclear if the generic avoid AoE does this well
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)

View File

@@ -6,14 +6,14 @@ void WotlkDungeonVHStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
// Erekem
// This boss has many purgable buffs, purging/dispels could be merged into generic strats though
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
// TODO: This guy has Optic Link which may require moving, add if needed
// Ichoron
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
// 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
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",
NextAction::array(0, new NextAction("attack void sentry", ACTION_RAID + 1), nullptr)));
{ NextAction("attack void sentry", ACTION_RAID + 1) }));
// Cyanigosa
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)

View File

@@ -10,5 +10,5 @@
void AttackEnemyPlayersStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{
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)
{
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("bg join", relevance), nullptr)));
triggers.push_back(new TriggerNode("bg invite active", NextAction::array(0, new NextAction("bg status check", relevance), nullptr)));
triggers.push_back(new TriggerNode("timer", NextAction::array(0, new NextAction("bg strategy check", relevance), nullptr)));
triggers.push_back(new TriggerNode("often", { NextAction("bg join", relevance)}));
triggers.push_back(new TriggerNode("bg invite active", { NextAction("bg status check", relevance)}));
triggers.push_back(new TriggerNode("timer", { NextAction("bg strategy check", relevance)}));
}
BGStrategy::BGStrategy(PlayerbotAI* botAI) : PassTroughStrategy(botAI) {}
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 active", NextAction::array(0, new NextAction("bg move to objective", ACTION_BG), nullptr)));
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("bg check objective", ACTION_BG + 1), nullptr)));
triggers.push_back(new TriggerNode("dead", NextAction::array(0, new NextAction("bg reset objective force", ACTION_EMERGENCY), nullptr)));
// 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)));
triggers.push_back(new TriggerNode("bg waiting", { NextAction("bg move to start", ACTION_BG)}));
triggers.push_back(new TriggerNode("bg active", { NextAction("bg move to objective", ACTION_BG)}));
triggers.push_back(new TriggerNode("often", { NextAction("bg check objective", ACTION_BG + 1)}));
triggers.push_back(new TriggerNode("dead", { NextAction("bg reset objective force", ACTION_EMERGENCY)}));
}
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("enemy flagcarrier near", NextAction::array(0, new NextAction("attack enemy flag carrier", ACTION_RAID + 1.0f), nullptr)));
triggers.push_back(new TriggerNode("team flagcarrier near", NextAction::array(0, new NextAction("bg protect fc", ACTION_RAID), nullptr)));
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("bg use buff", ACTION_BG), nullptr)));
triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("bg use buff", ACTION_MOVE), nullptr)));
triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("bg use buff", ACTION_MOVE), nullptr)));
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("timer bg", NextAction::array(0, new NextAction("bg reset objective force", 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("attack enemy flag carrier", ACTION_RAID + 1.0f)}));
triggers.push_back(new TriggerNode("team flagcarrier near", { NextAction("bg protect fc", ACTION_RAID)}));
triggers.push_back(new TriggerNode("often", { NextAction("bg use buff", ACTION_BG)}));
triggers.push_back(new TriggerNode("low health", { NextAction("bg use buff", ACTION_MOVE)}));
triggers.push_back(new TriggerNode("low mana", { NextAction("bg use buff", ACTION_MOVE)}));
triggers.push_back(new TriggerNode("player has flag", { NextAction("bg move to objective", ACTION_EMERGENCY)}));
triggers.push_back(new TriggerNode("timer bg", { NextAction("bg reset objective force", ACTION_EMERGENCY)}));
}
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("timer bg", NextAction::array(0, new NextAction("bg reset objective force", 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("bg reset objective force", ACTION_EMERGENCY)}));
}
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("often", NextAction::array(0, new NextAction("bg use buff", ACTION_BG), nullptr)));
triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("bg use buff", ACTION_MOVE), nullptr)));
triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("bg use buff", ACTION_MOVE), nullptr)));
triggers.push_back(new TriggerNode("bg active", { NextAction("bg check flag", ACTION_EMERGENCY)}));
triggers.push_back(new TriggerNode("often", { NextAction("bg use buff", ACTION_BG)}));
triggers.push_back(new TriggerNode("low health", { NextAction("bg use buff", ACTION_MOVE)}));
triggers.push_back(new TriggerNode("low mana", { NextAction("bg use buff", ACTION_MOVE)}));
}
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("often", NextAction::array(0, new NextAction("bg use buff", ACTION_BG), nullptr)));
triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("bg use buff", ACTION_MOVE), nullptr)));
triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("bg use buff", ACTION_MOVE), nullptr)));
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("player has flag",NextAction::array(0, new NextAction("bg move to objective", ACTION_EMERGENCY), nullptr)));
triggers.push_back(new TriggerNode("bg active", { NextAction("bg check flag", ACTION_EMERGENCY)}));
triggers.push_back(new TriggerNode("often", { NextAction("bg use buff", ACTION_BG)}));
triggers.push_back(new TriggerNode("low health", { NextAction("bg use buff", ACTION_MOVE)}));
triggers.push_back(new TriggerNode("low mana", { NextAction("bg use buff", ACTION_MOVE)}));
triggers.push_back(new TriggerNode("enemy flagcarrier near", { NextAction("attack enemy flag carrier", ACTION_RAID)}));
triggers.push_back(new TriggerNode("player has flag",{ NextAction("bg move to objective", ACTION_EMERGENCY)}));
}
//TODO: Do Priorities
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("timer", NextAction::array(0, new NextAction("enter vehicle", ACTION_MOVE + 8.0f), nullptr)));
triggers.push_back(new TriggerNode("random", NextAction::array(0, new NextAction("leave vehicle", ACTION_MOVE + 7.0f), nullptr)));
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::array(0, new NextAction("fire cannon", ACTION_MOVE + 9.0f), nullptr)));
triggers.push_back(new TriggerNode("in vehicle", NextAction::array(0, new NextAction("napalm", ACTION_MOVE + 9.0f), nullptr)));
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("in vehicle", NextAction::array(0, new NextAction("ram", ACTION_MOVE + 9.0f), nullptr)));
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 out of melee", NextAction::array(0, new NextAction("steam rush", ACTION_MOVE + 9.2f), nullptr)));
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::array(0, new NextAction("rocket blast", ACTION_MOVE + 9.0f), nullptr)));
triggers.push_back(new TriggerNode("bg active", { NextAction("bg check flag", ACTION_MOVE)}));
triggers.push_back(new TriggerNode("timer", { NextAction("enter vehicle", ACTION_MOVE + 8.0f)}));
triggers.push_back(new TriggerNode("random", { NextAction("leave vehicle", ACTION_MOVE + 7.0f)}));
triggers.push_back(new TriggerNode("in vehicle", { NextAction("hurl boulder", ACTION_MOVE + 9.0f)}));
triggers.push_back(new TriggerNode("in vehicle", { NextAction("fire cannon", ACTION_MOVE + 9.0f)}));
triggers.push_back(new TriggerNode("in vehicle", { NextAction("napalm", ACTION_MOVE + 9.0f)}));
triggers.push_back(new TriggerNode("enemy is close", { NextAction("steam blast", ACTION_MOVE + 9.0f)}));
triggers.push_back(new TriggerNode("in vehicle", { NextAction("ram", ACTION_MOVE + 9.0f)}));
triggers.push_back(new TriggerNode("enemy is close", { NextAction("ram", ACTION_MOVE + 9.1f)}));
triggers.push_back(new TriggerNode("enemy out of melee", { NextAction("steam rush", ACTION_MOVE + 9.2f)}));
triggers.push_back(new TriggerNode("in vehicle", { NextAction("incendiary rocket", ACTION_MOVE + 9.0f)}));
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)
// 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::array(0, new NextAction("glaive throw", 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("glaive throw", ACTION_MOVE + 9.0f)}));
}
void ArenaStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{
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)
{
return new ActionNode("tank attack chat shortcut",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ NextAction::array(0, new NextAction("attack my target", 100.0f), nullptr));
/*P*/ {},
/*A*/ {},
/*C*/ { NextAction("attack my target", 100.0f) });
}
};
@@ -26,86 +26,86 @@ void ChatCommandHandlerStrategy::InitTriggers(std::vector<TriggerNode*>& trigger
{
PassTroughStrategy::InitTriggers(triggers);
triggers.push_back(new TriggerNode("rep", NextAction::array(0, new NextAction("reputation", relevance), nullptr)));
triggers.push_back(new TriggerNode("q", NextAction::array(0, new NextAction("query quest", relevance),
new NextAction("query item usage", relevance), nullptr)));
triggers.push_back(new TriggerNode("add all loot", NextAction::array(0, new NextAction("add all loot", relevance),
new NextAction("loot", relevance), nullptr)));
triggers.push_back(new TriggerNode("u", NextAction::array(0, new NextAction("use", relevance), nullptr)));
triggers.push_back(new TriggerNode("c", NextAction::array(0, new NextAction("item count", relevance), nullptr)));
triggers.push_back(new TriggerNode("rep", { NextAction("reputation", relevance) }));
triggers.push_back(new TriggerNode("q", { NextAction("query quest", relevance),
NextAction("query item usage", relevance) }));
triggers.push_back(new TriggerNode("add all loot", { NextAction("add all loot", relevance),
NextAction("loot", relevance) }));
triggers.push_back(new TriggerNode("u", { NextAction("use", relevance) }));
triggers.push_back(new TriggerNode("c", { NextAction("item count", relevance) }));
triggers.push_back(
new TriggerNode("items", NextAction::array(0, new NextAction("item count", relevance), nullptr)));
triggers.push_back(new TriggerNode("inv", NextAction::array(0, new NextAction("item count", relevance), nullptr)));
triggers.push_back(new TriggerNode("e", NextAction::array(0, new NextAction("equip", relevance), nullptr)));
triggers.push_back(new TriggerNode("ue", NextAction::array(0, new NextAction("unequip", relevance), nullptr)));
triggers.push_back(new TriggerNode("t", NextAction::array(0, new NextAction("trade", relevance), nullptr)));
triggers.push_back(new TriggerNode("nt", NextAction::array(0, new NextAction("trade", relevance), nullptr)));
triggers.push_back(new TriggerNode("s", NextAction::array(0, new NextAction("sell", relevance), nullptr)));
triggers.push_back(new TriggerNode("b", NextAction::array(0, new NextAction("buy", relevance), nullptr)));
triggers.push_back(new TriggerNode("r", NextAction::array(0, new NextAction("reward", relevance), nullptr)));
new TriggerNode("items", { NextAction("item count", relevance) }));
triggers.push_back(new TriggerNode("inv", { NextAction("item count", relevance) }));
triggers.push_back(new TriggerNode("e", { NextAction("equip", relevance) }));
triggers.push_back(new TriggerNode("ue", { NextAction("unequip", relevance) }));
triggers.push_back(new TriggerNode("t", { NextAction("trade", relevance) }));
triggers.push_back(new TriggerNode("nt", { NextAction("trade", relevance) }));
triggers.push_back(new TriggerNode("s", { NextAction("sell", relevance) }));
triggers.push_back(new TriggerNode("b", { NextAction("buy", relevance) }));
triggers.push_back(new TriggerNode("r", { NextAction("reward", relevance) }));
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(
new TriggerNode("accept", NextAction::array(0, new NextAction("accept quest", relevance), nullptr)));
new TriggerNode("accept", { NextAction("accept quest", relevance) }));
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(
new TriggerNode("stay", NextAction::array(0, new NextAction("stay chat shortcut", relevance), nullptr)));
new TriggerNode("stay", { NextAction("stay chat shortcut", relevance) }));
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(
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(
"tank attack", NextAction::array(0, new NextAction("tank attack chat shortcut", relevance), nullptr)));
"tank attack", { NextAction("tank attack chat shortcut", relevance) }));
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(
new TriggerNode("talk", NextAction::array(0, new NextAction("gossip hello", relevance),
new NextAction("talk to quest giver", relevance), nullptr)));
new TriggerNode("talk", { NextAction("gossip hello", relevance),
NextAction("talk to quest giver", relevance) }));
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(
new TriggerNode("leave vehicle", NextAction::array(0, new NextAction("leave vehicle", relevance), nullptr)));
new TriggerNode("leave vehicle", { NextAction("leave vehicle", relevance) }));
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(
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(
new TriggerNode("revive", NextAction::array(0, new NextAction("spirit healer", relevance), nullptr)));
new TriggerNode("revive", { NextAction("spirit healer", relevance) }));
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(
new TriggerNode("warning", NextAction::array(0, new NextAction("runaway chat shortcut", relevance), nullptr)));
new TriggerNode("warning", { NextAction("runaway chat shortcut", relevance) }));
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(
new TriggerNode("attackers", NextAction::array(0, new NextAction("tell attackers", relevance), nullptr)));
new TriggerNode("attackers", { NextAction("tell attackers", relevance) }));
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(
new TriggerNode("ready", NextAction::array(0, new NextAction("ready check", relevance), nullptr)));
new TriggerNode("ready", { NextAction("ready check", relevance) }));
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(
new TriggerNode("dps", NextAction::array(0, new NextAction("tell estimated dps", relevance), NULL)));
new TriggerNode("dps", { NextAction("tell estimated dps", relevance) }));
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(
new TriggerNode("open items", NextAction::array(0, new NextAction("open items", relevance), nullptr)));
new TriggerNode("open items", { NextAction("open items", relevance) }));
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(
new TriggerNode("unlock items", NextAction::array(0, new NextAction("unlock items", relevance), nullptr)));
new TriggerNode("unlock items", { NextAction("unlock items", relevance) }));
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(
new TriggerNode("wipe", NextAction::array(0, new NextAction("wipe", relevance), nullptr)));
triggers.push_back(new TriggerNode("tame", NextAction::array(0, new NextAction("tame", relevance), nullptr)));
triggers.push_back(new TriggerNode("glyphs", NextAction::array(0, new NextAction("glyphs", relevance), nullptr))); // 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("pet", NextAction::array(0, new NextAction("pet", relevance), nullptr)));
triggers.push_back(new TriggerNode("pet attack", NextAction::array(0, new NextAction("pet attack", relevance), nullptr)));
triggers.push_back(new TriggerNode("roll", NextAction::array(0, new NextAction("roll", relevance), nullptr)));
new TriggerNode("wipe", { NextAction("wipe", relevance) }));
triggers.push_back(new TriggerNode("tame", { NextAction("tame", relevance) }));
triggers.push_back(new TriggerNode("glyphs", { NextAction("glyphs", relevance) })); // 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("pet", relevance) }));
triggers.push_back(new TriggerNode("pet attack", { NextAction("pet attack", relevance) }));
triggers.push_back(new TriggerNode("roll", { NextAction("roll", relevance) }));
}
ChatCommandHandlerStrategy::ChatCommandHandlerStrategy(PlayerbotAI* botAI) : PassTroughStrategy(botAI)

View File

@@ -10,70 +10,59 @@
void CombatStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{
triggers.push_back(new TriggerNode("enemy out of spell",
NextAction::array(0, new NextAction("reach spell", ACTION_HIGH), nullptr)));
triggers.push_back(
new TriggerNode(
"enemy out of spell",
{
NextAction("reach spell", ACTION_HIGH)
}
)
);
// drop target relevance 99 (lower than Worldpacket triggers)
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(
new TriggerNode("mounted", NextAction::array(0, new NextAction("check mount state", 54), nullptr)));
// triggers.push_back(new TriggerNode("out of react range", NextAction::array(0, new NextAction("flee to master",
// 55), nullptr)));
triggers.push_back(new TriggerNode("combat stuck", NextAction::array(0, new NextAction("reset", 1.0f), nullptr)));
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)));
new TriggerNode(
"mounted",
{
NextAction("check mount state", 54)
}
)
);
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.
// Pets will automatically attack the bot's enemy if they are in "defensive" or "aggressive"
// 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) {}
// class AvoidAoeStrategyMultiplier : public Multiplier
// {
// 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()
std::vector<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)
@@ -82,21 +71,24 @@ void AvoidAoeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
void AvoidAoeStrategy::InitMultipliers(std::vector<Multiplier*>& multipliers)
{
// multipliers.push_back(new AvoidAoeStrategyMultiplier(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)
{
}
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:
explicit AvoidAoeStrategy(PlayerbotAI* ai);
const std::string getName() override { return "avoid aoe"; }
NextAction** getDefaultActions() override;
std::vector<NextAction> getDefaultActions() override;
void InitMultipliers(std::vector<Multiplier*>& multipliers) override;
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
};
@@ -34,7 +34,7 @@ class TankFaceStrategy : public Strategy
public:
explicit TankFaceStrategy(PlayerbotAI* ai);
const std::string getName() override { return "tank face"; }
NextAction** getDefaultActions() override;
std::vector<NextAction> getDefaultActions() override;
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
};
@@ -43,7 +43,7 @@ class CombatFormationStrategy : public Strategy
public:
CombatFormationStrategy(PlayerbotAI* ai) : Strategy(ai) {}
const std::string getName() override { return "formation"; }
NextAction** getDefaultActions() override;
std::vector<NextAction> getDefaultActions() override;
};
#endif

View File

@@ -12,21 +12,21 @@ void DeadStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
PassTroughStrategy::InitTriggers(triggers);
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(
new TriggerNode("bg active", NextAction::array(0, new NextAction("auto release", relevance), nullptr)));
new TriggerNode("bg active", { NextAction("auto release", relevance) }));
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(
"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",
NextAction::array(0, new NextAction("accept resurrect", relevance), nullptr)));
{ NextAction("accept resurrect", relevance) }));
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(
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(
"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) {}

View File

@@ -10,11 +10,11 @@
void DpsAssistStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{
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)
{
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);
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(
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) {}

View File

@@ -11,25 +11,25 @@ void EmoteStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{
if (sPlayerbotAIConfig->randomBotEmote)
{
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("talk", 1.0f), nullptr)));
triggers.push_back(new TriggerNode("seldom", NextAction::array(0, new NextAction("emote", 1.0f), nullptr)));
triggers.push_back(new TriggerNode("often", { NextAction("talk", 1.0f) }));
triggers.push_back(new TriggerNode("seldom", { NextAction("emote", 1.0f) }));
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(
new TriggerNode("receive emote", NextAction::array(0, new NextAction("emote", 10.0f), nullptr)));
new TriggerNode("receive emote", { NextAction("emote", 10.0f) }));
}
if (sPlayerbotAIConfig->randomBotTalk)
{
triggers.push_back(new TriggerNode(
"often",
NextAction::array(0, new NextAction("suggest what to do", 10.0f), new NextAction("suggest dungeon", 3.0f),
new NextAction("suggest trade", 3.0f), nullptr)));
{ NextAction("suggest what to do", 10.0f), NextAction("suggest dungeon", 3.0f),
NextAction("suggest trade", 3.0f) }));
}
if (sPlayerbotAIConfig->enableGreet)
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)
{
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(
new TriggerNode("outnumbered", NextAction::array(0, new NextAction("flee", ACTION_EMERGENCY + 9), nullptr)));
new TriggerNode("outnumbered", { NextAction("flee", ACTION_EMERGENCY + 9) }));
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)
{
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"
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)
{
// 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) {}
std::string const getName() override { return "follow"; }
NextAction** getDefaultActions() override;
std::vector<NextAction> getDefaultActions() override;
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
};

View File

@@ -7,22 +7,35 @@
#include "Playerbots.h"
NextAction** GrindingStrategy::getDefaultActions()
std::vector<NextAction> GrindingStrategy::getDefaultActions()
{
return NextAction::array(0,
new NextAction("drink", 4.2f),
new NextAction("food", 4.1f),
nullptr);
return {
NextAction("drink", 4.2f),
NextAction("food", 4.1f),
};
}
void GrindingStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{
// reduce lower than loot
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)
{
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"; }
uint32 GetType() const override { return STRATEGY_TYPE_DPS; }
NextAction** getDefaultActions() override;
std::vector<NextAction> getDefaultActions() override;
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
};

View File

@@ -9,8 +9,8 @@
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("random", NextAction::array(0, new NextAction("invite guild", 4.0f), nullptr)));
triggers.push_back(new TriggerNode("random", NextAction::array(0, new NextAction("leave far away", 4.0f), nullptr)));
triggers.push_back(new TriggerNode("seldom", NextAction::array(0, new NextAction("reset instances", 1.0f), nullptr)));
triggers.push_back(new TriggerNode("often", { NextAction("invite nearby", 4.0f) }));
triggers.push_back(new TriggerNode("random", { NextAction("invite guild", 4.0f) }));
triggers.push_back(new TriggerNode("random", { NextAction("leave far away", 4.0f) }));
triggers.push_back(new TriggerNode("seldom", { NextAction("reset instances", 1.0f) }));
}

View File

@@ -7,6 +7,11 @@
#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) {}

View File

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

View File

@@ -10,13 +10,13 @@
void GuildStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{
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(
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(
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(
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(
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)
{
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)
{
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(
new TriggerNode("seldom", NextAction::array(0, new NextAction("lfg leave", relevance), nullptr)));
new TriggerNode("seldom", { NextAction("lfg leave", relevance) }));
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) {}

View File

@@ -9,29 +9,29 @@
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(
new TriggerNode("far from loot target", NextAction::array(0, new NextAction("move to loot", 7.0f), nullptr)));
triggers.push_back(new TriggerNode("can loot", NextAction::array(0, new NextAction("open loot", 8.0f), nullptr)));
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("add all loot", 5.0f), nullptr)));
new TriggerNode("far from loot target", { NextAction("move to loot", 7.0f) }));
triggers.push_back(new TriggerNode("can loot", { NextAction("open loot", 8.0f) }));
triggers.push_back(new TriggerNode("often", { NextAction("add all loot", 5.0f) }));
}
void GatherStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{
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)
{
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)
{
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(
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"
NextAction** MaintenanceStrategy::getDefaultActions() { return nullptr; }
std::vector<NextAction> MaintenanceStrategy::getDefaultActions() { return {}; }
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(new TriggerNode("random", NextAction::array(0, new NextAction("use random recipe", 1.0f), nullptr)));
triggers.push_back(new TriggerNode("random", NextAction::array(0, new NextAction("disenchant random item", 1.0f), nullptr)));
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)));
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("clean quest log", 6.0f)
}
)
);
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"; }
uint32 GetType() const override { return STRATEGY_TYPE_NONCOMBAT; }
NextAction** getDefaultActions() override;
std::vector<NextAction> getDefaultActions() override;
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
};

View File

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

View File

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

View File

@@ -9,41 +9,57 @@
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("timer", NextAction::array(0, new 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)));
triggers.push_back(new TriggerNode("random", { NextAction("clean quest log", 1.0f) }));
triggers.push_back(new TriggerNode("timer", { NextAction("check mount state", 1.0f) }));
}
void CollisionStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{
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)
{
/*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)
{
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)
{
triggers.push_back(new TriggerNode("very often", NextAction::array(0, new NextAction("move near water" , 10.0f), nullptr)));
triggers.push_back(new TriggerNode("very often", NextAction::array(0, new NextAction("go fishing" , 10.0f), nullptr)));
triggers.push_back(new TriggerNode("random", NextAction::array(0, new NextAction("end master fishing", 12.0f),
new NextAction("equip upgrades", 6.0f), nullptr)));
triggers.push_back(
new TriggerNode(
"very often",
{
NextAction("move near water" , 10.0f)
}
)
);
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++)
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);
}
NextAction** PullStrategy::getDefaultActions()
std::vector<NextAction> PullStrategy::getDefaultActions()
{
return NextAction::array(0, new NextAction(action, 105.0f), new NextAction("follow", 104.0f),
new NextAction("end pull", 103.0f), nullptr);
return {
NextAction(action, 105.0f),
NextAction("follow", 104.0f),
NextAction("end pull", 103.0f),
};
}
void PullStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) { CombatStrategy::InitTriggers(triggers); }
@@ -50,5 +53,11 @@ void PossibleAddsStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
Strategy::InitTriggers(triggers);
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 InitMultipliers(std::vector<Multiplier*>& multipliers) override;
std::string const getName() override { return "pull"; }
NextAction** getDefaultActions() override;
std::vector<NextAction> getDefaultActions() override;
private:
std::string const action;

View File

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

View File

@@ -16,26 +16,25 @@ private:
static ActionNode* lifeblood(PlayerbotAI* botAI)
{
return new ActionNode("lifeblood",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("gift of the naaru"), nullptr),
/*C*/ nullptr);
/*P*/ {},
/*A*/ { NextAction("gift of the naaru") },
/*C*/ {});
}
};
void RacialsStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{
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(
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(
"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(
"generic boost", NextAction::array(0, new NextAction("blood fury", ACTION_NORMAL + 5),
new NextAction("berserking", ACTION_NORMAL + 5),
new NextAction("use trinket", ACTION_NORMAL + 4),
nullptr)));
"generic boost", { NextAction("blood fury", ACTION_NORMAL + 5),
NextAction("berserking", ACTION_NORMAL + 5),
NextAction("use trinket", ACTION_NORMAL + 4) }));
}

View File

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

View File

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

View File

@@ -24,51 +24,145 @@ float RpgActionMultiplier::GetValue(Action* action)
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)
{
triggers.push_back(
new TriggerNode("no rpg target", NextAction::array(0, new NextAction("choose rpg target", 5.0f), nullptr)));
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("move random", 1.10f), NULL)));
triggers.push_back(new TriggerNode("far from rpg target",
NextAction::array(0, new NextAction("move to rpg target", 5.0f), nullptr)));
new TriggerNode(
"no rpg target",
{
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
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(
new TriggerNode("has rpg target", NextAction::array(0, new NextAction("rpg cancel", 1.101f), nullptr)));
// triggers.push_back(new TriggerNode("rpg taxi", NextAction::array(0, new NextAction("rpg taxi", 1.005f),
// nullptr)));
new TriggerNode(
"rpg",
{
NextAction("rpg stay", 1.101f)
}
)
);
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(
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(
new TriggerNode("rpg end quest", NextAction::array(0, new NextAction("rpg end quest", 1.190f), nullptr)));
triggers.push_back(new TriggerNode("rpg buy", NextAction::array(0, new NextAction("rpg buy", 1.130f), nullptr)));
// triggers.push_back(new TriggerNode("rpg sell", NextAction::array(0, new NextAction("rpg sell", 1.100f),
// nullptr)));
new TriggerNode(
"has rpg target",
{
NextAction("rpg cancel", 1.101f)
}
)
);
triggers.push_back(
new TriggerNode("rpg repair", NextAction::array(0, new NextAction("rpg repair", 1.195f), nullptr)));
// triggers.push_back(new TriggerNode("rpg train", NextAction::array(0, new NextAction("rpg train", 1.080f),
// nullptr)));
triggers.push_back(new TriggerNode("rpg heal", NextAction::array(0, new NextAction("rpg heal", 1.125f), nullptr)));
new TriggerNode(
"rpg discover",
{
NextAction("rpg discover", 1.210f)
}
)
);
triggers.push_back(
new TriggerNode("rpg home bind", NextAction::array(0, new NextAction("rpg home bind", 1.160f), nullptr)));
// triggers.push_back(new TriggerNode("rpg queue bg", NextAction::array(0, new NextAction("rpg queue bg", 1.085f),
// nullptr)));
new TriggerNode(
"rpg start quest",
{
NextAction("rpg start quest", 1.180f)
}
)
);
triggers.push_back(
new TriggerNode("rpg buy petition", NextAction::array(0, new NextAction("rpg buy petition", 1.140f), nullptr)));
triggers.push_back(new TriggerNode("rpg use", NextAction::array(0, new NextAction("rpg use", 1.102f), nullptr)));
// 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
// 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)));
new TriggerNode(
"rpg end quest",
{
NextAction("rpg end quest", 1.190f)
}
)
);
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)

View File

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

View File

@@ -10,5 +10,5 @@
void RunawayStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{
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)
{
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(
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(
new TriggerNode("low mana", NextAction::array(0, new NextAction("say::low mana", 99.0f), nullptr)));
triggers.push_back(new TriggerNode("tank aoe", NextAction::array(0, new NextAction("say::taunt", 99.0f), nullptr)));
triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("say::aoe", 99.0f), nullptr)));
new TriggerNode("low mana", { NextAction("say::low mana", 99.0f) }));
triggers.push_back(new TriggerNode("tank aoe", { NextAction("say::taunt", 99.0f) }));
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)
{
triggers.push_back(new TriggerNode(
triggers.push_back(
new TriggerNode(
"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)
{
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"; }
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
NextAction** getDefaultActions() override;
std::vector<NextAction> getDefaultActions() override;
};
class SitStrategy : public NonCombatStrategy

View File

@@ -10,5 +10,5 @@
void TankAssistStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{
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