Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
davidonete committed Dec 4, 2023
2 parents 5df163a + b1a06c8 commit 5e6c740
Show file tree
Hide file tree
Showing 10 changed files with 160 additions and 46 deletions.
3 changes: 3 additions & 0 deletions playerbot/LootObjectStack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ void LootObject::Refresh(Player* bot, ObjectGuid guid)
return;

uint32 goId = go->GetGOInfo()->id;
set<uint32>& skipGoLootList = ai->GetAiObjectContext()->GetValue<set<uint32>& >("skip go loot list")->Get();
if (skipGoLootList.find(goId) != skipGoLootList.end()) return;

uint32 lockId = go->GetGOInfo()->GetLockId();
LockEntry const *lockInfo = sLockStore.LookupEntry(lockId);
if (!lockInfo)
Expand Down
27 changes: 19 additions & 8 deletions playerbot/PlayerbotAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3317,14 +3317,7 @@ bool PlayerbotAI::CastSpell(uint32 spellId, Unit* target, Item* itemTarget, bool
if (spellSuccess != SPELL_CAST_OK)
return false;

if (urand(0, 100) < sPlayerbotAIConfig.attackEmoteChance * 600 && bot->IsInCombat())
{
vector<uint32> sounds;
sounds.push_back(TEXTEMOTE_OPENFIRE);
sounds.push_back(305);
sounds.push_back(307);
PlaySound(sounds[urand(0, sounds.size() - 1)]);
}
PlayAttackEmote(6);

if(waitForSpell)
{
Expand Down Expand Up @@ -6042,3 +6035,21 @@ void PlayerbotAI::QueueChatResponse(uint8 msgtype, ObjectGuid guid1, ObjectGuid
{
chatReplies.push(ChatQueuedReply(msgtype, guid1.GetCounter(), guid2.GetCounter(), message, chanName, name, time(0) + urand(inCombat ? 10 : 5, inCombat ? 25 : 15)));
}


bool PlayerbotAI::PlayAttackEmote(float chanceMultiplier)
{
auto group = bot->GetGroup();
if (group) chanceMultiplier /= (group->GetMembersCount() - 1);
if ((float)urand(0, 10000) * chanceMultiplier < sPlayerbotAIConfig.attackEmoteChance * 10000.0f && bot->IsInCombat())
{
vector<uint32> sounds;
sounds.push_back(TEXTEMOTE_OPENFIRE);
sounds.push_back(305);
sounds.push_back(307);
PlaySound(sounds[urand(0, sounds.size() - 1)]);
return true;
}

return false;
}
1 change: 1 addition & 0 deletions playerbot/PlayerbotAI.h
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ class PlayerbotAI : public PlayerbotAIBase
void WaitForSpellCast(Spell *spell);
bool PlaySound(uint32 emote);
bool PlayEmote(uint32 emote);
bool PlayAttackEmote(float chanceDivider);
void Ping(float x, float y);
void Poi(float x, float y, string icon_name = "This way", Player* player = nullptr, uint32 flags = 99, uint32 icon = 6 /* red flag */, uint32 icon_data = 0);
Item * FindPoison() const;
Expand Down
2 changes: 1 addition & 1 deletion playerbot/PlayerbotAIConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ bool PlayerbotAIConfig::Initialize()
randomBotMaxLevelChance = config.GetFloatDefault("AiPlayerbot.RandomBotMaxLevelChance", 0.15f);
randomBotRpgChance = config.GetFloatDefault("AiPlayerbot.RandomBotRpgChance", 0.35f);
usePotionChance = config.GetFloatDefault("AiPlayerbot.UsePotionChance", 1.0f);
attackEmoteChance = config.GetFloatDefault("AiPlayerbot.AttackEmoteChance", 0.01f);
attackEmoteChance = config.GetFloatDefault("AiPlayerbot.AttackEmoteChance", 0.0f);

iterationsPerTick = config.GetIntDefault("AiPlayerbot.IterationsPerTick", 100);

Expand Down
10 changes: 1 addition & 9 deletions playerbot/strategy/actions/AttackAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,15 +148,7 @@ bool AttackAction::Attack(Player* requester, Unit* target)
// Don't attack target if it is waiting for attack or in stealth
if (!ai->HasStrategy("stealthed", BotState::BOT_STATE_COMBAT) && !isWaitingForAttack)
{
if (urand(0, 100) < sPlayerbotAIConfig.attackEmoteChance * 100)
{
vector<uint32> sounds;
sounds.push_back(TEXTEMOTE_OPENFIRE);
sounds.push_back(305);
sounds.push_back(307);
ai->PlaySound(sounds[urand(0, sounds.size() - 1)]);
}

ai->PlayAttackEmote(1);
return bot->Attack(target, !ai->IsRanged(bot) || (sServerFacade.GetDistance2d(bot, target) < 5.0f));
}
else
Expand Down
4 changes: 4 additions & 0 deletions playerbot/strategy/actions/LootAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,10 @@ bool StoreLootAction::IsLootAllowed(ItemQualifier& itemQualifier, PlayerbotAI *a
if (lootItems.find(itemQualifier.GetId()) != lootItems.end())
return true;

set<uint32>& skipItems = AI_VALUE(set<uint32>&, "skip loot list");
if (skipItems.find(itemQualifier.GetId()) != skipItems.end())
return false;

uint32 max = proto->MaxCount;
if (max > 0 && ai->GetBot()->HasItemCount(itemQualifier.GetId(), max, true))
return false;
Expand Down
131 changes: 104 additions & 27 deletions playerbot/strategy/actions/LootStrategyAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ bool LootStrategyAction::Execute(Event& event)

LootObjectStack* lootItems = AI_VALUE(LootObjectStack*, "available loot");
set<uint32>& alwaysLootItems = AI_VALUE(set<uint32>&, "always loot list");
set<uint32>& skipLootItems = AI_VALUE(set<uint32>&, "skip loot list");
set<uint32>& skipGoLootList = AI_VALUE(set<uint32>&, "skip go loot list");

if (strategy == "?")
{
Expand All @@ -25,28 +27,23 @@ bool LootStrategyAction::Execute(Event& event)
ai->TellPlayer(requester, out);
}

{
ostringstream out;
out << "Always loot items: ";
for (set<uint32>::iterator i = alwaysLootItems.begin(); i != alwaysLootItems.end(); i++)
{
ItemPrototype const *proto = sItemStorage.LookupEntry<ItemPrototype>(*i);
if (!proto)
{
continue;
}

out << chat->formatItem(proto);
}

ai->TellPlayer(requester, out);
}
TellLootList(requester, "always loot list");
TellLootList(requester, "skip loot list");
TellGoList(requester, "skip go loot list");
}
else if (strategy == "clear")
{
alwaysLootItems.clear();
skipLootItems.clear();
ai->TellPlayer(requester, "My loot list is now empty");
return true;
}
else
{
set<string> itemQualifiers = chat->parseItemQualifiers(strategy);
list<ObjectGuid> gos = chat->parseGameobjects(strategy);

if (itemQualifiers.size() == 0)
if (itemQualifiers.size() == 0 && gos.size() == 0)
{
SET_AI_VALUE(string, "loot strategy", strategy);

Expand All @@ -58,11 +55,15 @@ bool LootStrategyAction::Execute(Event& event)
return true;
}

bool ignore = strategy.size() > 1 && strategy.substr(0, 1) == "!";
bool remove = strategy.size() > 1 && strategy.substr(0, 1) == "-";
bool query = strategy.size() > 1 && strategy.substr(0, 1) == "?";
bool add = !ignore && !remove && !query;
bool changes = false;
for (auto& qualifier : itemQualifiers)
{
ItemQualifier itemQualifier(qualifier);
auto itemid = itemQualifier.GetId();
if (query)
{
if (itemQualifier.GetProto())
Expand All @@ -72,24 +73,100 @@ bool LootStrategyAction::Execute(Event& event)
ai->TellPlayer(requester, out.str());
}
}
else if (remove)

if (remove || add)
{
set<uint32>::iterator j = alwaysLootItems.find(itemQualifier.GetId());
if (j != alwaysLootItems.end())
{
alwaysLootItems.erase(j);
}
set<uint32>::iterator j = skipLootItems.find(itemid);
if (j != skipLootItems.end()) skipLootItems.erase(j);
changes = true;
}

if (remove || ignore)
{
set<uint32>::iterator j = alwaysLootItems.find(itemid);
if (j != alwaysLootItems.end()) alwaysLootItems.erase(j);
changes = true;
}

if (ignore)
{
skipLootItems.insert(itemid);
changes = true;
}

ai->TellPlayer(requester, "Item(s) removed from always loot list");
if (add)
{
alwaysLootItems.insert(itemid);
changes = true;
}
else
}

for (list<ObjectGuid>::iterator i = gos.begin(); i != gos.end(); ++i)
{
GameObject *go = ai->GetGameObject(*i);
if (!go) continue;
uint32 goId = go->GetGOInfo()->id;

if (remove || add)
{
alwaysLootItems.insert(itemQualifier.GetId());
ai->TellPlayer(requester, "Item(s) added to always loot list");
set<uint32>::iterator j = skipGoLootList.find(goId);
if (j != skipGoLootList.end()) skipGoLootList.erase(j);
changes = true;
}

if (ignore)
{
skipGoLootList.insert(goId);
changes = true;
}
}

if (changes)
{
TellLootList(requester, "always loot list");
TellLootList(requester, "skip loot list");
TellGoList(requester, "skip go loot list");
AI_VALUE(LootObjectStack*, "available loot")->Clear();
}
}

return true;
}

void LootStrategyAction::TellLootList(Player* requester, const string& name)
{
set<uint32>& alwaysLootItems = AI_VALUE(set<uint32>&, name);
ostringstream out;
out << "My " << name << ":";

for (set<uint32>::iterator i = alwaysLootItems.begin(); i != alwaysLootItems.end(); i++)
{
ItemPrototype const *proto = sItemStorage.LookupEntry<ItemPrototype>(*i);
if (!proto)
{
continue;
}

out << " " << chat->formatItem(proto);
}

ai->TellPlayer(requester, out);
}

void LootStrategyAction::TellGoList(Player* requester, const string& name)
{
set<uint32>& skipGoItems = AI_VALUE(set<uint32>&, name);
ostringstream out;
out << "My " << name << ":";

for (set<uint32>::iterator i = skipGoItems.begin(); i != skipGoItems.end(); i++)
{
uint32 id = *i;
GameObjectInfo const *proto = sGOStorage.LookupEntry<GameObjectInfo>(id);
if (!proto)
continue;

out << " |cFFFFFF00|Hfound:" << 0 << ":" << id << ":" << "|h[" << proto->name << "]|h|r";
}
ai->TellPlayer(requester, out);
}
4 changes: 4 additions & 0 deletions playerbot/strategy/actions/LootStrategyAction.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,9 @@ namespace ai
public:
LootStrategyAction(PlayerbotAI* ai) : ChatCommandAction(ai, "ll") {}
virtual bool Execute(Event& event) override;

private:
void TellLootList(Player* requester, const string& name);
void TellGoList(Player* requester, const string& name);
};
}
18 changes: 18 additions & 0 deletions playerbot/strategy/actions/QueryQuestAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,24 @@ bool QueryQuestAction::Execute(Event& event)

