Compare commits

..

No commits in common. "09f8cb90785d8dba3cfe690dd6a7923ef094383a" and "c2a16e1ec161494707caa1dfc1ad7186f9f26806" have entirely different histories.

29 changed files with 52 additions and 1361 deletions

View File

@ -45,10 +45,8 @@
"Y": 58.56588,
"Z": -533.6083
},
"MinimumAngle": 185,
"MaximumAngle": 225,
"MinimumDistance": 2,
"MaximumDistance": 3
"MinimumAngle": 155,
"MaximumAngle": 325
}
]
}
@ -133,4 +131,4 @@
]
}
]
}
}

2
LLib

@ -1 +1 @@
Subproject commit e6e3a1f29715e2af4976dd7338ed2f09ae82c99c
Subproject commit 43c3dba112c202e2d0ff1a6909020c2b83e20dc3

View File

@ -127,8 +127,6 @@ internal static class QuestStepExtensions
.AsSyntaxNodeOrToken(),
AssignmentList(nameof(QuestStep.PointMenuChoices), step.PointMenuChoices)
.AsSyntaxNodeOrToken(),
Assignment(nameof(QuestStep.PurchaseMenu), step.PurchaseMenu, emptyStep.PurchaseMenu)
.AsSyntaxNodeOrToken(),
Assignment(nameof(QuestStep.PickUpQuestId), step.PickUpQuestId,
emptyStep.PickUpQuestId)
.AsSyntaxNodeOrToken(),

View File

@ -1,130 +0,0 @@
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
"Author": "plogon_enjoyer",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1016089,
"Position": {
"X": -799.46594,
"Y": -133.2695,
"Z": -404.1352
},
"TerritoryId": 401,
"InteractionType": "AcceptQuest"
}
]
},
{
"Sequence": 1,
"Steps": [
{
"DataId": 1016091,
"Position": {
"X": -804.25726,
"Y": -133.2695,
"Z": -390.89038
},
"TerritoryId": 401,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 2,
"Steps": [
{
"DataId": 1016093,
"Position": {
"X": -776.0281,
"Y": -133.35559,
"Z": -414.32825
},
"TerritoryId": 401,
"InteractionType": "Interact",
"Fly": true
}
]
},
{
"Sequence": 3,
"Steps": [
{
"Position": {
"X": -850.9607,
"Y": 2.3374987,
"Z": -234.1339
},
"TerritoryId": 401,
"InteractionType": "WalkTo",
"Fly": true
},
{
"DataId": 1016222,
"Position": {
"X": -853.8186,
"Y": 7.7667847,
"Z": -223.92621
},
"TerritoryId": 401,
"InteractionType": "Action",
"Action": "Buffet (Sanuwa)",
"Fly": true
},
{
"DataId": 1016221,
"Position": {
"X": -576.40955,
"Y": -51.59082,
"Z": -543.8773
},
"TerritoryId": 401,
"InteractionType": "Action",
"Action": "Buffet (Sanuwa)",
"Fly": true
},
{
"DataId": 1016220,
"Position": {
"X": -455.7718,
"Y": -20.828613,
"Z": -610.8644
},
"TerritoryId": 401,
"InteractionType": "Action",
"Action": "Buffet (Sanuwa)",
"Fly": true
}
]
},
{
"Sequence": 255,
"Steps": [
{
"Position": {
"X": -660.26556,
"Y": -49.27812,
"Z": -403.1036
},
"TerritoryId": 401,
"InteractionType": "WalkTo",
"AetheryteShortcut": "The Sea of Clouds - Ok' Zundu",
"Fly": true
},
{
"DataId": 1016091,
"Position": {
"X": -804.25726,
"Y": -133.2695,
"Z": -390.89038
},
"TerritoryId": 401,
"InteractionType": "CompleteQuest",
"Fly": true
}
]
}
]
}

View File

@ -1,106 +0,0 @@
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
"Author": "plogon_enjoyer",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1016089,
"Position": {
"X": -799.46594,
"Y": -133.2695,
"Z": -404.1352
},
"TerritoryId": 401,
"InteractionType": "AcceptQuest"
}
]
},
{
"Sequence": 1,
"Steps": [
{
"DataId": 1016090,
"Position": {
"X": -836.51483,
"Y": -133.26949,
"Z": -386.61786
},
"TerritoryId": 401,
"InteractionType": "Interact",
"Fly": true
}
]
},
{
"Sequence": 2,
"Steps": [
{
"Position": {
"X": 833.7674,
"Y": -97.81962,
"Z": -735.3544
},
"TerritoryId": 401,
"InteractionType": "WalkTo",
"Fly": true
},
{
"DataId": 1016223,
"Position": {
"X": 834.37854,
"Y": -97.83405,
"Z": -738.18567
},
"TerritoryId": 401,
"InteractionType": "Combat",
"EnemySpawnType": "AfterInteraction",
"KillEnemyDataIds": [5239]
}
]
},
{
"Sequence": 3,
"Steps": [
{
"DataId": 1016223,
"Position": {
"X": 834.37854,
"Y": -97.83405,
"Z": -738.18567
},
"TerritoryId": 401,
"InteractionType": "Interact"
}
]
},
{
"Sequence": 255,
"Steps": [
{
"Position": {
"X": -660.26556,
"Y": -49.27812,
"Z": -403.1036
},
"TerritoryId": 401,
"InteractionType": "WalkTo",
"AetheryteShortcut": "The Sea of Clouds - Ok' Zundu",
"Fly": true
},
{
"DataId": 1016090,
"Position": {
"X": -836.51483,
"Y": -133.26949,
"Z": -386.61786
},
"TerritoryId": 401,
"InteractionType": "CompleteQuest",
"Fly": true
}
]
}
]
}

