punish v6.8.18.0

This commit is contained in:
alydev 2025-10-09 07:47:19 +10:00
commit cfb4dea47e
316 changed files with 554088 additions and 0 deletions

View file

@ -0,0 +1,16 @@
using System.Globalization;
namespace Questionable.Model.Questing;
public sealed class AetherCurrentId : ElementId
{
public AetherCurrentId(ushort value)
: base(value)
{
}
public override string ToString()
{
return "C" + base.Value.ToString(CultureInfo.InvariantCulture);
}
}

View file

@ -0,0 +1,16 @@
using System.Globalization;
namespace Questionable.Model.Questing;
public sealed class AethernetId : ElementId
{
public AethernetId(ushort value)
: base(value)
{
}
public override string ToString()
{
return "N" + base.Value.ToString(CultureInfo.InvariantCulture);
}
}

View file

@ -0,0 +1,13 @@
namespace Questionable.Model.Questing;
public sealed class AlliedSocietyDailyId(byte alliedSociety, byte rank = 0) : ElementId((ushort)(alliedSociety * 10 + rank))
{
public byte AlliedSociety { get; } = alliedSociety;
public byte Rank { get; } = rank;
public override string ToString()
{
return "A" + AlliedSociety + "x" + Rank;
}
}

View file

@ -0,0 +1,8 @@
namespace Questionable.Model.Questing;
public sealed class ChatMessage
{
public string? ExcelSheet { get; set; }
public string Key { get; set; }
}

View file

@ -0,0 +1,14 @@
using System.Text.Json.Serialization;
using Questionable.Model.Questing.Converter;
namespace Questionable.Model.Questing;
public sealed class CombatItemUse
{
public uint ItemId { get; set; }
[JsonConverter(typeof(CombatItemUseConditionConverter))]
public ECombatItemUseCondition Condition { get; set; }
public int Value { get; set; }
}

View file

@ -0,0 +1,20 @@
using System.Collections.Generic;
namespace Questionable.Model.Questing;
public sealed class ComplexCombatData
{
public uint DataId { get; set; }
public uint? NameId { get; set; }
public uint? MinimumKillCount { get; set; }
public uint? RewardItemId { get; set; }
public int? RewardItemCount { get; set; }
public IList<QuestWorkValue?> CompletionQuestVariablesFlags { get; set; } = new List<QuestWorkValue>();
public bool IgnoreQuestMarker { get; set; }
}

View file

@ -0,0 +1,28 @@
using System.Text.Json.Serialization;
using Questionable.Model.Questing.Converter;
namespace Questionable.Model.Questing;
public sealed class DialogueChoice
{
[JsonConverter(typeof(DialogueChoiceTypeConverter))]
public EDialogChoiceType Type { get; set; }
public string? ExcelSheet { get; set; }
[JsonConverter(typeof(ExcelRefConverter))]
public ExcelRef? Prompt { get; set; }
public bool Yes { get; set; } = true;
[JsonConverter(typeof(ExcelRefConverter))]
public ExcelRef? Answer { get; set; }
public bool PromptIsRegularExpression { get; set; }
public bool AnswerIsRegularExpression { get; set; }
public uint? DataId { get; set; }
public string? SpecialCondition { get; set; }
}

View file

@ -0,0 +1,14 @@
using System.Collections.Generic;
namespace Questionable.Model.Questing;
public class DutyOptions
{
public bool Enabled { get; set; }
public uint ContentFinderConditionId { get; set; }
public bool LowPriority { get; set; }
public List<string> Notes { get; set; } = new List<string>();
}

View file

