/// <summary> /// Share supplied <see cref="Quest.Quest"/> with another <see cref="Player"/>. /// </summary> public void QuestShare(ushort questId) { QuestInfo info = GlobalQuestManager.GetQuestInfo(questId); if (info == null) { throw new ArgumentException($"Invalid quest {questId}!"); } Quest.Quest quest = GetQuest(questId); if (quest == null) { throw new QuestException($"Player {player.CharacterId} tried to share quest {questId} which they don't have!"); } if (!quest.CanShare()) { throw new QuestException($"Player {player.CharacterId} tried to share quest {questId} which can't be shared!"); } Player recipient = player.GetVisible <Player>(player.TargetGuid); if (recipient == null) { throw new QuestException($"Player {player.CharacterId} tried to share quest {questId} to an invalid player!"); } // TODO log.Trace($"Shared quest {questId} with player {recipient.Name}."); }
/// <summary> /// Complete single <see cref="QuestObjective"/> for supplied active <see cref="Quest.Quest"/>. /// </summary> public void QuestAchieveObjective(ushort questId, byte index) { if (GlobalQuestManager.GetQuestInfo(questId) == null) { throw new ArgumentException($"Invalid quest {questId}!"); } Quest.Quest quest = GetQuest(questId); if (quest == null || quest.PendingDelete) { throw new QuestException(); } if (quest.State != QuestState.Accepted) { throw new QuestException(); } QuestObjective objective = quest.SingleOrDefault(o => o.Index == index); if (objective == null) { throw new QuestException(); } quest.ObjectiveUpdate((QuestObjectiveType)objective.Entry.Type, objective.Entry.Data, objective.Entry.Count); }
/// <summary> /// Track or hide an active <see cref="Quest.Quest"/>. /// </summary> public void QuestTrack(ushort questId, bool tracked) { if (GlobalQuestManager.GetQuestInfo(questId) == null) { throw new ArgumentException($"Invalid quest {questId}!"); } Quest.Quest quest = GetQuest(questId, GetQuestFlags.Active); if (quest == null) { throw new QuestException($"Player {player.CharacterId} tried to track quest {questId} which they don't have!"); } if (quest.State != QuestState.Accepted && quest.State != QuestState.Achieved) { throw new QuestException($"Player {player.CharacterId} tried to track quest {questId} with invalid state!"); } if (tracked) { quest.Flags |= QuestFlags.Tracked; } else { quest.Flags &= ~QuestFlags.Tracked; } log.Trace($"Updated tracked state of quest {questId} to {tracked}."); }
/// <summary> /// Create a new <see cref="QuestManager"/> from existing <see cref="Character"/> database model. /// </summary> public QuestManager(Player owner, Character model) { player = owner; foreach (CharacterQuest questModel in model.CharacterQuest) { QuestInfo info = GlobalQuestManager.GetQuestInfo(questModel.QuestId); if (info == null) { log.Error($"Player {player.CharacterId} has an invalid quest {questModel.QuestId}!"); continue; } var quest = new Quest.Quest(player, info, questModel); switch (quest.State) { case QuestState.Completed: completedQuests.Add(quest.Id, quest); break; case QuestState.Botched: case QuestState.Ignored: inactiveQuests.Add(quest.Id, quest); break; case QuestState.Accepted: case QuestState.Achieved: activeQuests.Add(quest.Id, quest); break; } } }
/// <summary> /// Ignore or acknowledge an inactive <see cref="Quest.Quest"/>. /// </summary> public void QuestIgnore(ushort questId, bool ignored) { if (GlobalQuestManager.GetQuestInfo(questId) == null) { throw new ArgumentException($"Invalid quest {questId}!"); } // TODO: }
/// <summary> /// Add a <see cref="Quest.Quest"/> from supplied id, optionally supplying <see cref="Item"/> which was used to start the quest. /// </summary> public void QuestAdd(ushort questId, Item item) { QuestInfo info = GlobalQuestManager.GetQuestInfo(questId); if (info == null) { throw new ArgumentException($"Invalid quest {questId}!"); } if (DisableManager.Instance.IsDisabled(DisableType.Quest, questId)) { player.SendSystemMessage($"Unable to add quest {questId} because it is disabled."); return; } Quest.Quest quest = GetQuest(questId); QuestAdd(info, quest, item); }
public async Task QuestAddCommandHandler(CommandContext context, string command, string[] parameters) { if (parameters.Length != 1 || !ushort.TryParse(parameters[0], out ushort questId)) { await SendHelpAsync(context); return; } QuestInfo info = GlobalQuestManager.GetQuestInfo(questId); if (info == null) { await context.SendMessageAsync($"Quest id {questId} is invalid!"); return; } context.Session.Player.QuestManager.QuestAdd(info); }
/// <summary> /// Abandon an active <see cref="Quest.Quest"/>. /// </summary> public void QuestAbandon(ushort questId) { if (GlobalQuestManager.GetQuestInfo(questId) == null) { throw new ArgumentException($"Invalid quest {questId}!"); } Quest.Quest quest = GetQuest(questId, GetQuestFlags.Active | GetQuestFlags.Inactive); if (quest == null || quest.PendingDelete) { throw new QuestException($"Player {player.CharacterId} tried to abandon quest {questId} which they don't have!"); } if (!quest.CanAbandon()) { throw new QuestException($"Player {player.CharacterId} tried to abandon quest {questId} which can't be abandoned!"); } if (!quest.PendingCreate) { quest.EnqueueDelete(true); } else { switch (quest.State) { case QuestState.Accepted: case QuestState.Achieved: activeQuests.Remove(questId); break; case QuestState.Botched: inactiveQuests.Remove(quest.Id); break; } } quest.State = QuestState.Abandoned; log.Trace($"Abandoned quest {questId}."); }
/// <summary> /// Retry an inactive <see cref="Quest.Quest"/> that was previously failed. /// </summary> public void QuestRetry(ushort questId) { QuestInfo info = GlobalQuestManager.GetQuestInfo(questId); if (info == null) { throw new ArgumentException($"Invalid quest {questId}!"); } Quest.Quest quest = GetQuest(questId, GetQuestFlags.Inactive); if (quest == null) { throw new QuestException($"Player {player.CharacterId} tried to restart quest {questId} which they don't have!"); } if (quest.State != QuestState.Botched) { throw new QuestException($"Player {player.CharacterId} tried to restart quest {questId} which hasn't been failed!"); } QuestAdd(info, quest, null); }
/// <summary> /// Complete all <see cref="QuestObjective"/>'s for supplied active <see cref="Quest.Quest"/>. /// </summary> public void QuestAchieve(ushort questId) { if (GlobalQuestManager.GetQuestInfo(questId) == null) { throw new ArgumentException($"Invalid quest {questId}!"); } Quest.Quest quest = GetQuest(questId); if (quest == null || quest.PendingDelete) { throw new QuestException($"Player {player.CharacterId} tried to achieve quest {questId} which they don't have!"); } if (quest.State != QuestState.Accepted) { throw new QuestException($"Player {player.CharacterId} tried to achieve quest {questId} with invalid state!"); } foreach (QuestObjectiveEntry entry in quest.Info.Objectives) { quest.ObjectiveUpdate((QuestObjectiveType)entry.Type, entry.Data, entry.Count); } }
/// <summary> /// Complete an achieved <see cref="Quest.Quest"/> supplying an optional reward and whether the quest was completed from the communicator. /// </summary> public void QuestComplete(ushort questId, ushort reward, bool communicator) { if (GlobalQuestManager.GetQuestInfo(questId) == null) { throw new ArgumentException($"Invalid quest {questId}!"); } if (DisableManager.Instance.IsDisabled(DisableType.Quest, questId)) { player.SendSystemMessage($"Unable to complete quest {questId} because it is disabled."); return; } Quest.Quest quest = GetQuest(questId, GetQuestFlags.Active); if (quest == null) { throw new QuestException($"Player {player.CharacterId} tried to complete quest {questId} which they don't have!"); } if (quest.State != QuestState.Achieved) { throw new QuestException($"Player {player.CharacterId} tried to complete quest {questId} which wasn't complete!"); } if (communicator) { if (!quest.Info.IsCommunicatorReceived()) { throw new QuestException($"Player {player.CharacterId} tried to complete quest {questId} without communicator message!"); } } else { if (!GlobalQuestManager.GetQuestReceivers(questId).Any(c => player.GetVisibleCreature <WorldEntity>(c).Any())) { throw new QuestException($"Player {player.CharacterId} tried to complete quest {questId} without any quest receiver!"); } } // reclaim any quest specific items for (int i = 0; i < quest.Info.Entry.PushedItemIds.Length; i++) { uint itemId = quest.Info.Entry.PushedItemIds[i]; if (itemId != 0u) { player.Inventory.ItemDelete(itemId, quest.Info.Entry.PushedItemCounts[i]); } } RewardQuest(quest.Info, reward); quest.State = QuestState.Completed; // mark repeatable quests for reset switch ((QuestRepeatPeriod)quest.Info.Entry.QuestRepeatPeriodEnum) { case QuestRepeatPeriod.Daily: quest.Reset = GlobalQuestManager.NextDailyReset; break; case QuestRepeatPeriod.Weekly: quest.Reset = GlobalQuestManager.NextWeeklyReset; break; } activeQuests.Remove(questId); completedQuests.Add(questId, quest); }