View File

@ -1,109 +0,0 @@
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
"Author": "plogon_enjoyer",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1016089,
"Position": {
"X": -799.46594,
"Y": -133.2695,
"Z": -404.1352
},
"TerritoryId": 401,
"InteractionType": "AcceptQuest"
}
]
},
{
"Sequence": 1,
"Steps": [
{
"DataId": 1016090,
"Position": {
"X": -836.51483,
"Y": -133.26949,
"Z": -386.61786
},
"TerritoryId": 401,
"InteractionType": "Interact",
"Fly": true
}
]
},
{
"Sequence": 2,
"Steps": [
{
"DataId": 1016093,
"Position": {
"X": -776.0281,
"Y": -133.35559,
"Z": -414.32825
},
"TerritoryId": 401,
"InteractionType": "Interact",
"Fly": true
}
]
},
{
"Sequence": 3,
"Steps": [
{
"DataId": 1016227,
"Position": {
"X": 473.1975,
"Y": -98.03464,
"Z": -527.7333
},
"TerritoryId": 401,
"InteractionType": "Action",
"Action": "Buffet (Sanuwa)",
"Fly": true
},
{
"DataId": 1016226,
"Position": {
"X": 710.9331,
"Y": -98.032555,
"Z": -741.0239
},
"TerritoryId": 401,
"InteractionType": "Action",
"Action": "Buffet (Sanuwa)",
"Fly": true
}
]
},
{
"Sequence": 255,
"Steps": [
{
"Position": {
"X": -660.26556,
"Y": -49.27812,
"Z": -403.1036
},
"TerritoryId": 401,
"InteractionType": "WalkTo",
"AetheryteShortcut": "The Sea of Clouds - Ok' Zundu",
"Fly": true
},
{
"DataId": 1016090,
"Position": {
"X": -836.51483,
"Y": -133.26949,
"Z": -386.61786
},
"TerritoryId": 401,
"InteractionType": "CompleteQuest",
"Fly": true
}
]
}
]
}

View File

@ -1,129 +0,0 @@
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
"Author": "plogon_enjoyer",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1016089,
"Position": {
"X": -799.46594,
"Y": -133.2695,
"Z": -404.1352
},
"TerritoryId": 401,
"InteractionType": "AcceptQuest"
}
]
},
{
"Sequence": 1,
"Steps": [
{
"DataId": 1016092,
"Position": {
"X": -792.6299,
"Y": -133.32184,
"Z": -425.5589
},
"TerritoryId": 401,
"InteractionType": "Interact",
"Fly": true
}
]
},
{
"Sequence": 2,
"Steps": [
{
"DataId": 2006676,
"Position": {
"X": -717.0062,
"Y": -13.901062,
"Z": -101.487854
},
"TerritoryId": 401,
"InteractionType": "Interact",
"Fly": true,
"RequiredQuestVariables": [null, null, [16], null, null, null]
},
{
"DataId": 2006762,
"Position": {
"X": -781.52136,
"Y": -13.931519,
"Z": -114.30542
},
"TerritoryId": 401,
"InteractionType": "Interact",
"Fly": true,
"RequiredQuestVariables": [null, null, [32], null, null, null]
}
]
},
{
"Sequence": 3,
"Steps": [
{
"DataId": 2006675,
"Position": {
"X": -642.298,
"Y": -207.29382,
"Z": 211.10852
},
"TerritoryId": 401,
"InteractionType": "Combat",
"EnemySpawnType": "AfterItemUse",
"ItemId": 2001912,
"KillEnemyDataIds": [5240],
"Fly": true
}
]
},
{
"Sequence": 4,
"Steps": [
{
"DataId": 1012054,
"Position": {
"X": -640.1007,
"Y": -119.56208,
"Z": 469.5963
},
"TerritoryId": 401,
"InteractionType": "Interact",
"Fly": true,
"AetheryteShortcut": "The Sea of Clouds - Camp Cloudtop"
}
]
},
{
"Sequence": 255,
"Steps": [
{
"Position": {
"X": -660.26556,
"Y": -49.27812,
"Z": -403.1036
},
"TerritoryId": 401,
"InteractionType": "WalkTo",
"AetheryteShortcut": "The Sea of Clouds - Ok' Zundu",
"Fly": true
},
{
"DataId": 1016092,
"Position": {
"X": -792.6299,
"Y": -133.32184,
"Z": -425.5589
},
"TerritoryId": 401,
"InteractionType": "CompleteQuest",
"Fly": true
}
]
}
]
}

View File