@ -0,0 +1,80 @@
using System.Text.Json.Serialization;
using Questionable.Model.Questing.Converter;
namespace Questionable.Model.Questing;
[JsonConverter(typeof(ActionConverter))]
public enum EAction
{
DutyAction1 = 65562,
DutyAction2 = 65563,
HeavySwing = 31,
Bootshine = 53,
TwinSnakes = 61,
Demolish = 66,
DragonKick = 74,
HeavyShot = 97,
Cure = 120,
Cure2 = 135,
Eukrasia = 24290,
Diagnosis = 24284,
EukrasianDiagnosis = 24291,
Esuna = 7568,
Physick = 190,
AspectedBenefic = 3595,
FormShift = 4262,
FieryBreath = 1764,
BuffetSanuwa = 4931,
BuffetGriffin = 4583,
Trample = 4585,
Fumigate = 5872,
Roar = 6293,
Seed = 6294,
MagitekPulse = 8624,
MagitekThunder = 8625,
Inhale = 10013,
SiphonSnout = 18187,
PeculiarLight = 20030,
Cannonfire = 20121,
RedGulal = 29382,
YellowGulal = 29383,
BlueGulal = 29384,
ElectrixFlux = 29718,
HopStep = 31116,
Hide = 2245,
Ten = 2259,
Ninjutsu = 2260,
Chi = 2261,
Jin = 2263,
FumaShuriken = 2265,
Katon = 2266,
Raiton = 2267,
RabbitMedium = 2272,
SlugShot = 2868,
BosomBrook = 37173,
Souleater = 3632,
Fire3 = 152,
Adloquium = 185,
WaterCannon = 11385,
Wasshoi = 11499,
ShroudedLuminescence = 39505,
BigSneeze = 1765,
Prospect = 227,
CollectMiner = 240,
LuckOfTheMountaineer = 4081,
ScourMiner = 22182,
MeticulousMiner = 22184,
ScrutinyMiner = 22185,
Triangulate = 210,
CollectBotanist = 815,
LuckOfThePioneer = 4095,
ScourBotanist = 22186,
MeticulousBotanist = 22188,
ScrutinyBotanist = 22189,
SharpVision1 = 235,
SharpVision2 = 237,
SharpVision3 = 295,
FieldMastery1 = 218,
FieldMastery2 = 220,
FieldMastery3 = 294
}

View file

@ -0,0 +1,34 @@
namespace Questionable.Model.Questing;
public static class EActionExtensions
{
public static bool RequiresMount(this EAction action)
{
switch (action)
{
case EAction.FieryBreath:
case EAction.BigSneeze:
case EAction.BuffetGriffin:
case EAction.Trample:
case EAction.BuffetSanuwa:
case EAction.Fumigate:
case EAction.Roar:
case EAction.Seed:
case EAction.Inhale:
case EAction.Wasshoi:
case EAction.SiphonSnout:
case EAction.PeculiarLight:
case EAction.Cannonfire:
case EAction.RedGulal:
case EAction.YellowGulal:
case EAction.BlueGulal:
case EAction.ElectrixFlux:
case EAction.HopStep:
case EAction.BosomBrook:
case EAction.ShroudedLuminescence:
return true;
default:
return false;
}
}
}

View file

@ -0,0 +1,9 @@
namespace Questionable.Model.Questing;
public enum ECombatItemUseCondition
{
None,
Incapacitated,
HealthPercent,
MissingStatus
}

View file

@ -0,0 +1,8 @@
namespace Questionable.Model.Questing;
public enum EDialogChoiceType
{
None,
YesNo,
List
}

View file

