Files
AzerothAI/deploy/playable/native/trainer-methods.inc
2026-09-24 09:24:57 +12:00

46 lines
2.2 KiB
C++

// AzerothAI: inspect actual trainer eligibility; never synthesize spell requirements.
int GetClassTrainerStatus(lua_State* L, PlayerbotAI* botAI)
{
uint32 entry = ALE::CHECKVAL<uint32>(L, 2);
Player* bot = GetBotOrNull(botAI);
auto* trainer = sObjectMgr->GetTrainer(entry);
auto const* info = sObjectMgr->GetCreatureTemplate(entry);
uint32 pending = 0, cheapest = 0, total = 0;
if (bot && trainer && info && trainer->GetTrainerType() == Trainer::Type::Class && trainer->IsTrainerValidForPlayer(bot))
{
auto const* faction = sFactionTemplateStore.LookupEntry(info->faction);
float discount = faction ? bot->GetReputationPriceDiscount(faction) : 1.0f;
for (auto const& spell : trainer->GetSpells())
{
if (!trainer->CanTeachSpell(bot, &spell)) continue;
uint32 cost = uint32(spell.MoneyCost * discount);
if (!pending || cost < cheapest) cheapest = cost;
++pending; total += cost;
}
}
ALE::Push(L, pending); ALE::Push(L, cheapest); ALE::Push(L, total);
return 3;
}
// Same transaction as a player's trainer purchase, at an interactable class trainer.
int TrainAtClassTrainer(lua_State* L, PlayerbotAI* botAI)
{
Creature* npc = ALE::CHECKOBJ<Creature>(L, 2);
Player* bot = GetBotOrNull(botAI);
uint32 learned = 0;
if (!bot || botAI->HasGameClientMaster() || !bot->IsAlive() || bot->IsInCombat() || bot->IsInFlight() ||
!npc || bot->GetNPCIfCanInteractWith(npc->GetGUID(), UNIT_NPC_FLAG_TRAINER) != npc)
{ ALE::Push(L, learned); return 1; }
auto* trainer = sObjectMgr->GetTrainer(npc->GetEntry());
if (!trainer || trainer->GetTrainerType() != Trainer::Type::Class || !trainer->IsTrainerValidForPlayer(bot))
{ ALE::Push(L, learned); return 1; }
for (auto const& spell : trainer->GetSpells())
{
if (!trainer->CanTeachSpell(bot, &spell)) continue;
trainer->TeachSpell(npc, bot, spell.SpellId);
if (!trainer->CanTeachSpell(bot, &spell)) ++learned;
}
ALE::Push(L, learned);
return 1;
}