@ -1,95 +0,0 @@
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
"Author": "plogon_enjoyer",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1016089,
"Position": {
"X": -799.46594,
"Y": -133.2695,
"Z": -404.1352
},
"TerritoryId": 401,
"InteractionType": "AcceptQuest"
}
]
},
{
"Sequence": 1,
"Steps": [
{
"DataId": 1016092,
"Position": {
"X": -792.6299,
"Y": -133.32184,
"Z": -425.5589
},
"TerritoryId": 401,
"InteractionType": "Interact",
"Fly": true
}
]
},
{
"Sequence": 2,
"Steps": [
{
"DataId": 2006677,
"Position": {
"X": 117.96753,
"Y": 12.25293,
"Z": -412.92444
},
"TerritoryId": 401,
"InteractionType": "Combat",
"EnemySpawnType": "AfterInteraction",
"KillEnemyDataIds": [5241],
"Fly": true
},
{
"DataId": 2006678,
"Position": {
"X": 160.54016,
"Y": 11.856201,
"Z": -507.65244
},
"TerritoryId": 401,
"InteractionType": "Combat",
"EnemySpawnType": "AfterInteraction",
"KillEnemyDataIds": [5241],
"Fly": true
}
]
},
{
"Sequence": 255,
"Steps": [
{
"Position": {
"X": -660.26556,
"Y": -49.27812,
"Z": -403.1036
},
"TerritoryId": 401,
"InteractionType": "WalkTo",
"AetheryteShortcut": "The Sea of Clouds - Ok' Zundu",
"Fly": true
},
{
"DataId": 1016092,
"Position": {
"X": -792.6299,
"Y": -133.32184,
"Z": -425.5589
},
"TerritoryId": 401,
"InteractionType": "CompleteQuest",
"Fly": true
}
]
}
]
}

View File

@ -1,101 +0,0 @@
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
"Author": "plogon_enjoyer",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1016089,
"Position": {
"X": -799.46594,
"Y": -133.2695,
"Z": -404.1352
},
"TerritoryId": 401,
"InteractionType": "AcceptQuest"
}
]
},
{
"Sequence": 1,
"Steps": [
{
"DataId": 1016092,
"Position": {
"X": -792.6299,
"Y": -133.32184,
"Z": -425.5589
},
"TerritoryId": 401,
"InteractionType": "Interact",
"Fly": true
}
]
},
{
"Sequence": 2,
"Steps": [
{
"DataId": 2006679,
"Position": {
"X": -401.175,
"Y": -202.65509,
"Z": 432.39478
},
"TerritoryId": 401,
"InteractionType": "Combat",
"EnemySpawnType": "AfterInteraction",
"KillEnemyDataIds": [5242],
"AetheryteShortcut": "The Sea of Clouds - Camp Cloudtop",
"Fly": true
}
]
},
{
"Sequence": 3,
"Steps": [
{
"DataId": 2006680,
"Position": {
"X": -280.8728,
"Y": -202.01422,
"Z": 390.7987
},
"TerritoryId": 401,
"InteractionType": "Combat",
"EnemySpawnType": "AfterInteraction",
"KillEnemyDataIds": [5242],
"Fly": true
}
]
},
{
"Sequence": 255,
"Steps": [
{
"Position": {
"X": -660.26556,
"Y": -49.27812,
"Z": -403.1036
},
"TerritoryId": 401,
"InteractionType": "WalkTo",
"AetheryteShortcut": "The Sea of Clouds - Ok' Zundu",
"Fly": true
},
{
"DataId": 1016092,
"Position": {
"X": -792.6299,
"Y": -133.32184,
"Z": -425.5589
},
"TerritoryId": 401,
"InteractionType": "CompleteQuest",
"Fly": true
}
]
}
]
}

View File

@ -1,121 +0,0 @@
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
"Author": "plogon_enjoyer",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1016089,
"Position": {
"X": -799.46594,
"Y": -133.2695,
"Z": -404.1352
},
"TerritoryId": 401,
"InteractionType": "AcceptQuest"
}
]
},
{
"Sequence": 1,
"Steps": [
{
"DataId": 1016092,
"Position": {
"X": -792.6299,
"Y": -133.32184,
"Z": -425.5589
},
"TerritoryId": 401,
"InteractionType": "Interact",
"Fly": true
}
]
},
{
"Sequence": 2,
"Steps": [
{
"DataId": 2006682,
"Position": {
"X": 25.711426,
"Y": 150.46924,
"Z": -133.56226
},
"TerritoryId": 401,
"InteractionType": "Interact",
"Fly": true
},
{
"DataId": 2006681,
"Position": {
"X": 237.07935,
"Y": 163.95813,
"Z": -46.433228
},
"TerritoryId": 401,
"InteractionType": "Interact",
"Fly": true
},
{
"Position": {
"X": 237.02913,
"Y": 169.13622,
"Z": -44.168194
},
"TerritoryId": 401,
"InteractionType": "WalkTo",
"Fly": true
},
{
"DataId": 2006683,
"Position": {
"X": 332.5094,
"Y": 106.79785,
"Z": -68.2536
},
"TerritoryId": 401,
"InteractionType": "Interact",
"Fly": true
}
]
},
{
"Sequence": 255,
"Steps": [
{
"Position": {
"X": 297.20715,
"Y": 106.011185,
"Z": -25.524097
},
"TerritoryId": 401,
"InteractionType": "WalkTo"
},
{
"Position": {
"X": -660.26556,
"Y": -49.27812,
"Z": -403.1036
},
"TerritoryId": 401,
"InteractionType": "WalkTo",
"AetheryteShortcut": "The Sea of Clouds - Ok' Zundu",
"Fly": true
},
{
"DataId": 1016092,
"Position": {
"X": -792.6299,
"Y": -133.32184,
"Z": -425.5589
},
"TerritoryId": 401,
"InteractionType": "CompleteQuest",
"Fly": true
}
]
}
]
}