@ -0,0 +1,275 @@
using System.Text.Json.Serialization;
using Questionable.Model.Questing.Converter;
namespace Questionable.Model.Questing;
[JsonConverter(typeof(EmoteConverter))]
public enum EEmote
{
None = 0,
Surprised = 1,
Angry = 2,
Furious = 3,
Blush = 4,
Bow = 5,
Cheer = 6,
Clap = 7,
Beckon = 8,
Comfort = 9,
Cry = 10,
Dance = 11,
Doubt = 12,
Doze = 13,
Fume = 14,
Goodbye = 15,
Wave = 16,
Huh = 17,
Joy = 18,
Kneel = 19,
Chuckle = 20,
Laugh = 21,
Lookout = 22,
Me = 23,
No = 24,
Deny = 25,
Panic = 26,
Point = 27,
Poke = 28,
Congratulate = 29,
Psych = 30,
Salute = 31,
Shocked = 32,
Shrug = 33,
Rally = 34,
Soothe = 35,
Stagger = 36,
Stretch = 37,
Sulk = 38,
Think = 39,
Upset = 40,
Welcome = 41,
Yes = 42,
ThumbsUp = 43,
ExamineSelf = 44,
Pose = 45,
BlowKiss = 46,
Grovel = 47,
Happy = 48,
Disappointed = 49,
Lounge = 50,
GroundSit = 52,
AirQuotes = 54,
GcSalute = 55,
Pray = 58,
ImperialSalute = 59,
Visor = 60,
Megaflare = 62,
CrimsonLotus = 63,
Charmed = 64,
CheerOn = 65,
CheerWave = 66,
CheerJump = 67,
StraightFace = 68,
Smile = 69,
Grin = 70,
Smirk = 71,
Taunt = 72,
ShutEyes = 73,
Sad = 74,
Scared = 75,
Amazed = 76,
Ouch = 77,
Annoyed = 78,
Alert = 79,
Worried = 80,
BigGrin = 81,
Reflect = 82,
Furrow = 83,
Scoff = 84,
Throw = 85,
ChangePose = 90,
StepDance = 101,
HarvestDance = 102,
BallDance = 103,
MandervilleDance = 104,
Pet = 105,
HandOver = 106,
BombDance = 109,
Hurray = 110,
Slap = 111,
Hug = 112,
Embrace = 113,
Hildibrand = 114,
FistBump = 115,
ThavDance = 118,
GoldDance = 119,
SundropDance = 120,
BattleStance = 121,
VictoryPose = 122,
Backflip = 123,
EasternGreeting = 124,
Eureka = 125,
MogDance = 126,
Haurchefant = 127,
EasternStretch = 128,
EasternDance = 129,
RangerPose1R = 130,
RangerPose2R = 131,
RangerPose3R = 132,
Wink = 133,
RangerPose1L = 134,
RangerPose2L = 135,
RangerPose3L = 136,
Facepalm = 137,
Zantetsuken = 138,
Flex = 139,
Respect = 140,
Sneer = 141,
PrettyPlease = 142,
PlayDead = 143,
IceHeart = 144,
MoonLift = 145,
Dote = 146,
Spectacles = 148,
Songbird = 149,
WaterFloat = 150,
WaterFlip = 151,
PuckerUp = 152,
PowerUp = 153,
EasternBow = 154,
Squats = 155,
PushUps = 156,
SitUps = 157,
BreathControl = 158,
Converse = 159,
Concentrate = 160,
Disturbed = 161,
Simper = 162,
Beam = 163,
Attention = 164,
AtEase = 165,
Box = 166,
RitualPrayer = 167,
Tremble = 169,
Winded = 170,
Aback = 171,
Greeting = 172,
BoxStep = 173,
SideStep = 174,
Ultima = 175,
YolDance = 176,
Splash = 178,
Sweat = 180,
Shiver = 181,
Elucidate = 182,
Ponder = 183,
LeftWink = 184,
GetFantasy = 185,
PopotoStep = 186,
Hum = 187,
Confirm = 188,
Scheme = 189,
Endure = 190,
Tomestone = 191,
HeelToe = 192,
GoobbueDouble = 193,
Gratuity = 194,
FistPump = 195,
Reprimand = 196,
Sabotender = 197,
MandervilleMambo = 198,
LaliHo = 199,
SimulationM = 200,
SimulationF = 201,
Toast = 202,
Lean = 203,
Headache = 204,
Snap = 205,
BreakFast = 206,
Read = 207,
Insist = 208,
Consider = 209,
Wasshoi = 210,
FlowerShower = 211,
FlameDance = 212,
HighFive = 213,
Guard = 214,
Malevolence = 215,
BeesKnees = 216,
LaliHop = 217,
EatRiceBall = 220,
EatApple = 221,
WringHands = 222,
Sweep = 223,
PaintBlack = 224,
PaintRed = 225,
PaintYellow = 226,
PaintBlue = 227,
FakeSmile = 228,
Pantomime = 229,
Vexed = 230,
Shush = 231,
EatPizza = 232,
ClutchHead = 233,
EatChocolate = 234,
EatEgg = 235,
Content = 236,
Sheathe = 237,
Draw = 238,
Tea = 239,
Determined = 240,
ShowRight = 241,
ShowLeft = 242,
Deride = 245,
Wow = 246,
EatPumpkinCookie = 247,
Spirit = 248,
MagicTrick = 249,
LittleLadiesDance = 250,
Linkpearl = 251,
EarWiggle = 252,
Frighten = 256,
AdventOfLight = 257,
JumpForJoy1 = 258,
JumpForJoy2 = 259,
JumpForJoy3 = 260,
JumpForJoy4 = 261,
JumpForJoy5 = 262,
HandToHeart = 263,
CheerOnBright = 264,
CheerWaveViolet = 265,
CheerJumpGreen = 266,
AllSaintsCharm = 267,
LopHop = 269,
Reference = 270,
EatChicken = 271,
Sundering = 272,
Slump = 273,
LoveHeart = 274,
HumbleTriumph = 275,
VictoryReveal = 276,
FryEgg = 277,
Uchiwasshoi = 278,
Attend = 279,
Water = 280,
ShakeDrink = 281,
Unbound = 282,
Bouquet = 283,
BlowBubbles = 284,
Ohokaliy = 285,
Visage = 286,
Photograph = 288,
Overreact = 291,
Twirl = 292,
Dazed = 293,
Rage = 294,
TomeScroll = 295,
Study = 296,
GridanianSip = 298,
UldahnSip = 299,
LominsanSip = 300,
GridanianGulp = 301,
UldahnGulp = 302,
LominsanGulp = 303,
Pen = 307
}