PlayerbotChatHandler ch(bot);
uint32 questId = ch.extractQuestId(text);
if (!questId)
{
for (uint8 slot = 0; slot < MAX_QUEST_LOG_SIZE; ++slot)
{
uint32 logQuest = bot->GetQuestSlotQuestId(slot);

Quest const* quest = sObjectMgr.GetQuestTemplate(logQuest);
if (!quest)
continue;

if (text.find(quest->GetTitle()) != string::npos)
{
questId = quest->GetQuestId();
break;
}
}
}

if (!questId)
return false;

Expand Down
6 changes: 5 additions & 1 deletion playerbot/strategy/values/ValueContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ namespace ai
creators["stack space for item"] = &ValueContext::stack_space_for_item;
creators["should loot object"] = &ValueContext::should_loot_object;
creators["always loot list"] = &ValueContext::always_loot_list;
creators["skip loot list"] = &ValueContext::skip_loot_list;
creators["skip go loot list"] = &ValueContext::skip_go_loot_list;
creators["loot strategy"] = &ValueContext::loot_strategy;
creators["active rolls"] = &ValueContext::active_rolls;
creators["last movement"] = &ValueContext::last_movement;
Expand Down Expand Up @@ -456,7 +458,9 @@ namespace ai
static UntypedValue* has_available_loot(PlayerbotAI* ai) { return new HasAvailableLootValue(ai); }
static UntypedValue* stack_space_for_item(PlayerbotAI* ai) { return new StackSpaceForItem(ai); }
static UntypedValue* should_loot_object(PlayerbotAI* ai) { return new ShouldLootObject(ai); }
static UntypedValue* always_loot_list(PlayerbotAI* ai) { return new AlwaysLootListValue(ai); }
static UntypedValue* always_loot_list(PlayerbotAI* ai) { return new AlwaysLootListValue(ai, "always loot list"); }
static UntypedValue* skip_loot_list(PlayerbotAI* ai) { return new AlwaysLootListValue(ai, "skip loot list"); }
static UntypedValue* skip_go_loot_list(PlayerbotAI* ai) { return new AlwaysLootListValue(ai, "skip go loot list"); }
static UntypedValue* loot_strategy(PlayerbotAI* ai) { return new LootStrategyValue(ai); }
static UntypedValue* active_rolls(PlayerbotAI* ai) { return new ActiveRolls(ai); }

Expand Down

0 comments on commit 5e6c740

Please sign in to comment.