View File

@ -1,173 +0,0 @@
{
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
"Author": "plogon_enjoyer",
"QuestSequence": [
{
"Sequence": 0,
"Steps": [
{
"DataId": 1016087,
"Position": {
"X": -796.7498,
"Y": -133.2695,
"Z": -410.6966
},
"TerritoryId": 401,
"InteractionType": "AcceptQuest"
}
]
},
{
"Sequence": 1,
"Steps": [
{
"DataId": 1012064,
"Position": {
"X": -542.7787,
"Y": -37.11544,
"Z": -386.7094
},
"TerritoryId": 401,
"InteractionType": "Interact",
"AetheryteShortcut": "The Sea of Clouds - Ok' Zundu",
"Fly": true
}
]
},
{
"Sequence": 2,
"Steps": [
{
"DataId": 1016174,
"Position": {
"X": -606.4088,
"Y": -51.071037,
"Z": -370.87054
},
"TerritoryId": 401,
"InteractionType": "Interact",
"Fly": true
}
]
},
{
"Sequence": 3,
"Steps": [
{
"Position": {
"X": -589.2831,
"Y": -1.0348412,
"Z": -340.14413
},
"TerritoryId": 401,
"InteractionType": "WalkTo",
"Fly": true,
"Land": true
},
{
"Position": {
"X": -589.2831,
"Y": -1.0348412,
"Z": -340.14413
},
"TerritoryId": 401,
"InteractionType": "Emote",
"Emote": "dance",
"Mount": false
}
]
},
{
"Sequence": 4,
"Steps": [
{
"DataId": 1016174,
"Position": {
"X": -606.4088,
"Y": -51.071037,
"Z": -370.87054
},
"TerritoryId": 401,
"InteractionType": "Interact",
"Fly": true
}
]
},
{
"Sequence": 5,
"Steps": [
{
"DataId": 1016175,
"Position": {
"X": 657.557,
"Y": -125.6886,
"Z": 307.60657
},
"TerritoryId": 401,
"InteractionType": "Interact",
"Fly": true
}
]
},
{
"Sequence": 6,
"Steps": [
{
"Position": {
"X": 702.4233,
"Y": -60.78939,
"Z": 145.91805
},
"TerritoryId": 401,
"InteractionType": "WalkTo",
"Fly": true,
"Land": true
},
{
"Position": {
"X": 702.4233,
"Y": -60.78939,
"Z": 145.91805
},
"TerritoryId": 401,
"InteractionType": "Emote",
"Emote": "dance",
"Mount": false
}
]
},
{
"Sequence": 7,
"Steps": [
{
"DataId": 1016175,
"Position": {
"X": 657.557,
"Y": -125.6886,
"Z": 307.60657
},
"TerritoryId": 401,
"InteractionType": "Interact",
"Fly": true
}
]
},
{
"Sequence": 255,
"Steps": [
{
"DataId": 1016174,
"Position": {
"X": -606.4088,
"Y": -51.071037,
"Z": -370.87054
},
"TerritoryId": 401,
"InteractionType": "CompleteQuest",
"AetheryteShortcut": "The Sea of Clouds - Ok' Zundu",
"Fly": true
}
]
}
]
}

View File

@ -43,14 +43,7 @@
"Z": 150.92688
},
"TerritoryId": 886,
"InteractionType": "PurchaseItem",
"PurchaseMenu": {
"ExcelSheet": "GilShop",
"Key": 262151,
"$": "This isn't the correct shop id, but it's also unclear how you'd find out"
},
"ItemId": 5768,
"ItemCount": 2,
"InteractionType": "Instruction",
"Comment": "Buy cream yellow dye",
"AethernetShortcut": [
"[Firmament] The New Nest",

View File

@ -20,6 +20,11 @@
{
"Sequence": 1,
"Steps": [
{
"TerritoryId": 963,
"InteractionType": "AttuneAethernetShard",
"AethernetShard": "[Radz-at-Han] The High Crucible of Al-Kimiya"
},
{
"DataId": 1039589,
"Position": {

View File

@ -13,13 +13,7 @@
"Z": 75.66943
},
"TerritoryId": 1185,
"InteractionType": "AcceptQuest",
"AetheryteShortcut": "Tuliyollal",
"SkipConditions": {
"AetheryteShortcutIf": {
"InSameTerritory": true
}
}
"InteractionType": "AcceptQuest"
}
]
},
@ -83,12 +77,7 @@
},
"TerritoryId": 1187,
"InteractionType": "Interact",
"AetheryteShortcut": "Urqopacha - Worlar's Echo",
"SkipConditions": {
"AetheryteShortcutIf": {
"InSameTerritory": true
}
}
"AetheryteShortcut": "Urqopacha - Worlar's Echo"
}
]
},
@ -103,14 +92,7 @@
"Z": 145.00647
},
"TerritoryId": 1187,
"InteractionType": "CompleteQuest",
"AetheryteShortcut": "Urqopacha - Worlar's Echo",
"Fly": true,
"SkipConditions": {
"AetheryteShortcutIf": {
"InSameTerritory": true
}
}
"InteractionType": "CompleteQuest"
}
]
}

View File