View file

@ -0,0 +1,19 @@
using System.Text.Json.Serialization;
using Questionable.Model.Questing.Converter;
namespace Questionable.Model.Questing;
[JsonConverter(typeof(EnemySpawnTypeConverter))]
public enum EEnemySpawnType
{
None,
AfterInteraction,
AfterItemUse,
AfterAction,
AfterEmote,
AutoOnEnterArea,
OverworldEnemies,
FateEnemies,
FinishCombatIfAny,
QuestInterruption
}

View file

@ -0,0 +1,58 @@
using System.Text.Json.Serialization;
using Questionable.Model.Questing.Converter;
namespace Questionable.Model.Questing;
[JsonConverter(typeof(ExtendedClassJobConverter))]
public enum EExtendedClassJob
{
None,
Gladiator,
Pugilist,
Marauder,
Lancer,
Archer,
Conjurer,
Thaumaturge,
Carpenter,
Blacksmith,
Armorer,
Goldsmith,
Leatherworker,
Weaver,
Alchemist,
Culinarian,
Miner,
Botanist,
Fisher,
Paladin,
Monk,
Warrior,
Dragoon,
Bard,
WhiteMage,
BlackMage,
Arcanist,
Summoner,
Scholar,
Rogue,
Ninja,
Machinist,
DarkKnight,
Astrologian,
Samurai,
RedMage,
BlueMage,
Gunbreaker,
Dancer,
Reaper,
Sage,
Viper,
Pictomancer,
DoW,
DoM,
DoH,
DoL,
ConfiguredCombatJob,
QuestStartJob
}

View file

@ -0,0 +1,16 @@
using System.Text.Json.Serialization;
using Questionable.Model.Questing.Converter;
namespace Questionable.Model.Questing;
[JsonConverter(typeof(SkipConditionConverter))]
public enum EExtraSkipCondition
{
None,
WakingSandsMainArea,
WakingSandsSolar,
RisingStonesSolar,
RoguesGuild,
NotRoguesGuild,
DockStorehouse
}

View file

@ -0,0 +1,39 @@
using System.Text.Json.Serialization;
using Questionable.Model.Questing.Converter;
namespace Questionable.Model.Questing;
[JsonConverter(typeof(InteractionTypeConverter))]
public enum EInteractionType
{
None,
Interact,
WalkTo,
AttuneAethernetShard,
AttuneAetheryte,
RegisterFreeOrFavoredAetheryte,
AttuneAetherCurrent,
Combat,
UseItem,
EquipItem,
PurchaseItem,
EquipRecommended,
Say,
Emote,
Action,
StatusOff,
WaitForObjectAtPosition,
WaitForManualProgress,
Duty,
SinglePlayerDuty,
Jump,
Dive,
Craft,
Gather,
Snipe,
SwitchClass,
UnlockTaxiStand,
Instruction,
AcceptQuest,
CompleteQuest
}

View file

@ -0,0 +1,11 @@
using System.Text.Json.Serialization;
using Questionable.Model.Questing.Converter;
namespace Questionable.Model.Questing;
[JsonConverter(typeof(JumpTypeConverter))]
public enum EJumpType
{
SingleJump,
RepeatedJumps
}

View file

@ -0,0 +1,11 @@
using System.Text.Json.Serialization;
using Questionable.Model.Questing.Converter;
namespace Questionable.Model.Questing;
[JsonConverter(typeof(LockedSkipConditionConverter))]
public enum ELockedSkipCondition
{
Locked,
Unlocked
}

View file

@ -0,0 +1,11 @@
using System.Text.Json.Serialization;
using Questionable.Model.Questing.Converter;
namespace Questionable.Model.Questing;
[JsonConverter(typeof(QuestWorkModeConverter))]
public enum EQuestWorkMode
{
Bitwise,
Exact
}

View file

@ -0,0 +1,15 @@
using System.Text.Json.Serialization;
using Questionable.Model.Questing.Converter;
namespace Questionable.Model.Questing;
[JsonConverter(typeof(StatusConverter))]
public enum EStatus : uint
{
Triangulate = 217u,
GatheringRateUp = 218u,
Prospect = 225u,
Hidden = 614u,
Eukrasia = 2606u,
Jog = 4209u
}

View file

