Skip to content

Commit 1b16f38

Browse files
committed
Travel: Action refactor to improve performance and simply the system
1 parent 769a47a commit 1b16f38

13 files changed

+303
-643
lines changed

playerbot/TravelMgr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ namespace ai
166166
virtual GameObjectInfo const* GetGoInfo() const { return goInfo; }
167167
virtual CreatureInfo const* GetCreatureInfo() const { return creatureInfo; }
168168
TravelDestinationPurpose GetPurpose() const { return purpose; }
169+
bool HasNpcFlag(uint32 flag) { if(GetCreatureInfo() && (GetCreatureInfo()->NpcFlags & flag)) return true; return false; }
169170
private:
170171
CreatureInfo const* creatureInfo = nullptr;
171172
GameObjectInfo const* goInfo = nullptr;

playerbot/strategy/actions/ActionContext.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,14 @@ namespace ai
8282
creators["choose rpg target"] = &ActionContext::choose_rpg_target;
8383
creators["move to rpg target"] = &ActionContext::move_to_rpg_target;
8484
creators["travel"] = &ActionContext::travel;
85-
creators["choose travel target"] = &ActionContext::choose_travel_target;
86-
creators["move to travel target"] = &ActionContext::move_to_travel_target;
85+
creators["choose travel target"] = [](PlayerbotAI* ai) { return new ChooseTravelTargetAction(ai); };
8786
creators["choose group travel target"] = [](PlayerbotAI* ai) { return new ChooseGroupTravelTargetAction(ai); };
8887
creators["refresh travel target"] = [](PlayerbotAI* ai) { return new RefreshTravelTargetAction(ai); };
89-
creators["choose async travel target"] = [](PlayerbotAI* ai) { return new ChooseAsyncTravelTargetAction(ai); };
90-
creators["choose async named travel target"] = [](PlayerbotAI* ai) { return new ChooseAsyncNamedTravelTargetAction(ai); };
91-
creators["choose async quest travel target"] = [](PlayerbotAI* ai) { return new ChooseAsyncQuestTravelTargetAction(ai); };
88+
creators["request travel target"] = [](PlayerbotAI* ai) { return new RequestTravelTargetAction(ai); };
89+
creators["request named travel target"] = [](PlayerbotAI* ai) { return new RequestNamedTravelTargetAction(ai); };
90+
creators["request quest travel target"] = [](PlayerbotAI* ai) { return new RequestQuestTravelTargetAction(ai); };
91+
creators["reset travel target"] = [](PlayerbotAI* ai) { return new ResetTargetAction(ai); };
92+
creators["move to travel target"] = &ActionContext::move_to_travel_target;
9293
creators["move out of collision"] = &ActionContext::move_out_of_collision;
9394
creators["move random"] = &ActionContext::move_random;
9495
creators["attack"] = &ActionContext::melee;
@@ -352,7 +353,6 @@ namespace ai
352353
static Action* choose_rpg_target(PlayerbotAI* ai) { return new ChooseRpgTargetAction(ai); }
353354
static Action* move_to_rpg_target(PlayerbotAI* ai) { return new MoveToRpgTargetAction(ai); }
354355
static Action* travel(PlayerbotAI* ai) { return new TravelAction(ai); }
355-
static Action* choose_travel_target(PlayerbotAI* ai) { return new ChooseTravelTargetAction(ai); }
356356
static Action* move_to_travel_target(PlayerbotAI* ai) { return new MoveToTravelTargetAction(ai); }
357357
static Action* move_out_of_collision(PlayerbotAI* ai) { return new MoveOutOfCollisionAction(ai); }
358358
static Action* move_random(PlayerbotAI* ai) { return new MoveRandomAction(ai); }

playerbot/strategy/actions/ChooseTravelTargetAction.cpp

Lines changed: 175 additions & 456 deletions
Large diffs are not rendered by default.

playerbot/strategy/actions/ChooseTravelTargetAction.h

Lines changed: 28 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,23 @@
77