@ -16,17 +16,7 @@
"Z": 198.07727
},
"TerritoryId": 1186,
"InteractionType": "AcceptQuest",
"AetheryteShortcut": "Solution Nine",
"AethernetShortcut": [
"[Solution Nine] Aetheryte Plaza",
"[Solution Nine] Neon Stein"
],
"SkipConditions": {
"AetheryteShortcutIf": {
"InSameTerritory": true
}
}
"InteractionType": "AcceptQuest"
}
]
},
@ -41,13 +31,7 @@
"Z": 761.68445
},
"TerritoryId": 1192,
"InteractionType": "Interact",
"AetheryteShortcut": "Living Memory - Leynode Mnemo",
"SkipConditions": {
"AetheryteShortcutIf": {
"InSameTerritory": true
}
}
"InteractionType": "Interact"
}
]
},
@ -79,13 +63,7 @@
},
"TerritoryId": 1192,
"InteractionType": "Interact",
"Fly": true,
"AetheryteShortcut": "Living Memory - Leynode Mnemo",
"SkipConditions": {
"AetheryteShortcutIf": {
"InSameTerritory": true
}
}
"Fly": true
}
]
},
@ -112,13 +90,7 @@
"StopDistance": 7,
"TerritoryId": 1192,
"InteractionType": "Interact",
"Fly": true,
"AetheryteShortcut": "Living Memory - Leynode Mnemo",
"SkipConditions": {
"AetheryteShortcutIf": {
"InSameTerritory": true
}
}
"Fly": true
}
]
},

View File