@ -0,0 +1,123 @@
using System;
using System.Globalization;
namespace Questionable.Model.Questing;
public abstract class ElementId : IComparable<ElementId>, IEquatable<ElementId>
{
public ushort Value { get; }
protected ElementId(ushort value)
{
Value = value;
}
public int CompareTo(ElementId? other)
{
if ((object)this == other)
{
return 0;
}
if ((object)other == null)
{
return 1;
}
return Value.CompareTo(other.Value);
}
public bool Equals(ElementId? other)
{
if ((object)other == null)
{
return false;
}
if ((object)this == other)
{
return true;
}
if (other.GetType() != GetType())
{
return false;
}
return Value == other.Value;
}
public override bool Equals(object? obj)
{
if (obj == null)
{
return false;
}
if (this == obj)
{
return true;
}
if (obj.GetType() != GetType())
{
return false;
}
return Equals((ElementId)obj);
}
public override int GetHashCode()
{
return Value.GetHashCode();
}
public static bool operator ==(ElementId? left, ElementId? right)
{
return object.Equals(left, right);
}
public static bool operator !=(ElementId? left, ElementId? right)
{
return !object.Equals(left, right);
}
public static ElementId FromString(string value)
{
if (value.StartsWith("S"))
{
return new SatisfactionSupplyNpcId(ushort.Parse(value.Substring(1), CultureInfo.InvariantCulture));
}
if (value.StartsWith("U"))
{
return new UnlockLinkId(ushort.Parse(value.Substring(1), CultureInfo.InvariantCulture));
}
if (value.StartsWith("N"))
{
return new AethernetId(ushort.Parse(value.Substring(1), CultureInfo.InvariantCulture));
}
if (value.StartsWith("C"))
{
return new AetherCurrentId(ushort.Parse(value.Substring(1), CultureInfo.InvariantCulture));
}
if (value.StartsWith("A"))
{
value = value.Substring(1);
string[] array = value.Split(new char[1] { 'x' });
if (array.Length == 2)
{
return new AlliedSocietyDailyId(byte.Parse(array[0], CultureInfo.InvariantCulture), byte.Parse(array[1], CultureInfo.InvariantCulture));
}
return new AlliedSocietyDailyId(byte.Parse(value, CultureInfo.InvariantCulture), 0);
}
return new QuestId(ushort.Parse(value, CultureInfo.InvariantCulture));
}
public static bool TryFromString(string value, out ElementId? elementId)
{
try
{
elementId = FromString(value);
return true;
}
catch (Exception)
{
elementId = null;
return false;
}
}
public abstract override string ToString();
}

View file

@ -0,0 +1,83 @@
using System;
namespace Questionable.Model.Questing;
public class ExcelRef
{
public enum EType
{
None,
Key,
RowId,
RawString
}
private readonly string? _stringValue;
private readonly uint? _rowIdValue;
public EType Type { get; }
public ExcelRef(string value)
{
_stringValue = value;
_rowIdValue = null;
Type = EType.Key;
}
public ExcelRef(uint value)
{
_stringValue = null;
_rowIdValue = value;
Type = EType.RowId;
}
private ExcelRef(string? stringValue, uint? rowIdValue, EType type)
{
_stringValue = stringValue;
_rowIdValue = rowIdValue;
Type = type;
}
public static ExcelRef FromKey(string value)
{
return new ExcelRef(value, null, EType.Key);
}
public static ExcelRef FromRowId(uint rowId)
{
return new ExcelRef(null, rowId, EType.RowId);
}
public static ExcelRef FromSheetValue(string value)
{
return new ExcelRef(value, null, EType.RawString);
}
public string AsKey()
{
if (Type != EType.Key)
{
throw new InvalidOperationException();
}
return _stringValue;
}
public uint AsRowId()
{
if (Type != EType.RowId)
{
throw new InvalidOperationException();
}
return _rowIdValue.Value;
}
public string AsRawString()
{
if (Type != EType.RawString)
{
throw new InvalidOperationException();
}
return _stringValue;
}
}

View file

@ -0,0 +1,12 @@
namespace Questionable.Model.Questing;
public sealed class GatheredItem
{
public uint ItemId { get; set; }
public uint AlternativeItemId { get; set; }
public int ItemCount { get; set; }
public ushort Collectability { get; set; }
}

View file

@ -0,0 +1,22 @@
using System.Numerics;
using System.Text.Json.Serialization;
using Questionable.Model.Common.Converter;
namespace Questionable.Model.Questing;
public sealed class JumpDestination
{
[JsonConverter(typeof(VectorConverter))]
public Vector3 Position { get; set; }
public float? StopDistance { get; set; }
public float? DelaySeconds { get; set; }
public EJumpType Type { get; set; }
public float CalculateStopDistance()
{
return StopDistance ?? 1f;
}
}

