Skip to content

Commit

Permalink
Learn my level command
Browse files Browse the repository at this point in the history
  • Loading branch information
celguar committed Sep 4, 2022
1 parent 8f4a9d7 commit ecff4c9
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 40 deletions.
1 change: 1 addition & 0 deletions src/game/Chat/Chat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,7 @@ ChatCommand* ChatHandler::getCommandTable()
{ "all_mypettalents", SEC_ADMINISTRATOR, false, &ChatHandler::HandleLearnAllMyPetTalentsCommand, "", nullptr },
{ "all_myspells", SEC_ADMINISTRATOR, false, &ChatHandler::HandleLearnAllMySpellsCommand, "", nullptr },
{ "all_mytalents", SEC_ADMINISTRATOR, false, &ChatHandler::HandleLearnAllMyTalentsCommand, "", nullptr },
{ "all_mylevel", SEC_ADMINISTRATOR, false, &ChatHandler::HandleLearnAllMyLevelCommand, "", nullptr },
{ "all_recipes", SEC_GAMEMASTER, false, &ChatHandler::HandleLearnAllRecipesCommand, "", nullptr },
{ "", SEC_ADMINISTRATOR, false, &ChatHandler::HandleLearnCommand, "", nullptr },
{ nullptr, 0, false, nullptr, "", nullptr }
Expand Down
1 change: 1 addition & 0 deletions src/game/Chat/Chat.h
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,7 @@ class ChatHandler
bool HandleLearnAllMyPetTalentsCommand(char* args);
bool HandleLearnAllMySpellsCommand(char* args);
bool HandleLearnAllMyTalentsCommand(char* args);
bool HandleLearnAllMyLevelCommand(char* args);

bool HandleListAreaTriggerCommand(char* args);
bool HandleListAurasCommand(char* args);
Expand Down
9 changes: 9 additions & 0 deletions src/game/Chat/Level3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2019,6 +2019,15 @@ bool ChatHandler::HandleLearnAllMyTalentsCommand(char* /*args*/)
return true;
}

bool ChatHandler::HandleLearnAllMyLevelCommand(char* /*args*/)
{
Player* player = m_session->GetPlayer();
player->learnClassLevelSpells();

SendSysMessage(LANG_COMMAND_LEARN_CLASS_SPELLS);
return true;
}

bool ChatHandler::HandleLearnAllMyPetTalentsCommand(char* /*args*/)
{
Player* player = m_session->GetPlayer();
Expand Down
207 changes: 167 additions & 40 deletions src/game/Entities/Player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23198,53 +23198,23 @@ void Player::RestoreBaseRune(uint8 index)
std::vector<Aura const*> removeList;
std::unordered_set<Aura const*>& auras = m_runes->runes[index].ConvertAuras;

//auto criteria = [&removeList](Aura const* storedAura) -> bool
//{
// // AuraEffect already gone
// if (!storedAura)
// return true;

// if (storedAura->GetSpellProto()->HasAttribute(SPELL_ATTR_PASSIVE))
// {
// // Don't drop passive talents providing rune conversion
// if (storedAura->GetModifier()->m_auraname == SPELL_AURA_CONVERT_RUNE)
// removeList.push_back(storedAura);
// return true;
// }

// // If rune was converted by a non-passive aura that is still active we should keep it converted
// return false;
//};

//for (auto itr = auras.begin(); itr != auras.end();)
//{
// if (criteria(*itr))
// auras.erase(itr++);
// else
// ++itr;
//}

for (auto aura : auras)
auto criteria = [&removeList](Aura const* storedAura) -> bool
{
// AuraEffect already gone
if (!aura)
continue;
if (!storedAura)
return true;

if (aura->GetSpellProto()->HasAttribute(SPELL_ATTR_PASSIVE))
if (storedAura->GetSpellProto()->HasAttribute(SPELL_ATTR_PASSIVE))
{
// Don't drop passive talents providing rune conversion
if (aura->GetModifier()->m_auraname == SPELL_AURA_CONVERT_RUNE)
removeList.push_back(aura);

aura = nullptr;
if (storedAura->GetModifier()->m_auraname == SPELL_AURA_CONVERT_RUNE)
removeList.push_back(storedAura);
return true;
}
}

for (auto aura : auras)
{
if (aura != nullptr)
return;
}
// If rune was converted by a non-passive aura that is still active we should keep it converted
return false;
};

ConvertRune(index, GetBaseRune(index));

Expand All @@ -23257,6 +23227,8 @@ void Player::RestoreBaseRune(uint8 index)
uint8 itr = 0;
for (; itr < MAX_RUNES; ++itr)
{
RemoveRuneConvertAura(itr, storedAura);

if (m_runes->runes[itr].ConvertAuras.find(storedAura) != m_runes->runes[itr].ConvertAuras.end())
break;
}
Expand Down Expand Up @@ -23480,6 +23452,161 @@ void Player::learnSpellHighRank(uint32 spellid)
sSpellMgr.doForHighRanks(spellid, worker);
}

