diff --git a/Source/Framework/Constants/AccountConst.cs b/Source/Framework/Constants/AccountConst.cs index fa411b45d..4963efcd0 100644 --- a/Source/Framework/Constants/AccountConst.cs +++ b/Source/Framework/Constants/AccountConst.cs @@ -789,7 +789,8 @@ namespace Framework.Constants CommandLookupMapId = 875, CommandLookupItemId = 876, CommandLookupQuestId = 877, - // 878-879 previously used, do not reuse + // 878 previously used, do not reuse + CommandDebugPoolstatus = 879, CommandPdumpCopy = 880, CommandReloadVehicleTemplate = 881, // Custom Permissions 1000+ diff --git a/Source/Game/AI/CoreAI/PetAI.cs b/Source/Game/AI/CoreAI/PetAI.cs index 8b72950b9..cb8382f76 100644 --- a/Source/Game/AI/CoreAI/PetAI.cs +++ b/Source/Game/AI/CoreAI/PetAI.cs @@ -476,6 +476,12 @@ namespace Game.AI return false; } + if (me.GetCharmInfo() == null) + { + //Log.outError(LogFilter.ScriptsAi, $"me.GetCharmInfo() is NULL in PetAI::CanAttack(). Debug info: {}", GetDebugInfo()); + return false; + } + // Passive - passive pets can attack if told to if (me.HasReactState(ReactStates.Passive)) return me.GetCharmInfo().IsCommandAttack(); diff --git a/Source/Game/BattlePets/BattlePetManager.cs b/Source/Game/BattlePets/BattlePetManager.cs index d5a1e0fb6..848195819 100644 --- a/Source/Game/BattlePets/BattlePetManager.cs +++ b/Source/Game/BattlePets/BattlePetManager.cs @@ -47,18 +47,18 @@ namespace Game.BattlePets foreach (var battlePetBreedState in CliDB.BattlePetBreedStateStorage.Values) { - if (!_battlePetBreedStates.ContainsKey(battlePetBreedState.BattlePetBreedID)) - _battlePetBreedStates[battlePetBreedState.BattlePetBreedID] = new Dictionary(); + if (!BattlePetBreedStates.ContainsKey(battlePetBreedState.BattlePetBreedID)) + BattlePetBreedStates[battlePetBreedState.BattlePetBreedID] = new Dictionary(); - _battlePetBreedStates[battlePetBreedState.BattlePetBreedID][(BattlePetState)battlePetBreedState.BattlePetStateID] = battlePetBreedState.Value; + BattlePetBreedStates[battlePetBreedState.BattlePetBreedID][(BattlePetState)battlePetBreedState.BattlePetStateID] = battlePetBreedState.Value; } foreach (var battlePetSpeciesState in CliDB.BattlePetSpeciesStateStorage.Values) { - if (!_battlePetSpeciesStates.ContainsKey(battlePetSpeciesState.BattlePetSpeciesID)) - _battlePetSpeciesStates[battlePetSpeciesState.BattlePetSpeciesID] = new Dictionary(); + if (!BattlePetSpeciesStates.ContainsKey(battlePetSpeciesState.BattlePetSpeciesID)) + BattlePetSpeciesStates[battlePetSpeciesState.BattlePetSpeciesID] = new Dictionary(); - _battlePetSpeciesStates[battlePetSpeciesState.BattlePetSpeciesID][(BattlePetState)battlePetSpeciesState.BattlePetStateID] = battlePetSpeciesState.Value; + BattlePetSpeciesStates[battlePetSpeciesState.BattlePetSpeciesID][(BattlePetState)battlePetSpeciesState.BattlePetStateID] = battlePetSpeciesState.Value; } LoadAvailablePetBreeds(); @@ -709,62 +709,62 @@ namespace Game.BattlePets Dictionary _pets = new(); List _slots = new(); - static Dictionary> _battlePetBreedStates = new(); - static Dictionary> _battlePetSpeciesStates = new(); + public static Dictionary> BattlePetBreedStates = new(); + public static Dictionary> BattlePetSpeciesStates = new(); static MultiMap _availableBreedsPerSpecies = new(); static Dictionary _defaultQualityPerSpecies = new(); + } - public class BattlePet + public class BattlePet + { + public void CalculateStats() { - public void CalculateStats() + // get base breed stats + var breedState = BattlePetMgr.BattlePetBreedStates.LookupByKey(PacketInfo.Breed); + if (breedState == null) // non existing breed id + return; + + float health = breedState[BattlePetState.StatStamina]; + float power = breedState[BattlePetState.StatPower]; + float speed = breedState[BattlePetState.StatSpeed]; + + // modify stats depending on species - not all pets have this + var speciesState = BattlePetMgr.BattlePetSpeciesStates.LookupByKey(PacketInfo.Species); + if (speciesState != null) { - // get base breed stats - var breedState = _battlePetBreedStates.LookupByKey(PacketInfo.Breed); - if (breedState == null) // non existing breed id - return; - - float health = breedState[BattlePetState.StatStamina]; - float power = breedState[BattlePetState.StatPower]; - float speed = breedState[BattlePetState.StatSpeed]; - - // modify stats depending on species - not all pets have this - var speciesState = _battlePetSpeciesStates.LookupByKey(PacketInfo.Species); - if (speciesState != null) - { - health += speciesState[BattlePetState.StatStamina]; - power += speciesState[BattlePetState.StatPower]; - speed += speciesState[BattlePetState.StatSpeed]; - } - - // modify stats by quality - foreach (var battlePetBreedQuality in CliDB.BattlePetBreedQualityStorage.Values) - { - if (battlePetBreedQuality.QualityEnum == PacketInfo.Quality) - { - health *= battlePetBreedQuality.StateMultiplier; - power *= battlePetBreedQuality.StateMultiplier; - speed *= battlePetBreedQuality.StateMultiplier; - break; - } - // TOOD: add check if pet has existing quality - } - - // scale stats depending on level - health *= PacketInfo.Level; - power *= PacketInfo.Level; - speed *= PacketInfo.Level; - - // set stats - // round, ceil or floor? verify this - PacketInfo.MaxHealth = (uint)((Math.Round(health / 20) + 100)); - PacketInfo.Power = (uint)(Math.Round(power / 100)); - PacketInfo.Speed = (uint)(Math.Round(speed / 100)); + health += speciesState[BattlePetState.StatStamina]; + power += speciesState[BattlePetState.StatPower]; + speed += speciesState[BattlePetState.StatSpeed]; } - public BattlePetStruct PacketInfo; - public long NameTimestamp; - public DeclinedName DeclinedName; - public BattlePetSaveInfo SaveInfo; + // modify stats by quality + foreach (var battlePetBreedQuality in CliDB.BattlePetBreedQualityStorage.Values) + { + if (battlePetBreedQuality.QualityEnum == PacketInfo.Quality) + { + health *= battlePetBreedQuality.StateMultiplier; + power *= battlePetBreedQuality.StateMultiplier; + speed *= battlePetBreedQuality.StateMultiplier; + break; + } + // TOOD: add check if pet has existing quality + } + + // scale stats depending on level + health *= PacketInfo.Level; + power *= PacketInfo.Level; + speed *= PacketInfo.Level; + + // set stats + // round, ceil or floor? verify this + PacketInfo.MaxHealth = (uint)((Math.Round(health / 20) + 100)); + PacketInfo.Power = (uint)(Math.Round(power / 100)); + PacketInfo.Speed = (uint)(Math.Round(speed / 100)); } + + public BattlePetStruct PacketInfo; + public long NameTimestamp; + public DeclinedName DeclinedName; + public BattlePetSaveInfo SaveInfo; } } diff --git a/Source/Game/Chat/Channels/ChannelManager.cs b/Source/Game/Chat/Channels/ChannelManager.cs index 72cbd8bab..fee43c755 100644 --- a/Source/Game/Chat/Channels/ChannelManager.cs +++ b/Source/Game/Chat/Channels/ChannelManager.cs @@ -33,7 +33,6 @@ namespace Game.Chat _guidGenerator = new ObjectGuidGenerator(HighGuid.ChatChannel); } - /*static*/ public static void LoadFromDB() { if (!WorldConfig.GetBoolValue(WorldCfg.PreserveCustomChannels)) diff --git a/Source/Game/Combat/CombatManager.cs b/Source/Game/Combat/CombatManager.cs index adaaa7a7b..2537e26f7 100644 --- a/Source/Game/Combat/CombatManager.cs +++ b/Source/Game/Combat/CombatManager.cs @@ -271,7 +271,7 @@ namespace Game.Combat { _owner.AddUnitFlag(UnitFlags.InCombat); _owner.AtEnterCombat(); - if (_owner.IsCreature()) + if (!_owner.IsCreature()) _owner.AtEngage(GetAnyTarget()); } else diff --git a/Source/Game/Entities/Object/Update/UpdateFields.cs b/Source/Game/Entities/Object/Update/UpdateFields.cs index 01c49a37d..a5bb8a8c1 100644 --- a/Source/Game/Entities/Object/Update/UpdateFields.cs +++ b/Source/Game/Entities/Object/Update/UpdateFields.cs @@ -1210,7 +1210,7 @@ namespace Game.Entities public UpdateField MaxItemLevel = new(96, 106); public UpdateField AzeriteItemLevel = new(96, 107); public UpdateField WildBattlePetLevel = new(96, 108); - public UpdateField BattlePetCompanionExperience = new(96, 109); + public UpdateField BattlePetCompanionExperience = new(96, 109); public UpdateField BattlePetCompanionNameTimestamp = new(96, 110); public UpdateField InteractSpellID = new(96, 111); public UpdateField ScaleDuration = new(96, 112); @@ -1403,7 +1403,7 @@ namespace Game.Entities data.WriteUInt32(MaxItemLevel); data.WriteInt32(AzeriteItemLevel); data.WriteUInt32(WildBattlePetLevel); - data.WriteInt32(BattlePetCompanionExperience); + data.WriteUInt32(BattlePetCompanionExperience); data.WriteUInt32(BattlePetCompanionNameTimestamp); data.WriteInt32(InteractSpellID); data.WriteInt32(ScaleDuration); @@ -1944,7 +1944,7 @@ namespace Game.Entities } if (changesMask[109]) { - data.WriteInt32(BattlePetCompanionExperience); + data.WriteUInt32(BattlePetCompanionExperience); } if (changesMask[110]) { diff --git a/Source/Game/Entities/Player/Player.cs b/Source/Game/Entities/Player/Player.cs index 2184b3d23..23e82faeb 100644 --- a/Source/Game/Entities/Player/Player.cs +++ b/Source/Game/Entities/Player/Player.cs @@ -4847,7 +4847,7 @@ namespace Game.Entities void SendTameFailure(PetTameResult result) { PetTameFailure petTameFailure = new(); - petTameFailure.Result = result; + petTameFailure.Result = (byte)result; SendPacket(petTameFailure); } diff --git a/Source/Game/Handlers/BattlePetHandler.cs b/Source/Game/Handlers/BattlePetHandler.cs index 0572926c3..980d6fc97 100644 --- a/Source/Game/Handlers/BattlePetHandler.cs +++ b/Source/Game/Handlers/BattlePetHandler.cs @@ -44,7 +44,7 @@ namespace Game [WorldPacketHandler(ClientOpcodes.BattlePetSetBattleSlot)] void HandleBattlePetSetBattleSlot(BattlePetSetBattleSlot battlePetSetBattleSlot) { - BattlePetMgr.BattlePet pet = GetBattlePetMgr().GetPet(battlePetSetBattleSlot.PetGuid); + BattlePet pet = GetBattlePetMgr().GetPet(battlePetSetBattleSlot.PetGuid); if (pet != null) { BattlePetSlot slot = GetBattlePetMgr().GetSlot((BattlePetSlots)battlePetSetBattleSlot.Slot); @@ -82,7 +82,7 @@ namespace Game return; } - BattlePetMgr.BattlePet battlePet = petOwner.ToPlayer().GetSession().GetBattlePetMgr().GetPet(queryBattlePetName.BattlePetID); + BattlePet battlePet = petOwner.ToPlayer().GetSession().GetBattlePetMgr().GetPet(queryBattlePetName.BattlePetID); if (battlePet == null) { SendPacket(response); diff --git a/Source/Game/Miscellaneous/CommonPredicates.cs b/Source/Game/Miscellaneous/CommonPredicates.cs new file mode 100644 index 000000000..0b88ee5fc --- /dev/null +++ b/Source/Game/Miscellaneous/CommonPredicates.cs @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2012-2020 CypherCore + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Game.Entities; + +namespace Game.Miscellaneous +{ + /// Only returns true for the given attacker's current victim, if any + public class IsVictimOf : ICheck + { + WorldObject _victim; + + public IsVictimOf(Unit attacker) + { + _victim = attacker?.GetVictim(); + } + + public bool Invoke(WorldObject obj) + { + return obj != null && (_victim == obj); + } + } +} diff --git a/Source/Game/Spells/SpellEffects.cs b/Source/Game/Spells/SpellEffects.cs index 796985e78..717ff5583 100644 --- a/Source/Game/Spells/SpellEffects.cs +++ b/Source/Game/Spells/SpellEffects.cs @@ -2784,10 +2784,6 @@ namespace Game.Spells if (unitTarget != null && unitCaster != null) unitCaster.CastSpell(unitTarget, Convert.ToBoolean(RandomHelper.IRand(0, 1)) ? (uint)damage : 52505, new CastSpellExtraArgs(TriggerCastFlags.FullMask).SetOriginalCastId(m_castId)); return; - case 53110: // Devour Humanoid - if (unitTarget != null) - unitTarget.CastSpell(m_caster, (uint)damage, new CastSpellExtraArgs(TriggerCastFlags.FullMask).SetOriginalCastId(m_castId)); - return; case 57347: // Retrieving (Wintergrasp RP-GG pickup spell) { if (unitTarget == null || !unitTarget.IsTypeId(TypeId.Unit) || !m_caster.IsTypeId(TypeId.Player)) diff --git a/Source/Scripts/World/ItemScripts.cs b/Source/Scripts/World/ItemScripts.cs index 50a5588b6..9cd5ffe40 100644 --- a/Source/Scripts/World/ItemScripts.cs +++ b/Source/Scripts/World/ItemScripts.cs @@ -214,40 +214,6 @@ namespace Scripts.World.ItemScripts } } - [Script] - class item_pile_fake_furs : ItemScript - { - public item_pile_fake_furs() : base("item_pile_fake_furs") { } - - public override bool OnUse(Player player, Item item, SpellCastTargets targets, ObjectGuid castId) - { - GameObject go = null; - foreach (var id in GameObjectIds.CaribouTraps) - { - go = player.FindNearestGameObject(id, 5.0f); - if (go) - break; - } - - if (!go) - return false; - - if (go.FindNearestCreature(CreatureIds.NesingwaryTrapper, 10.0f, true) || go.FindNearestCreature(CreatureIds.NesingwaryTrapper, 10.0f, false) || go.FindNearestGameObject(GameObjectIds.HighQualityFur, 2.0f)) - return true; - - go.GetClosePoint(out float x, out float y, out float z, go.GetCombatReach() / 3, 7.0f); - go.SummonGameObject(GameObjectIds.HighQualityFur, go, Quaternion.CreateFromRotationMatrix(Extensions.fromEulerAnglesZYX(go.GetOrientation(), 0.0f, 0.0f)), 1); - TempSummon summon = player.SummonCreature(CreatureIds.NesingwaryTrapper, x, y, z, go.GetOrientation(), TempSummonType.DeadDespawn, 1000); - if (summon) - { - summon.SetVisible(false); - summon.SetReactState(ReactStates.Passive); - summon.SetImmuneToPC(true); - } - return false; - } - } - [Script] class item_petrov_cluster_bombs : ItemScript {