View file

@ -0,0 +1,15 @@
using System.Numerics;
using System.Text.Json.Serialization;
using Questionable.Model.Common.Converter;
namespace Questionable.Model.Questing;
public sealed class NearPositionCondition
{
[JsonConverter(typeof(VectorConverter))]
public Vector3 Position { get; set; }
public float MaximumDistance { get; set; }
public ushort TerritoryId { get; set; }
}

View file

@ -0,0 +1,12 @@
using System.Text.Json.Serialization;
using Questionable.Model.Questing.Converter;
namespace Questionable.Model.Questing;
public sealed class PurchaseMenu
{
public string? ExcelSheet { get; set; }
[JsonConverter(typeof(ExcelRefConverter))]
public ExcelRef? Key { get; set; }
}

View file

@ -0,0 +1,21 @@
using System.Globalization;
namespace Questionable.Model.Questing;
public sealed class QuestId : ElementId
{
public QuestId(ushort value)
: base(value)
{
}
public static QuestId FromRowId(uint rowId)
{
return new QuestId((ushort)(rowId & 0xFFFF));
}
public override string ToString()
{
return base.Value.ToString(CultureInfo.InvariantCulture);
}
}

View file

@ -0,0 +1,19 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Questionable.Model.Common.Converter;
namespace Questionable.Model.Questing;
public sealed class QuestRoot
{
[JsonConverter(typeof(StringListOrValueConverter))]
public List<string> Author { get; set; } = new List<string>();
public bool Disabled { get; set; }
public bool Interruptible { get; set; } = true;
public string? Comment { get; set; }
public List<QuestSequence> QuestSequence { get; set; } = new List<QuestSequence>();
}

View file

@ -0,0 +1,27 @@
using System.Collections.Generic;
using System.Linq;
namespace Questionable.Model.Questing;
public sealed class QuestSequence
{
public byte Sequence { get; set; }
public string? Comment { get; set; }
public List<QuestStep> Steps { get; set; } = new List<QuestStep>();
public QuestStep? FindStep(int step)
{
if (step < 0 || step >= Steps.Count)
{
return null;
}
return Steps[step];
}
public QuestStep? LastStep()
{
return Steps.LastOrDefault();
}
}

View file