88
namespace ai
99
{
10-
class ChooseTravelTargetAction : public MovementAction {
10+
class ChooseTravelTargetAction : public Action {
1111
public:
12-
ChooseTravelTargetAction(PlayerbotAI* ai, std::string name = "choose travel target") : MovementAction(ai, name) {}
13-
14-
virtual bool Execute(Event& event);
15-
virtual bool isUseful();
16-
17-
void getNewTarget(Player* requester, TravelTarget* newTarget, TravelTarget* oldTarget);
12+
ChooseTravelTargetAction(PlayerbotAI* ai, std::string name = "choose travel target") : Action(ai, name) {}
1813

14+
virtual bool Execute(Event& event) override;
15+
virtual bool isUseful() override;
1916
protected:
2017
void setNewTarget(Player* requester, TravelTarget* newTarget, TravelTarget* oldTarget);
2118
void ReportTravelTarget(Player* requester, TravelTarget* newTarget, TravelTarget* oldTarget);
2219

2320
bool SetBestTarget(Player* requester, TravelTarget* target, PartitionedTravelList& travelPartitions, bool onlyActive = true);
2421

25-
bool SetNpcFlagTarget(Player* requester, TravelTarget* target, std::vector<NPCFlags> flags, std::string name = "", std::vector<uint32> items = {}, bool force = false);
22+
//bool SetNpcFlagTarget(Player* requester, TravelTarget* target, std::vector<NPCFlags> flags, std::string name = "", std::vector<uint32> items = {}, bool force = false);
2623

2724
bool SetNullTarget(TravelTarget* target);
2825
public:
2926
static DestinationList FindDestination(PlayerTravelInfo info, std::string name, bool zones = true, bool npcs = true, bool quests = true, bool mobs = true, bool bosses = true);
30-
protected:
31-
const std::vector<uint32> travelPartitions = { 100, 250, 500, 1000, 2000, 3000, 4000, 5000, 6000, 10000, 50000, 100000, 500000 };
3227
private:
3328
#ifdef GenerateBotHelp
3429
virtual std::string GetHelpName() { return "choose travel target"; } //Must equal iternal name
@@ -48,57 +43,51 @@ namespace ai
4843
public:
4944
ChooseGroupTravelTargetAction(PlayerbotAI* ai, std::string name = "choose group travel target") : ChooseTravelTargetAction(ai, name) {}
5045

51-
virtual bool Execute(Event& event);
52-
virtual bool isUseful() { return ChooseTravelTargetAction::isUseful() && bot->GetGroup(); }
46+
virtual bool Execute(Event& event) override;
47+
virtual bool isUseful() override;
5348
};
5449

5550
class RefreshTravelTargetAction : public ChooseTravelTargetAction {
5651
public:
5752
RefreshTravelTargetAction(PlayerbotAI* ai, std::string name = "refresh travel target") : ChooseTravelTargetAction(ai, name) {}
5853

59-
virtual bool Execute(Event& event);
60-
virtual bool isUseful() { return ChooseTravelTargetAction::isUseful() && AI_VALUE(TravelTarget*, "travel target")->GetDestination()->IsActive(bot, PlayerTravelInfo(bot)) && (!WorldPosition(bot).isOverworld() || urand(1, 100) > 10); }
54+
virtual bool Execute(Event& event) override;
55+
virtual bool isUseful() override;
6156
};
6257

63-
using FutureDestinations = std::future<PartitionedTravelList>;
64-
65-
class ChooseAsyncTravelTargetAction : public ChooseTravelTargetAction, public Qualified {
58+
class ResetTargetAction : public ChooseTravelTargetAction {
6659
public:
67-
ChooseAsyncTravelTargetAction(PlayerbotAI* ai, std::string name = "choose async travel target") : ChooseTravelTargetAction(ai, name), Qualified() {}
68-
protected:
69-
TravelDestinationPurpose actionPurpose = TravelDestinationPurpose::None;
60+
ResetTargetAction(PlayerbotAI* ai, std::string name = "reset travel target") : ChooseTravelTargetAction(ai, name) {}
7061

71-
virtual bool RequestNewDestinations(Event& event);
72-
virtual bool isAllowed() const; //We need this skip on the request instead of isUsefull to only skip the request sometimes but not the Wait and Set that could follow a nonskip.
62+
virtual bool Execute(Event& event) override;
63+
virtual bool isUseful() override;
64+
};
7365

74-
bool hasDestinations = false;
75-
PartitionedTravelList destinationList = {};
76-
FutureDestinations futureDestinations;
66+
class RequestTravelTargetAction : public Action, public Qualified {
67+
public:
68+
RequestTravelTargetAction(PlayerbotAI* ai, std::string name = "request travel target") : Action(ai, name), Qualified() {}
69+
protected:
70+
const std::vector<uint32> travelPartitions = { 100, 250, 500, 1000, 2000, 3000, 4000, 5000, 6000, 10000, 50000, 100000, 500000 };
7771
private:
7872
virtual bool Execute(Event& event) override;
79-
8073
virtual bool isUseful() override;
81-
bool WaitForDestinations();
82-
bool SetBestDestination(Event& event);
74+
virtual bool isAllowed() const;
8375
};
8476

85-
class ChooseAsyncNamedTravelTargetAction : public ChooseAsyncTravelTargetAction {
77+
class RequestNamedTravelTargetAction : public RequestTravelTargetAction {
8678
public:
87-
ChooseAsyncNamedTravelTargetAction(PlayerbotAI* ai, std::string name = "choose async named travel target") : ChooseAsyncTravelTargetAction(ai, name) {}
88-
protected:
79+
RequestNamedTravelTargetAction(PlayerbotAI* ai, std::string name = "request named travel target") : RequestTravelTargetAction(ai, name) {}
80+
private:
81+
virtual bool Execute(Event& event) override;
8982
virtual bool isAllowed() const override;
90-
virtual bool RequestNewDestinations(Event& event) override;
91-
virtual bool isUseful() override { return !AI_VALUE(TravelTarget*, "travel target")->IsPreparing() &&
92-
ChooseTravelTargetAction::isUseful(); };
9383
};
9484

95-
class ChooseAsyncQuestTravelTargetAction : public ChooseAsyncTravelTargetAction {
85+
class RequestQuestTravelTargetAction : public RequestTravelTargetAction {
9686
public:
97-
ChooseAsyncQuestTravelTargetAction(PlayerbotAI* ai, std::string name = "choose async quest travel target") : ChooseAsyncTravelTargetAction(ai, name) {}
98-
protected:
87+
RequestQuestTravelTargetAction(PlayerbotAI* ai, std::string name = "choose async quest travel target") : RequestTravelTargetAction(ai, name) {}
88+
private:
89+
virtual bool Execute(Event& event) override;
9990
virtual bool isAllowed() const override;
100-
virtual bool RequestNewDestinations(Event& event) override;
101-
virtual bool isUseful() override { return !AI_VALUE(TravelTarget*, "travel target")->IsPreparing() && ChooseTravelTargetAction::isUseful(); };
10291
};
10392

10493
class FocusTravelTargetAction : public ChatCommandAction {

playerbot/strategy/actions/GoAction.cpp

Lines changed: 2 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -166,56 +166,8 @@ bool GoAction::TellWhereToGo(std::string& param, Player* requester) const
166166
if (param.size() > 6)
167167
text = param.substr(6);
168168

169-
ChooseTravelTargetAction* travelAction = new ChooseTravelTargetAction(ai);
170-
171-
TravelTarget* target = context->GetValue<TravelTarget*>("travel target")->Get();
172-
173-
target->SetStatus(TravelStatus::TRAVEL_STATUS_EXPIRED);
174-
175-
travelAction->getNewTarget(requester, target, target);
176-
177-
if (!target->GetDestination() || target->GetDestination()->GetTitle().empty())
178-
{
179-
ai->TellPlayerNoFacing(requester, "I have no place I want to go to.");
180-
return false;
181-
}
182-
183-
std::string title = target->GetDestination()->GetTitle();
184-
185-
if (title.find('[') != std::string::npos)
186-
title = title.substr(title.find("[") + 1, title.find("]") - title.find("[") - 1);
187-
188-
189-
DestinationList dests;
190-
TravelDestination* dest = nullptr;
191-
192-
dests = ChooseTravelTargetAction::FindDestination(bot, title);
193-
194-
if (dests.empty())
195-
{
196-
ai->TellPlayerNoFacing(requester, "I don't know how to travel to " + title);
197-
return false;
198-
}
199-
200-
WorldPosition botPos(bot);
201-
202-
dest = *std::min_element(dests.begin(), dests.end(), [botPos](TravelDestination* i, TravelDestination* j) {return i->DistanceTo(botPos) < j->DistanceTo(botPos); });
203-
204-
if (!dest)
205-
dest = target->GetDestination();
206-
207-
if (!dest)
208-
{
209-
ai->TellPlayerNoFacing(requester, "I don't know how to travel to " + title);
210-
return false;
211-
}
212-
213-
std::string link = ChatHelper::formatValue("command", "go to " + title, title, "FF00FFFF");
214-
215-
ai->TellPlayerNoFacing(requester, "I would like to travel to " + link + "(" + target->GetDestination()->GetTitle() + ")");
216-
217-
delete travelAction;
218-
return true;
169+
ai->TellPlayerNoFacing(requester, "I have no place I want to go to.");
170+
return false;
219171
}
220172

221173
bool GoAction::LeaderAlreadyTraveling(TravelDestination* dest) const

playerbot/strategy/actions/GuildCreateActions.cpp

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -270,23 +270,29 @@ bool PetitionTurnInAction::Execute(Event& event)
270270
return true;
271271
}
272272

273-
TravelTarget* oldTarget = context->GetValue<TravelTarget*>("travel target")->Get();
274-
275273
//Select a new target to travel to.
276274
TravelTarget newTarget = TravelTarget(ai);
277275

278276
ai->TellDebug(requester, "Handing in guild petition", "debug travel");
279277

280-
bool foundTarget = SetNpcFlagTarget(requester, &newTarget, { UNIT_NPC_FLAG_PETITIONER });
278+
TravelTarget* oldTarget = AI_VALUE(TravelTarget*, "travel target");
281279

282-
if (!foundTarget || !newTarget.IsActive())
280+
if (oldTarget->IsPreparing())
283281
return false;
284282

285-
newTarget.SetRadius(INTERACTION_DISTANCE);
283+
if (oldTarget->GetDestination())
284+
{
285+
TravelDestination* dest = oldTarget->GetDestination();
286286

287-
setNewTarget(requester, &newTarget, oldTarget);
287+
EntryTravelDestination* eDest = dynamic_cast<EntryTravelDestination*>(dest);
288288

289-
return true;
289+
if (eDest && eDest->HasNpcFlag(UNIT_NPC_FLAG_PETITIONER))
290+
return false;
291+
}
292+
293+
oldTarget->SetStatus(TravelStatus::TRAVEL_STATUS_EXPIRED);
294+
295+
return ai->DoSpecificAction("request named travel target::petition", Event("buy tabard"), true);
290296
};
291297

292298
bool PetitionTurnInAction::isUseful()
@@ -322,23 +328,22 @@ bool BuyTabardAction::Execute(Event& event)
322328
if (canBuy && AI_VALUE2(uint32, "item count", chat->formatQItem(5976)))
323329
return true;
324330

325-
TravelTarget* oldTarget = context->GetValue<TravelTarget*>("travel target")->Get();
331+
TravelTarget* oldTarget = AI_VALUE(TravelTarget*, "travel target");
326332

327-
//Select a new target to travel to.
328-
TravelTarget newTarget = TravelTarget(ai);
329-
330-
ai->TellDebug(requester, "Buying a tabard", "debug travel");
331-
332-
bool foundTarget = SetNpcFlagTarget(requester, &newTarget, { UNIT_NPC_FLAG_TABARDDESIGNER }, "Tabard Vendor", { 5976 });
333-
334-
if (!foundTarget || !newTarget.IsActive())
333+
if (oldTarget->IsPreparing())
335334
return false;
336335

337-
newTarget.SetRadius(INTERACTION_DISTANCE);
336+
if (oldTarget->GetDestination())
337+
{
338+
TravelDestination* dest = oldTarget->GetDestination();
339+
340+
EntryTravelDestination* eDest = dynamic_cast<EntryTravelDestination*>(dest);
338341

339-
setNewTarget(requester, &newTarget, oldTarget);
342+
if (eDest && eDest->HasNpcFlag(UNIT_NPC_FLAG_TABARDDESIGNER))
343+
return false;
344+
}
340345

341-
return true;
346+
return ai->DoSpecificAction("request named travel target::tabard", Event("buy tabard"), true);
342347
};
343348

344349
bool BuyTabardAction::isUseful()

0 commit comments

Comments
 (0)