@ -119,7 +119,6 @@
"Combat",
"UseItem",
"EquipItem",
"PurchaseItem",
"EquipRecommended",
"Say",
"Emote",
@ -708,44 +707,6 @@
]
}
},
{
"if": {
"properties": {
"InteractionType": {
"const": "PurchaseItem"
}
}
},
"then": {
"properties": {
"ItemCount": {
"type": "integer"
},
"PurchaseMenu": {
"type": "object",
"description": "The text to use with /say",
"properties": {
"ExcelSheet": {
"type": "string"
},
"Key": {
"type": [
"string",
"integer"
]
}
},
"required": [
"Key"
]
}
},
"required": [
"ItemId",
"ItemCount"
]
}
},
{
"if": {
"properties": {

View File

@ -16,7 +16,6 @@ public sealed class InteractionTypeConverter() : EnumConverter<EInteractionType>
{ EInteractionType.Combat, "Combat" },
{ EInteractionType.UseItem, "UseItem" },
{ EInteractionType.EquipItem, "EquipItem" },
{ EInteractionType.PurchaseItem, "PurchaseItem" },
{ EInteractionType.EquipRecommended, "EquipRecommended" },
{ EInteractionType.Say, "Say" },
{ EInteractionType.Emote, "Emote" },

View File

@ -15,7 +15,6 @@ public enum EInteractionType
Combat,
UseItem,
EquipItem,
PurchaseItem,
EquipRecommended,
Say,
Emote,

View File

@ -1,12 +0,0 @@
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

@ -78,7 +78,6 @@ public sealed class QuestStep
public List<QuestWorkValue?> CompletionQuestVariablesFlags { get; set; } = [];
public List<DialogueChoice> DialogueChoices { get; set; } = [];
public List<uint> PointMenuChoices { get; set; } = [];
public PurchaseMenu? PurchaseMenu { get; set; }
// TODO: Not implemented
[JsonConverter(typeof(ElementIdConverter))]

View File

@ -35,7 +35,6 @@ internal sealed class CombatController : IDisposable
private CurrentFight? _currentFight;
private bool _wasInCombat;
private ulong? _lastTargetId;
public CombatController(
IEnumerable<ICombatModule> combatModules,
@ -93,33 +92,6 @@ internal sealed class CombatController : IDisposable
_movementController.MovementStartedAt > DateTime.Now.AddSeconds(-1))
return EStatus.Moving;
// Overworld enemies typically means that if we want to kill 3 enemies, we could have anywhere from 0 to 20
// enemies in the area (0 if someone else killed them before, like can happen with bots in Fools' Falls in
// La Noscea).
//
// For all 'normal' types, e.g. auto-spawning on entering an area, there's a fixed number of enemies that you're
// fighting with, and the enemies in the overworld aren't relevant.
if (_currentFight.Data.SpawnType is EEnemySpawnType.OverworldEnemies)
{
if (_targetManager.Target != null)
_lastTargetId = _targetManager.Target?.GameObjectId;
else
{
if (_lastTargetId != null)
{
IGameObject? lastTarget = _objectTable.FirstOrDefault(x => x.GameObjectId == _lastTargetId);
if (lastTarget != null)
{
// wait until the game cleans up the target
if (lastTarget.IsDead)
return EStatus.InCombat;
}
else
_lastTargetId = null;
}
}
}
var target = _targetManager.Target;
if (target != null)
{
@ -220,36 +192,44 @@ internal sealed class CombatController : IDisposable
public unsafe int GetKillPriority(IGameObject gameObject)
{
if (_currentFight == null)
return 0;
if (gameObject is IBattleNpc battleNpc)
{
if (!_currentFight.Module.CanAttack(battleNpc))
if (_currentFight != null && !_currentFight.Module.CanAttack(battleNpc))
return 0;
if (battleNpc.IsDead)
return 0;
// TODO this works as somewhat of a delay between killing enemies if certain items/flags are checked
// but also delays killing the next enemy a little
if (_currentFight == null ||
_currentFight.Data.SpawnType == EEnemySpawnType.OverworldEnemies ||
_currentFight.Data.SpawnType == EEnemySpawnType.FateEnemies ||
_currentFight.Data.KillEnemyDataIds.Count > 0)
{
if (battleNpc.IsDead)
return 0;
}
if (!battleNpc.IsTargetable)
return 0;
var complexCombatData = _currentFight.Data.ComplexCombatDatas;
if (complexCombatData.Count >= 0)
if (_currentFight != null)
{
for (int i = 0; i < complexCombatData.Count; ++i)
var complexCombatData = _currentFight.Data.ComplexCombatDatas;
if (complexCombatData.Count >= 0)
{
if (_currentFight.Data.CompletedComplexDatas.Contains(i))
continue;
for (int i = 0; i < complexCombatData.Count; ++i)
{
if (_currentFight.Data.CompletedComplexDatas.Contains(i))
continue;
if (complexCombatData[i].DataId == battleNpc.DataId)
return 100;
if (complexCombatData[i].DataId == battleNpc.DataId)
return 100;
}
}
else
{
if (_currentFight.Data.KillEnemyDataIds.Contains(battleNpc.DataId))
return 90;
}
}
else
{
if (_currentFight.Data.KillEnemyDataIds.Contains(battleNpc.DataId))
return 90;
}
// enemies that we have aggro on
@ -261,7 +241,8 @@ internal sealed class CombatController : IDisposable
if (gameObjectStruct->NamePlateIconId is 60093 or 60732)
return 0;
var enemyData = _currentFight.Data.ComplexCombatDatas.FirstOrDefault(x => x.DataId == battleNpc.DataId);
var enemyData =
_currentFight?.Data.ComplexCombatDatas.FirstOrDefault(x => x.DataId == battleNpc.DataId);
if (enemyData is { IgnoreQuestMarker: true })
{
if (battleNpc.StatusFlags.HasFlag(StatusFlags.InCombat))
@ -274,8 +255,7 @@ internal sealed class CombatController : IDisposable
// for enemies that are very far away, their nameplate doesn't render but they're in the object table
if (_currentFight?.Data.SpawnType == EEnemySpawnType.OverworldEnemies &&
Vector3.Distance(_clientState.LocalPlayer?.Position ?? Vector3.Zero, battleNpc.Position) >
MaxNameplateRange)
Vector3.Distance(_clientState.LocalPlayer?.Position ?? Vector3.Zero, battleNpc.Position) > MaxNameplateRange)
return 25;
}
else
@ -318,14 +298,12 @@ internal sealed class CombatController : IDisposable
}
else if (Vector3.Distance(_clientState.LocalPlayer!.Position, target.Position) > MaxTargetRange)
{
_logger.LogInformation("Moving to target, distance: {Distance:N2}",
Vector3.Distance(_clientState.LocalPlayer!.Position, target.Position));
_logger.LogInformation("Moving to target, distance: {Distance:N2}", Vector3.Distance(_clientState.LocalPlayer!.Position, target.Position));
_currentFight!.Module.MoveToTarget(target);
}
else
{
_logger.LogInformation("Setting target to {TargetName} ({TargetId:X8})", target.Name.ToString(),
target.GameObjectId);
_logger.LogInformation("Setting target to {TargetName} ({TargetId:X8})", target.Name.ToString(), target.GameObjectId);
_targetManager.Target = target;
_currentFight!.Module.MoveToTarget(target);
}

View File

@ -46,7 +46,6 @@ internal sealed class InteractionUiController : IDisposable
private readonly IGameGui _gameGui;
private readonly ITargetManager _targetManager;
private readonly IClientState _clientState;
private readonly ShopController _shopController;
private readonly ILogger<InteractionUiController> _logger;
private readonly Regex _returnRegex;
@ -68,7 +67,6 @@ internal sealed class InteractionUiController : IDisposable
ITargetManager targetManager,
IPluginLog pluginLog,
IClientState clientState,
ShopController shopController,
ILogger<InteractionUiController> logger)
{
_addonLifecycle = addonLifecycle;
@ -85,7 +83,6 @@ internal sealed class InteractionUiController : IDisposable
_gameGui = gameGui;
_targetManager = targetManager;
_clientState = clientState;
_shopController = shopController;
_logger = logger;
_returnRegex = _dataManager.GetExcelSheet<Addon>()!.GetRow(196)!.GetRegex(addon => addon.Text, pluginLog)!;
@ -337,17 +334,7 @@ internal sealed class InteractionUiController : IDisposable
if (step == null)
_logger.LogDebug("Ignoring current quest dialogue choices, no active step");
else
{
dialogueChoices.AddRange(step.DialogueChoices.Select(x => new DialogueChoiceInfo(quest, x)));
if (step.PurchaseMenu != null)
dialogueChoices.Add(new DialogueChoiceInfo(quest, new DialogueChoice
{
Type = EDialogChoiceType.List,
ExcelSheet = step.PurchaseMenu.ExcelSheet,
Prompt = null,
Answer = step.PurchaseMenu.Key,
}));
}
}
// add all travel dialogue choices
@ -529,13 +516,6 @@ internal sealed class InteractionUiController : IDisposable
return;
_logger.LogTrace("Prompt: '{Prompt}'", actualPrompt);
if (_shopController.IsAutoBuyEnabled && _shopController.IsAwaitingYesNo)
{
addonSelectYesno->AtkUnitBase.FireCallbackInt(0);
_shopController.IsAwaitingYesNo = false;
return;
}
var director = UIState.Instance()->DirectorTodo.Director;
if (director != null &&
director->Info.EventId.ContentId == EventHandlerType.GatheringLeveDirector &&

View File

@ -1,156 +0,0 @@
using System;
using System.Linq;
using System.Numerics;
using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Component.GUI;
using LLib.GameUI;
using LLib.Shop;
using Microsoft.Extensions.Logging;
using Questionable.Model.Questing;
using Workshoppa.GameData.Shops;
using ValueType = FFXIVClientStructs.FFXIV.Component.GUI.ValueType;
namespace Questionable.Controller.GameUi;
internal sealed class ShopController : IDisposable, IShopWindow
{
private readonly QuestController _questController;
private readonly IGameGui _gameGui;
private readonly IFramework _framework;
private readonly RegularShopBase _shop;
private readonly ILogger<ShopController> _logger;
public ShopController(QuestController questController, IGameGui gameGui, IAddonLifecycle addonLifecycle,
IFramework framework, ILogger<ShopController> logger, IPluginLog pluginLog)
{
_questController = questController;
_gameGui = gameGui;
_framework = framework;
_shop = new RegularShopBase(this, "Shop", pluginLog, gameGui, addonLifecycle);
_logger = logger;
_framework.Update += FrameworkUpdate;
}
public bool IsEnabled => _questController.IsRunning;
public bool IsOpen { get; set; }
public bool IsAutoBuyEnabled => _shop.AutoBuyEnabled;
public bool IsAwaitingYesNo
{
get { return _shop.IsAwaitingYesNo; }
set { _shop.IsAwaitingYesNo = value; }
}
public Vector2? Position { get; set; } // actual implementation doesn't matter, not a real window
public void Dispose()
{
_framework.Update -= FrameworkUpdate;
_shop.Dispose();
}
private void FrameworkUpdate(IFramework framework)
{
if (IsOpen && _shop.ItemForSale != null)
{
if (_shop.PurchaseState != null)
{
_shop.HandleNextPurchaseStep();
}
else
{
var currentStep = FindCurrentStep();
if (currentStep == null || currentStep.InteractionType != EInteractionType.PurchaseItem)
return;
int missingItems = Math.Max(0,
currentStep.ItemCount.GetValueOrDefault() - (int)_shop.ItemForSale.OwnedItems);
int toPurchase = Math.Min(_shop.GetMaxItemsToPurchase(), missingItems);
if (toPurchase > 0)
{
_logger.LogDebug("Auto-buying {MissingItems} {ItemName}", missingItems, _shop.ItemForSale.ItemName);
_shop.StartAutoPurchase(missingItems);
_shop.HandleNextPurchaseStep();
}
else
_shop.CancelAutoPurchase();
}
}
}
public int GetCurrencyCount() => _shop.GetItemCount(1); // TODO: support other currencies
private QuestStep? FindCurrentStep()
{
var currentQuest = _questController.CurrentQuest;
QuestSequence? currentSequence = currentQuest?.Quest.FindSequence(currentQuest.Sequence);
return currentSequence?.FindStep(currentQuest?.Step ?? 0);
}
public unsafe void UpdateShopStock(AtkUnitBase* addon)
{
var currentStep = FindCurrentStep();
if (currentStep == null || currentStep.InteractionType != EInteractionType.PurchaseItem)
{
_shop.ItemForSale = null;
return;
}
if (addon->AtkValuesCount != 625)
{
_logger.LogError("Unexpected amount of atkvalues for Shop addon ({AtkValueCount})", addon->AtkValuesCount);
_shop.ItemForSale = null;
return;
}
var atkValues = addon->AtkValues;
// Check if on 'Current Stock' tab?
if (atkValues[0].UInt != 0)
{
_shop.ItemForSale = null;
return;
}
uint itemCount = atkValues[2].UInt;
if (itemCount == 0)
{
_shop.ItemForSale = null;
return;
}
_shop.ItemForSale = Enumerable.Range(0, (int)itemCount)
.Select(i => new ItemForSale
{
Position = i,
ItemName = atkValues[14 + i].ReadAtkString(),
Price = atkValues[75 + i].UInt,
OwnedItems = atkValues[136 + i].UInt,
ItemId = atkValues[441 + i].UInt,
})
.FirstOrDefault(x => x.ItemId == currentStep.ItemId);
}
public unsafe void TriggerPurchase(AtkUnitBase* addonShop, int buyNow)
{
var buyItem = stackalloc AtkValue[]
{
new() { Type = ValueType.Int, Int = 0 },
new() { Type = ValueType.Int, Int = _shop.ItemForSale!.Position },
new() { Type = ValueType.Int, Int = buyNow },
new() { Type = 0, Int = 0 }
};
addonShop->FireCallback(4, buyItem);
}
public void SaveExternalPluginState()
{
}
public unsafe void RestoreExternalPluginState()
{
if (_gameGui.TryGetAddonByName("Shop", out AtkUnitBase* addonShop))
addonShop->FireCallbackInt(-1);
}
}

View File

@ -35,11 +35,6 @@ internal static class Interact
if (step.DataId == null)
yield break;
}
else if (step.InteractionType == EInteractionType.PurchaseItem)
{
if (step.DataId == null)
yield break;
}
else if (step.InteractionType == EInteractionType.Snipe)
{
if (!configuration.General.AutomaticallyCompleteSnipeTasks)
@ -56,8 +51,7 @@ internal static class Interact
yield return new Task(step.DataId.Value, quest, step.InteractionType,
step.TargetTerritoryId != null || quest.Id is SatisfactionSupplyNpcId ||
step.SkipConditions is { StepIf.Never: true } || step.InteractionType == EInteractionType.PurchaseItem,
step.PickUpItemId, step.SkipConditions?.StepIf);
step.SkipConditions is { StepIf.Never: true }, step.PickUpItemId, step.SkipConditions?.StepIf);
}
}
@ -153,8 +147,7 @@ internal static class Interact
}
else
{
if (ProgressContext != null && (ProgressContext.WasSuccessful() ||
_interactionState == EInteractionState.InteractionConfirmed))
if (ProgressContext != null && (ProgressContext.WasSuccessful() || _interactionState == EInteractionState.InteractionConfirmed))
return ETaskResult.TaskComplete;
if (InteractionType == EInteractionType.Gather && condition[ConditionFlag.Gathering])

View File

@ -1,22 +0,0 @@
using Questionable.Model;
using Questionable.Model.Questing;
namespace Questionable.Controller.Steps.Interactions;
internal static class PurchaseItem
{
internal sealed class Factory : SimpleTaskFactory
{
public override ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step)
{
if (step.InteractionType != EInteractionType.PurchaseItem)
return null;
throw new System.NotImplementedException();
}
}
internal sealed class PurchaseRequest
{
}
}