@ -0,0 +1,172 @@
using System.Collections.Generic;
using System.Numerics;
using System.Text.Json.Serialization;
using Questionable.Model.Common;
using Questionable.Model.Common.Converter;
using Questionable.Model.Questing.Converter;
namespace Questionable.Model.Questing;
public sealed class QuestStep
{
public const float DefaultStopDistance = 3f;
public const int VesperBayAetheryteTicket = 30362;
public uint? DataId { get; set; }
[JsonConverter(typeof(VectorConverter))]
public Vector3? Position { get; set; }
public float? StopDistance { get; set; }
public ushort TerritoryId { get; set; }
[JsonIgnore(/*Could not decode attribute arguments.*/)]
public EInteractionType InteractionType { get; set; }
public float? NpcWaitDistance { get; set; }
public ushort? TargetTerritoryId { get; set; }
public float? DelaySecondsAtStart { get; set; }
public uint? PickUpItemId { get; set; }
public bool Disabled { get; set; }
public bool DisableNavmesh { get; set; }
public bool? Mount { get; set; }
public bool? Fly { get; set; }
public bool? Land { get; set; }
public bool? Sprint { get; set; }
public bool? IgnoreDistanceToObject { get; set; }
public bool? RestartNavigationIfCancelled { get; set; }
public string? Comment { get; set; }
public EAetheryteLocation? Aetheryte { get; set; }
[JsonConverter(typeof(AethernetShardConverter))]
public EAetheryteLocation? AethernetShard { get; set; }
public EAetheryteLocation? AetheryteShortcut { get; set; }
public AethernetShortcut? AethernetShortcut { get; set; }
public uint? AetherCurrentId { get; set; }
public uint? ItemId { get; set; }
public bool? GroundTarget { get; set; }
public int? ItemCount { get; set; }
public EEmote? Emote { get; set; }
public ChatMessage? ChatMessage { get; set; }
public EAction? Action { get; set; }
public EStatus? Status { get; set; }
public EExtendedClassJob TargetClass { get; set; }
public byte? TaxiStandId { get; set; }
public EEnemySpawnType? EnemySpawnType { get; set; }
public List<uint> KillEnemyDataIds { get; set; } = new List<uint>();
public List<ComplexCombatData> ComplexCombatData { get; set; } = new List<ComplexCombatData>();
public CombatItemUse? CombatItemUse { get; set; }
public float? CombatDelaySecondsAtStart { get; set; }
public JumpDestination? JumpDestination { get; set; }
public DutyOptions? DutyOptions { get; set; }
public SinglePlayerDutyOptions? SinglePlayerDutyOptions { get; set; }
public byte SinglePlayerDutyIndex => SinglePlayerDutyOptions?.Index ?? 0;
public SkipConditions? SkipConditions { get; set; }
public List<List<QuestWorkValue>?> RequiredQuestVariables { get; set; } = new List<List<QuestWorkValue>>();
public List<EExtendedClassJob> RequiredCurrentJob { get; set; } = new List<EExtendedClassJob>();
public List<EExtendedClassJob> RequiredQuestAcceptedJob { get; set; } = new List<EExtendedClassJob>();
public List<GatheredItem> ItemsToGather { get; set; } = new List<GatheredItem>();
public List<QuestWorkValue?> CompletionQuestVariablesFlags { get; set; } = new List<QuestWorkValue>();
public List<DialogueChoice> DialogueChoices { get; set; } = new List<DialogueChoice>();
public List<uint> PointMenuChoices { get; set; } = new List<uint>();
public PurchaseMenu? PurchaseMenu { get; set; }
[JsonConverter(typeof(ElementIdConverter))]
public ElementId? PickUpQuestId { get; set; }
[JsonConverter(typeof(ElementIdConverter))]
public ElementId? TurnInQuestId { get; set; }
[JsonConverter(typeof(ElementIdConverter))]
public ElementId? NextQuestId { get; set; }
[JsonConstructor]
public QuestStep()
{
}
public QuestStep(EInteractionType interactionType, uint? dataId, Vector3? position, ushort territoryId)
{
InteractionType = interactionType;
DataId = dataId;
Position = position;
TerritoryId = territoryId;
}
public float CalculateActualStopDistance()
{
float? stopDistance = StopDistance;
if (stopDistance.HasValue)
{
return stopDistance.GetValueOrDefault();
}
switch (InteractionType)
{
case EInteractionType.WalkTo:
return 0.25f;
case EInteractionType.AttuneAetheryte:
case EInteractionType.RegisterFreeOrFavoredAetheryte:
return 10f;
default:
return 3f;
}
}
public bool IsTeleportableForPriorityQuests()
{
if (AetheryteShortcut.HasValue)
{
return true;
}
if (InteractionType == EInteractionType.UseItem && ItemId == 30362)
{
return true;
}
return false;
}
}

View file

@ -0,0 +1,36 @@
using System.Text.Json.Serialization;
using Questionable.Model.Questing.Converter;
namespace Questionable.Model.Questing;
[JsonConverter(typeof(QuestWorkConfigConverter))]
public sealed class QuestWorkValue(byte? high, byte? low, EQuestWorkMode mode)
{
public byte? High { get; set; } = high;
public byte? Low { get; set; } = low;
public EQuestWorkMode Mode { get; set; } = mode;
public QuestWorkValue(byte value)
: this((byte)(value >> 4), (byte)(value & 0xF), EQuestWorkMode.Bitwise)
{
}
public override string ToString()
{
if (High.HasValue && Low.HasValue)
{
return ((byte)(High << 4).Value + Low).ToString();
}
if (High.HasValue)
{
return High + "H";
}
if (Low.HasValue)
{
return Low + "L";
}
return "-";
}
}

View file

@ -0,0 +1,16 @@
using System.Globalization;
namespace Questionable.Model.Questing;
public sealed class SatisfactionSupplyNpcId : ElementId
{
public SatisfactionSupplyNpcId(ushort value)
: base(value)
{
}
public override string ToString()
{
return "S" + base.Value.ToString(CultureInfo.InvariantCulture);
}
}

View file

@ -0,0 +1,12 @@
using System.Collections.Generic;
namespace Questionable.Model.Questing;
public sealed class SinglePlayerDutyOptions
{
public bool Enabled { get; set; }
public List<string> Notes { get; set; } = new List<string>();
public byte Index { get; set; }
}

View file

