diff --git a/Source/Framework/Constants/Spells/SpellConst.cs b/Source/Framework/Constants/Spells/SpellConst.cs index 09434bb44..a24cee0d5 100644 --- a/Source/Framework/Constants/Spells/SpellConst.cs +++ b/Source/Framework/Constants/Spells/SpellConst.cs @@ -2122,7 +2122,7 @@ namespace Framework.Constants Unk17 = 0x20000, // 17 ActivatesRequiredShapeshift = 0x40000, // 18 Unk19 = 0x80000, // 19 - Unk20 = 0x100000, // 20 + PeriodicRefreshExtendsDuration = 0x100000, // 20 Periodic Refresh Extends Duration Unk21 = 0x200000, // 21 Unk22 = 0x400000, // 22 Unk23 = 0x800000, // 23 diff --git a/Source/Game/Achievements/AchievementManager.cs b/Source/Game/Achievements/AchievementManager.cs index 230b8a176..a72c5e002 100644 --- a/Source/Game/Achievements/AchievementManager.cs +++ b/Source/Game/Achievements/AchievementManager.cs @@ -63,13 +63,6 @@ namespace Game.Achievements return false; } - if (achievement.InstanceID != -1 && referencePlayer.GetMapId() != achievement.InstanceID) - { - Log.outTrace(LogFilter.Achievement, "CanUpdateCriteriaTree: (Id: {0} Type {1} Achievement {2}) Wrong map", - criteria.Id, criteria.Entry.Type, achievement.Id); - return false; - } - if ((achievement.Faction == AchievementFaction.Horde && referencePlayer.GetTeam() != Team.Horde) || (achievement.Faction == AchievementFaction.Alliance && referencePlayer.GetTeam() != Team.Alliance)) { @@ -360,40 +353,6 @@ namespace Game.Achievements } } - public void ResetCriteria(CriteriaFailEvent failEvent, uint failAsset, bool evenIfCriteriaComplete) - { - Log.outDebug(LogFilter.Achievement, $"ResetAchievementCriteria({failEvent}, {failAsset}, {evenIfCriteriaComplete})"); - - // Disable for GameMasters with GM-mode enabled or for players that don't have the related RBAC permission - if (_owner.IsGameMaster() || _owner.GetSession().HasPermission(RBACPermissions.CannotEarnAchievements)) - return; - - var achievementCriteriaList = Global.CriteriaMgr.GetCriteriaByFailEvent(failEvent, (int)failAsset); - if (!achievementCriteriaList.Empty()) - { - foreach (Criteria achievementCriteria in achievementCriteriaList) - { - - var trees = Global.CriteriaMgr.GetCriteriaTreesByCriteria(achievementCriteria.Id); - bool allComplete = true; - foreach (CriteriaTree tree in trees) - { - // don't update already completed criteria if not forced or achievement already complete - if (!(IsCompletedCriteriaTree(tree) && !evenIfCriteriaComplete) || !HasAchieved(tree.Achievement.Id)) - { - allComplete = false; - break; - } - } - - if (allComplete) - continue; - - RemoveCriteriaProgress(achievementCriteria); - } - } - } - public override void SendAllData(Player receiver) { AllAccountCriteria allAccountCriteria = new(); diff --git a/Source/Game/Achievements/CriteriaHandler.cs b/Source/Game/Achievements/CriteriaHandler.cs index abee4ff5e..3b722b1e6 100644 --- a/Source/Game/Achievements/CriteriaHandler.cs +++ b/Source/Game/Achievements/CriteriaHandler.cs @@ -24,7 +24,7 @@ namespace Game.Achievements public class CriteriaHandler { protected Dictionary _criteriaProgress = new(); - Dictionary _timeCriteriaTrees = new(); + Dictionary _startedCriteria = new(); public virtual void Reset() { @@ -444,75 +444,89 @@ namespace Game.Achievements } } - public void UpdateTimedCriteria(uint timeDiff) + public void UpdateTimedCriteria(TimeSpan timeDiff) { - if (!_timeCriteriaTrees.Empty()) + foreach (var key in _startedCriteria.Keys.ToList()) { - foreach (var key in _timeCriteriaTrees.Keys.ToList()) + // Time is up, remove timer and reset progress + if (_startedCriteria[key] <= timeDiff) { - var value = _timeCriteriaTrees[key]; - // Time is up, remove timer and reset progress - if (value <= timeDiff) - { - CriteriaTree criteriaTree = Global.CriteriaMgr.GetCriteriaTree(key); - if (criteriaTree.Criteria != null) - RemoveCriteriaProgress(criteriaTree.Criteria); + RemoveCriteriaProgress(Global.CriteriaMgr.GetCriteria(key)); - _timeCriteriaTrees.Remove(key); - } - else - { - _timeCriteriaTrees[key] -= timeDiff; - } + _startedCriteria.Remove(key); } - } + else + _startedCriteria[key] -= timeDiff; + } } - public void StartCriteriaTimer(CriteriaStartEvent startEvent, uint entry, uint timeLost = 0) + public void StartCriteria(CriteriaStartEvent startEvent, uint entry, TimeSpan timeLost = default) { - List criteriaList = Global.CriteriaMgr.GetTimedCriteriaByType(startEvent); + List criteriaList = Global.CriteriaMgr.GetCriteriaByStartEvent(startEvent, (int)entry); + if (criteriaList.Empty()) + return; + foreach (Criteria criteria in criteriaList) { - if (criteria.Entry.StartAsset != entry) + TimeSpan timeLimit = TimeSpan.MaxValue; // this value is for criteria that have a start event requirement but no time limit + if (criteria.Entry.StartTimer != 0) + timeLimit = TimeSpan.FromSeconds(criteria.Entry.StartTimer); + + timeLimit -= timeLost; + + if (timeLimit <= TimeSpan.Zero) continue; List trees = Global.CriteriaMgr.GetCriteriaTreesByCriteria(criteria.Id); - bool canStart = false; - foreach (CriteriaTree tree in trees) - { - if ((!_timeCriteriaTrees.ContainsKey(tree.Id) || criteria.Entry.GetFlags().HasFlag(CriteriaFlags.ResetOnStart)) && !IsCompletedCriteriaTree(tree)) - { - // Start the timer - if (criteria.Entry.StartTimer * Time.InMilliseconds > timeLost) - { - _timeCriteriaTrees[tree.Id] = (uint)(criteria.Entry.StartTimer * Time.InMilliseconds - timeLost); - canStart = true; - } - } - } + bool canStart = trees.Any(tree => !IsCompletedCriteriaTree(tree)); if (!canStart) continue; + bool isNew = _startedCriteria.TryAdd(criteria.Id, timeLimit); + if (!isNew) + { + if (!criteria.Entry.GetFlags().HasFlag(CriteriaFlags.ResetOnStart)) + continue; + + _startedCriteria[criteria.Id] = timeLimit; + } + // and at client too SetCriteriaProgress(criteria, 0, null, ProgressType.Set); } } - public void RemoveCriteriaTimer(CriteriaStartEvent startEvent, uint entry) + public void FailCriteria(CriteriaFailEvent failEvent, uint asset) { - List criteriaList = Global.CriteriaMgr.GetTimedCriteriaByType(startEvent); + List criteriaList = Global.CriteriaMgr.GetCriteriaByFailEvent(failEvent, (int)asset); + if (criteriaList.Empty()) + return; + foreach (Criteria criteria in criteriaList) { - if (criteria.Entry.StartAsset != entry) - continue; + _startedCriteria.Remove(criteria.Id); List trees = Global.CriteriaMgr.GetCriteriaTreesByCriteria(criteria.Id); - // Remove the timer from all trees - foreach (CriteriaTree tree in trees) - _timeCriteriaTrees.Remove(tree.Id); + bool allTreesFullyComplete = trees.All(tree => + { + CriteriaTree root = tree; + CriteriaTree parent = Global.CriteriaMgr.GetCriteriaTree(root.Entry.Parent); + if (parent != null) + { + do + { + root = parent; + parent = Global.CriteriaMgr.GetCriteriaTree(root.Entry.Parent); + } while (parent != null); + } + + return IsCompletedCriteriaTree(root); + }); + + if (allTreesFullyComplete) + continue; - // remove progress RemoveCriteriaProgress(criteria); } } @@ -524,29 +538,6 @@ namespace Game.Achievements public void SetCriteriaProgress(Criteria criteria, ulong changeValue, Player referencePlayer, ProgressType progressType = ProgressType.Set) { - // Don't allow to cheat - doing timed criteria without timer active - List trees = null; - if (criteria.Entry.StartTimer != 0) - { - trees = Global.CriteriaMgr.GetCriteriaTreesByCriteria(criteria.Id); - if (trees.Empty()) - return; - - bool hasTreeForTimed = false; - foreach (CriteriaTree tree in trees) - { - var timedIter = _timeCriteriaTrees.LookupByKey(tree.Id); - if (timedIter != 0) - { - hasTreeForTimed = true; - break; - } - } - - if (!hasTreeForTimed) - return; - } - Log.outDebug(LogFilter.Achievement, "SetCriteriaProgress({0}, {1}) for {2}", criteria.Id, changeValue, GetOwnerInfo()); CriteriaProgress progress = GetCriteriaProgress(criteria); @@ -596,20 +587,18 @@ namespace Game.Achievements TimeSpan timeElapsed = TimeSpan.Zero; if (criteria.Entry.StartTimer != 0) { - Cypher.Assert(trees != null); - - foreach (CriteriaTree tree in trees) + if (_startedCriteria.TryGetValue(criteria.Id, out TimeSpan startedTime)) { - var timed = _timeCriteriaTrees.LookupByKey(tree.Id); - if (timed != 0) - { - // Client expects this in packet - timeElapsed = TimeSpan.FromSeconds(criteria.Entry.StartTimer - (timed / Time.InMilliseconds)); + // Client expects this in packet + timeElapsed = TimeSpan.FromSeconds(criteria.Entry.StartTimer) - startedTime; - // Remove the timer, we wont need it anymore - if (IsCompletedCriteriaTree(tree)) - _timeCriteriaTrees.Remove(tree.Id); - } + // Remove the timer, we wont need it anymore + var trees = Global.CriteriaMgr.GetCriteriaTreesByCriteria(criteria.Id); + + bool allTreesCompleted = trees.All(IsCompletedCriteriaTree); + + if (allTreesCompleted) + _startedCriteria.Remove(criteria.Id); } } @@ -626,7 +615,8 @@ namespace Game.Achievements SendCriteriaProgressRemoved(criteria.Id); - _criteriaProgress.Remove(criteria.Id); + _criteriaProgress[criteria.Id].Counter = 0; + _criteriaProgress[criteria.Id].Changed = true; } public bool IsCompletedCriteriaTree(CriteriaTree tree) @@ -888,22 +878,8 @@ namespace Game.Achievements bool ConditionsSatisfied(Criteria criteria, Player referencePlayer) { - if (criteria.Entry.FailEvent == 0) - return true; - - switch ((CriteriaFailEvent)criteria.Entry.FailEvent) - { - case CriteriaFailEvent.LeaveBattleground: - if (!referencePlayer.InBattleground()) - return false; - break; - case CriteriaFailEvent.ModifyPartyStatus: - if (referencePlayer.GetGroup() != null) - return false; - break; - default: - break; - } + if (criteria.Entry.StartEvent != 0 && !_startedCriteria.ContainsKey(criteria.Id)) + return false; return true; } @@ -3720,7 +3696,7 @@ namespace Game.Achievements MultiMap[] _scenarioCriteriasByTypeAndScenarioId = new MultiMap[(int)CriteriaType.Count]; MultiMap _questObjectiveCriteriasByType = new(); - MultiMap _criteriasByTimedType = new(); + MultiMap[] _criteriasByStartEvent = new MultiMap[(int)CriteriaStartEvent.Max]; MultiMap[] _criteriasByFailEvent = new MultiMap[(int)CriteriaFailEvent.Max]; CriteriaManager() @@ -3943,7 +3919,7 @@ namespace Game.Achievements } if (criteriaEntry.StartTimer != 0) - _criteriasByTimedType.Add((CriteriaStartEvent)criteriaEntry.StartEvent, criteria); + _criteriasByStartEvent[criteriaEntry.StartEvent].Add((int)criteriaEntry.StartAsset, criteria); if (criteriaEntry.FailEvent != 0) _criteriasByFailEvent[criteriaEntry.FailEvent].Add((int)criteriaEntry.FailAsset, criteria); @@ -4083,6 +4059,16 @@ namespace Game.Achievements { return _scenarioCriteriasByTypeAndScenarioId[(int)type].LookupByKey(scenarioId); } + + public List GetCriteriaByStartEvent(CriteriaStartEvent startEvent, int asset) + { + return _criteriasByStartEvent[(int)startEvent].LookupByKey(asset); + } + + public List GetCriteriaByFailEvent(CriteriaFailEvent failEvent, int asset) + { + return _criteriasByFailEvent[(int)failEvent].LookupByKey(asset); + } public List GetGuildCriteriaByType(CriteriaType type) { @@ -4099,16 +4085,6 @@ namespace Game.Achievements return _criteriaTreeByCriteria.LookupByKey(criteriaId); } - public List GetTimedCriteriaByType(CriteriaStartEvent startEvent) - { - return _criteriasByTimedType.LookupByKey(startEvent); - } - - public List GetCriteriaByFailEvent(CriteriaFailEvent failEvent, int asset) - { - return _criteriasByFailEvent[(int)failEvent].LookupByKey(asset); - } - public CriteriaDataSet GetCriteriaDataSet(Criteria criteria) { return _criteriaDataMap.LookupByKey(criteria.Id); diff --git a/Source/Game/Arenas/Arena.cs b/Source/Game/Arenas/Arena.cs index 1ead61a89..80b7186a4 100644 --- a/Source/Game/Arenas/Arena.cs +++ b/Source/Game/Arenas/Arena.cs @@ -237,6 +237,7 @@ namespace Game.Arenas { // update achievement BEFORE personal rating update uint rating = player.GetArenaPersonalRating(winnerArenaTeam.GetSlot()); + player.StartCriteria(CriteriaStartEvent.WinRankedArenaMatchWithTeamSize, 0); player.UpdateCriteria(CriteriaType.WinAnyRankedArena, rating != 0 ? rating : 1); player.UpdateCriteria(CriteriaType.WinArena, GetMapId()); @@ -266,7 +267,7 @@ namespace Game.Arenas loserArenaTeam.MemberLost(player, winnerMatchmakerRating, loserMatchmakerChange); // Arena lost => reset the win_rated_arena having the "no_lose" condition - player.ResetCriteria(CriteriaFailEvent.LoseRankedArenaMatchWithTeamSize, 0); + player.FailCriteria(CriteriaFailEvent.LoseRankedArenaMatchWithTeamSize, 0); } } diff --git a/Source/Game/BattleGrounds/BattleGround.cs b/Source/Game/BattleGrounds/BattleGround.cs index ba892a2e9..215de378a 100644 --- a/Source/Game/BattleGrounds/BattleGround.cs +++ b/Source/Game/BattleGrounds/BattleGround.cs @@ -352,9 +352,12 @@ namespace Game.BattleGrounds foreach (var (guid, _) in GetPlayers()) { - Player player = Global.ObjAccessor.FindPlayer(guid); + Player player = Global.ObjAccessor.GetPlayer(GetBgMap(), guid); if (player != null) + { + player.StartCriteria(CriteriaStartEvent.StartBattleground, GetBgMap().GetId()); player.AtStartOfEncounter(EncounterType.Battleground); + } } // Remove preparation @@ -874,7 +877,7 @@ namespace Game.BattleGrounds player.SetBGTeam(0); // remove all criterias on bg leave - player.ResetCriteria(CriteriaFailEvent.LeaveBattleground, GetMapId(), true); + player.FailCriteria(CriteriaFailEvent.LeaveBattleground, 0); if (Transport) player.TeleportToBGEntryPoint(); @@ -1041,10 +1044,6 @@ namespace Game.BattleGrounds } } - // reset all map criterias on map enter - if (!isInBattleground) - player.ResetCriteria(CriteriaFailEvent.LeaveBattleground, GetMapId(), true); - // setup BG group membership PlayerAddedToBGCheckIfBGIsRunning(player); AddOrSetPlayerToCorrectBgGroup(player, team); diff --git a/Source/Game/BattleGrounds/Zones/WarsongGluch.cs b/Source/Game/BattleGrounds/Zones/WarsongGluch.cs index 505aef043..c39da30dd 100644 --- a/Source/Game/BattleGrounds/Zones/WarsongGluch.cs +++ b/Source/Game/BattleGrounds/Zones/WarsongGluch.cs @@ -439,7 +439,7 @@ namespace Game.BattleGrounds.Zones //update world state to show correct flag carrier UpdateFlagState(Team.Horde, WSGFlagState.OnPlayer); player.CastSpell(player, WSGSpellId.SilverwingFlag, true); - player.StartCriteriaTimer(CriteriaStartEvent.BeSpellTarget, WSGSpellId.SilverwingFlagPicked); + //player.StartCriteria(CriteriaStartEvent.BeSpellTarget, WSGSpellId.SilverwingFlagPicked); if (_flagState[1] == WSGFlagState.OnPlayer) _bothFlagsKept = true; @@ -461,7 +461,7 @@ namespace Game.BattleGrounds.Zones //update world state to show correct flag carrier UpdateFlagState(Team.Alliance, WSGFlagState.OnPlayer); player.CastSpell(player, WSGSpellId.WarsongFlag, true); - player.StartCriteriaTimer(CriteriaStartEvent.BeSpellTarget, WSGSpellId.WarsongFlagPicked); + //player.StartCriteriaTimer(CriteriaStartEvent.BeSpellTarget, WSGSpellId.WarsongFlagPicked); if (_flagState[0] == WSGFlagState.OnPlayer) _bothFlagsKept = true; diff --git a/Source/Game/Entities/Player/Player.Achievement.cs b/Source/Game/Entities/Player/Player.Achievement.cs index 632486de9..4e3c11855 100644 --- a/Source/Game/Entities/Player/Player.Achievement.cs +++ b/Source/Game/Entities/Player/Player.Achievement.cs @@ -6,6 +6,7 @@ using Game.Achievements; using Game.DataStorage; using Game.Guilds; using Game.Scenarios; +using System; using System.Collections.Generic; namespace Game.Entities @@ -36,20 +37,16 @@ namespace Game.Entities { return m_achievementSys.HasAchieved(achievementId); } - public void StartCriteriaTimer(CriteriaStartEvent startEvent, uint entry, uint timeLost = 0) + + public void StartCriteria(CriteriaStartEvent startEvent, uint entry, TimeSpan timeLost = default) { - m_achievementSys.StartCriteriaTimer(startEvent, entry, timeLost); + m_achievementSys.StartCriteria(startEvent, entry, timeLost); } - public void RemoveCriteriaTimer(CriteriaStartEvent startEvent, uint entry) + public void FailCriteria(CriteriaFailEvent failEvent, uint failAsset) { - m_achievementSys.RemoveCriteriaTimer(startEvent, entry); - } - - public void ResetCriteria(CriteriaFailEvent failEvent, uint failAsset, bool evenIfCriteriaComplete = false) - { - m_achievementSys.ResetCriteria(failEvent, failAsset, evenIfCriteriaComplete); - m_questObjectiveCriteriaMgr.ResetCriteria(failEvent, failAsset, evenIfCriteriaComplete); + m_achievementSys.FailCriteria(failEvent, failAsset); + m_questObjectiveCriteriaMgr.FailCriteria(failEvent, failAsset); } public void UpdateCriteria(CriteriaType type, ulong miscValue1 = 0, ulong miscValue2 = 0, ulong miscValue3 = 0, WorldObject refe = null) diff --git a/Source/Game/Entities/Player/Player.Quest.cs b/Source/Game/Entities/Player/Player.Quest.cs index cb06bb46f..b74d2cc6c 100644 --- a/Source/Game/Entities/Player/Player.Quest.cs +++ b/Source/Game/Entities/Player/Player.Quest.cs @@ -194,6 +194,8 @@ namespace Game.Entities if (_garrison != null) _garrison.ResetFollowerActivationLimit(); + + FailCriteria(CriteriaFailEvent.DailyQuestsCleared, 0); } public void ResetWeeklyQuestStatus() @@ -837,7 +839,7 @@ namespace Game.Entities m_QuestStatusSave[questId] = QuestSaveType.Default; - StartCriteriaTimer(CriteriaStartEvent.AcceptQuest, questId); + StartCriteria(CriteriaStartEvent.AcceptQuest, questId); SendQuestUpdate(questId); @@ -1146,6 +1148,7 @@ namespace Game.Entities SetDailyQuestStatus(questId); if (quest.IsDaily()) { + StartCriteria(CriteriaStartEvent.CompleteDailyQuest, 0); UpdateCriteria(CriteriaType.CompleteDailyQuest, questId); UpdateCriteria(CriteriaType.CompleteAnyDailyQuestPerDay, questId); } @@ -2393,7 +2396,7 @@ namespace Game.Entities real_entry = killed.GetEntry(); } - StartCriteriaTimer(CriteriaStartEvent.KillNPC, real_entry); // MUST BE CALLED FIRST + StartCriteria(CriteriaStartEvent.KillNPC, real_entry); // MUST BE CALLED FIRST UpdateCriteria(CriteriaType.KillCreature, real_entry, addKillCount, 0, killed); UpdateQuestObjectiveProgress(QuestObjectiveType.Monster, (int)entry, 1, guid); @@ -2401,6 +2404,7 @@ namespace Game.Entities public void KilledPlayerCredit(ObjectGuid victimGuid) { + StartCriteria(CriteriaStartEvent.KillPlayer, 0); UpdateQuestObjectiveProgress(QuestObjectiveType.PlayerKills, 0, 1, victimGuid); } diff --git a/Source/Game/Entities/Player/Player.cs b/Source/Game/Entities/Player/Player.cs index d59deec8d..f13222c12 100644 --- a/Source/Game/Entities/Player/Player.cs +++ b/Source/Game/Entities/Player/Player.cs @@ -416,7 +416,7 @@ namespace Game.Entities } } - m_achievementSys.UpdateTimedCriteria(diff); + m_achievementSys.UpdateTimedCriteria(TimeSpan.FromMilliseconds(diff)); if (HasUnitState(UnitState.MeleeAttacking) && !HasUnitState(UnitState.Casting | UnitState.Charging)) { @@ -662,7 +662,7 @@ namespace Game.Entities UpdateCriteria(CriteriaType.DieInInstance, 1); // reset all death criterias - ResetCriteria(CriteriaFailEvent.Death, 0); + FailCriteria(CriteriaFailEvent.Death, 0); } base.SetDeathState(s); @@ -5365,6 +5365,7 @@ namespace Game.Entities DB.Characters.CommitTransaction(trans); } + StartCriteria(CriteriaStartEvent.ReachLevel, level); UpdateCriteria(CriteriaType.ReachLevel); UpdateCriteria(CriteriaType.ActivelyReachLevel, level); diff --git a/Source/Game/Entities/Unit/Unit.Spells.cs b/Source/Game/Entities/Unit/Unit.Spells.cs index 60913b759..f1c7c7d11 100644 --- a/Source/Game/Entities/Unit/Unit.Spells.cs +++ b/Source/Game/Entities/Unit/Unit.Spells.cs @@ -3754,8 +3754,12 @@ namespace Game.Entities Player player = ToPlayer(); if (player != null) + { if (Global.ConditionMgr.IsSpellUsedInSpellClickConditions(aurApp.GetBase().GetId())) player.UpdateVisibleGameobjectsOrSpellClicks(); + + player.FailCriteria(CriteriaFailEvent.LoseAura, aurApp.GetBase().GetId()); + } } public void _UnapplyAura(AuraApplication aurApp, AuraRemoveMode removeMode) @@ -3970,8 +3974,14 @@ namespace Game.Entities Player player = ToPlayer(); if (player != null) + { if (Global.ConditionMgr.IsSpellUsedInSpellClickConditions(aurApp.GetBase().GetId())) - player.UpdateVisibleGameobjectsOrSpellClicks(); + player.UpdateVisibleGameobjectsOrSpellClicks(); + + player.FailCriteria(CriteriaFailEvent.GainAura, aurApp.GetBase().GetId()); + player.StartCriteria(CriteriaStartEvent.GainAura, aurApp.GetBase().GetId()); + player.UpdateCriteria(CriteriaType.GainAura, aurApp.GetBase().GetId()); + } } public void _AddAura(UnitAura aura, Unit caster) @@ -4370,10 +4380,19 @@ namespace Game.Entities public void _RegisterAuraEffect(AuraEffect aurEff, bool apply) { if (apply) + { m_modAuras.Add(aurEff.GetAuraType(), aurEff); + Player player = ToPlayer(); + if (player != null) + { + player.StartCriteria(CriteriaStartEvent.GainAuraEffect, (uint)aurEff.GetAuraType()); + player.FailCriteria(CriteriaFailEvent.GainAuraEffect, (uint)aurEff.GetAuraType()); + } + } else m_modAuras.Remove(aurEff.GetAuraType(), aurEff); } + public float GetTotalAuraModValue(UnitMods unitMod) { if (unitMod >= UnitMods.End) diff --git a/Source/Game/Events/GameEventSender.cs b/Source/Game/Events/GameEventSender.cs index 26d6440ba..04a945ef5 100644 --- a/Source/Game/Events/GameEventSender.cs +++ b/Source/Game/Events/GameEventSender.cs @@ -46,8 +46,8 @@ namespace Game Map map = source.GetMap(); if (map.Instanceable()) { - source.StartCriteriaTimer(CriteriaStartEvent.SendEvent, gameEventId); - source.ResetCriteria(CriteriaFailEvent.SendEvent, gameEventId); + source.FailCriteria(CriteriaFailEvent.SendEvent, gameEventId); + source.StartCriteria(CriteriaStartEvent.SendEvent, gameEventId); } source.UpdateCriteria(CriteriaType.PlayerTriggerGameEvent, gameEventId, 0, 0, source); diff --git a/Source/Game/Groups/Group.cs b/Source/Game/Groups/Group.cs index b6553ac13..2270f160b 100644 --- a/Source/Game/Groups/Group.cs +++ b/Source/Game/Groups/Group.cs @@ -476,6 +476,8 @@ namespace Game.Groups if (IsRaidGroup()) player.UpdateVisibleGameobjectsOrSpellClicks(); + player.FailCriteria(CriteriaFailEvent.ModifyPartyStatus, 0); + { // Broadcast new player group member fields to rest of the group UpdateData groupData = new(player.GetMapId()); @@ -544,6 +546,9 @@ namespace Game.Groups if (IsLFGGroup() && method == RemoveMethod.Kick) return m_memberSlots.Count != 0; + if (player != null) + player.FailCriteria(CriteriaFailEvent.ModifyPartyStatus, 0); + // remove member and change leader (if need) only if strong more 2 members _before_ member remove (BG/BF allow 1 member group) if (GetMembersCount() > ((IsBGGroup() || IsLFGGroup() || IsBFGroup()) ? 1 : 2)) { diff --git a/Source/Game/Handlers/QuestHandler.cs b/Source/Game/Handlers/QuestHandler.cs index df5145d2f..4fd229f1a 100644 --- a/Source/Game/Handlers/QuestHandler.cs +++ b/Source/Game/Handlers/QuestHandler.cs @@ -437,7 +437,6 @@ namespace Game GetPlayer().TakeQuestSourceItem(questId, true); // remove quest src item from player GetPlayer().AbandonQuest(questId); // remove all quest items player received before abandoning quest. Note, this does not remove normal drop items that happen to be quest requirements. GetPlayer().RemoveActiveQuest(questId); - GetPlayer().RemoveCriteriaTimer(CriteriaStartEvent.AcceptQuest, questId); Log.outInfo(LogFilter.Network, "Player {0} abandoned quest {1}", GetPlayer().GetGUID().ToString(), questId); diff --git a/Source/Game/Quest/QuestObjectiveCriteriaManager.cs b/Source/Game/Quest/QuestObjectiveCriteriaManager.cs index ee18dbcb8..d0eee5030 100644 --- a/Source/Game/Quest/QuestObjectiveCriteriaManager.cs +++ b/Source/Game/Quest/QuestObjectiveCriteriaManager.cs @@ -150,36 +150,6 @@ namespace Game } } - public void ResetCriteria(CriteriaFailEvent failEvent, uint failAsset, bool evenIfCriteriaComplete) - { - Log.outDebug(LogFilter.Player, $"QuestObjectiveCriteriaMgr.ResetCriteria({failEvent}, {failAsset}, {evenIfCriteriaComplete})"); - - // disable for gamemasters with GM-mode enabled - if (_owner.IsGameMaster()) - return; - - var playerCriteriaList = Global.CriteriaMgr.GetCriteriaByFailEvent(failEvent, (int)failAsset); - foreach (Criteria playerCriteria in playerCriteriaList) - { - var trees = Global.CriteriaMgr.GetCriteriaTreesByCriteria(playerCriteria.Id); - bool allComplete = true; - foreach (CriteriaTree tree in trees) - { - // don't update already completed criteria if not forced - if (!(IsCompletedCriteriaTree(tree) && !evenIfCriteriaComplete)) - { - allComplete = false; - break; - } - } - - if (allComplete) - continue; - - RemoveCriteriaProgress(playerCriteria); - } - } - public void ResetCriteriaTree(uint criteriaTreeId) { CriteriaTree tree = Global.CriteriaMgr.GetCriteriaTree(criteriaTreeId); diff --git a/Source/Game/Scenarios/Scenario.cs b/Source/Game/Scenarios/Scenario.cs index 517dd1e3d..a0db7294e 100644 --- a/Source/Game/Scenarios/Scenario.cs +++ b/Source/Game/Scenarios/Scenario.cs @@ -97,7 +97,15 @@ namespace Game.Scenarios { _currentstep = step; if (step != null) + { SetStepState(step, ScenarioStepState.InProgress); + foreach (ObjectGuid guid in _players) + { + Player player = Global.ObjAccessor.GetPlayer(_map, guid); + if (player != null) + player.StartCriteria(CriteriaStartEvent.BeginScenarioStep, step.Id); + } + } ScenarioState scenarioState = new(); BuildScenarioState(scenarioState); diff --git a/Source/Game/Spells/Spell.cs b/Source/Game/Spells/Spell.cs index c78a5effe..2f8741249 100644 --- a/Source/Game/Spells/Spell.cs +++ b/Source/Game/Spells/Spell.cs @@ -2164,17 +2164,14 @@ namespace Game.Spells Player player = unit.ToPlayer(); if (player != null) { - player.StartCriteriaTimer(CriteriaStartEvent.BeSpellTarget, m_spellInfo.Id); + player.FailCriteria(CriteriaFailEvent.BeSpellTarget, m_spellInfo.Id); + player.StartCriteria(CriteriaStartEvent.BeSpellTarget, m_spellInfo.Id); player.UpdateCriteria(CriteriaType.BeSpellTarget, m_spellInfo.Id, 0, 0, m_caster); - player.UpdateCriteria(CriteriaType.GainAura, m_spellInfo.Id); } Player casterPlayer = m_caster.ToPlayer(); if (casterPlayer != null) - { - casterPlayer.StartCriteriaTimer(CriteriaStartEvent.CastSpell, m_spellInfo.Id); casterPlayer.UpdateCriteria(CriteriaType.LandTargetedSpellOnTarget, m_spellInfo.Id, 0, 0, unit); - } if (m_caster != unit) { @@ -2915,10 +2912,12 @@ namespace Game.Spells { if (!Convert.ToBoolean(_triggeredCastFlags & TriggerCastFlags.IgnoreCastItem) && m_CastItem != null) { - player.StartCriteriaTimer(CriteriaStartEvent.UseItem, m_CastItem.GetEntry()); + player.StartCriteria(CriteriaStartEvent.UseItem, m_CastItem.GetEntry()); player.UpdateCriteria(CriteriaType.UseItem, m_CastItem.GetEntry()); } + player.FailCriteria(CriteriaFailEvent.CastSpell, m_spellInfo.Id); + player.StartCriteria(CriteriaStartEvent.CastSpell, m_spellInfo.Id); player.UpdateCriteria(CriteriaType.CastSpell, m_spellInfo.Id); }