View File

@ -5,7 +5,6 @@ namespace Questionable.Controller.Steps;
internal interface ITaskExecutor
{
ITask CurrentTask { get; }
public InteractionProgressContext? ProgressContext { get; }
Type GetTaskType();
@ -20,7 +19,7 @@ internal abstract class TaskExecutor<T> : ITaskExecutor
where T : class, ITask
{
protected T Task { get; set; } = null!;
public InteractionProgressContext? ProgressContext { get; set; }
protected InteractionProgressContext? ProgressContext { get; set; }
ITask ITaskExecutor.CurrentTask => Task;
public bool WasInterrupted()

View File

@ -91,11 +91,6 @@ internal sealed class ExcelFunctions
var questRow = _dataManager.GetExcelSheet<EventPathMove>()!.GetRow(rowId);
return questRow?.Unknown10;
}
else if (excelSheet is "GilShop")
{
var questRow = _dataManager.GetExcelSheet<GilShop>()!.GetRow(rowId);
return questRow?.Name;
}
else if (excelSheet is "ContentTalk" or null)
{
var questRow = _dataManager.GetExcelSheet<ContentTalk>()!.GetRow(rowId);

View File

@ -224,7 +224,6 @@ public sealed class QuestionablePlugin : IDalamudPlugin
serviceCollection.AddSingleton<CombatController>();
serviceCollection.AddSingleton<GatheringController>();
serviceCollection.AddSingleton<ContextMenuController>();
serviceCollection.AddSingleton<ShopController>();
serviceCollection.AddSingleton<CraftworksSupplyController>();
serviceCollection.AddSingleton<CreditsController>();
@ -285,7 +284,6 @@ public sealed class QuestionablePlugin : IDalamudPlugin
serviceProvider.GetRequiredService<CreditsController>();
serviceProvider.GetRequiredService<HelpUiController>();
serviceProvider.GetRequiredService<LeveUiController>();
serviceProvider.GetRequiredService<ShopController>();
serviceProvider.GetRequiredService<QuestionableIpc>();
serviceProvider.GetRequiredService<DalamudInitializer>();
serviceProvider.GetRequiredService<AutoSnipeHandler>().Enable();

View File

@ -29,7 +29,6 @@ namespace Questionable.Windows.QuestComponents;
internal sealed class CreationUtilsComponent
{
private readonly QuestController _questController;
private readonly MovementController _movementController;
private readonly GameFunctions _gameFunctions;
private readonly QuestFunctions _questFunctions;
@ -44,7 +43,6 @@ internal sealed class CreationUtilsComponent
private readonly ILogger<CreationUtilsComponent> _logger;
public CreationUtilsComponent(
QuestController questController,
MovementController movementController,
GameFunctions gameFunctions,
QuestFunctions questFunctions,
@ -58,7 +56,6 @@ internal sealed class CreationUtilsComponent
Configuration configuration,
ILogger<CreationUtilsComponent> logger)
{
_questController = questController;
_movementController = movementController;
_gameFunctions = gameFunctions;
_questFunctions = questFunctions;
@ -157,14 +154,13 @@ internal sealed class CreationUtilsComponent
}
#endif
#if true
#if false
unsafe
{
var actionManager = ActionManager.Instance();
ImGui.Text(
$"A1: {actionManager->CastActionId} ({actionManager->LastUsedActionSequence} → {actionManager->LastHandledActionSequence})");
ImGui.Text($"A2: {actionManager->CastTimeElapsed} / {actionManager->CastTimeTotal}");
ImGui.Text($"{_questController.TaskQueue.CurrentTaskExecutor?.ProgressContext}");
}
#endif