@ -0,0 +1,33 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Questionable.Model.Common;
using Questionable.Model.Questing.Converter;
namespace Questionable.Model.Questing;
public sealed class SkipAetheryteCondition
{
public bool Never { get; set; }
public bool InSameTerritory { get; set; }
public List<ushort> InTerritory { get; set; } = new List<ushort>();
[JsonConverter(typeof(ElementIdListConverter))]
public List<ElementId> QuestsAccepted { get; set; } = new List<ElementId>();
[JsonConverter(typeof(ElementIdListConverter))]
public List<ElementId> QuestsCompleted { get; set; } = new List<ElementId>();
public EAetheryteLocation? AetheryteLocked { get; set; }
public EAetheryteLocation? AetheryteUnlocked { get; set; }
public bool RequiredQuestVariablesNotMet { get; set; }
public NearPositionCondition? NearPosition { get; set; }
public NearPositionCondition? NotNearPosition { get; set; }
public EExtraSkipCondition? ExtraCondition { get; set; }
}

View file

@ -0,0 +1,10 @@
namespace Questionable.Model.Questing;
public sealed class SkipConditions
{
public SkipStepConditions? StepIf { get; set; }
public SkipAetheryteCondition? AetheryteShortcutIf { get; set; }
public SkipAetheryteCondition? AethernetShortcutIf { get; set; }
}

View file

@ -0,0 +1,6 @@
namespace Questionable.Model.Questing;
public sealed class SkipItemConditions
{
public bool NotInInventory { get; set; }
}

View file

@ -0,0 +1,64 @@
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;
using Questionable.Model.Common;
using Questionable.Model.Questing.Converter;
namespace Questionable.Model.Questing;
public sealed class SkipStepConditions
{
public bool Never { get; set; }
public IList<QuestWorkValue?> CompletionQuestVariablesFlags { get; set; } = new List<QuestWorkValue>();
public ELockedSkipCondition? Flying { get; set; }
public ELockedSkipCondition? Chocobo { get; set; }
public bool? Diving { get; set; }
public bool NotTargetable { get; set; }
public List<ushort> InTerritory { get; set; } = new List<ushort>();
public List<ushort> NotInTerritory { get; set; } = new List<ushort>();
public SkipItemConditions? Item { get; set; }
[JsonConverter(typeof(ElementIdListConverter))]
public List<ElementId> QuestsAccepted { get; set; } = new List<ElementId>();
[JsonConverter(typeof(ElementIdListConverter))]
public List<ElementId> QuestsCompleted { get; set; } = new List<ElementId>();
public List<uint> NotNamePlateIconId { get; set; } = new List<uint>();
public EAetheryteLocation? AetheryteLocked { get; set; }
public EAetheryteLocation? AetheryteUnlocked { get; set; }
public NearPositionCondition? NearPosition { get; set; }
public NearPositionCondition? NotNearPosition { get; set; }
public EExtraSkipCondition? ExtraCondition { get; set; }
public bool HasSkipConditions()
{
if (Never)
{
return false;
}
if ((CompletionQuestVariablesFlags.Count <= 0 || !CompletionQuestVariablesFlags.Any((QuestWorkValue x) => x != null)) && !Flying.HasValue && !Chocobo.HasValue && !Diving.HasValue && !NotTargetable && InTerritory.Count <= 0 && NotInTerritory.Count <= 0 && Item == null && QuestsAccepted.Count <= 0 && QuestsCompleted.Count <= 0 && NotNamePlateIconId.Count <= 0 && !AetheryteLocked.HasValue && !AetheryteUnlocked.HasValue && NearPosition == null && NotNearPosition == null)
{
return ExtraCondition.HasValue;
}
return true;
}
public override string ToString()
{
return string.Format("{0}: {1}, {2}: {3}, {4}: {5}, {6}: {7}, {8}: {9}, {10}: {11}, {12}: {13}, {14}: {15}, {16}: {17}, {18}: {19}, {20}: {21}, {22}: {23}, {24}: {25}, {26}: {27}", "Never", Never, "CompletionQuestVariablesFlags", CompletionQuestVariablesFlags, "Flying", Flying, "Chocobo", Chocobo, "Diving", Diving, "NotTargetable", NotTargetable, "InTerritory", string.Join(" ", InTerritory), "NotInTerritory", string.Join(" ", NotInTerritory), "Item", Item, "QuestsAccepted", string.Join(" ", QuestsAccepted), "QuestsCompleted", string.Join(" ", QuestsCompleted), "NotNamePlateIconId", string.Join(" ", NotNamePlateIconId), "NearPosition", NearPosition, "ExtraCondition", ExtraCondition);
}
}

View file

@ -0,0 +1,16 @@
using System.Globalization;
namespace Questionable.Model.Questing;
public sealed class UnlockLinkId : ElementId
{
public UnlockLinkId(ushort value)
: base(value)
{
}
public override string ToString()
{
return "U" + base.Value.ToString(CultureInfo.InvariantCulture);
}
}