Core/Quests: Improved criteria tree quest objective type

* Fixed _completedObjectives not being cleaned when adding quest
* Fixed objective credit being granted if just the criteria tree row containing criteria id was completed (instead of the entire tree linked to objective)
* Retroactively grant progress on quest accept for criteria types that require action that cannot be repeated (such as learning a spell)
Port From (https://github.com/TrinityCore/TrinityCore/commit/4e89a302fcce7644bcd8cf239edad3b409950438)
This commit is contained in:
Hondacrx
2025-02-24 11:21:04 -05:00
parent 0d5c0b572d
commit 0e050f6c54
3 changed files with 795 additions and 779 deletions
+26 -21
View File
@@ -70,18 +70,21 @@ namespace Game.Achievements
List<Criteria> criteriaList = GetCriteriaByType(type, (uint)miscValue1);
foreach (Criteria criteria in criteriaList)
UpdateCriteria(criteria, miscValue1, miscValue2, miscValue3, refe, referencePlayer);
}
public void UpdateCriteria(Criteria criteria, ulong miscValue1 = 0, ulong miscValue2 = 0, ulong miscValue3 = 0, WorldObject refe = null, Player referencePlayer = null)
{
List<CriteriaTree> trees = Global.CriteriaMgr.GetCriteriaTreesByCriteria(criteria.Id);
var trees = Global.CriteriaMgr.GetCriteriaTreesByCriteria(criteria.Id);
if (!CanUpdateCriteria(criteria, trees, miscValue1, miscValue2, miscValue3, refe, referencePlayer))
continue;
return;
// requirements not found in the dbc
CriteriaDataSet data = Global.CriteriaMgr.GetCriteriaDataSet(criteria);
if (data != null)
if (!data.Meets(referencePlayer, refe, (uint)miscValue1, (uint)miscValue2))
continue;
if (data != null && !data.Meets(referencePlayer, refe, (uint)miscValue1, (uint)miscValue2))
return;
switch (type)
switch (criteria.Entry.Type)
{
// std. case: increment at 1
case CriteriaType.WinBattleground:
@@ -123,7 +126,7 @@ namespace Game.Achievements
case CriteriaType.KillPlayer:
case CriteriaType.DeliveredKillingBlow:
case CriteriaType.PVPKillInArea:
case CriteriaType.WinArena: // This also behaves like CriteriaType.WinAnyRankedArena
case CriteriaType.WinArena: // This also behaves like CriteriaType::WinAnyRankedArena
case CriteriaType.ParticipateInArena:
case CriteriaType.PlayerTriggerGameEvent:
case CriteriaType.Login:
@@ -202,7 +205,7 @@ namespace Game.Achievements
SetCriteriaProgress(criteria, maxSkillvalue, referencePlayer);
break;
case CriteriaType.CompleteQuestsCount:
SetCriteriaProgress(criteria, (uint)referencePlayer.GetRewardedQuestCount(), referencePlayer);
SetCriteriaProgress(criteria, (ulong)referencePlayer.GetRewardedQuestCount(), referencePlayer);
break;
case CriteriaType.CompleteAnyDailyQuestPerDay:
{
@@ -213,8 +216,8 @@ namespace Game.Achievements
{
// reset if player missed one day.
if (progress != null && progress.Date < (nextDailyResetTime - 2 * Time.Day))
SetCriteriaProgress(criteria, 0, referencePlayer);
continue;
SetCriteriaProgress(criteria, 0, referencePlayer, ProgressType.Set);
return;
}
ProgressType progressType;
@@ -229,7 +232,7 @@ namespace Game.Achievements
progressType = ProgressType.Accumulate;
else
// last progress is within the day before the reset => Already counted today.
continue;
return;
SetCriteriaProgress(criteria, 1, referencePlayer, progressType);
break;
@@ -245,13 +248,14 @@ namespace Game.Achievements
uint counter = 0;
var rewQuests = referencePlayer.GetRewardedQuests();
foreach (var id in rewQuests)
foreach (uint rewQuest in rewQuests)
{
Quest quest = Global.ObjectMgr.GetQuestTemplate(id);
Quest quest = Global.ObjectMgr.GetQuestTemplate(rewQuest);
if (quest != null && quest.QuestSortID >= 0 && quest.QuestSortID == criteria.Entry.Asset)
++counter;
}
SetCriteriaProgress(criteria, counter, referencePlayer);
SetCriteriaProgress(criteria, counter, referencePlayer, ProgressType.Highest);
}
break;
}
@@ -286,7 +290,7 @@ namespace Game.Achievements
{
int reputation = referencePlayer.GetReputationMgr().GetReputation(criteria.Entry.Asset);
if (reputation > 0)
SetCriteriaProgress(criteria, (uint)reputation, referencePlayer);
SetCriteriaProgress(criteria, (ulong)reputation, referencePlayer);
break;
}
case CriteriaType.TotalExaltedFactions:
@@ -299,9 +303,9 @@ namespace Game.Achievements
foreach (var (spellId, _) in referencePlayer.GetSpellMap())
{
var bounds = Global.SpellMgr.GetSkillLineAbilityMapBounds(spellId);
foreach (var skill in bounds)
foreach (var skillLineRecord in bounds)
{
if (skill.SkillLine == criteria.Entry.Asset)
if (skillLineRecord.SkillLine == criteria.Entry.Asset)
{
// do not add couter twice if by any chance skill is listed twice in dbc (eg. skill 777 and spell 22717)
++spellCount;
@@ -309,6 +313,7 @@ namespace Game.Achievements
}
}
}
SetCriteriaProgress(criteria, spellCount, referencePlayer);
break;
}
@@ -329,7 +334,7 @@ namespace Game.Achievements
break;
case CriteriaType.EarnAchievementPoints:
if (miscValue1 == 0)
continue;
return;
SetCriteriaProgress(criteria, miscValue1, referencePlayer, ProgressType.Accumulate);
break;
case CriteriaType.EarnPersonalArenaRating:
@@ -339,13 +344,12 @@ namespace Game.Achievements
if (miscValue1 != 0)
{
if (miscValue2 != reqTeamType)
continue;
return;
SetCriteriaProgress(criteria, miscValue1, referencePlayer, ProgressType.Highest);
}
else // login case
{
for (byte arena_slot = 0; arena_slot < SharedConst.MaxArenaSlot; ++arena_slot)
{
uint teamId = referencePlayer.GetArenaTeamId(arena_slot);
@@ -363,6 +367,7 @@ namespace Game.Achievements
break;
}
}
}
break;
}
@@ -440,6 +445,7 @@ namespace Game.Achievements
case CriteriaType.ObtainAnyItemWithCurrencyValue:
case CriteriaType.EarnExpansionLevel:
case CriteriaType.LearnTransmog:
default:
break; // Not implemented yet :(
}
@@ -451,7 +457,6 @@ namespace Game.Achievements
AfterCriteriaTreeUpdate(tree, referencePlayer);
}
}
}
public void UpdateTimedCriteria(TimeSpan timeDiff)
{
+1 -1
View File
@@ -785,7 +785,7 @@ namespace Game.Entities
GetReputationMgr().SetVisible(factionEntry);
break;
case QuestObjectiveType.CriteriaTree:
m_questObjectiveCriteriaMgr.ResetCriteriaTree((uint)obj.ObjectID);
m_questObjectiveCriteriaMgr.ResetCriteriaTree(obj);
break;
default:
break;
@@ -9,6 +9,7 @@ using Game.Networking;
using Game.Networking.Packets;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Game
{
@@ -150,9 +151,11 @@ namespace Game
}
}
public void ResetCriteriaTree(uint criteriaTreeId)
public void ResetCriteriaTree(QuestObjective questObjective)
{
CriteriaTree tree = Global.CriteriaMgr.GetCriteriaTree(criteriaTreeId);
_completedObjectives.Remove(questObjective.Id);
CriteriaTree tree = Global.CriteriaMgr.GetCriteriaTree((uint)questObjective.ObjectID);
if (tree == null)
return;
@@ -160,6 +163,12 @@ namespace Game
{
RemoveCriteriaProgress(criteriaTree.Criteria);
});
CriteriaManager.WalkCriteriaTree(tree, criteriaTree =>
{
if (criteriaTree.Criteria != null && CriteriaManager.GetRetroactivelyUpdateableCriteriaTypes().Contains(criteriaTree.Criteria.Entry.Type))
UpdateCriteria(criteriaTree.Criteria, 0, 0, 0, null, _owner);
});
}
public override void SendAllData(Player receiver)
@@ -274,6 +283,8 @@ namespace Game
if (objective == null)
return;
CriteriaTree entireObjectiveTree = Global.CriteriaMgr.GetCriteriaTree((uint)objective.ObjectID);
if (IsCompletedCriteriaTree(entireObjectiveTree))
CompletedObjective(objective, referencePlayer);
}