220 lines
8.4 KiB
C#
220 lines
8.4 KiB
C#
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using Dalamud.Game.ClientState.Objects.Types;
|
|
using Dalamud.Plugin.Services;
|
|
using Lumina.Excel;
|
|
using Lumina.Excel.Sheets;
|
|
using Questionable.Functions;
|
|
using Questionable.Model;
|
|
using Questionable.Model.Questing;
|
|
|
|
namespace Questionable.Controller.DebugCommands;
|
|
|
|
internal sealed class QuestKillsCommandHandler : IDebugCommandHandler
|
|
{
|
|
private readonly QuestController _questController;
|
|
|
|
private readonly QuestFunctions _questFunctions;
|
|
|
|
private readonly IDataManager _dataManager;
|
|
|
|
private readonly IObjectTable _objectTable;
|
|
|
|
private readonly IChatGui _chatGui;
|
|
|
|
public string CommandName => "quest-kills";
|
|
|
|
public QuestKillsCommandHandler(QuestController questController, QuestFunctions questFunctions, IDataManager dataManager, IObjectTable objectTable, IChatGui chatGui)
|
|
{
|
|
_questController = questController;
|
|
_questFunctions = questFunctions;
|
|
_dataManager = dataManager;
|
|
_objectTable = objectTable;
|
|
_chatGui = chatGui;
|
|
}
|
|
|
|
public void Execute(string[] arguments)
|
|
{
|
|
(QuestController.QuestProgress, QuestController.ECurrentQuestType)? currentQuestDetails = _questController.CurrentQuestDetails;
|
|
if (!currentQuestDetails.HasValue)
|
|
{
|
|
_chatGui.PrintError("No active quest.", "Questionable", 576);
|
|
return;
|
|
}
|
|
QuestController.QuestProgress item = currentQuestDetails.Value.Item1;
|
|
Questionable.Model.Quest quest = item.Quest;
|
|
QuestProgressInfo questProgressInfo = null;
|
|
if (quest.Id is QuestId elementId)
|
|
{
|
|
questProgressInfo = _questFunctions.GetQuestProgressInfo(elementId);
|
|
}
|
|
if (questProgressInfo == null)
|
|
{
|
|
_chatGui.PrintError("Unable to retrieve quest progress information.", "Questionable", 576);
|
|
return;
|
|
}
|
|
QuestSequence questSequence = quest.FindSequence(item.Sequence);
|
|
if (questSequence == null)
|
|
{
|
|
_chatGui.PrintError($"Sequence {item.Sequence} not found for quest {quest.Id}.", "Questionable", 576);
|
|
return;
|
|
}
|
|
QuestStep questStep = ((item.Step < questSequence.Steps.Count) ? questSequence.Steps[item.Step] : null);
|
|
if (questStep == null)
|
|
{
|
|
_chatGui.PrintError($"Step {item.Step} not found in sequence {item.Sequence}.", "Questionable", 576);
|
|
return;
|
|
}
|
|
_chatGui.Print($"Quest: {quest.Info.Name} ({quest.Id})", "Questionable", 576);
|
|
_chatGui.Print($"Sequence: {item.Sequence}, Step: {item.Step}", "Questionable", 576);
|
|
_chatGui.Print("", "Questionable", 576);
|
|
_chatGui.Print("Quest Variables: " + string.Join(", ", questProgressInfo.Variables.Select((byte v, int i) => $"[{i}]={v}")), "Questionable", 576);
|
|
_chatGui.Print("", "Questionable", 576);
|
|
ExcelSheet<BNpcName> bnpcNameSheet = _dataManager.GetExcelSheet<BNpcName>();
|
|
HashSet<uint> hashSet = new HashSet<uint>(questStep.KillEnemyDataIds);
|
|
foreach (ComplexCombatData complexCombatDatum in questStep.ComplexCombatData)
|
|
{
|
|
hashSet.Add(complexCombatDatum.DataId);
|
|
}
|
|
if (hashSet.Count > 0)
|
|
{
|
|
_chatGui.Print($"All Enemy DataIds Found: {hashSet.Count}", "Questionable", 576);
|
|
foreach (uint item3 in hashSet.OrderBy((uint x) => x))
|
|
{
|
|
(string Name, bool Found) tuple = GetEnemyName(item3);
|
|
var (value, _) = tuple;
|
|
if (tuple.Found)
|
|
{
|
|
_chatGui.Print($" - {value} (DataId: {item3})", "Questionable", 576);
|
|
}
|
|
else
|
|
{
|
|
_chatGui.Print($" - DataId: {item3}", "Questionable", 576);
|
|
}
|
|
}
|
|
_chatGui.Print("", "Questionable", 576);
|
|
}
|
|
if (questStep.ComplexCombatData.Count > 0)
|
|
{
|
|
_chatGui.Print($"Complex Combat Data Entries: {questStep.ComplexCombatData.Count}", "Questionable", 576);
|
|
_chatGui.Print("Kill Progress:", "Questionable", 576);
|
|
if (questStep.ComplexCombatData.Count == 1 && hashSet.Count > 1)
|
|
{
|
|
ComplexCombatData complexCombatData = questStep.ComplexCombatData[0];
|
|
int num = -1;
|
|
byte? b = null;
|
|
for (int num2 = 0; num2 < complexCombatData.CompletionQuestVariablesFlags.Count; num2++)
|
|
{
|
|
QuestWorkValue questWorkValue = complexCombatData.CompletionQuestVariablesFlags[num2];
|
|
if (questWorkValue != null && questWorkValue.Low.HasValue)
|
|
{
|
|
num = num2;
|
|
b = questWorkValue.Low;
|
|
break;
|
|
}
|
|
}
|
|
byte b2 = (byte)(((num >= 0 && num < questProgressInfo.Variables.Count) ? questProgressInfo.Variables[num] : 0) & 0xF);
|
|
string value2 = (b.HasValue ? $" {b2}/{b}" : "");
|
|
string value3 = ((b.HasValue && b2 >= b) ? "✓" : "○");
|
|
foreach (uint item4 in hashSet.OrderBy((uint x) => x))
|
|
{
|
|
(string Name, bool Found) tuple3 = GetEnemyName(item4);
|
|
var (value4, _) = tuple3;
|
|
if (tuple3.Found)
|
|
{
|
|
_chatGui.Print($" {value3} Slay {value4}.{value2} (DataId: {item4})", "Questionable", 576);
|
|
}
|
|
else
|
|
{
|
|
_chatGui.Print($" {value3} Slay enemy.{value2} (DataId: {item4})", "Questionable", 576);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int num3 = 0; num3 < questStep.ComplexCombatData.Count; num3++)
|
|
{
|
|
ComplexCombatData complexCombatData2 = questStep.ComplexCombatData[num3];
|
|
int num4 = -1;
|
|
byte? b3 = null;
|
|
bool flag = false;
|
|
for (int num5 = 0; num5 < complexCombatData2.CompletionQuestVariablesFlags.Count; num5++)
|
|
{
|
|
QuestWorkValue questWorkValue2 = complexCombatData2.CompletionQuestVariablesFlags[num5];
|
|
if (questWorkValue2 != null)
|
|
{
|
|
if (questWorkValue2.Low.HasValue)
|
|
{
|
|
num4 = num5;
|
|
b3 = questWorkValue2.Low;
|
|
flag = false;
|
|
break;
|
|
}
|
|
if (questWorkValue2.High.HasValue)
|
|
{
|
|
num4 = num5;
|
|
b3 = questWorkValue2.High;
|
|
flag = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
byte b4 = (byte)((num4 >= 0 && num4 < questProgressInfo.Variables.Count) ? questProgressInfo.Variables[num4] : 0);
|
|
byte b5 = (flag ? ((byte)(b4 >> 4)) : ((byte)(b4 & 0xF)));
|
|
string value5;
|
|
if (complexCombatData2.NameId.HasValue)
|
|
{
|
|
BNpcName? bNpcName = bnpcNameSheet?.GetRowOrDefault(complexCombatData2.NameId.Value);
|
|
value5 = ((!bNpcName.HasValue || string.IsNullOrEmpty(bNpcName.Value.Singular.ToString())) ? "enemy" : bNpcName.Value.Singular.ToString());
|
|
}
|
|
else
|
|
{
|
|
(string Name, bool Found) tuple5 = GetEnemyName(complexCombatData2.DataId);
|
|
string item2 = tuple5.Name;
|
|
value5 = (tuple5.Found ? item2 : "enemy");
|
|
}
|
|
string value6 = (b3.HasValue ? $" {b5}/{b3}" : "");
|
|
string value7 = ((b3.HasValue && b5 >= b3) ? "✓" : "○");
|
|
string value8 = (complexCombatData2.NameId.HasValue ? $" (DataId: {complexCombatData2.DataId}, NameId: {complexCombatData2.NameId})" : $" (DataId: {complexCombatData2.DataId})");
|
|
_chatGui.Print($" {value7} Slay {value5}.{value6}{value8}", "Questionable", 576);
|
|
}
|
|
}
|
|
_chatGui.Print("", "Questionable", 576);
|
|
}
|
|
else if (questStep.KillEnemyDataIds.Count == 0)
|
|
{
|
|
_chatGui.Print("No kill enemy data for this step.", "Questionable", 576);
|
|
_chatGui.Print("", "Questionable", 576);
|
|
}
|
|
if (questStep.CompletionQuestVariablesFlags.Count <= 0 || !questStep.CompletionQuestVariablesFlags.Any((QuestWorkValue x) => x != null))
|
|
{
|
|
return;
|
|
}
|
|
_chatGui.Print("Completion Flags (Debug):", "Questionable", 576);
|
|
for (int num6 = 0; num6 < questStep.CompletionQuestVariablesFlags.Count; num6++)
|
|
{
|
|
QuestWorkValue questWorkValue3 = questStep.CompletionQuestVariablesFlags[num6];
|
|
if (questWorkValue3 != null)
|
|
{
|
|
int num7 = ((num6 < questProgressInfo.Variables.Count) ? questProgressInfo.Variables[num6] : 0);
|
|
byte b6 = (byte)(num7 >> 4);
|
|
byte b7 = (byte)(num7 & 0xF);
|
|
string value9 = (((!questWorkValue3.High.HasValue || questWorkValue3.High == b6) && (!questWorkValue3.Low.HasValue || questWorkValue3.Low == b7)) ? " ✓" : " ✗");
|
|
_chatGui.Print($" [{num6}] Expected: H={questWorkValue3.High?.ToString(CultureInfo.InvariantCulture) ?? "any"} L={questWorkValue3.Low?.ToString(CultureInfo.InvariantCulture) ?? "any"} | Actual: H={b6.ToString(CultureInfo.InvariantCulture)} L={b7.ToString(CultureInfo.InvariantCulture)}{value9}", "Questionable", 576);
|
|
}
|
|
}
|
|
(string Name, bool Found) GetEnemyName(uint dataId)
|
|
{
|
|
if (_objectTable.FirstOrDefault((IGameObject x) => x is IBattleNpc battleNpc2 && battleNpc2.BaseId == dataId) is IBattleNpc { NameId: not 0u } battleNpc)
|
|
{
|
|
BNpcName? bNpcName2 = bnpcNameSheet?.GetRowOrDefault(battleNpc.NameId);
|
|
if (bNpcName2.HasValue && !string.IsNullOrEmpty(bNpcName2.Value.Singular.ToString()))
|
|
{
|
|
return (Name: bNpcName2.Value.Singular.ToString(), Found: true);
|
|
}
|
|
}
|
|
return (Name: string.Empty, Found: false);
|
|
}
|
|
}
|
|
}
|