diff --git a/Source/Game/AI/SmartScripts/SmartScript.cs b/Source/Game/AI/SmartScripts/SmartScript.cs index bf9b5dc43..bb3eaac28 100644 --- a/Source/Game/AI/SmartScripts/SmartScript.cs +++ b/Source/Game/AI/SmartScripts/SmartScript.cs @@ -441,7 +441,7 @@ namespace Game.AI if (vehicle != null) foreach (var seat in vehicle.Seats) { - Player player = Global.ObjAccessor.FindPlayer(seat.Value.Passenger.Guid); + Player player = Global.ObjAccessor.GetPlayer(obj, seat.Value.Passenger.Guid); if (player != null) player.AreaExploredOrEventHappens(e.Action.quest.questId); } @@ -540,7 +540,7 @@ namespace Game.AI } case SmartActions.InvokerCast: { - Unit tempLastInvoker = GetLastInvoker(); + Unit tempLastInvoker = GetLastInvoker(unit); if (tempLastInvoker == null) break; @@ -795,7 +795,7 @@ namespace Game.AI { foreach (var seat in vehicle.Seats) { - Player player = Global.ObjAccessor.FindPlayer(seat.Value.Passenger.Guid); + Player player = Global.ObjAccessor.GetPlayer(unit, seat.Value.Passenger.Guid); if (player != null) player.GroupEventHappens(e.Action.quest.questId, GetBaseObject()); } @@ -935,7 +935,7 @@ namespace Game.AI { foreach (var seat in vehicle.Seats) { - Player player = Global.ObjAccessor.FindPlayer(seat.Value.Passenger.Guid); + Player player = Global.ObjAccessor.GetPlayer(obj, seat.Value.Passenger.Guid); if (player != null) player.KilledMonsterCredit(e.Action.killedMonster.creature); } @@ -3919,16 +3919,17 @@ namespace Game.AI } } - Unit GetLastInvoker() + Unit GetLastInvoker(Unit invoker = null) { - WorldObject lookupRoot = me; - if (!lookupRoot) - lookupRoot = go; + // Look for invoker only on map of base object... Prevents multithreaded crashes + WorldObject baseObject = GetBaseObject(); + if (baseObject != null) + return Global.ObjAccessor.GetUnit(baseObject, mLastInvoker); + // used for area triggers invoker cast + else if (invoker != null) + return Global.ObjAccessor.GetUnit(invoker, mLastInvoker); - if (lookupRoot) - return Global.ObjAccessor.GetUnit(lookupRoot, mLastInvoker); - - return Global.ObjAccessor.FindPlayer(mLastInvoker); + return null; } public void SetPathId(uint id) { mPathId = id; } diff --git a/Source/Game/Combat/ThreatManager.cs b/Source/Game/Combat/ThreatManager.cs index 307263ac3..f749ed416 100644 --- a/Source/Game/Combat/ThreatManager.cs +++ b/Source/Game/Combat/ThreatManager.cs @@ -81,7 +81,8 @@ namespace Game.Combat { float redirectThreat = MathFunctions.CalculatePct(threat, redirectThreadPct); threat -= redirectThreat; - _addThreat(redirectTarget, redirectThreat); + if (isValidProcess(redirectTarget, GetOwner())) + _addThreat(redirectTarget, redirectThreat); } } @@ -286,7 +287,7 @@ namespace Game.Combat return hatedUnit.ApplyTotalThreatModifier(threat, schoolMask); } - public static bool isValidProcess(Unit hatedUnit, Unit hatingUnit, SpellInfo threatSpell) + public static bool isValidProcess(Unit hatedUnit, Unit hatingUnit, SpellInfo threatSpell = null) { //function deals with adding threat and adding players and pets into ThreatList //mobs, NPCs, guards have ThreatList and HateOfflineList diff --git a/Source/Game/DungeonFinding/LFGManager.cs b/Source/Game/DungeonFinding/LFGManager.cs index 3f3610d50..667b948ae 100644 --- a/Source/Game/DungeonFinding/LFGManager.cs +++ b/Source/Game/DungeonFinding/LFGManager.cs @@ -1280,18 +1280,18 @@ namespace Game.DungeonFinding Log.outDebug(LogFilter.Lfg, "TeleportPlayer: Player {0} is being teleported in to map {1} (x: {2}, y: {3}, z: {4}) Result: {5}", player.GetName(), dungeon.map, dungeon.x, dungeon.y, dungeon.z, error); } - public void FinishDungeon(ObjectGuid gguid, uint dungeonId) + public void FinishDungeon(ObjectGuid gguid, uint dungeonId, Map currMap) { uint gDungeonId = GetDungeon(gguid); if (gDungeonId != dungeonId) { - Log.outDebug(LogFilter.Lfg, "FinishDungeon: [{0}] Finished dungeon {1} but group queued for {2}. Ignoring", gguid, dungeonId, gDungeonId); + Log.outDebug(LogFilter.Lfg, $"Group {gguid.ToString()} finished dungeon {dungeonId} but queued for {gDungeonId}. Ignoring"); return; } if (GetState(gguid) == LfgState.FinishedDungeon) // Shouldn't happen. Do not reward multiple times { - Log.outDebug(LogFilter.Lfg, "FinishDungeon: [{0}] Already rewarded group. Ignoring", gguid); + Log.outDebug(LogFilter.Lfg, $"Group {gguid.ToString()} already rewarded"); return; } @@ -1302,7 +1302,7 @@ namespace Game.DungeonFinding { if (GetState(guid) == LfgState.FinishedDungeon) { - Log.outDebug(LogFilter.Lfg, "FinishDungeon: [{0}] Already rewarded player. Ignoring", guid); + Log.outDebug(LogFilter.Lfg, $"Group: {gguid.ToString()}, Player: {guid.ToString()} already rewarded"); continue; } @@ -1318,14 +1318,14 @@ namespace Game.DungeonFinding if (dungeon == null || (dungeon.type != LfgType.RandomDungeon && !dungeon.seasonal)) { - Log.outDebug(LogFilter.Lfg, "FinishDungeon: [{0}] dungeon {1} is not random or seasonal", guid, rDungeonId); + Log.outDebug(LogFilter.Lfg, $"Group: {gguid.ToString()}, Player: {guid.ToString()} dungeon {rDungeonId} is not random or seasonal"); continue; } Player player = Global.ObjAccessor.FindPlayer(guid); - if (!player || !player.IsInWorld) + if (!player || player.GetMap() != currMap) { - Log.outDebug(LogFilter.Lfg, "FinishDungeon: [{0}] not found in world", guid); + Log.outDebug(LogFilter.Lfg, $"Group: {gguid.ToString()}, Player: {guid.ToString()} not found in world"); continue; } @@ -1334,7 +1334,7 @@ namespace Game.DungeonFinding if (player.GetMapId() != mapId) { - Log.outDebug(LogFilter.Lfg, "FinishDungeon: [{0}] is in map {1} and should be in {2} to get reward", guid, player.GetMapId(), mapId); + Log.outDebug(LogFilter.Lfg, $"Group: {gguid.ToString()}, Player: {guid.ToString()} is in map {player.GetMapId()} and should be in {mapId} to get reward"); continue; } @@ -1365,7 +1365,8 @@ namespace Game.DungeonFinding } // Give rewards - Log.outDebug(LogFilter.Lfg, "FinishDungeon: [{0}] done dungeon {1}, {2} previously done.", player.GetGUID(), GetDungeon(gguid), done ? " " : " not"); + string doneString = done ? "" : "not"; + Log.outDebug(LogFilter.Lfg, $"Group: {gguid.ToString()}, Player: {guid.ToString()} done dungeon {GetDungeon(gguid)}, {doneString} previously done."); LfgPlayerRewardData data = new LfgPlayerRewardData(dungeon.Entry(), GetDungeon(gguid, false), done, quest); player.GetSession().SendLfgPlayerReward(data); } diff --git a/Source/Game/Entities/Player/Player.cs b/Source/Game/Entities/Player/Player.cs index f91394224..9ae3f9287 100644 --- a/Source/Game/Entities/Player/Player.cs +++ b/Source/Game/Entities/Player/Player.cs @@ -863,6 +863,9 @@ namespace Game.Entities StopCastingBindSight(); UnsummonPetTemporaryIfAny(); ClearComboPoints(); + ObjectGuid lootGuid = GetLootGUID(); + if (!lootGuid.IsEmpty()) + GetSession().DoLootRelease(lootGuid); Global.OutdoorPvPMgr.HandlePlayerLeaveZone(this, m_zoneUpdateId); Global.BattleFieldMgr.HandlePlayerLeaveZone(this, m_zoneUpdateId); } diff --git a/Source/Game/Handlers/InspectHandler.cs b/Source/Game/Handlers/InspectHandler.cs index fc0b3600e..df0fae4af 100644 --- a/Source/Game/Handlers/InspectHandler.cs +++ b/Source/Game/Handlers/InspectHandler.cs @@ -29,7 +29,7 @@ namespace Game [WorldPacketHandler(ClientOpcodes.Inspect)] void HandleInspect(Inspect inspect) { - Player player = Global.ObjAccessor.FindPlayer(inspect.Target); + Player player = Global.ObjAccessor.GetPlayer(_player, inspect.Target); if (!player) { Log.outDebug(LogFilter.Network, "WorldSession.HandleInspectOpcode: Target {0} not found.", inspect.Target.ToString()); @@ -79,7 +79,7 @@ namespace Game [WorldPacketHandler(ClientOpcodes.QueryInspectAchievements)] void HandleQueryInspectAchievements(QueryInspectAchievements inspect) { - Player player = Global.ObjAccessor.FindPlayer(inspect.Guid); + Player player = Global.ObjAccessor.GetPlayer(_player, inspect.Guid); if (!player) { Log.outDebug(LogFilter.Network, "WorldSession.HandleQueryInspectAchievements: [{0}] inspected unknown Player [{1}]", GetPlayer().GetGUID().ToString(), inspect.Guid.ToString()); diff --git a/Source/Game/Handlers/LootHandler.cs b/Source/Game/Handlers/LootHandler.cs index a851204a0..9399c1026 100644 --- a/Source/Game/Handlers/LootHandler.cs +++ b/Source/Game/Handlers/LootHandler.cs @@ -470,7 +470,8 @@ namespace Game return; } - Player target = Global.ObjAccessor.FindPlayer(target_playerguid); + // player on other map + Player target = Global.ObjAccessor.GetPlayer(_player, target_playerguid); if (!target) { GetPlayer().SendLootError(lootguid, ObjectGuid.Empty, LootError.PlayerNotFound); diff --git a/Source/Game/Handlers/VehicleHandler.cs b/Source/Game/Handlers/VehicleHandler.cs index 6391b185b..bf1770463 100644 --- a/Source/Game/Handlers/VehicleHandler.cs +++ b/Source/Game/Handlers/VehicleHandler.cs @@ -144,7 +144,7 @@ namespace Game [WorldPacketHandler(ClientOpcodes.RideVehicleInteract)] void HandleRideVehicleInteract(RideVehicleInteract packet) { - Player player = Global.ObjAccessor.FindPlayer(packet.Vehicle); + Player player = Global.ObjAccessor.GetPlayer(_player, packet.Vehicle); if (player) { if (!player.GetVehicleKit()) @@ -153,6 +153,9 @@ namespace Game return; if (!player.IsWithinDistInMap(GetPlayer(), SharedConst.InteractionDistance)) return; + // Dont' allow players to enter player vehicle on arena + if (!_player.GetMap() || _player.GetMap().IsBattleArena()) + return; GetPlayer().EnterVehicle(player); } diff --git a/Source/Game/Maps/Instances/InstanceScript.cs b/Source/Game/Maps/Instances/InstanceScript.cs index 0ef755ed0..d40482561 100644 --- a/Source/Game/Maps/Instances/InstanceScript.cs +++ b/Source/Game/Maps/Instances/InstanceScript.cs @@ -719,7 +719,7 @@ namespace Game.Maps if (grp != null) if (grp.isLFGGroup()) { - Global.LFGMgr.FinishDungeon(grp.GetGUID(), dungeonId); + Global.LFGMgr.FinishDungeon(grp.GetGUID(), dungeonId, instance); return; } } diff --git a/Source/Game/Maps/Map.cs b/Source/Game/Maps/Map.cs index 56e8cddfe..4219d4d60 100644 --- a/Source/Game/Maps/Map.cs +++ b/Source/Game/Maps/Map.cs @@ -3228,7 +3228,10 @@ namespace Game.Maps { return (Conversation)_objectsStore.LookupByKey(guid); } - + public Player GetPlayer(ObjectGuid guid) + { + return Global.ObjAccessor.GetPlayer(this, guid); + } public Corpse GetCorpse(ObjectGuid guid) { if (!guid.IsCorpse()) @@ -3681,7 +3684,7 @@ namespace Game.Maps switch (step.sourceGUID.GetHigh()) { case HighGuid.Item: // as well as HIGHGUID_CONTAINER - Player player = Global.ObjAccessor.FindPlayer(step.ownerGUID); + Player player = GetPlayer(step.ownerGUID); if (player != null) source = player.GetItemByGuid(step.sourceGUID); break; @@ -3693,7 +3696,7 @@ namespace Game.Maps source = GetPet(step.sourceGUID); break; case HighGuid.Player: - source = Global.ObjAccessor.FindPlayer(step.sourceGUID); + source = GetPlayer(step.sourceGUID); break; case HighGuid.GameObject: case HighGuid.Transport: @@ -3722,7 +3725,7 @@ namespace Game.Maps target = GetPet(step.targetGUID); break; case HighGuid.Player: - target = Global.ObjAccessor.FindPlayer(step.targetGUID); + target = GetPlayer(step.targetGUID); break; case HighGuid.GameObject: case HighGuid.Transport: diff --git a/Source/Game/Spells/Auras/Aura.cs b/Source/Game/Spells/Auras/Aura.cs index e0bd487c0..15f378e1c 100644 --- a/Source/Game/Spells/Auras/Aura.cs +++ b/Source/Game/Spells/Auras/Aura.cs @@ -928,7 +928,8 @@ namespace Game.Spells if (IsPassive()) return false; - if (GetCasterGUID() != GetOwner().GetGUID()) + // Check if aura is single target, not only spell info + if (GetCasterGUID() != GetOwner().GetGUID() || IsSingleTarget()) if (GetSpellInfo().IsSingleTarget()) return false; @@ -940,6 +941,18 @@ namespace Game.Spells if (HasEffectType(AuraType.ControlVehicle)) return false; + // do not save bind sight auras + if (HasEffectType(AuraType.BindSight)) + return false; + + // no charming auras (taking direct control) + if (HasEffectType(AuraType.ModPossess) || HasEffectType(AuraType.ModPossessPet)) + return false; + + // no charming auras can be saved + if (HasEffectType(AuraType.ModCharm) || HasEffectType(AuraType.AoeCharm)) + return false; + // Incanter's Absorbtion - considering the minimal duration and problems with aura stacking // we skip saving this aura // Also for some reason other auras put as MultiSlot crash core on keeping them after restart, diff --git a/Source/Game/Spells/Spell.cs b/Source/Game/Spells/Spell.cs index 8b84a63d0..91daa874f 100644 --- a/Source/Game/Spells/Spell.cs +++ b/Source/Game/Spells/Spell.cs @@ -4284,7 +4284,7 @@ namespace Game.Spells return SpellCastResult.SpellInProgress; // check if we are using a potion in combat for the 2nd+ time. Cooldown is added only after caster gets out of combat - if (m_caster.ToPlayer().GetLastPotionId() != 0 && m_CastItem && (m_CastItem.IsPotion() || m_spellInfo.IsCooldownStartedOnEvent())) + if (!IsIgnoringCooldowns() && m_caster.ToPlayer().GetLastPotionId() != 0 && m_CastItem && (m_CastItem.IsPotion() || m_spellInfo.IsCooldownStartedOnEvent())) return SpellCastResult.NotReady; } diff --git a/Source/Game/Spells/SpellHistory.cs b/Source/Game/Spells/SpellHistory.cs index 230e76738..608a6ae02 100644 --- a/Source/Game/Spells/SpellHistory.cs +++ b/Source/Game/Spells/SpellHistory.cs @@ -189,6 +189,9 @@ namespace Game.Spells public void HandleCooldowns(SpellInfo spellInfo, uint itemId, Spell spell = null) { + if (spell != null && spell.IsIgnoringCooldowns()) + return; + if (ConsumeCharge(spellInfo.ChargeCategoryId)) return; @@ -207,7 +210,7 @@ namespace Game.Spells } } - if (spellInfo.IsCooldownStartedOnEvent() || spellInfo.IsPassive() || (spell && spell.IsIgnoringCooldowns())) + if (spellInfo.IsCooldownStartedOnEvent() || spellInfo.IsPassive()) return; StartCooldown(spellInfo, itemId, spell); diff --git a/Source/Game/Spells/SpellInfo.cs b/Source/Game/Spells/SpellInfo.cs index 48b418ec2..6714d4b69 100644 --- a/Source/Game/Spells/SpellInfo.cs +++ b/Source/Game/Spells/SpellInfo.cs @@ -3860,8 +3860,7 @@ namespace Game.Spells { return (Effect == SpellEffectName.SummonPlayer) || (Effect == SpellEffectName.SummonRafFriend) - || (Effect == SpellEffectName.Resurrect) - || (Effect == SpellEffectName.SkinPlayerCorpse); + || (Effect == SpellEffectName.Resurrect); } bool IsFarDestTargetEffect()