muffin v7.4.15
This commit is contained in:
parent
9bf3dbdf69
commit
0b1b2d38c7
14 changed files with 1215 additions and 1057 deletions
|
|
@ -52,6 +52,11 @@
|
||||||
},
|
},
|
||||||
"minItems": 1
|
"minItems": 1
|
||||||
},
|
},
|
||||||
|
"RequiredQuestId": {
|
||||||
|
"description": "Quest ID that must be completed before this FATE can be farmed",
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 1
|
||||||
|
},
|
||||||
"RequiredStatusId": {
|
"RequiredStatusId": {
|
||||||
"description": "Status effect required to participate in the FATE",
|
"description": "Status effect required to participate in the FATE",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
|
@ -65,6 +70,10 @@
|
||||||
"description": "Position of the transform NPC",
|
"description": "Position of the transform NPC",
|
||||||
"$ref": "https://github.com/WigglyMuffin/Questionable/raw/refs/heads/main/Questionable.Model/common-vector3.json"
|
"$ref": "https://github.com/WigglyMuffin/Questionable/raw/refs/heads/main/Questionable.Model/common-vector3.json"
|
||||||
},
|
},
|
||||||
|
"StopAction": {
|
||||||
|
"description": "Action to use when stopping FATE farming (e.g. to remove a transformation debuff). Only used if the player has RequiredStatusId.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"EventExpiry": {
|
"EventExpiry": {
|
||||||
"description": "If this is a seasonal/event FATE, the date and time (in UTC) when it is no longer available. Date-only values are treated as ending at daily reset (14:59:59 UTC).",
|
"description": "If this is a seasonal/event FATE, the date and time (in UTC) when it is no longer available. Date-only values are treated as ending at daily reset (14:59:59 UTC).",
|
||||||
"format": "date-time",
|
"format": "date-time",
|
||||||
|
|
|
||||||
|
|
@ -478824,10 +478824,7 @@ public static class AssemblyQuestLoader
|
||||||
reference212 = obj228;
|
reference212 = obj228;
|
||||||
index2++;
|
index2++;
|
||||||
ref QuestStep reference213 = ref span297[index2];
|
ref QuestStep reference213 = ref span297[index2];
|
||||||
QuestStep obj229 = new QuestStep(EInteractionType.FateAction, null, new Vector3(-38.322124f, 3.9999998f, -144.23155f), 130)
|
QuestStep questStep20 = new QuestStep(EInteractionType.FateAction, null, new Vector3(-38.322124f, 3.9999998f, -144.23155f), 130);
|
||||||
{
|
|
||||||
Comment = "Use correct Cheer Rhythm color on each randomly-appearing performer NPC"
|
|
||||||
};
|
|
||||||
index3 = 4;
|
index3 = 4;
|
||||||
List<FateActionTarget> list299 = new List<FateActionTarget>(index3);
|
List<FateActionTarget> list299 = new List<FateActionTarget>(index3);
|
||||||
CollectionsMarshal.SetCount(list299, index3);
|
CollectionsMarshal.SetCount(list299, index3);
|
||||||
|
|
@ -478856,13 +478853,13 @@ public static class AssemblyQuestLoader
|
||||||
DataId = 18859u,
|
DataId = 18859u,
|
||||||
Action = EAction.CheerRhythmRed
|
Action = EAction.CheerRhythmRed
|
||||||
};
|
};
|
||||||
obj229.FateActionTargets = list299;
|
questStep20.FateActionTargets = list299;
|
||||||
reference213 = obj229;
|
reference213 = questStep20;
|
||||||
obj227.Steps = list297;
|
obj227.Steps = list297;
|
||||||
reference211 = obj227;
|
reference211 = obj227;
|
||||||
num++;
|
num++;
|
||||||
ref QuestSequence reference214 = ref span287[num];
|
ref QuestSequence reference214 = ref span287[num];
|
||||||
QuestSequence obj230 = new QuestSequence
|
QuestSequence obj229 = new QuestSequence
|
||||||
{
|
{
|
||||||
Sequence = byte.MaxValue
|
Sequence = byte.MaxValue
|
||||||
};
|
};
|
||||||
|
|
@ -478875,8 +478872,8 @@ public static class AssemblyQuestLoader
|
||||||
{
|
{
|
||||||
NextQuestId = new QuestId(5445)
|
NextQuestId = new QuestId(5445)
|
||||||
};
|
};
|
||||||
obj230.Steps = list300;
|
obj229.Steps = list300;
|
||||||
reference214 = obj230;
|
reference214 = obj229;
|
||||||
questRoot25.QuestSequence = list287;
|
questRoot25.QuestSequence = list287;
|
||||||
AddQuest(questId25, questRoot25);
|
AddQuest(questId25, questRoot25);
|
||||||
QuestId questId26 = new QuestId(5445);
|
QuestId questId26 = new QuestId(5445);
|
||||||
|
|
@ -478896,7 +478893,7 @@ public static class AssemblyQuestLoader
|
||||||
Span<QuestSequence> span302 = CollectionsMarshal.AsSpan(list302);
|
Span<QuestSequence> span302 = CollectionsMarshal.AsSpan(list302);
|
||||||
num = 0;
|
num = 0;
|
||||||
ref QuestSequence reference215 = ref span302[num];
|
ref QuestSequence reference215 = ref span302[num];
|
||||||
QuestSequence obj231 = new QuestSequence
|
QuestSequence obj230 = new QuestSequence
|
||||||
{
|
{
|
||||||
Sequence = 0
|
Sequence = 0
|
||||||
};
|
};
|
||||||
|
|
@ -478916,11 +478913,11 @@ public static class AssemblyQuestLoader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
obj231.Steps = list303;
|
obj230.Steps = list303;
|
||||||
reference215 = obj231;
|
reference215 = obj230;
|
||||||
num++;
|
num++;
|
||||||
ref QuestSequence reference216 = ref span302[num];
|
ref QuestSequence reference216 = ref span302[num];
|
||||||
QuestSequence obj232 = new QuestSequence
|
QuestSequence obj231 = new QuestSequence
|
||||||
{
|
{
|
||||||
Sequence = 1
|
Sequence = 1
|
||||||
};
|
};
|
||||||
|
|
@ -478930,11 +478927,11 @@ public static class AssemblyQuestLoader
|
||||||
Span<QuestStep> span304 = CollectionsMarshal.AsSpan(list304);
|
Span<QuestStep> span304 = CollectionsMarshal.AsSpan(list304);
|
||||||
num2 = 0;
|
num2 = 0;
|
||||||
span304[num2] = new QuestStep(EInteractionType.Interact, 1056476u, new Vector3(-35.1416f, 5.000001f, -130.38837f), 130);
|
span304[num2] = new QuestStep(EInteractionType.Interact, 1056476u, new Vector3(-35.1416f, 5.000001f, -130.38837f), 130);
|
||||||
obj232.Steps = list304;
|
obj231.Steps = list304;
|
||||||
reference216 = obj232;
|
reference216 = obj231;
|
||||||
num++;
|
num++;
|
||||||
ref QuestSequence reference217 = ref span302[num];
|
ref QuestSequence reference217 = ref span302[num];
|
||||||
QuestSequence obj233 = new QuestSequence
|
QuestSequence obj232 = new QuestSequence
|
||||||
{
|
{
|
||||||
Sequence = byte.MaxValue
|
Sequence = byte.MaxValue
|
||||||
};
|
};
|
||||||
|
|
@ -478944,8 +478941,8 @@ public static class AssemblyQuestLoader
|
||||||
Span<QuestStep> span305 = CollectionsMarshal.AsSpan(list305);
|
Span<QuestStep> span305 = CollectionsMarshal.AsSpan(list305);
|
||||||
index2 = 0;
|
index2 = 0;
|
||||||
span305[index2] = new QuestStep(EInteractionType.CompleteQuest, 1056476u, new Vector3(-35.1416f, 5.000001f, -130.38837f), 130);
|
span305[index2] = new QuestStep(EInteractionType.CompleteQuest, 1056476u, new Vector3(-35.1416f, 5.000001f, -130.38837f), 130);
|
||||||
obj233.Steps = list305;
|
obj232.Steps = list305;
|
||||||
reference217 = obj233;
|
reference217 = obj232;
|
||||||
questRoot26.QuestSequence = list302;
|
questRoot26.QuestSequence = list302;
|
||||||
AddQuest(questId26, questRoot26);
|
AddQuest(questId26, questRoot26);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -218,6 +218,10 @@ public sealed class ActionConverter : EnumConverter<EAction>
|
||||||
{
|
{
|
||||||
EAction.CheerRhythmYellow,
|
EAction.CheerRhythmYellow,
|
||||||
"Cheer Rhythm: Yellow"
|
"Cheer Rhythm: Yellow"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
EAction.CurtainCall,
|
||||||
|
"Curtain Call"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@ public enum EAction
|
||||||
CheerRhythmBlue = 44502,
|
CheerRhythmBlue = 44502,
|
||||||
CheerRhythmGreen = 44503,
|
CheerRhythmGreen = 44503,
|
||||||
CheerRhythmYellow = 44504,
|
CheerRhythmYellow = 44504,
|
||||||
|
CurtainCall = 11063,
|
||||||
Prospect = 227,
|
Prospect = 227,
|
||||||
CollectMiner = 240,
|
CollectMiner = 240,
|
||||||
LuckOfTheMountaineer = 4081,
|
LuckOfTheMountaineer = 4081,
|
||||||
|
|
|
||||||
|
|
@ -31,5 +31,9 @@ public sealed class FateDefinition
|
||||||
|
|
||||||
public List<DialogueChoice>? TransformDialogueChoices { get; set; }
|
public List<DialogueChoice>? TransformDialogueChoices { get; set; }
|
||||||
|
|
||||||
|
public ushort? RequiredQuestId { get; set; }
|
||||||
|
|
||||||
|
public EAction? StopAction { get; set; }
|
||||||
|
|
||||||
public DateTime? EventExpiry { get; set; }
|
public DateTime? EventExpiry { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ internal static class FateAction
|
||||||
}
|
}
|
||||||
foreach (FateActionTarget target in base.Task.Targets)
|
foreach (FateActionTarget target in base.Task.Targets)
|
||||||
{
|
{
|
||||||
IGameObject gameObject = gameFunctions.FindObjectByDataId(target.DataId);
|
IGameObject gameObject = gameFunctions.FindObjectByDataId(target.DataId, null, warnIfMissing: false);
|
||||||
if (gameObject != null && gameObject.IsTargetable)
|
if (gameObject != null && gameObject.IsTargetable)
|
||||||
{
|
{
|
||||||
bool flag = gameFunctions.UseAction(gameObject, target.Action);
|
bool flag = gameFunctions.UseAction(gameObject, target.Action);
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,12 @@ internal static class FateFarming
|
||||||
{
|
{
|
||||||
private DateTime _nextPollAt = DateTime.MinValue;
|
private DateTime _nextPollAt = DateTime.MinValue;
|
||||||
|
|
||||||
|
private bool _loggedWaitingForFate;
|
||||||
|
|
||||||
protected override bool Start()
|
protected override bool Start()
|
||||||
{
|
{
|
||||||
logger.LogInformation("Waiting for FATE targets to appear ({Count} targets)", base.Task.Targets.Count);
|
logger.LogInformation("Waiting for FATE targets to appear ({Count} targets)", base.Task.Targets.Count);
|
||||||
|
_loggedWaitingForFate = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -33,12 +36,24 @@ internal static class FateFarming
|
||||||
{
|
{
|
||||||
return ETaskResult.StillRunning;
|
return ETaskResult.StillRunning;
|
||||||
}
|
}
|
||||||
|
ushort currentFateId = gameFunctions.GetCurrentFateId();
|
||||||
|
if (currentFateId == 0)
|
||||||
|
{
|
||||||
|
if (!_loggedWaitingForFate)
|
||||||
|
{
|
||||||
|
logger.LogInformation("No active FATE yet, waiting for FATE to start before checking targets");
|
||||||
|
_loggedWaitingForFate = true;
|
||||||
|
}
|
||||||
|
_nextPollAt = DateTime.Now.AddSeconds(1.0);
|
||||||
|
return ETaskResult.StillRunning;
|
||||||
|
}
|
||||||
|
_loggedWaitingForFate = false;
|
||||||
foreach (FateActionTarget target in base.Task.Targets)
|
foreach (FateActionTarget target in base.Task.Targets)
|
||||||
{
|
{
|
||||||
IGameObject gameObject = gameFunctions.FindObjectByDataId(target.DataId);
|
IGameObject gameObject = gameFunctions.FindObjectByDataId(target.DataId, null, warnIfMissing: false);
|
||||||
if (gameObject != null && gameObject.IsTargetable)
|
if (gameObject != null && gameObject.IsTargetable)
|
||||||
{
|
{
|
||||||
logger.LogInformation("FATE target {DataId} is now targetable", target.DataId);
|
logger.LogInformation("FATE {FateId} active and target {DataId} is targetable", currentFateId, target.DataId);
|
||||||
return ETaskResult.TaskComplete;
|
return ETaskResult.TaskComplete;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -86,7 +101,7 @@ internal static class FateFarming
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal sealed record FateActionLoop(IReadOnlyList<FateActionTarget> Targets) : ITask
|
internal sealed record FateActionLoop(IReadOnlyList<FateActionTarget> Targets, EStatus? RequiredStatusId = null) : ITask
|
||||||
{
|
{
|
||||||
public bool ShouldRedoOnInterrupt()
|
public bool ShouldRedoOnInterrupt()
|
||||||
{
|
{
|
||||||
|
|
@ -103,12 +118,12 @@ internal static class FateFarming
|
||||||
{
|
{
|
||||||
private DateTime _nextActionAt = DateTime.MinValue;
|
private DateTime _nextActionAt = DateTime.MinValue;
|
||||||
|
|
||||||
private bool _fateWasActive;
|
private ushort _trackedFateId;
|
||||||
|
|
||||||
protected override bool Start()
|
protected override bool Start()
|
||||||
{
|
{
|
||||||
logger.LogInformation("Starting FATE action loop with {Count} targets", base.Task.Targets.Count);
|
_trackedFateId = gameFunctions.GetCurrentFateId();
|
||||||
_fateWasActive = gameFunctions.GetCurrentFateId() != 0;
|
logger.LogInformation("Starting FATE action loop with {Count} targets, tracking FATE {FateId}", base.Task.Targets.Count, _trackedFateId);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -118,33 +133,31 @@ internal static class FateFarming
|
||||||
{
|
{
|
||||||
return ETaskResult.StillRunning;
|
return ETaskResult.StillRunning;
|
||||||
}
|
}
|
||||||
bool flag = gameFunctions.GetCurrentFateId() != 0;
|
if (base.Task.RequiredStatusId.HasValue && !gameFunctions.HasStatus(base.Task.RequiredStatusId.Value))
|
||||||
if (_fateWasActive && !flag)
|
|
||||||
{
|
{
|
||||||
bool flag2 = false;
|
logger.LogInformation("Required status {StatusId} lost during FATE action loop, ending cycle to re-apply", base.Task.RequiredStatusId.Value);
|
||||||
foreach (FateActionTarget target in base.Task.Targets)
|
return ETaskResult.TaskComplete;
|
||||||
|
}
|
||||||
|
if (_trackedFateId == 0)
|
||||||
|
{
|
||||||
|
_trackedFateId = gameFunctions.GetCurrentFateId();
|
||||||
|
if (_trackedFateId != 0)
|
||||||
{
|
{
|
||||||
IGameObject gameObject = gameFunctions.FindObjectByDataId(target.DataId);
|
logger.LogInformation("Now tracking FATE {FateId}", _trackedFateId);
|
||||||
if (gameObject != null && gameObject.IsTargetable)
|
|
||||||
{
|
|
||||||
flag2 = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!flag2)
|
|
||||||
{
|
|
||||||
logger.LogInformation("FATE completed (was active, now inactive, no targetable NPCs)");
|
|
||||||
return ETaskResult.TaskComplete;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_fateWasActive = flag;
|
if (_trackedFateId != 0 && !gameFunctions.IsFateStillActive(_trackedFateId))
|
||||||
foreach (FateActionTarget target2 in base.Task.Targets)
|
|
||||||
{
|
{
|
||||||
IGameObject gameObject2 = gameFunctions.FindObjectByDataId(target2.DataId);
|
logger.LogInformation("FATE {FateId} is no longer running, cycle complete", _trackedFateId);
|
||||||
if (gameObject2 != null && gameObject2.IsTargetable)
|
return ETaskResult.TaskComplete;
|
||||||
|
}
|
||||||
|
foreach (FateActionTarget target in base.Task.Targets)
|
||||||
|
{
|
||||||
|
IGameObject gameObject = gameFunctions.FindObjectByDataId(target.DataId, null, warnIfMissing: false);
|
||||||
|
if (gameObject != null && gameObject.IsTargetable)
|
||||||
{
|
{
|
||||||
bool flag3 = gameFunctions.UseAction(gameObject2, target2.Action);
|
bool flag = gameFunctions.UseAction(gameObject, target.Action);
|
||||||
_nextActionAt = (flag3 ? DateTime.Now.AddSeconds(2.5) : DateTime.Now.AddSeconds(0.5));
|
_nextActionAt = (flag ? DateTime.Now.AddSeconds(2.5) : DateTime.Now.AddSeconds(0.5));
|
||||||
return ETaskResult.StillRunning;
|
return ETaskResult.StillRunning;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -107,13 +107,13 @@ internal static class Interact
|
||||||
|
|
||||||
public SkipStepConditions? SkipConditions { get; init; }
|
public SkipStepConditions? SkipConditions { get; init; }
|
||||||
|
|
||||||
public EStatus? RequiredStatusId { get; init; }
|
public EStatus? CompletionStatusId { get; init; }
|
||||||
|
|
||||||
public List<QuestWorkValue?> CompletionQuestVariablesFlags { get; }
|
public List<QuestWorkValue?> CompletionQuestVariablesFlags { get; }
|
||||||
|
|
||||||
public bool HasCompletionQuestVariablesFlags { get; }
|
public bool HasCompletionQuestVariablesFlags { get; }
|
||||||
|
|
||||||
public Task(uint DataId, Quest? Quest, EInteractionType InteractionType, bool SkipMarkerCheck = false, uint? PickUpItemId = null, byte? TaxiStandId = null, SkipStepConditions? SkipConditions = null, List<QuestWorkValue?>? CompletionQuestVariablesFlags = null, EStatus? RequiredStatusId = null)
|
public Task(uint DataId, Quest? Quest, EInteractionType InteractionType, bool SkipMarkerCheck = false, uint? PickUpItemId = null, byte? TaxiStandId = null, SkipStepConditions? SkipConditions = null, List<QuestWorkValue?>? CompletionQuestVariablesFlags = null, EStatus? CompletionStatusId = null)
|
||||||
{
|
{
|
||||||
this.DataId = DataId;
|
this.DataId = DataId;
|
||||||
this.Quest = Quest;
|
this.Quest = Quest;
|
||||||
|
|
@ -122,7 +122,7 @@ internal static class Interact
|
||||||
this.PickUpItemId = PickUpItemId;
|
this.PickUpItemId = PickUpItemId;
|
||||||
this.TaxiStandId = TaxiStandId;
|
this.TaxiStandId = TaxiStandId;
|
||||||
this.SkipConditions = SkipConditions;
|
this.SkipConditions = SkipConditions;
|
||||||
this.RequiredStatusId = RequiredStatusId;
|
this.CompletionStatusId = CompletionStatusId;
|
||||||
this.CompletionQuestVariablesFlags = CompletionQuestVariablesFlags ?? new List<QuestWorkValue>();
|
this.CompletionQuestVariablesFlags = CompletionQuestVariablesFlags ?? new List<QuestWorkValue>();
|
||||||
HasCompletionQuestVariablesFlags = Quest != null && CompletionQuestVariablesFlags != null && QuestWorkUtils.HasCompletionFlags(CompletionQuestVariablesFlags);
|
HasCompletionQuestVariablesFlags = Quest != null && CompletionQuestVariablesFlags != null && QuestWorkUtils.HasCompletionFlags(CompletionQuestVariablesFlags);
|
||||||
base._002Ector();
|
base._002Ector();
|
||||||
|
|
@ -139,7 +139,7 @@ internal static class Interact
|
||||||
}
|
}
|
||||||
|
|
||||||
[CompilerGenerated]
|
[CompilerGenerated]
|
||||||
public void Deconstruct(out uint DataId, out Quest? Quest, out EInteractionType InteractionType, out bool SkipMarkerCheck, out uint? PickUpItemId, out byte? TaxiStandId, out SkipStepConditions? SkipConditions, out List<QuestWorkValue?>? CompletionQuestVariablesFlags, out EStatus? RequiredStatusId)
|
public void Deconstruct(out uint DataId, out Quest? Quest, out EInteractionType InteractionType, out bool SkipMarkerCheck, out uint? PickUpItemId, out byte? TaxiStandId, out SkipStepConditions? SkipConditions, out List<QuestWorkValue?>? CompletionQuestVariablesFlags, out EStatus? CompletionStatusId)
|
||||||
{
|
{
|
||||||
DataId = this.DataId;
|
DataId = this.DataId;
|
||||||
Quest = this.Quest;
|
Quest = this.Quest;
|
||||||
|
|
@ -149,7 +149,7 @@ internal static class Interact
|
||||||
TaxiStandId = this.TaxiStandId;
|
TaxiStandId = this.TaxiStandId;
|
||||||
SkipConditions = this.SkipConditions;
|
SkipConditions = this.SkipConditions;
|
||||||
CompletionQuestVariablesFlags = this.CompletionQuestVariablesFlags;
|
CompletionQuestVariablesFlags = this.CompletionQuestVariablesFlags;
|
||||||
RequiredStatusId = this.RequiredStatusId;
|
CompletionStatusId = this.CompletionStatusId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -228,10 +228,10 @@ internal static class Interact
|
||||||
}
|
}
|
||||||
_needsUnmount = false;
|
_needsUnmount = false;
|
||||||
}
|
}
|
||||||
EStatus? requiredStatusId = base.Task.RequiredStatusId;
|
EStatus? completionStatusId = base.Task.CompletionStatusId;
|
||||||
if (requiredStatusId.HasValue)
|
if (completionStatusId.HasValue)
|
||||||
{
|
{
|
||||||
EStatus valueOrDefault = requiredStatusId.GetValueOrDefault();
|
EStatus valueOrDefault = completionStatusId.GetValueOrDefault();
|
||||||
if (gameFunctions.HasStatus(valueOrDefault))
|
if (gameFunctions.HasStatus(valueOrDefault))
|
||||||
{
|
{
|
||||||
return ETaskResult.TaskComplete;
|
return ETaskResult.TaskComplete;
|
||||||
|
|
|
||||||
|
|
@ -102,16 +102,12 @@ internal sealed class FateController : MiniTaskController<FateController>
|
||||||
}
|
}
|
||||||
if (_currentFate.RequiredStatusId.HasValue && _currentFate.TransformNpcDataId.HasValue && _currentFate.TransformNpcPosition.HasValue && !_gameFunctions.HasStatus(_currentFate.RequiredStatusId.Value))
|
if (_currentFate.RequiredStatusId.HasValue && _currentFate.TransformNpcDataId.HasValue && _currentFate.TransformNpcPosition.HasValue && !_gameFunctions.HasStatus(_currentFate.RequiredStatusId.Value))
|
||||||
{
|
{
|
||||||
ILogger<FateController> logger = _logger;
|
_logger.LogInformation("Player missing required status {StatusId}, enqueuing transform", _currentFate.RequiredStatusId.Value);
|
||||||
object[] array = new object[1];
|
|
||||||
EStatus? requiredStatusId = _currentFate.RequiredStatusId;
|
|
||||||
array[0] = requiredStatusId.Value;
|
|
||||||
logger.LogInformation("Player missing required status {StatusId}, enqueuing transform", array);
|
|
||||||
_taskQueue.Enqueue(new MoveTask(_currentFate.TerritoryId, _currentFate.TransformNpcPosition.Value, null, 3f));
|
_taskQueue.Enqueue(new MoveTask(_currentFate.TerritoryId, _currentFate.TransformNpcPosition.Value, null, 3f));
|
||||||
_taskQueue.Enqueue(new Mount.UnmountTask());
|
_taskQueue.Enqueue(new Mount.UnmountTask());
|
||||||
TaskQueue taskQueue = _taskQueue;
|
TaskQueue taskQueue = _taskQueue;
|
||||||
uint value = _currentFate.TransformNpcDataId.Value;
|
uint value = _currentFate.TransformNpcDataId.Value;
|
||||||
requiredStatusId = _currentFate.RequiredStatusId.Value;
|
EStatus? requiredStatusId = _currentFate.RequiredStatusId;
|
||||||
taskQueue.Enqueue(new Interact.Task(value, null, EInteractionType.Interact, SkipMarkerCheck: true, null, null, null, null, requiredStatusId));
|
taskQueue.Enqueue(new Interact.Task(value, null, EInteractionType.Interact, SkipMarkerCheck: true, null, null, null, null, requiredStatusId));
|
||||||
_taskQueue.Enqueue(new WaitAtEnd.WaitDelay(TimeSpan.FromSeconds(2L)));
|
_taskQueue.Enqueue(new WaitAtEnd.WaitDelay(TimeSpan.FromSeconds(2L)));
|
||||||
}
|
}
|
||||||
|
|
@ -119,7 +115,7 @@ internal sealed class FateController : MiniTaskController<FateController>
|
||||||
_taskQueue.Enqueue(new Mount.UnmountTask());
|
_taskQueue.Enqueue(new Mount.UnmountTask());
|
||||||
_taskQueue.Enqueue(new FateFarming.WaitForFateTargets(_currentFate.Targets));
|
_taskQueue.Enqueue(new FateFarming.WaitForFateTargets(_currentFate.Targets));
|
||||||
_taskQueue.Enqueue(new FateFarming.SyncFateLevel());
|
_taskQueue.Enqueue(new FateFarming.SyncFateLevel());
|
||||||
_taskQueue.Enqueue(new FateFarming.FateActionLoop(_currentFate.Targets));
|
_taskQueue.Enqueue(new FateFarming.FateActionLoop(_currentFate.Targets, _currentFate.RequiredStatusId));
|
||||||
_taskQueue.Enqueue(new WaitAtEnd.WaitDelay(TimeSpan.FromSeconds(3L)));
|
_taskQueue.Enqueue(new WaitAtEnd.WaitDelay(TimeSpan.FromSeconds(3L)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -129,6 +125,11 @@ internal sealed class FateController : MiniTaskController<FateController>
|
||||||
if (_currentFate != null)
|
if (_currentFate != null)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Stopping FATE farming: {Label} (completed {Cycles} cycles)", label, _completedCycles);
|
_logger.LogInformation("Stopping FATE farming: {Label} (completed {Cycles} cycles)", label, _completedCycles);
|
||||||
|
if (_currentFate.StopAction.HasValue && _currentFate.RequiredStatusId.HasValue && _gameFunctions.HasStatus(_currentFate.RequiredStatusId.Value))
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Using stop action {Action} to remove transformation", _currentFate.StopAction.Value);
|
||||||
|
_gameFunctions.UseAction(_currentFate.StopAction.Value);
|
||||||
|
}
|
||||||
_currentFate = null;
|
_currentFate = null;
|
||||||
_completedCycles = 0;
|
_completedCycles = 0;
|
||||||
_cycleLimit = null;
|
_cycleLimit = null;
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -121,7 +121,7 @@ internal sealed class GameFunctions
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IGameObject? FindObjectByDataId(uint dataId, Dalamud.Game.ClientState.Objects.Enums.ObjectKind? kind = null)
|
public IGameObject? FindObjectByDataId(uint dataId, Dalamud.Game.ClientState.Objects.Enums.ObjectKind? kind = null, bool warnIfMissing = true)
|
||||||
{
|
{
|
||||||
foreach (IGameObject item in _objectTable)
|
foreach (IGameObject item in _objectTable)
|
||||||
{
|
{
|
||||||
|
|
@ -132,7 +132,10 @@ internal sealed class GameFunctions
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_logger.LogWarning("Could not find GameObject with dataId {DataId}", dataId);
|
if (warnIfMissing)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Could not find GameObject with dataId {DataId}", dataId);
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -581,6 +584,25 @@ internal sealed class GameFunctions
|
||||||
return ptr->CurrentFate->FateId;
|
return ptr->CurrentFate->FateId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public unsafe bool IsFateStillActive(ushort fateId)
|
||||||
|
{
|
||||||
|
if (fateId == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
FateManager* ptr = FateManager.Instance();
|
||||||
|
if (ptr == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
FateContext* fateById = ptr->GetFateById(fateId);
|
||||||
|
if (fateById == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return fateById->State == FateState.Running;
|
||||||
|
}
|
||||||
|
|
||||||
public uint GetItemLevel(uint itemId)
|
public uint GetItemLevel(uint itemId)
|
||||||
{
|
{
|
||||||
return (_dataManager.GetExcelSheet<Item>()?.GetRowOrDefault(itemId))?.LevelItem.RowId ?? 0;
|
return (_dataManager.GetExcelSheet<Item>()?.GetRowOrDefault(itemId))?.LevelItem.RowId ?? 0;
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,11 @@ internal sealed class ActiveQuestComponent
|
||||||
|
|
||||||
public void Draw(bool isMinimized)
|
public void Draw(bool isMinimized)
|
||||||
{
|
{
|
||||||
|
if (_fateController.IsRunning)
|
||||||
|
{
|
||||||
|
DrawFateActive(isMinimized);
|
||||||
|
return;
|
||||||
|
}
|
||||||
(QuestController.QuestProgress, QuestController.ECurrentQuestType)? currentQuestDetails = _questController.CurrentQuestDetails;
|
(QuestController.QuestProgress, QuestController.ECurrentQuestType)? currentQuestDetails = _questController.CurrentQuestDetails;
|
||||||
QuestController.QuestProgress questProgress = currentQuestDetails?.Item1;
|
QuestController.QuestProgress questProgress = currentQuestDetails?.Item1;
|
||||||
QuestController.ECurrentQuestType? currentQuestType = currentQuestDetails?.Item2;
|
QuestController.ECurrentQuestType? currentQuestType = currentQuestDetails?.Item2;
|
||||||
|
|
@ -131,12 +136,12 @@ internal sealed class ActiveQuestComponent
|
||||||
if (interactionType == EInteractionType.WaitForManualProgress || interactionType == EInteractionType.Snipe || interactionType == EInteractionType.Instruction)
|
if (interactionType == EInteractionType.WaitForManualProgress || interactionType == EInteractionType.Snipe || interactionType == EInteractionType.Instruction)
|
||||||
{
|
{
|
||||||
flag = true;
|
flag = true;
|
||||||
goto IL_0154;
|
goto IL_0169;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
flag = false;
|
flag = false;
|
||||||
goto IL_0154;
|
goto IL_0169;
|
||||||
IL_0154:
|
IL_0169:
|
||||||
if (flag)
|
if (flag)
|
||||||
{
|
{
|
||||||
color.Push(ImGuiCol.Text, ImGuiColors.DalamudOrange);
|
color.Push(ImGuiCol.Text, ImGuiColors.DalamudOrange);
|
||||||
|
|
@ -178,7 +183,7 @@ internal sealed class ActiveQuestComponent
|
||||||
text2.AppendFormatted((item2 == 1) ? string.Empty : "s");
|
text2.AppendFormatted((item2 == 1) ? string.Empty : "s");
|
||||||
text2.AppendLiteral(" - Leveling mode will start automatically");
|
text2.AppendLiteral(" - Leveling mode will start automatically");
|
||||||
ImGui.TextColored(in col, text2);
|
ImGui.TextColored(in col, text2);
|
||||||
using (ImRaii.Disabled(_questController.IsRunning || !_autoDutyIpc.IsStopped()))
|
using (ImRaii.Disabled(_questController.IsRunning || _fateController.IsRunning || !_autoDutyIpc.IsStopped()))
|
||||||
{
|
{
|
||||||
if (ImGuiComponents.IconButton(FontAwesomeIcon.Play))
|
if (ImGuiComponents.IconButton(FontAwesomeIcon.Play))
|
||||||
{
|
{
|
||||||
|
|
@ -247,6 +252,32 @@ internal sealed class ActiveQuestComponent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DrawFateActive(bool isMinimized)
|
||||||
|
{
|
||||||
|
using (ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.ParsedGold))
|
||||||
|
{
|
||||||
|
ImU8String text = new ImU8String(6, 1);
|
||||||
|
text.AppendLiteral("FATE: ");
|
||||||
|
text.AppendFormatted(Shorten(_fateController.CurrentFate.Name));
|
||||||
|
ImGui.TextUnformatted(text);
|
||||||
|
}
|
||||||
|
IList<string> remainingTaskNames = _fateController.GetRemainingTaskNames();
|
||||||
|
if (remainingTaskNames.Count > 0)
|
||||||
|
{
|
||||||
|
ImGui.TextColored(ImGuiColors.DalamudGrey, remainingTaskNames[0]);
|
||||||
|
}
|
||||||
|
if (!isMinimized)
|
||||||
|
{
|
||||||
|
string text2 = (_fateController.CycleLimit.HasValue ? $"Cycle {_fateController.CompletedCycles + 1} / {_fateController.CycleLimit}" : $"Cycle {_fateController.CompletedCycles + 1}");
|
||||||
|
ImGui.TextColored(ImGuiColors.DalamudGrey3, text2);
|
||||||
|
}
|
||||||
|
if (ImGuiComponents.IconButton(FontAwesomeIcon.Stop))
|
||||||
|
{
|
||||||
|
_fateController.Stop("UI stop");
|
||||||
|
_movementController.Stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void DrawQuestNames(QuestController.QuestProgress currentQuest, QuestController.ECurrentQuestType? currentQuestType)
|
private void DrawQuestNames(QuestController.QuestProgress currentQuest, QuestController.ECurrentQuestType? currentQuestType)
|
||||||
{
|
{
|
||||||
if (currentQuestType == QuestController.ECurrentQuestType.Simulated)
|
if (currentQuestType == QuestController.ECurrentQuestType.Simulated)
|
||||||
|
|
@ -563,7 +594,7 @@ internal sealed class ActiveQuestComponent
|
||||||
|
|
||||||
private void DrawQuestButtons(QuestController.QuestProgress currentQuest, QuestStep? currentStep, QuestProgressInfo? questProgressInfo, bool isMinimized)
|
private void DrawQuestButtons(QuestController.QuestProgress currentQuest, QuestStep? currentStep, QuestProgressInfo? questProgressInfo, bool isMinimized)
|
||||||
{
|
{
|
||||||
using (ImRaii.Disabled(_questController.IsRunning))
|
using (ImRaii.Disabled(_questController.IsRunning || _fateController.IsRunning))
|
||||||
{
|
{
|
||||||
if (ImGuiComponents.IconButton(FontAwesomeIcon.Play))
|
if (ImGuiComponents.IconButton(FontAwesomeIcon.Play))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,8 @@ using Dalamud.Interface.Windowing;
|
||||||
using LLib.ImGui;
|
using LLib.ImGui;
|
||||||
using Questionable.Controller;
|
using Questionable.Controller;
|
||||||
using Questionable.Data;
|
using Questionable.Data;
|
||||||
|
using Questionable.Functions;
|
||||||
|
using Questionable.Model;
|
||||||
using Questionable.Model.Questing;
|
using Questionable.Model.Questing;
|
||||||
using Questionable.Windows.QuestComponents;
|
using Questionable.Windows.QuestComponents;
|
||||||
|
|
||||||
|
|
@ -28,17 +30,23 @@ internal sealed class FateSelectionWindow : LWindow
|
||||||
|
|
||||||
private readonly MovementController _movementController;
|
private readonly MovementController _movementController;
|
||||||
|
|
||||||
|
private readonly QuestFunctions _questFunctions;
|
||||||
|
|
||||||
|
private readonly QuestData _questData;
|
||||||
|
|
||||||
private readonly TerritoryData _territoryData;
|
private readonly TerritoryData _territoryData;
|
||||||
|
|
||||||
private int _cycleLimit;
|
private int _cycleLimit;
|
||||||
|
|
||||||
public FateSelectionWindow(FateController fateController, FateDefinitionRegistry fateDefinitionRegistry, QuestController questController, MovementController movementController, TerritoryData territoryData)
|
public FateSelectionWindow(FateController fateController, FateDefinitionRegistry fateDefinitionRegistry, QuestController questController, MovementController movementController, QuestFunctions questFunctions, QuestData questData, TerritoryData territoryData)
|
||||||
: base("FATE Farming###QuestionableFateFarming")
|
: base("FATE Farming###QuestionableFateFarming")
|
||||||
{
|
{
|
||||||
_fateController = fateController;
|
_fateController = fateController;
|
||||||
_fateDefinitionRegistry = fateDefinitionRegistry;
|
_fateDefinitionRegistry = fateDefinitionRegistry;
|
||||||
_questController = questController;
|
_questController = questController;
|
||||||
_movementController = movementController;
|
_movementController = movementController;
|
||||||
|
_questFunctions = questFunctions;
|
||||||
|
_questData = questData;
|
||||||
_territoryData = territoryData;
|
_territoryData = territoryData;
|
||||||
base.Size = new Vector2(600f, 400f);
|
base.Size = new Vector2(600f, 400f);
|
||||||
base.SizeCondition = ImGuiCond.FirstUseEver;
|
base.SizeCondition = ImGuiCond.FirstUseEver;
|
||||||
|
|
@ -335,12 +343,31 @@ internal sealed class FateSelectionWindow : LWindow
|
||||||
|
|
||||||
private void DrawFateRowActions(FateDefinition fate, bool disabled)
|
private void DrawFateRowActions(FateDefinition fate, bool disabled)
|
||||||
{
|
{
|
||||||
using (ImRaii.Disabled(disabled))
|
bool flag = fate.RequiredQuestId.HasValue && !_questFunctions.IsQuestComplete(new QuestId(fate.RequiredQuestId.Value));
|
||||||
|
ImU8String id = new ImU8String(5, 1);
|
||||||
|
id.AppendLiteral("fate_");
|
||||||
|
id.AppendFormatted(fate.Name);
|
||||||
|
using (ImRaii.PushId(id))
|
||||||
{
|
{
|
||||||
ImU8String id = new ImU8String(5, 1);
|
if (flag)
|
||||||
id.AppendLiteral("fate_");
|
{
|
||||||
id.AppendFormatted(fate.Name);
|
using (ImRaii.PushFont(UiBuilder.IconFont))
|
||||||
using (ImRaii.PushId(id))
|
{
|
||||||
|
ImGui.TextColored(ImGuiColors.DalamudRed, FontAwesomeIcon.Times.ToIconString());
|
||||||
|
}
|
||||||
|
if (ImGui.IsItemHovered())
|
||||||
|
{
|
||||||
|
IQuestInfo questInfo;
|
||||||
|
string value = (_questData.TryGetQuestInfo(new QuestId(fate.RequiredQuestId.Value), out questInfo) ? questInfo.Name : fate.RequiredQuestId.Value.ToString(CultureInfo.InvariantCulture));
|
||||||
|
ImU8String tooltip = new ImU8String(33, 1);
|
||||||
|
tooltip.AppendLiteral("Requires \"");
|
||||||
|
tooltip.AppendFormatted(value);
|
||||||
|
tooltip.AppendLiteral("\" to be completed first");
|
||||||
|
ImGui.SetTooltip(tooltip);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
using (ImRaii.Disabled(disabled))
|
||||||
{
|
{
|
||||||
if (ImGuiComponents.IconButton(FontAwesomeIcon.Play))
|
if (ImGuiComponents.IconButton(FontAwesomeIcon.Play))
|
||||||
{
|
{
|
||||||
|
|
@ -350,16 +377,16 @@ internal sealed class FateSelectionWindow : LWindow
|
||||||
_fateController.Start(fate, cycleLimit);
|
_fateController.Start(fate, cycleLimit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if (disabled && ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
|
||||||
if (disabled && ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
|
|
||||||
{
|
|
||||||
if (_fateController.IsRunning)
|
|
||||||
{
|
{
|
||||||
ImGui.SetTooltip("Already farming a FATE");
|
if (_fateController.IsRunning)
|
||||||
}
|
{
|
||||||
else
|
ImGui.SetTooltip("Already farming a FATE");
|
||||||
{
|
}
|
||||||
ImGui.SetTooltip("Stop quest automation first");
|
else
|
||||||
|
{
|
||||||
|
ImGui.SetTooltip("Stop quest automation first");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ internal sealed class QuestWindow : LWindow, IPersistableWindowConfig
|
||||||
{
|
{
|
||||||
private static readonly Version PluginVersion = typeof(QuestionablePlugin).Assembly.GetName().Version;
|
private static readonly Version PluginVersion = typeof(QuestionablePlugin).Assembly.GetName().Version;
|
||||||
|
|
||||||
|
private const string TestingSuffix = "";
|
||||||
|
|
||||||
private readonly IDalamudPluginInterface _pluginInterface;
|
private readonly IDalamudPluginInterface _pluginInterface;
|
||||||
|
|
||||||
private readonly QuestController _questController;
|
private readonly QuestController _questController;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue