mirror of
https://github.com/liyunfan1223/mod-playerbots.git
synced 2026-02-20 18:10:02 +01:00
PVP Talents and InitGlyph changes
This PR adds 3 pvp specs for each class, as well as their glyphs. It also adds exceptions to the Initglyph function, based on pvp-based talents for each class.
conf\playerbots.conf.dist - Adds 3 pvp specs/glyphs for each class.
src\factory\PlayerbotFactory.cpp - InitGlyph in its current form is unable to correctly assign glyphs on specindexes (or tab) over 2 without an exception. That is why this exception already exists in the code:
if (bot->getClass() == CLASS_DRUID && tab == DRUID_TAB_FERAL && bot->GetLevel() >= 20 && !bot->HasAura(16931))
tab = 3;
This checks if the class is a Druid, if the tab is feral, if they are equal to or above level 20, and they don't have the Thick Hide talent. If all of these are true, then it manually sets the tab = 3. I first discovered this when I noticed that my frostfire mage would never be assigned the correct glyphs in the config - aka glyph of frosfire. It is because the frostfire spec is tab = 3, and no such logic exists. When I started adding the additional pvp specs, I noticed that they never would assign the correct glyphs. I had to add an exception to all pvp specs, and have them check for certain pvp related talents to correlate the tab manually. This is because tab is derived from the AiFactory::GetPlayerSpecTab(bot); function. The only possible tab values from this function are 0, 1, and 2.
**TLDR: Added code to support Frostfire Mage, dual-aura Blood DK, and all the PvP specs for correct glyph assignment.**
src\strategy\actions\ChangeTalentsAction.cpp: When you pick a spec with "talents spec" function, such as "talents spec arms pve", it will now correctly assign glyphs without the player having to execute the maintenance command. Setting the InitGlyphs to false removes prior glyphs.
src\strategy\actions\TrainerAction.cpp - Changed factory.InitGlyphs(true); to factory.InitGlyphs(false);. This makes it so all prior glyphs that were assigned are correctly deleted. I first noticed this when switching between specs and using the maintenance command - I had to login to the bot and manually delete the old glyphs, in order for the maintenance command to assign the new, correct glyphs.
239 lines
6.9 KiB
C++
239 lines
6.9 KiB
C++
/*
|
|
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it
|
|
* and/or modify it under version 2 of the License, or (at your option), any later version.
|
|
*/
|
|
|
|
#include "TrainerAction.h"
|
|
|
|
#include "BudgetValues.h"
|
|
#include "Event.h"
|
|
#include "PlayerbotFactory.h"
|
|
#include "Playerbots.h"
|
|
|
|
void TrainerAction::Learn(uint32 cost, TrainerSpell const* tSpell, std::ostringstream& msg)
|
|
{
|
|
if (sPlayerbotAIConfig->autoTrainSpells != "free" && !botAI->HasCheat(BotCheatMask::gold))
|
|
{
|
|
if (AI_VALUE2(uint32, "free money for", (uint32)NeedMoneyFor::spells) < cost)
|
|
{
|
|
msg << " - too expensive";
|
|
return;
|
|
}
|
|
|
|
bot->ModifyMoney(-int32(cost));
|
|
}
|
|
|
|
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(tSpell->spell);
|
|
if (!spellInfo)
|
|
return;
|
|
|
|
bool learned = false;
|
|
for (uint8 j = 0; j < 3; ++j)
|
|
{
|
|
if (spellInfo->Effects[j].Effect == SPELL_EFFECT_LEARN_SPELL)
|
|
{
|
|
uint32 learnedSpell = spellInfo->Effects[j].TriggerSpell;
|
|
if (!bot->HasSpell(learnedSpell))
|
|
{
|
|
bot->learnSpell(learnedSpell);
|
|
learned = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!learned && !bot->HasSpell(tSpell->spell))
|
|
{
|
|
bot->learnSpell(tSpell->spell);
|
|
}
|
|
|
|
msg << " - learned";
|
|
}
|
|
|
|
void TrainerAction::Iterate(Creature* creature, TrainerSpellAction action, SpellIds& spells)
|
|
{
|
|
TellHeader(creature);
|
|
|
|
TrainerSpellData const* trainer_spells = creature->GetTrainerSpells();
|
|
float fDiscountMod = bot->GetReputationPriceDiscount(creature);
|
|
uint32 totalCost = 0;
|
|
|
|
for (TrainerSpellMap::const_iterator itr = trainer_spells->spellList.begin();
|
|
itr != trainer_spells->spellList.end(); ++itr)
|
|
{
|
|
TrainerSpell const* tSpell = &itr->second;
|
|
if (!tSpell)
|
|
continue;
|
|
|
|
TrainerSpellState state = bot->GetTrainerSpellState(tSpell);
|
|
if (state != TRAINER_SPELL_GREEN)
|
|
continue;
|
|
|
|
uint32 spellId = tSpell->spell;
|
|
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
|
|
if (!spellInfo)
|
|
continue;
|
|
|
|
if (!spells.empty() && spells.find(tSpell->spell) == spells.end())
|
|
continue;
|
|
|
|
uint32 cost = uint32(floor(tSpell->spellCost * fDiscountMod));
|
|
totalCost += cost;
|
|
|
|
std::ostringstream out;
|
|
out << chat->FormatSpell(spellInfo) << chat->formatMoney(cost);
|
|
|
|
if (action)
|
|
(this->*action)(cost, tSpell, out);
|
|
|
|
botAI->TellMaster(out);
|
|
}
|
|
|
|
TellFooter(totalCost);
|
|
}
|
|
|
|
bool TrainerAction::Execute(Event event)
|
|
{
|
|
std::string const text = event.getParam();
|
|
|
|
Player* master = GetMaster();
|
|
|
|
Creature* creature = botAI->GetCreature(bot->GetTarget());
|
|
|
|
if (master)
|
|
{
|
|
creature = master->GetSelectedUnit() ? master->GetSelectedUnit()->ToCreature() : nullptr;
|
|
}
|
|
// if (AI_VALUE(GuidPosition, "rpg target") != bot->GetTarget())
|
|
// if (master)
|
|
// creature = botAI->GetCreature(master->GetTarget());
|
|
// else
|
|
// return false;
|
|
|
|
if (!creature || !creature->IsTrainer())
|
|
return false;
|
|
|
|
if (!creature->IsValidTrainerForPlayer(bot))
|
|
{
|
|
botAI->TellError("This trainer cannot teach me");
|
|
return false;
|
|
}
|
|
|
|
// check present spell in trainer spell list
|
|
TrainerSpellData const* cSpells = creature->GetTrainerSpells();
|
|
if (!cSpells)
|
|
{
|
|
botAI->TellError("No spells can be learned from this trainer");
|
|
return false;
|
|
}
|
|
|
|
uint32 spell = chat->parseSpell(text);
|
|
SpellIds spells;
|
|
if (spell)
|
|
spells.insert(spell);
|
|
|
|
if (text.find("learn") != std::string::npos || sRandomPlayerbotMgr->IsRandomBot(bot) ||
|
|
(sPlayerbotAIConfig->autoTrainSpells != "no" &&
|
|
(creature->GetCreatureTemplate()->trainer_type != TRAINER_TYPE_TRADESKILLS ||
|
|
!botAI->HasActivePlayerMaster()))) // Todo rewrite to only exclude start primary profession skills and make
|
|
// config dependent.
|
|
Iterate(creature, &TrainerAction::Learn, spells);
|
|
else
|
|
Iterate(creature, nullptr, spells);
|
|
|
|
return true;
|
|
}
|
|
|
|
void TrainerAction::TellHeader(Creature* creature)
|
|
{
|
|
std::ostringstream out;
|
|
out << "--- Can learn from " << creature->GetName() << " ---";
|
|
botAI->TellMaster(out);
|
|
}
|
|
|
|
void TrainerAction::TellFooter(uint32 totalCost)
|
|
{
|
|
if (totalCost)
|
|
{
|
|
std::ostringstream out;
|
|
out << "Total cost: " << chat->formatMoney(totalCost);
|
|
botAI->TellMaster(out);
|
|
}
|
|
}
|
|
|
|
bool MaintenanceAction::Execute(Event event)
|
|
{
|
|
if (!sPlayerbotAIConfig->maintenanceCommand)
|
|
{
|
|
botAI->TellError("maintenance command is not allowed, please check the configuration.");
|
|
return false;
|
|
}
|
|
|
|
botAI->TellMaster("I'm maintaining");
|
|
PlayerbotFactory factory(bot, bot->GetLevel());
|
|
factory.InitAttunementQuests();
|
|
factory.InitBags(false);
|
|
factory.InitAmmo();
|
|
factory.InitFood();
|
|
factory.InitReagents();
|
|
factory.InitTalentsTree(true);
|
|
factory.InitPet();
|
|
factory.InitPetTalents();
|
|
factory.InitClassSpells();
|
|
factory.InitAvailableSpells();
|
|
factory.InitSkills();
|
|
factory.InitReputation();
|
|
factory.InitSpecialSpells();
|
|
factory.InitMounts();
|
|
factory.InitGlyphs(false);
|
|
factory.InitKeyring();
|
|
factory.InitPotions();
|
|
if (bot->GetLevel() >= sPlayerbotAIConfig->minEnchantingBotLevel)
|
|
factory.ApplyEnchantAndGemsNew();
|
|
|
|
bot->DurabilityRepairAll(false, 1.0f, false);
|
|
bot->SendTalentsInfoData(false);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool RemoveGlyphAction::Execute(Event event)
|
|
{
|
|
for (uint32 slotIndex = 0; slotIndex < MAX_GLYPH_SLOT_INDEX; ++slotIndex)
|
|
{
|
|
bot->SetGlyph(slotIndex, 0, true);
|
|
}
|
|
bot->SendTalentsInfoData(false);
|
|
return true;
|
|
}
|
|
|
|
bool AutoGearAction::Execute(Event event)
|
|
{
|
|
if (!sPlayerbotAIConfig->autoGearCommand)
|
|
{
|
|
botAI->TellError("autogear command is not allowed, please check the configuration.");
|
|
return false;
|
|
}
|
|
|
|
if (!sPlayerbotAIConfig->autoGearCommandAltBots &&
|
|
!sPlayerbotAIConfig->IsInRandomAccountList(bot->GetSession()->GetAccountId()))
|
|
{
|
|
botAI->TellError("You cannot use autogear on alt bots.");
|
|
return false;
|
|
}
|
|
|
|
botAI->TellMaster("I'm auto gearing");
|
|
uint32 gs = sPlayerbotAIConfig->autoGearScoreLimit == 0
|
|
? 0
|
|
: PlayerbotFactory::CalcMixedGearScore(sPlayerbotAIConfig->autoGearScoreLimit,
|
|
sPlayerbotAIConfig->autoGearQualityLimit);
|
|
PlayerbotFactory factory(bot, bot->GetLevel(), sPlayerbotAIConfig->autoGearQualityLimit, gs);
|
|
factory.InitEquipment(true);
|
|
factory.InitAmmo();
|
|
if (bot->GetLevel() >= sPlayerbotAIConfig->minEnchantingBotLevel)
|
|
{
|
|
factory.ApplyEnchantAndGemsNew();
|
|
}
|
|
bot->DurabilityRepairAll(false, 1.0f, false);
|
|
return true;
|
|
}
|