void Player::learnClassLevelSpells(bool includeHighLevelQuestRewards)
{
ChrClassesEntry const* clsEntry = sChrClassesStore.LookupEntry(getClass());
if (!clsEntry)
return;
uint32 family = clsEntry->spellfamily;

// special cases which aren't sourced from trainers and normally require quests to obtain - added here for convenience
ObjectMgr::QuestMap const& qTemplates = sObjectMgr.GetQuestTemplates();
for (const auto& qTemplate : qTemplates)
{
Quest const* quest = qTemplate.second;
if (!quest)
continue;

// only class quests player could do
if (quest->GetRequiredClasses() == 0 || !SatisfyQuestClass(quest, false) || !SatisfyQuestRace(quest, false) || !SatisfyQuestLevel(quest, false))
continue;

// custom filter for scripting purposes
if (!includeHighLevelQuestRewards && quest->GetMinLevel() >= 60)
continue;

learnQuestRewardedSpells(quest);
}

// learn trainer spells
for (uint32 id = 0; id < sCreatureStorage.GetMaxEntry(); ++id)
{
CreatureInfo const* co = sCreatureStorage.LookupEntry<CreatureInfo>(id);
if (!co)
continue;

if (co->TrainerType != TRAINER_TYPE_CLASS)
continue;

if (co->TrainerType == TRAINER_TYPE_CLASS && co->TrainerClass != getClass())
continue;

uint32 trainerId = co->TrainerTemplateId;
if (!trainerId)
trainerId = co->Entry;

TrainerSpellData const* trainer_spells = sObjectMgr.GetNpcTrainerTemplateSpells(trainerId);
if (!trainer_spells)
trainer_spells = sObjectMgr.GetNpcTrainerSpells(trainerId);

if (!trainer_spells)
continue;

for (TrainerSpellMap::const_iterator itr = trainer_spells->spellList.begin(); itr != trainer_spells->spellList.end(); ++itr)
{
TrainerSpell const* tSpell = &itr->second;

if (!tSpell)
continue;

uint32 reqLevel = 0;

// skip wrong class/race skills
if (!IsSpellFitByClassAndRace(tSpell->learnedSpell))
continue;

if (tSpell->conditionId && !sObjectMgr.IsConditionSatisfied(tSpell->conditionId, this, GetMap(), this, CONDITION_FROM_TRAINER))
continue;

bool isTalent = false;
bool hasTalent = false;

// skip spells with first rank learned as talent (and all talents then also)
uint32 first_rank = sSpellMgr.GetFirstSpellInChain(tSpell->learnedSpell);
isTalent = GetTalentSpellCost(first_rank) > 0;
hasTalent = isTalent && HasSpell(first_rank);

if (isTalent && !hasTalent)
continue;

reqLevel = tSpell->isProvidedReqLevel ? tSpell->reqLevel : std::max(reqLevel, tSpell->reqLevel);
TrainerSpellState state = GetTrainerSpellState(tSpell, reqLevel);
if (state != TRAINER_SPELL_GREEN && (!isTalent || (isTalent && !hasTalent)))
continue;

//if (first_rank && tSpell->learnedSpell == first_rank)
// continue;

SpellEntry const* proto = sSpellTemplate.LookupEntry<SpellEntry>(tSpell->spell);
if (!proto)
continue;

// fix activate state for non-stackable low rank (and find next spell for !active case)
if (uint32 nextId = sSpellMgr.GetSpellBookSuccessorSpellId(proto->Id))
{
if (HasSpell(nextId))
{
// high rank already known so this must !active
continue;
}
}

// skip other spell families (minus a few exceptions)
if (proto->SpellFamilyName != family)
{
SkillLineAbilityMapBounds bounds = sSpellMgr.GetSkillLineAbilityMapBoundsBySpellId(tSpell->learnedSpell);
if (bounds.first == bounds.second)
continue;

SkillLineAbilityEntry const* skillInfo = bounds.first->second;
if (!skillInfo)
continue;

switch (skillInfo->skillId)
{
case SKILL_SUBTLETY:
//case SKILL_POISONS:
case SKILL_BEAST_MASTERY:
case SKILL_SURVIVAL:
case SKILL_DEFENSE:
case SKILL_DUAL_WIELD:
case SKILL_FERAL_COMBAT:
case SKILL_PROTECTION:
//case SKILL_BEAST_TRAINING:
case SKILL_PLATE_MAIL:
case SKILL_DEMONOLOGY:
case SKILL_ENHANCEMENT:
case SKILL_MAIL:
case SKILL_HOLY2:
case SKILL_LOCKPICKING:
break;
default:
continue;
}
}

// skip broken spells
if (!SpellMgr::IsSpellValid(proto, this, false))
continue;

if (tSpell->learnedSpell)
{
bool learned = false;
for (int j = 0; j < 3; ++j)
{
if (proto->Effect[j] == SPELL_EFFECT_LEARN_SPELL)
{
uint32 learnedSpell = proto->EffectTriggerSpell[j];
learnSpell(learnedSpell, false);
learned = true;
}
}
if (!learned) learnSpell(tSpell->learnedSpell, false);
}
}
}
}

void Player::_LoadSkills(QueryResult* result)
{
// 0 1 2
Expand Down
1 change: 1 addition & 0 deletions src/game/Entities/Player.h
Original file line number Diff line number Diff line change
Expand Up @@ -1740,6 +1740,7 @@ class Player : public Unit
void learnQuestRewardedSpells();
void learnQuestRewardedSpells(Quest const* quest);
void learnSpellHighRank(uint32 spellid);
void learnClassLevelSpells(bool includeHighLevelQuestRewards = false);

uint32 GetFreeTalentPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS1); }
void SetFreeTalentPoints(uint32 points) { SetUInt32Value(PLAYER_CHARACTER_POINTS1, points); }
Expand Down

0 comments on commit ecff4c9

Please sign in to comment.