From 66ad9f4ce0639b7fdb9991849917b1a236cfc43a Mon Sep 17 00:00:00 2001 From: hondacrx Date: Sat, 22 Oct 2022 22:24:44 -0400 Subject: [PATCH] Core/GameObjects: Implemented gathering nodes (gameobject type 50) Port From (https://github.com/TrinityCore/TrinityCore/commit/1011cb73c92ddb90589452f70a1dd33830689e32) --- Source/Game/Entities/GameObject/GameObject.cs | 88 +++++++++ .../Entities/GameObject/GameObjectData.cs | 173 +++++++++++++----- .../Entities/Object/Update/UpdateFields.cs | 9 + Source/Game/Entities/Player/Player.Spells.cs | 34 +++- Source/Game/Garrisons/Garrisons.cs | 4 +- Source/Game/Globals/ObjectManager.cs | 2 +- Source/Game/Handlers/LootHandler.cs | 2 +- Source/Game/Spells/Spell.cs | 3 + Source/Game/Spells/SpellEffects.cs | 2 +- 9 files changed, 259 insertions(+), 58 deletions(-) diff --git a/Source/Game/Entities/GameObject/GameObject.cs b/Source/Game/Entities/GameObject/GameObject.cs index 029bf0b8b..2d83d698b 100644 --- a/Source/Game/Entities/GameObject/GameObject.cs +++ b/Source/Game/Entities/GameObject/GameObject.cs @@ -2410,6 +2410,64 @@ namespace Game.Entities player.SendPacket(gameObjectUILink); return; } + case GameObjectTypes.GatheringNode: //50 + { + Player player = user.ToPlayer(); + if (player == null) + return; + + GameObjectTemplate info = GetGoInfo(); + if (!m_personalLoot.ContainsKey(player.GetGUID())) + { + if (info.GatheringNode.chestLoot != 0) + { + Loot newLoot = new(GetMap(), GetGUID(), LootType.Chest, null); + m_personalLoot[player.GetGUID()] = newLoot; + + newLoot.FillLoot(info.GatheringNode.chestLoot, LootStorage.Gameobject, player, true, false, GetLootMode(), GetMap().GetDifficultyLootItemContext()); + } + + if (info.GatheringNode.triggeredEvent != 0) + GameEvents.Trigger(info.GatheringNode.triggeredEvent, player, this); + + // triggering linked GO + uint trapEntry = info.GatheringNode.linkedTrap; + if (trapEntry != 0) + TriggeringLinkedGameObject(trapEntry, player); + + if (info.GatheringNode.xpDifficulty != 0 && info.GatheringNode.xpDifficulty < 10) + { + QuestXPRecord questXp = CliDB.QuestXPStorage.LookupByKey(player.GetLevel()); + if (questXp != null) + { + uint xp = Quest.RoundXPValue(questXp.Difficulty[info.GatheringNode.xpDifficulty]); + if (xp != 0) + player.GiveXP(xp, null); + } + } + + spellId = info.GatheringNode.spell; + } + + if (m_personalLoot.Count >= info.GatheringNode.MaxNumberofLoots) + { + SetGoState(GameObjectState.Active); + SetDynamicFlag(GameObjectDynamicLowFlags.NoInterract); + } + + if (GetLootState() != LootState.Activated) + { + SetLootState(LootState.Activated, player); + if (info.GatheringNode.ObjectDespawnDelay != 0) + DespawnOrUnsummon(TimeSpan.FromSeconds(info.GatheringNode.ObjectDespawnDelay)); + } + + // Send loot + Loot loot = GetLootForPlayer(player); + if (loot != null) + player.SendLoot(loot); + break; + } default: if (GetGoType() >= GameObjectTypes.Max) Log.outError(LogFilter.Server, "GameObject.Use(): unit (type: {0}, guid: {1}, name: {2}) tries to use object (guid: {3}, entry: {4}, name: {5}) of unknown type ({6})", @@ -2859,6 +2917,20 @@ namespace Game.Entities } break; } + case GameObjectTypes.GatheringNode: + { + SetGoStateFor(GameObjectState.Active, looter); + + ObjectFieldData objMask = new(); + GameObjectFieldData goMask = new(); + objMask.MarkChanged(objMask.DynamicFlags); + + UpdateData udata = new(GetMapId()); + BuildValuesUpdateForPlayerWithMask(udata, objMask.GetUpdateMask(), goMask.GetUpdateMask(), looter); + udata.BuildPacket(out UpdateObject packet); + looter.SendPacket(packet); + break; + } } } @@ -3132,6 +3204,9 @@ namespace Game.Entities public float GetInteractionDistance() { + if (GetGoInfo().GetInteractRadiusOverride() != 0) + return (float)GetGoInfo().GetInteractRadiusOverride() / 100.0f; + switch (GetGoType()) { case GameObjectTypes.AreaDamage: @@ -3377,6 +3452,19 @@ namespace Game.Entities || m_goValue.CapturePoint.State == BattlegroundCapturePointState.HordeCaptured; } + public bool MeetsInteractCondition(Player user) + { + if (m_goInfo.GetConditionID1() == 0) + return true; + + PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(m_goInfo.GetConditionID1()); + if (playerCondition != null) + if (!ConditionManager.IsPlayerMeetingCondition(user, playerCondition)) + return false; + + return true; + } + Dictionary GetOrCreatePerPlayerStates() { if (m_perPlayerState == null) diff --git a/Source/Game/Entities/GameObject/GameObjectData.cs b/Source/Game/Entities/GameObject/GameObjectData.cs index e01a2f2ea..fb11a0fc8 100644 --- a/Source/Game/Entities/GameObject/GameObjectData.cs +++ b/Source/Game/Entities/GameObject/GameObjectData.cs @@ -163,7 +163,7 @@ namespace Game.Entities public newflagdrop NewFlagDrop; [FieldOffset(68)] - public Garrisonbuilding garrisonBuilding; + public garrisonbuilding GarrisonBuilding; [FieldOffset(68)] public garrisonplot GarrisonPlot; @@ -274,6 +274,89 @@ namespace Game.Entities } } + public uint GetConditionID1() => type switch + { + GameObjectTypes.Door => Door.conditionID1, + GameObjectTypes.Button => Button.conditionID1, + GameObjectTypes.QuestGiver => QuestGiver.conditionID1, + GameObjectTypes.Chest => Chest.conditionID1, + GameObjectTypes.Generic => Generic.conditionID1, + GameObjectTypes.Trap => Trap.conditionID1, + GameObjectTypes.Chair => Chair.conditionID1, + GameObjectTypes.SpellFocus => SpellFocus.conditionID1, + GameObjectTypes.Text => Text.conditionID1, + GameObjectTypes.Goober => Goober.conditionID1, + GameObjectTypes.Camera => Camera.conditionID1, + GameObjectTypes.Ritual => Ritual.conditionID1, + GameObjectTypes.Mailbox => MailBox.conditionID1, + GameObjectTypes.SpellCaster => SpellCaster.conditionID1, + GameObjectTypes.FlagStand => FlagStand.conditionID1, + GameObjectTypes.AuraGenerator => AuraGenerator.conditionID1, + GameObjectTypes.GuildBank => GuildBank.conditionID1, + GameObjectTypes.NewFlag => NewFlag.conditionID1, + GameObjectTypes.ItemForge => ItemForge.conditionID1, + GameObjectTypes.GatheringNode => GatheringNode.conditionID1, + _ => 0, + }; + + public uint GetInteractRadiusOverride() => type switch + { + + GameObjectTypes.Door => Door.InteractRadiusOverride, + GameObjectTypes.Button => Button.InteractRadiusOverride, + GameObjectTypes.QuestGiver => QuestGiver.InteractRadiusOverride, + GameObjectTypes.Chest => Chest.InteractRadiusOverride, + GameObjectTypes.Binder => Binder.InteractRadiusOverride, + GameObjectTypes.Generic => Generic.InteractRadiusOverride, + GameObjectTypes.Trap => Trap.InteractRadiusOverride, + GameObjectTypes.Chair => Chair.InteractRadiusOverride, + GameObjectTypes.SpellFocus => SpellFocus.InteractRadiusOverride, + GameObjectTypes.Text => Text.InteractRadiusOverride, + GameObjectTypes.Goober => Goober.InteractRadiusOverride, + GameObjectTypes.Transport => Transport.InteractRadiusOverride, + GameObjectTypes.AreaDamage => AreaDamage.InteractRadiusOverride, + GameObjectTypes.Camera => Camera.InteractRadiusOverride, + GameObjectTypes.MapObjTransport => MoTransport.InteractRadiusOverride, + GameObjectTypes.DuelArbiter => DuelFlag.InteractRadiusOverride, + GameObjectTypes.FishingNode => FishingNode.InteractRadiusOverride, + GameObjectTypes.Ritual => Ritual.InteractRadiusOverride, + GameObjectTypes.Mailbox => MailBox.InteractRadiusOverride, + GameObjectTypes.GuardPost => GuardPost.InteractRadiusOverride, + GameObjectTypes.SpellCaster => SpellCaster.InteractRadiusOverride, + GameObjectTypes.MeetingStone => MeetingStone.InteractRadiusOverride, + GameObjectTypes.FlagStand => FlagStand.InteractRadiusOverride, + GameObjectTypes.FishingHole => FishingHole.InteractRadiusOverride, + GameObjectTypes.FlagDrop => FlagDrop.InteractRadiusOverride, + GameObjectTypes.ControlZone => ControlZone.InteractRadiusOverride, + GameObjectTypes.AuraGenerator => AuraGenerator.InteractRadiusOverride, + GameObjectTypes.DungeonDifficulty => DungeonDifficulty.InteractRadiusOverride, + GameObjectTypes.BarberChair => BarberChair.InteractRadiusOverride, + GameObjectTypes.DestructibleBuilding => DestructibleBuilding.InteractRadiusOverride, + GameObjectTypes.GuildBank => GuildBank.InteractRadiusOverride, + GameObjectTypes.TrapDoor => TrapDoor.InteractRadiusOverride, + GameObjectTypes.NewFlag => NewFlag.InteractRadiusOverride, + GameObjectTypes.NewFlagDrop => NewFlagDrop.InteractRadiusOverride, + GameObjectTypes.GarrisonBuilding => GarrisonBuilding.InteractRadiusOverride, + GameObjectTypes.GarrisonPlot => GarrisonPlot.InteractRadiusOverride, + GameObjectTypes.CapturePoint => CapturePoint.InteractRadiusOverride, + GameObjectTypes.PhaseableMo => PhaseableMO.InteractRadiusOverride, + GameObjectTypes.GarrisonMonument => GarrisonMonument.InteractRadiusOverride, + GameObjectTypes.GarrisonShipment => GarrisonShipment.InteractRadiusOverride, + GameObjectTypes.GarrisonMonumentPlaque => GarrisonMonumentPlaque.InteractRadiusOverride, + GameObjectTypes.ItemForge => ItemForge.InteractRadiusOverride, + GameObjectTypes.UILink => UILink.InteractRadiusOverride, + GameObjectTypes.KeystoneReceptacle => KeystoneReceptacle.InteractRadiusOverride, + GameObjectTypes.GatheringNode => GatheringNode.InteractRadiusOverride, + GameObjectTypes.ChallengeModeReward => ChallengeModeReward.InteractRadiusOverride, + GameObjectTypes.SiegeableMo => SiegeableMO.InteractRadiusOverride, + GameObjectTypes.PvpReward => PvpReward.InteractRadiusOverride, + GameObjectTypes.PlayerChoiceChest => PlayerChoiceChest.InteractRadiusOverride, + GameObjectTypes.LegendaryForge => LegendaryForge.InteractRadiusOverride, + GameObjectTypes.GarrTalentTree => GarrTalentTree.InteractRadiusOverride, + GameObjectTypes.WeeklyRewardChest => WeeklyRewardChest.InteractRadiusOverride, + _ => 0 + }; + public uint GetRequireLOS() => type switch { GameObjectTypes.Button => Button.requireLOS, @@ -287,48 +370,27 @@ namespace Game.Entities _ => 0, }; - public uint GetLockId() + public uint GetLockId() => type switch { - switch (type) - { - case GameObjectTypes.Door: - return Door.open; - case GameObjectTypes.Button: - return Button.open; - case GameObjectTypes.QuestGiver: - return QuestGiver.open; - case GameObjectTypes.Chest: - return Chest.open; - case GameObjectTypes.Trap: - return Trap.open; - case GameObjectTypes.Goober: - return Goober.open; - case GameObjectTypes.AreaDamage: - return AreaDamage.open; - case GameObjectTypes.Camera: - return Camera.open; - case GameObjectTypes.FlagStand: - return FlagStand.open; - case GameObjectTypes.FishingHole: - return FishingHole.open; - case GameObjectTypes.FlagDrop: - return FlagDrop.open; - case GameObjectTypes.NewFlag: - return NewFlag.open; - case GameObjectTypes.NewFlagDrop: - return NewFlagDrop.open; - case GameObjectTypes.CapturePoint: - return CapturePoint.open; - case GameObjectTypes.GatheringNode: - return GatheringNode.open; - case GameObjectTypes.ChallengeModeReward: - return ChallengeModeReward.open; - case GameObjectTypes.PvpReward: - return PvpReward.open; - default: - return 0; - } - } + GameObjectTypes.Door => Door.open, + GameObjectTypes.Button => Button.open, + GameObjectTypes.QuestGiver => QuestGiver.open, + GameObjectTypes.Chest => Chest.open, + GameObjectTypes.Trap => Trap.open, + GameObjectTypes.Goober => Goober.open, + GameObjectTypes.AreaDamage => AreaDamage.open, + GameObjectTypes.Camera => Camera.open, + GameObjectTypes.FlagStand => FlagStand.open, + GameObjectTypes.FishingHole => FishingHole.open, + GameObjectTypes.FlagDrop => FlagDrop.open, + GameObjectTypes.NewFlag => NewFlag.open, + GameObjectTypes.NewFlagDrop => NewFlagDrop.open, + GameObjectTypes.CapturePoint => CapturePoint.open, + GameObjectTypes.GatheringNode => GatheringNode.open, + GameObjectTypes.ChallengeModeReward => ChallengeModeReward.open, + GameObjectTypes.PvpReward => PvpReward.open, + _ => 0, + }; // despawn at targeting of cast? public bool GetDespawnPossibility() @@ -378,7 +440,14 @@ namespace Game.Entities return 0; } } - + + public uint GetNotInCombat() => type switch + { + GameObjectTypes.Chest => Chest.notInCombat, + GameObjectTypes.GatheringNode => GatheringNode.notInCombat, + _ => 0, + }; + /// /// despawn at uses amount /// @@ -492,6 +561,20 @@ namespace Game.Entities } } + public uint GetTrivialSkillHigh() => type switch + { + GameObjectTypes.Chest => Chest.trivialSkillHigh, + GameObjectTypes.GatheringNode => GatheringNode.trivialSkillHigh, + _ => 0, + }; + + public uint GetTrivialSkillLow() => type switch + { + GameObjectTypes.Chest => Chest.trivialSkillLow, + GameObjectTypes.GatheringNode => GatheringNode.trivialSkillLow, + _ => 0, + }; + // Cooldown preventing goober and traps to cast spell public uint GetCooldown() { @@ -1182,7 +1265,7 @@ namespace Game.Entities public uint InteractRadiusOverride; // 2 Interact Radius Override (in hundredths), int, Min value: 0, Max value: 2147483647, Default value: 0 } - public struct Garrisonbuilding + public struct garrisonbuilding { public int SpawnMap; // 0 Spawn Map, References: Map, NoValue = -1 public uint InteractRadiusOverride; // 1 Interact Radius Override (in hundredths), int, Min value: 0, Max value: 2147483647, Default value: 0 @@ -1395,7 +1478,7 @@ namespace Game.Entities public uint open; // 1 open, References: Lock_, NoValue = 0 public uint InteractRadiusOverride; // 2 Interact Radius Override (in hundredths), int, Min value: 0, Max value: 2147483647, Default value: 0 } - + public struct clientmodel { public uint LargeAOI; // 0 Large AOI, enum { false, true, }; Default: false diff --git a/Source/Game/Entities/Object/Update/UpdateFields.cs b/Source/Game/Entities/Object/Update/UpdateFields.cs index c38efa3bd..d280e7921 100644 --- a/Source/Game/Entities/Object/Update/UpdateFields.cs +++ b/Source/Game/Entities/Object/Update/UpdateFields.cs @@ -154,10 +154,19 @@ namespace Game.Entities else dynFlags &= ~GameObjectDynamicLowFlags.NoInterract; break; + case GameObjectTypes.GatheringNode: + if (gameObject.ActivateToQuest(receiver)) + dynFlags |= GameObjectDynamicLowFlags.Activate | GameObjectDynamicLowFlags.Sparkle | GameObjectDynamicLowFlags.Highlight; + if (gameObject.GetGoStateFor(receiver.GetGUID()) == GameObjectState.Active) + dynFlags |= GameObjectDynamicLowFlags.Depleted; + break; default: break; } + if (!gameObject.MeetsInteractCondition(receiver)) + dynFlags |= GameObjectDynamicLowFlags.NoInterract; + unitDynFlags = ((uint)pathProgress << 16) | (uint)dynFlags; } } diff --git a/Source/Game/Entities/Player/Player.Spells.cs b/Source/Game/Entities/Player/Player.Spells.cs index 340b7853a..34c96dded 100644 --- a/Source/Game/Entities/Player/Player.Spells.cs +++ b/Source/Game/Entities/Player/Player.Spells.cs @@ -1257,16 +1257,34 @@ namespace Game.Entities } return false; } - public bool UpdateGatherSkill(uint SkillId, uint SkillValue, uint RedLevel, uint Multiplicator = 1) + + public bool UpdateGatherSkill(uint SkillId, uint SkillValue, uint RedLevel, uint Multiplicator = 1, WorldObject obj = null) { - return UpdateGatherSkill((SkillType)SkillId, SkillValue, RedLevel, Multiplicator); + return UpdateGatherSkill((SkillType)SkillId, SkillValue, RedLevel, Multiplicator, obj); } - public bool UpdateGatherSkill(SkillType SkillId, uint SkillValue, uint RedLevel, uint Multiplicator = 1) + + public bool UpdateGatherSkill(SkillType SkillId, uint SkillValue, uint RedLevel, uint Multiplicator = 1, WorldObject obj = null) { Log.outDebug(LogFilter.Player, "UpdateGatherSkill(SkillId {0} SkillLevel {1} RedLevel {2})", SkillId, SkillValue, RedLevel); uint gathering_skill_gain = WorldConfig.GetUIntValue(WorldCfg.SkillGainGathering); + uint grayLevel = RedLevel + 100; + uint greenLevel = RedLevel + 50; + uint yellowLevel = RedLevel + 25; + + GameObject go = obj?.ToGameObject(); + if (go != null) + { + if (go.GetGoInfo().GetTrivialSkillLow() != 0) + yellowLevel = go.GetGoInfo().GetTrivialSkillLow(); + + if (go.GetGoInfo().GetTrivialSkillHigh() != 0) + grayLevel = go.GetGoInfo().GetTrivialSkillHigh(); + + greenLevel = (yellowLevel + grayLevel) / 2; + } + // For skinning and Mining chance decrease with level. 1-74 - no decrease, 75-149 - 2 times, 225-299 - 8 times switch (SkillId) { @@ -1281,7 +1299,7 @@ namespace Game.Entities case SkillType.KulTiranHerbalism: case SkillType.Jewelcrafting: case SkillType.Inscription: - return UpdateSkillPro(SkillId, SkillGainChance(SkillValue, RedLevel + 100, RedLevel + 50, RedLevel + 25) * (int)Multiplicator, gathering_skill_gain); + return UpdateSkillPro(SkillId, SkillGainChance(SkillValue, grayLevel, greenLevel, yellowLevel) * (int)Multiplicator, gathering_skill_gain); case SkillType.Skinning: case SkillType.Skinning2: case SkillType.OutlandSkinning: @@ -1292,9 +1310,9 @@ namespace Game.Entities case SkillType.LegionSkinning: case SkillType.KulTiranSkinning: if (WorldConfig.GetIntValue(WorldCfg.SkillChanceSkinningSteps) == 0) - return UpdateSkillPro(SkillId, SkillGainChance(SkillValue, RedLevel + 100, RedLevel + 50, RedLevel + 25) * (int)Multiplicator, gathering_skill_gain); + return UpdateSkillPro(SkillId, SkillGainChance(SkillValue, grayLevel, greenLevel, yellowLevel) * (int)Multiplicator, gathering_skill_gain); else - return UpdateSkillPro(SkillId, (int)(SkillGainChance(SkillValue, RedLevel + 100, RedLevel + 50, RedLevel + 25) * Multiplicator) >> (int)(SkillValue / WorldConfig.GetIntValue(WorldCfg.SkillChanceSkinningSteps)), gathering_skill_gain); + return UpdateSkillPro(SkillId, (int)(SkillGainChance(SkillValue, grayLevel, greenLevel, yellowLevel) * Multiplicator) >> (int)(SkillValue / WorldConfig.GetIntValue(WorldCfg.SkillChanceSkinningSteps)), gathering_skill_gain); case SkillType.Mining: case SkillType.Mining2: case SkillType.OutlandMining: @@ -1305,9 +1323,9 @@ namespace Game.Entities case SkillType.LegionMining: case SkillType.KulTiranMining: if (WorldConfig.GetIntValue(WorldCfg.SkillChanceMiningSteps) == 0) - return UpdateSkillPro(SkillId, SkillGainChance(SkillValue, RedLevel + 100, RedLevel + 50, RedLevel + 25) * (int)Multiplicator, gathering_skill_gain); + return UpdateSkillPro(SkillId, SkillGainChance(SkillValue, grayLevel, greenLevel, yellowLevel) * (int)Multiplicator, gathering_skill_gain); else - return UpdateSkillPro(SkillId, (int)(SkillGainChance(SkillValue, RedLevel + 100, RedLevel + 50, RedLevel + 25) * Multiplicator) >> (int)(SkillValue / WorldConfig.GetIntValue(WorldCfg.SkillChanceMiningSteps)), gathering_skill_gain); + return UpdateSkillPro(SkillId, (int)(SkillGainChance(SkillValue, grayLevel, greenLevel, yellowLevel) * Multiplicator) >> (int)(SkillValue / WorldConfig.GetIntValue(WorldCfg.SkillChanceMiningSteps)), gathering_skill_gain); } return false; } diff --git a/Source/Game/Garrisons/Garrisons.cs b/Source/Game/Garrisons/Garrisons.cs index a2429b269..6ba089df8 100644 --- a/Source/Game/Garrisons/Garrisons.cs +++ b/Source/Game/Garrisons/Garrisons.cs @@ -750,9 +750,9 @@ namespace Game.Garrisons } } - if (go.GetGoType() == GameObjectTypes.GarrisonBuilding && go.GetGoInfo().garrisonBuilding.SpawnMap != 0) + if (go.GetGoType() == GameObjectTypes.GarrisonBuilding && go.GetGoInfo().GarrisonBuilding.SpawnMap != 0) { - foreach (var cellGuids in Global.ObjectMgr.GetMapObjectGuids((uint)go.GetGoInfo().garrisonBuilding.SpawnMap, map.GetDifficultyID())) + foreach (var cellGuids in Global.ObjectMgr.GetMapObjectGuids((uint)go.GetGoInfo().GarrisonBuilding.SpawnMap, map.GetDifficultyID())) { foreach (var spawnId in cellGuids.Value.creatures) { diff --git a/Source/Game/Globals/ObjectManager.cs b/Source/Game/Globals/ObjectManager.cs index 02cba3051..394f6700d 100644 --- a/Source/Game/Globals/ObjectManager.cs +++ b/Source/Game/Globals/ObjectManager.cs @@ -4182,7 +4182,7 @@ namespace Game break; case GameObjectTypes.GarrisonBuilding: { - int transportMap = got.garrisonBuilding.SpawnMap; + int transportMap = got.GarrisonBuilding.SpawnMap; if (transportMap != 0) _transportMaps.Add((ushort)transportMap); } diff --git a/Source/Game/Handlers/LootHandler.cs b/Source/Game/Handlers/LootHandler.cs index b4121e6fc..66bc78860 100644 --- a/Source/Game/Handlers/LootHandler.cs +++ b/Source/Game/Handlers/LootHandler.cs @@ -296,7 +296,7 @@ namespace Game else go.SetLootState(LootState.Ready); } - else if (go.IsFullyLooted()) + else if (go.GetGoType() != GameObjectTypes.GatheringNode && go.IsFullyLooted()) go.SetLootState(LootState.JustDeactivated); go.OnLootRelease(player); diff --git a/Source/Game/Spells/Spell.cs b/Source/Game/Spells/Spell.cs index 2f8477545..6b6a15ffe 100644 --- a/Source/Game/Spells/Spell.cs +++ b/Source/Game/Spells/Spell.cs @@ -5242,6 +5242,9 @@ namespace Game.Spells lockId = go.GetGoInfo().GetLockId(); if (lockId == 0) return SpellCastResult.BadTargets; + + if (go.GetGoInfo().GetNotInCombat() != 0 && m_caster.ToUnit().IsInCombat()) + return SpellCastResult.AffectingCombat; } else if (itm != null) lockId = itm.GetTemplate().GetLockID(); diff --git a/Source/Game/Spells/SpellEffects.cs b/Source/Game/Spells/SpellEffects.cs index af8991bf3..959834e65 100644 --- a/Source/Game/Spells/SpellEffects.cs +++ b/Source/Game/Spells/SpellEffects.cs @@ -1300,7 +1300,7 @@ namespace Game.Spells { // Allow one skill-up until respawned if (!gameObjTarget.IsInSkillupList(player.GetGUID()) && - player.UpdateGatherSkill(skillId, pureSkillValue, (uint)reqSkillValue)) + player.UpdateGatherSkill(skillId, pureSkillValue, (uint)reqSkillValue, 1, gameObjTarget)) gameObjTarget.AddToSkillupList(player.GetGUID()); } else if (itemTarget != null)