Skip to content

Commit

Permalink
Skill action: New skill command which lists all current skills, a spe…
Browse files Browse the repository at this point in the history
…cific skill based on namepart or link and allows unlearning of skills using skill unlearn link/namepart
  • Loading branch information
mostlikely4r committed Nov 13, 2024
1 parent c6f2c42 commit 5706830
Show file tree
Hide file tree
Showing 7 changed files with 184 additions and 0 deletions.
16 changes: 16 additions & 0 deletions playerbot/ChatHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,22 @@ std::set<uint32> ChatHelper::ExtractAllItemIds(const std::string& text)
return ids;
}

std::set<uint32> ChatHelper::ExtractAllSkillIds(const std::string& text)
{
std::set<uint32> ids;

std::regex rgx("Hskill:[0-9]+");
auto begin = std::sregex_iterator(text.begin(), text.end(), rgx);
auto end = std::sregex_iterator();
for (std::sregex_iterator i = begin; i != end; ++i)
{
std::smatch match = *i;
ids.insert(std::stoi(match.str().erase(0, 7)));
}

return ids;
}

ItemIds ChatHelper::parseItems(const std::string& text, bool validate)
{
std::vector<uint32> itemIDsUnordered = parseItemsUnordered(text, validate);
Expand Down
1 change: 1 addition & 0 deletions playerbot/ChatHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ namespace ai

static std::set<uint32> ExtractAllQuestIds(const std::string& text);
static std::set<uint32> ExtractAllItemIds(const std::string& text);
static std::set<uint32> ExtractAllSkillIds(const std::string& text);

static std::string formatQuest(Quest const* quest);

Expand Down
2 changes: 2 additions & 0 deletions playerbot/strategy/actions/ChatActionContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
#include "ValueActions.h"
#include "QuestRewardActions.h"
#include "ChooseTravelTargetAction.h"
#include "SkillAction.h"

namespace ai
{
Expand Down Expand Up @@ -206,6 +207,7 @@ namespace ai

creators["jump"] = &ChatActionContext::jump;
creators["doquest"] = [](PlayerbotAI* ai) { return new FocusTravelTargetAction(ai); };
creators["skill"] = [](PlayerbotAI* ai) { return new SkillAction(ai); };
}

private:
Expand Down
136 changes: 136 additions & 0 deletions playerbot/strategy/actions/SkillAction.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@

#include "playerbot/playerbot.h"
#include "SkillAction.h"
#include "Tools/Language.h"

using namespace ai;

bool SkillAction::Execute(Event& event)
{
Player* requester = event.getOwner() ? event.getOwner() : GetMaster();
std::string cmd = event.getParam();

bool unlearn = (cmd.find("unlearn ") == 0);

std::string skillName = cmd;

if (unlearn)
skillName = skillName.substr(8);

std::wstring wnamepart;

if (!Utf8toWStr(skillName, wnamepart))
return false;

std::set<uint32> skillIds = ChatHelper::ExtractAllSkillIds(skillName);

// converting string that we try to find to lower case
wstrToLower(wnamepart);

bool skillFound = false;
std::map<std::string, std::string> args;

for (uint32 id = 0; id < sSkillLineStore.GetNumRows(); ++id)
{
if (!bot->HasSkill(id))
continue;

SkillLineEntry const* skillInfo = sSkillLineStore.LookupEntry(id);
if (skillInfo)
{
int loc = requester->GetSession()->GetSessionDbcLocale();

std::string name = skillInfo->name[loc];

if (!skillName.empty() && skillIds.empty())
{
if (name.empty())
continue;

if (!Utf8FitTo(name, wnamepart))
{
loc = 0;
for (; loc < MAX_LOCALE; ++loc)
{
if (loc == requester->GetSession()->GetSessionDbcLocale())
continue;

name = skillInfo->name[loc];
if (name.empty())
continue;

if (Utf8FitTo(name, wnamepart))
break;
}
}
}

if (skillName.empty() || skillIds.find(id) != skillIds.end() || (loc < MAX_LOCALE && skillIds.empty()))
{
if (unlearn)
{
args["%skillname"] = name;

if (!bot->GetSkillInfo(uint16(id), ([](SkillRaceClassInfoEntry const& entry) { return (entry.flags & SKILL_FLAG_CAN_UNLEARN); })))
{
ai->TellPlayerNoFacing(requester, BOT_TEXT2("Unable to unlearn %skillname", args));
return false;
}

bot->SetSkillStep(uint16(id), 0);

ai->TellPlayerNoFacing(requester, BOT_TEXT2("Unlearned %skillname", args));

return true;
}

char valStr[50] = "";
char const* knownStr = "";
knownStr = requester->GetSession()->GetMangosString(LANG_KNOWN);
uint32 curValue = bot->GetSkillValuePure(id);
uint32 maxValue = bot->GetSkillMaxPure(id);
uint32 permValue = bot->GetSkillBonusPermanent(id);
uint32 tempValue = bot->GetSkillBonusTemporary(id);

char const* valFormat = requester->GetSession()->GetMangosString(LANG_SKILL_VALUES);
snprintf(valStr, 50, valFormat, curValue, maxValue, permValue, tempValue);
std::ostringstream out;
out << "|cffffffff|Hskill:";
out << id;
out << "|h[";
out << name;
out << "]|h|r (";

out << curValue << "/" << maxValue;

if (permValue)
out << " +perm " << permValue;

if (tempValue)
out << " +temp " << permValue;

out << ")";

ai->TellPlayerNoFacing(requester, out);

skillFound = true;
}
}
}

if (!skillFound)
{
if (skillName.empty())
{
ai->TellPlayerNoFacing(requester, BOT_TEXT2("No skills found.", args));
}
else
{
args["%skillname"] = skillName;
ai->TellPlayerNoFacing(requester, BOT_TEXT2("Skill %skillname not found.", args));
}
return false;
}

return true;
}
27 changes: 27 additions & 0 deletions playerbot/strategy/actions/SkillAction.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once
#include "playerbot/LootObjectStack.h"
#include "GenericActions.h"

namespace ai
{
class SkillAction : public ChatCommandAction
{
public:
SkillAction(PlayerbotAI* ai) : ChatCommandAction(ai, "skill") {}
virtual bool Execute(Event& event) override;

#ifdef GenerateBotHelp
virtual std::string GetHelpName() { return "skill"; } //Must equal iternal name
virtual std::string GetHelpDescription()
{
return "This chat command gives information about a bot\'s skills.\n"
"Examples:\n"
"skill : List all skills and their current level.\n"
"skill [name] : List the skill level of a current skill.\n"
"ss unlearn [name] : Unlearns a primary profession.\n";
}
virtual std::vector<std::string> GetUsedActions() { return {}; }
virtual std::vector<std::string> GetUsedValues() { return {}; }
#endif
};
}
1 change: 1 addition & 0 deletions playerbot/strategy/generic/ChatCommandHandlerStrategy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ ChatCommandHandlerStrategy::ChatCommandHandlerStrategy(PlayerbotAI* ai) : PassTr
supported.push_back("move style");
supported.push_back("jump");
supported.push_back("doquest");
supported.push_back("skill");
}

void ChatCommandHandlerStrategy::InitReactionTriggers(std::list<TriggerNode*> &triggers)
Expand Down
1 change: 1 addition & 0 deletions playerbot/strategy/triggers/ChatTriggerContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ namespace ai
creators["move style"] = &ChatTriggerContext::move_style;
creators["jump"] = &ChatTriggerContext::jump;
creators["doquest"] = [](PlayerbotAI* ai) { return new ChatCommandTrigger(ai, "doquest"); };
creators["skill"] = [](PlayerbotAI* ai) { return new ChatCommandTrigger(ai, "skill"); };
}

private:
Expand Down

0 comments on commit 5706830

Please sign in to comment.