Core/Spells: Implemented battle pet experience related spell effects and auras (#27488)

* Spell effect 286 (SPELL_EFFECT_GRANT_BATTLEPET_EXPERIENCE)
* Aura type 420 (SPELL_AURA_MOD_BATTLE_PET_XP_PCT)
This commit is contained in:
Meji
2021-12-30 20:38:29 +01:00
committed by GitHub
parent 9cc3cd128c
commit 9354b4ac8e
10 changed files with 125 additions and 7 deletions

View File

@@ -541,6 +541,8 @@ void CriteriaHandler::UpdateCriteria(CriteriaType type, uint64 miscValue1 /*= 0*
case CriteriaType::PVPKillInArea:
case CriteriaType::WinArena: // This also behaves like CriteriaType::WinAnyRankedArena
case CriteriaType::Login:
case CriteriaType::BattlePetReachLevel:
case CriteriaType::ActivelyEarnPetLevel:
case CriteriaType::PlaceGarrisonBuilding:
case CriteriaType::ActivateAnyGarrisonBuilding:
case CriteriaType::HonorLevelIncrease:
@@ -789,9 +791,7 @@ void CriteriaHandler::UpdateCriteria(CriteriaType type, uint64 miscValue1 /*= 0*
case CriteriaType::CompleteScenario:
case CriteriaType::AccountObtainPetThroughBattle:
case CriteriaType::WinPetBattle:
case CriteriaType::BattlePetReachLevel:
case CriteriaType::PlayerObtainPetThroughBattle:
case CriteriaType::ActivelyEarnPetLevel:
case CriteriaType::EnterArea:
case CriteriaType::LeaveArea:
case CriteriaType::DefeatDungeonEncounter:
@@ -1203,6 +1203,8 @@ bool CriteriaHandler::IsCompletedCriteria(Criteria const* criteria, uint64 requi
case CriteriaType::CurrencyGained:
case CriteriaType::PlaceGarrisonBuilding:
case CriteriaType::UniquePetsOwned:
case CriteriaType::BattlePetReachLevel:
case CriteriaType::ActivelyEarnPetLevel:
case CriteriaType::LearnAnyTransmogInSlot:
case CriteriaType::ParagonLevelIncreaseWithFaction:
case CriteriaType::PlayerHasEarnedHonor:
@@ -1629,9 +1631,15 @@ bool CriteriaHandler::RequirementsSatisfied(Criteria const* criteria, uint64 mis
if (miscValue1 != uint32(criteria->Entry->Asset.TransmogSetGroupID))
return false;
break;
case CriteriaType::BattlePetReachLevel:
case CriteriaType::ActivelyEarnPetLevel:
if (!miscValue1 || !miscValue2 || miscValue2 != uint32(criteria->Entry->Asset.PetLevel))
return false;
break;
case CriteriaType::ActivelyReachLevel:
if (!miscValue1 || miscValue1 != uint32(criteria->Entry->Asset.PlayerLevel))
return false;
break;
default:
break;
}

View File

@@ -20,6 +20,7 @@
#include "Containers.h"
#include "Creature.h"
#include "DatabaseEnv.h"
#include "GameTables.h"
#include "GameTime.h"
#include "Item.h"
#include "Log.h"
@@ -677,6 +678,76 @@ void BattlePetMgr::ChangeBattlePetQuality(ObjectGuid guid, BattlePetBreedQuality
// _owner->GetPlayer()->SetCurrentBattlePetBreedQuality(qualityValue);
}
void BattlePetMgr::GrantBattlePetExperience(ObjectGuid guid, uint16 xp, BattlePetXpSource xpSource)
{
if (!HasJournalLock())
return;
BattlePet* pet = GetPet(guid);
if (!pet)
return;
if (xp <= 0 || xpSource >= BattlePetXpSource::Count)
return;
if (BattlePetSpeciesEntry const* battlePetSpecies = sBattlePetSpeciesStore.LookupEntry(pet->PacketInfo.Species))
if (battlePetSpecies->GetFlags().HasFlag(BattlePetSpeciesFlags::CantBattle))
return;
uint16 level = pet->PacketInfo.Level;
if (level >= MAX_BATTLE_PET_LEVEL)
return;
GtBattlePetXPEntry const* xpEntry = sBattlePetXPGameTable.GetRow(level);
if (!xpEntry)
return;
Player* player = _owner->GetPlayer();
uint16 nextLevelXp = uint16(GetBattlePetXPPerLevel(xpEntry));
if (xpSource == BattlePetXpSource::PetBattle)
xp *= player->GetTotalAuraMultiplier(SPELL_AURA_MOD_BATTLE_PET_XP_PCT);
xp += pet->PacketInfo.Exp;
while (xp >= nextLevelXp && level < MAX_BATTLE_PET_LEVEL)
{
xp -= nextLevelXp;
xpEntry = sBattlePetXPGameTable.GetRow(++level);
if (!xpEntry)
return;
nextLevelXp = uint16(GetBattlePetXPPerLevel(xpEntry));
player->UpdateCriteria(CriteriaType::BattlePetReachLevel, pet->PacketInfo.Species, level);
if (xpSource == BattlePetXpSource::PetBattle)
player->UpdateCriteria(CriteriaType::ActivelyEarnPetLevel, pet->PacketInfo.Species, level);
}
pet->PacketInfo.Level = level;
pet->PacketInfo.Exp = level < MAX_BATTLE_PET_LEVEL ? xp : 0;
pet->CalculateStats();
pet->PacketInfo.Health = pet->PacketInfo.MaxHealth;
if (pet->SaveInfo != BATTLE_PET_NEW)
pet->SaveInfo = BATTLE_PET_CHANGED;
std::vector<std::reference_wrapper<BattlePet>> updates;
updates.push_back(std::ref(*pet));
SendUpdates(std::move(updates), false);
// Update battle pet related update fields
if (Creature* summonedBattlePet = player->GetSummonedBattlePet())
{
if (summonedBattlePet->GetBattlePetCompanionGUID() == guid)
{
summonedBattlePet->SetWildBattlePetLevel(pet->PacketInfo.Level);
player->SetBattlePetData(pet);
}
}
}
void BattlePetMgr::HealBattlePetsPct(uint8 pct)
{
// TODO: After each Pet Battle, any injured companion will automatically

View File

@@ -85,6 +85,14 @@ enum class BattlePetSlot : uint8
Count
};
enum class BattlePetXpSource : uint8
{
PetBattle = 0,
SpellEffect = 1,
Count
};
// 6.2.4
enum FlagsControlType
{
@@ -172,6 +180,7 @@ public:
void CageBattlePet(ObjectGuid guid);
void ChangeBattlePetQuality(ObjectGuid guid, BattlePetBreedQuality quality);
void GrantBattlePetExperience(ObjectGuid guid, uint16 xp, BattlePetXpSource xpSource);
void HealBattlePetsPct(uint8 pct);
void SummonPet(ObjectGuid guid);

View File

@@ -487,9 +487,9 @@ enum class CriteriaType : uint8
AccountObtainPetThroughBattle = 157, /*NYI*/ // (Account Only) Obtain a pet through battle
WinPetBattle = 158, /*NYI*/ // Win a pet battle
LosePetBattle = 159, /*NYI*/ // Lose a pet battle
BattlePetReachLevel = 160, /*NYI*/ // (Account Only) Battle pet has reached level {#Level}
BattlePetReachLevel = 160, // (Account Only) Battle pet has reached level {#Level}
PlayerObtainPetThroughBattle = 161, /*NYI*/ // (Player) Obtain a pet through battle
ActivelyEarnPetLevel = 162, /*NYI*/ // (Player) Actively earn level {#Level} with a pet by a player
ActivelyEarnPetLevel = 162, // (Player) Actively earn level {#Level} with a pet by a player
EnterArea = 163, /*NYI*/ // Enter Map Area "{AreaTable}"
LeaveArea = 164, /*NYI*/ // Leave Map Area "{AreaTable}"
DefeatDungeonEncounter = 165, /*NYI*/ // Defeat Encounter "{DungeonEncounter}"

View File

@@ -28,6 +28,7 @@ GameTable<GtArtifactKnowledgeMultiplierEntry> sArtifactKnowledgeMultiplierGame
GameTable<GtArtifactLevelXPEntry> sArtifactLevelXPGameTable;
GameTable<GtBarberShopCostBaseEntry> sBarberShopCostBaseGameTable;
GameTable<GtBaseMPEntry> sBaseMPGameTable;
GameTable<GtBattlePetXPEntry> sBattlePetXPGameTable;
GameTable<GtCombatRatingsEntry> sCombatRatingsGameTable;
GameTable<GtCombatRatingsMultByILvl> sCombatRatingsMultByILvlGameTable;
GameTable<GtHpPerStaEntry> sHpPerStaGameTable;
@@ -113,6 +114,7 @@ void LoadGameTables(std::string const& dataPath)
LOAD_GT(sArtifactLevelXPGameTable, "ArtifactLevelXP.txt");
LOAD_GT(sBarberShopCostBaseGameTable, "BarberShopCostBase.txt");
LOAD_GT(sBaseMPGameTable, "BaseMp.txt");
LOAD_GT(sBattlePetXPGameTable, "BattlePetXP.txt");
LOAD_GT(sCombatRatingsGameTable, "CombatRatings.txt");
LOAD_GT(sCombatRatingsMultByILvlGameTable, "CombatRatingsMultByILvl.txt");
LOAD_GT(sItemSocketCostPerLevelGameTable, "ItemSocketCostPerLevel.txt");

View File

@@ -56,6 +56,12 @@ struct GtBaseMPEntry
float DemonHunter = 0.0f;
};
struct GtBattlePetXPEntry
{
float Wins = 0.0f;
float Xp = 0.0f;
};
struct GtCombatRatingsEntry
{
float Amplify = 0.0f;
@@ -180,6 +186,7 @@ TC_GAME_API extern GameTable<GtArtifactKnowledgeMultiplierEntry> sArtifactKno
TC_GAME_API extern GameTable<GtArtifactLevelXPEntry> sArtifactLevelXPGameTable;
TC_GAME_API extern GameTable<GtBarberShopCostBaseEntry> sBarberShopCostBaseGameTable;
TC_GAME_API extern GameTable<GtBaseMPEntry> sBaseMPGameTable;
TC_GAME_API extern GameTable<GtBattlePetXPEntry> sBattlePetXPGameTable;
TC_GAME_API extern GameTable<GtCombatRatingsEntry> sCombatRatingsGameTable;
TC_GAME_API extern GameTable<GtCombatRatingsMultByILvl> sCombatRatingsMultByILvlGameTable;
TC_GAME_API extern GameTable<GtHpPerStaEntry> sHpPerStaGameTable;
@@ -279,6 +286,11 @@ inline float GetSpellScalingColumnForClass(GtSpellScalingEntry const* row, int32
return 0.0f;
}
inline float GetBattlePetXPPerLevel(GtBattlePetXPEntry const* row)
{
return row->Wins * row->Xp;
}
template<class T>
float GetIlvlStatMultiplier(T const* row, InventoryType invType);

View File

@@ -511,7 +511,7 @@ enum AuraType : uint32
SPELL_AURA_MOD_GLOBAL_COOLDOWN_BY_HASTE_REGEN = 417,
SPELL_AURA_MOD_MAX_POWER = 418, // NYI
SPELL_AURA_MOD_BASE_MANA_PCT = 419,
SPELL_AURA_MOD_BATTLE_PET_XP_PCT = 420, // NYI
SPELL_AURA_MOD_BATTLE_PET_XP_PCT = 420,
SPELL_AURA_MOD_ABSORB_EFFECTS_DONE_PCT = 421, // NYI
SPELL_AURA_MOD_ABSORB_EFFECTS_TAKEN_PCT = 422, // NYI
SPELL_AURA_MOD_MANA_COST_PCT = 423,

View File

@@ -488,7 +488,7 @@ NonDefaultConstructible<pAuraEffectHandler> AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleNoImmediateEffect, //417 SPELL_AURA_MOD_GLOBAL_COOLDOWN_BY_HASTE_REGEN implemented in Spell::TriggerGlobalCooldown
&AuraEffect::HandleAuraModMaxPower, //418 SPELL_AURA_MOD_MAX_POWER
&AuraEffect::HandleAuraModIncreaseBaseManaPercent, //419 SPELL_AURA_MOD_BASE_MANA_PCT
&AuraEffect::HandleNULL, //420 SPELL_AURA_MOD_BATTLE_PET_XP_PCT
&AuraEffect::HandleNoImmediateEffect, //420 SPELL_AURA_MOD_BATTLE_PET_XP_PCT - Implemented in BattlePetMgr::GrantBattlePetExperience
&AuraEffect::HandleNULL, //421 SPELL_AURA_MOD_ABSORB_EFFECTS_DONE_PCT
&AuraEffect::HandleNULL, //422 SPELL_AURA_MOD_ABSORB_EFFECTS_TAKEN_PCT
&AuraEffect::HandleModManaCostPct, //423 SPELL_AURA_MOD_MANA_COST_PCT

View File

@@ -399,6 +399,7 @@ class TC_GAME_API Spell
void EffectLearnAzeriteEssencePower();
void EffectCreatePrivateConversation();
void EffectSendChatMessage();
void EffectGrantBattlePetExperience();
typedef std::unordered_set<Aura*> UsedSpellMods;

View File

@@ -367,7 +367,7 @@ NonDefaultConstructible<SpellEffectHandlerFn> SpellEffectHandlers[TOTAL_SPELL_EF
&Spell::EffectNULL, //283 SPELL_EFFECT_COMPLETE_CAMPAIGN
&Spell::EffectSendChatMessage, //284 SPELL_EFFECT_SEND_CHAT_MESSAGE
&Spell::EffectNULL, //285 SPELL_EFFECT_MODIFY_KEYSTONE_2
&Spell::EffectNULL, //286 SPELL_EFFECT_GRANT_BATTLEPET_EXPERIENCE
&Spell::EffectGrantBattlePetExperience, //286 SPELL_EFFECT_GRANT_BATTLEPET_EXPERIENCE
&Spell::EffectNULL, //287 SPELL_EFFECT_SET_GARRISON_FOLLOWER_LEVEL
};
@@ -5722,3 +5722,18 @@ void Spell::EffectSendChatMessage()
ChatMsg chatType = ChatMsg(effectInfo->MiscValueB);
unitCaster->Talk(broadcastTextId, chatType, CreatureTextMgr::GetRangeForChatType(chatType), unitTarget);
}
void Spell::EffectGrantBattlePetExperience()
{
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
return;
Player* playerCaster = m_caster->ToPlayer();
if (!playerCaster)
return;
if (!unitTarget || !unitTarget->IsCreature())
return;
playerCaster->GetSession()->GetBattlePetMgr()->GrantBattlePetExperience(unitTarget->GetBattlePetCompanionGUID(), damage, BattlePets::BattlePetXpSource::SpellEffect);
}