From bd80047a096c15d472eb6f976f25e6be9ecc1128 Mon Sep 17 00:00:00 2001 From: hondacrx Date: Thu, 17 Feb 2022 10:40:20 -0500 Subject: [PATCH] Core/Spells: Implemented battle pet experience related spell effects and auras Port From (https://github.com/TrinityCore/TrinityCore/commit/9354b4ac8ec63f0b2ee5ceb3c8b6a3c6a75bd99f) --- .../Framework/Constants/AchievementConst.cs | 4 +- Source/Framework/Constants/BattlePetConst.cs | 8 ++ Source/Game/Achievements/CriteriaHandler.cs | 11 ++- Source/Game/BattlePets/BattlePetManager.cs | 74 ++++++++++++++++++- Source/Game/DataStorage/CliDB.cs | 7 ++ .../DataStorage/Structs/GameTablesRecords.cs | 6 ++ Source/Game/Spells/SpellEffects.cs | 16 ++++ 7 files changed, 121 insertions(+), 5 deletions(-) diff --git a/Source/Framework/Constants/AchievementConst.cs b/Source/Framework/Constants/AchievementConst.cs index bd0b628fe..90ee8cda0 100644 --- a/Source/Framework/Constants/AchievementConst.cs +++ b/Source/Framework/Constants/AchievementConst.cs @@ -637,9 +637,9 @@ namespace Framework.Constants 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}" diff --git a/Source/Framework/Constants/BattlePetConst.cs b/Source/Framework/Constants/BattlePetConst.cs index 0761c34bb..4126d8b24 100644 --- a/Source/Framework/Constants/BattlePetConst.cs +++ b/Source/Framework/Constants/BattlePetConst.cs @@ -77,4 +77,12 @@ namespace Framework.Constants Max } + + public enum BattlePetXpSource + { + PetBattle = 0, + SpellEffect = 1, + + Count + } } diff --git a/Source/Game/Achievements/CriteriaHandler.cs b/Source/Game/Achievements/CriteriaHandler.cs index fd221080f..62cdb2b9f 100644 --- a/Source/Game/Achievements/CriteriaHandler.cs +++ b/Source/Game/Achievements/CriteriaHandler.cs @@ -137,6 +137,8 @@ namespace Game.Achievements 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: @@ -389,9 +391,7 @@ namespace Game.Achievements 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: @@ -812,6 +812,8 @@ namespace Game.Achievements case CriteriaType.CurrencyGained: case CriteriaType.PlaceGarrisonBuilding: case CriteriaType.UniquePetsOwned: + case CriteriaType.BattlePetReachLevel: + case CriteriaType.ActivelyEarnPetLevel: case CriteriaType.LearnAnyTransmogInSlot: case CriteriaType.ParagonLevelIncreaseWithFaction: case CriteriaType.PlayerHasEarnedHonor: @@ -1207,6 +1209,11 @@ namespace Game.Achievements if (miscValue1 != criteria.Entry.Asset) return false; break; + case CriteriaType.BattlePetReachLevel: + case CriteriaType.ActivelyEarnPetLevel: + if (miscValue1 == 0 || miscValue2 == 0 || miscValue2 != criteria.Entry.Asset) + return false; + break; case CriteriaType.ActivelyReachLevel: if (miscValue1 == 0 || miscValue1 != criteria.Entry.Asset) return false; diff --git a/Source/Game/BattlePets/BattlePetManager.cs b/Source/Game/BattlePets/BattlePetManager.cs index 2d4ff28b7..33a6ca824 100644 --- a/Source/Game/BattlePets/BattlePetManager.cs +++ b/Source/Game/BattlePets/BattlePetManager.cs @@ -625,7 +625,79 @@ namespace Game.BattlePets SendUpdates(updates, false); // UF::PlayerData::CurrentBattlePetBreedQuality isn't updated (Intended) - // _owner->GetPlayer()->SetCurrentBattlePetBreedQuality(qualityValue); + // _owner.GetPlayer().SetCurrentBattlePetBreedQuality(qualityValue); + } + + public void GrantBattlePetExperience(ObjectGuid guid, ushort xp, BattlePetXpSource xpSource) + { + if (!HasJournalLock()) + return; + + BattlePet pet = GetPet(guid); + if (pet == null) + return; + + if (xp <= 0 || xpSource >= BattlePetXpSource.Count) + return; + + var battlePetSpecies = CliDB.BattlePetSpeciesStorage.LookupByKey(pet.PacketInfo.Species); + if (battlePetSpecies != null) + if (battlePetSpecies.GetFlags().HasFlag(BattlePetSpeciesFlags.CantBattle)) + return; + + ushort level = pet.PacketInfo.Level; + if (level >= SharedConst.MaxBattlePetLevel) + return; + + var xpEntry = CliDB.BattlePetXPGameTable.GetRow(level); + if (xpEntry == null) + return; + + Player player = _owner.GetPlayer(); + ushort nextLevelXp = (ushort)CliDB.GetBattlePetXPPerLevel(xpEntry); + + if (xpSource == BattlePetXpSource.PetBattle) + xp = (ushort)(xp * player.GetTotalAuraMultiplier(AuraType.ModBattlePetXpPct)); + + xp += pet.PacketInfo.Exp; + + while (xp >= nextLevelXp && level < SharedConst.MaxBattlePetLevel) + { + xp -= nextLevelXp; + + xpEntry = CliDB.BattlePetXPGameTable.GetRow(++level); + if (xpEntry == null) + return; + + nextLevelXp = (ushort)CliDB.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 = (ushort)(level < SharedConst.MaxBattlePetLevel ? xp : 0); + pet.CalculateStats(); + pet.PacketInfo.Health = pet.PacketInfo.MaxHealth; + + if (pet.SaveInfo != BattlePetSaveInfo.New) + pet.SaveInfo = BattlePetSaveInfo.Changed; + + List updates = new(); + updates.Add(pet); + SendUpdates(updates, false); + + // Update battle pet related update fields + Creature summonedBattlePet = player.GetSummonedBattlePet(); + if (summonedBattlePet != null) + { + if (summonedBattlePet.GetBattlePetCompanionGUID() == guid) + { + summonedBattlePet.SetWildBattlePetLevel(pet.PacketInfo.Level); + player.SetBattlePetData(pet); + } + } } public void HealBattlePetsPct(byte pct) diff --git a/Source/Game/DataStorage/CliDB.cs b/Source/Game/DataStorage/CliDB.cs index d11ac5a11..926f09218 100644 --- a/Source/Game/DataStorage/CliDB.cs +++ b/Source/Game/DataStorage/CliDB.cs @@ -425,6 +425,7 @@ namespace Game.DataStorage ArtifactLevelXPGameTable = ReadGameTable("artifactLevelXP.txt"); BarberShopCostBaseGameTable = ReadGameTable("BarberShopCostBase.txt"); BaseMPGameTable = ReadGameTable("BaseMp.txt"); + BattlePetXPGameTable = ReadGameTable("BattlePetXP.txt"); CombatRatingsGameTable = ReadGameTable("CombatRatings.txt"); CombatRatingsMultByILvlGameTable = ReadGameTable("CombatRatingsMultByILvl.txt"); ItemSocketCostPerLevelGameTable = ReadGameTable("ItemSocketCostPerLevel.txt"); @@ -737,6 +738,7 @@ namespace Game.DataStorage public static GameTable ArtifactLevelXPGameTable; public static GameTable BarberShopCostBaseGameTable; public static GameTable BaseMPGameTable; + public static GameTable BattlePetXPGameTable; public static GameTable CombatRatingsGameTable; public static GameTable CombatRatingsMultByILvlGameTable; public static GameTable HpPerStaGameTable; @@ -844,6 +846,11 @@ namespace Game.DataStorage return 0.0f; } + public static float GetBattlePetXPPerLevel(GtBattlePetXPRecord row) + { + return row.Wins * row.Xp; + } + public static float GetIlvlStatMultiplier(GtGenericMultByILvlRecord row, InventoryType invType) { switch (invType) diff --git a/Source/Game/DataStorage/Structs/GameTablesRecords.cs b/Source/Game/DataStorage/Structs/GameTablesRecords.cs index 81ff12d76..8e15ace4d 100644 --- a/Source/Game/DataStorage/Structs/GameTablesRecords.cs +++ b/Source/Game/DataStorage/Structs/GameTablesRecords.cs @@ -49,6 +49,12 @@ namespace Game.DataStorage public float DemonHunter; } + public sealed class GtBattlePetXPRecord + { + public float Wins; + public float Xp; + } + public sealed class GtCombatRatingsRecord { public float Amplify; diff --git a/Source/Game/Spells/SpellEffects.cs b/Source/Game/Spells/SpellEffects.cs index 0b89e510b..e21d45a87 100644 --- a/Source/Game/Spells/SpellEffects.cs +++ b/Source/Game/Spells/SpellEffects.cs @@ -5508,6 +5508,22 @@ namespace Game.Spells ChatMsg chatType = (ChatMsg)effectInfo.MiscValueB; unitCaster.Talk(broadcastTextId, chatType, Global.CreatureTextMgr.GetRangeForChatType(chatType), unitTarget); } + + [SpellEffectHandler(SpellEffectName.GrantBattlepetExperience)] + void EffectGrantBattlePetExperience() + { + if (effectHandleMode != SpellEffectHandleMode.HitTarget) + return; + + Player playerCaster = m_caster.ToPlayer(); + if (playerCaster == null) + return; + + if (!unitTarget || !unitTarget.IsCreature()) + return; + + playerCaster.GetSession().GetBattlePetMgr().GrantBattlePetExperience(unitTarget.GetBattlePetCompanionGUID(), (ushort)damage, BattlePetXpSource.SpellEffect); + } } public class DispelableAura