Skip to content

Commit 59c28b6

Browse files
committed
Add The Last Faith
1 parent 6b7d1a6 commit 59c28b6

File tree

2 files changed

+225
-0
lines changed

2 files changed

+225
-0
lines changed
+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<Settings>
2+
<Setting Id="boss_death" Label="Split on defeating a boss" State="false">
3+
<Setting Id="boss_1" Label="Giant Patron" State="false" />
4+
<Setting Id="boss_2" Label="Winged Pale Laments" State="false" />
5+
<Setting Id="boss_3" Label="Dr. Ridley Hermann" State="false" />
6+
<Setting Id="boss_4" Label="Edwyn the Shadowscourge Horror" State="false" />
7+
<Setting Id="boss_5" Label="Starborn Nighthunter #1" State="false" />
8+
<Setting Id="boss_11" Label="The Burnt Apostate" State="false" />
9+
<Setting Id="boss_6" Label="Yegor &amp; Leena" State="false" />
10+
<Setting Id="boss_7" Label="Voracious Terror" State="false" />
11+
<Setting Id="boss_21" Label="Starborn Nighthunter #2" State="false" />
12+
<Setting Id="boss_9" Label="Lisa" State="false" />
13+
<Setting Id="boss_10" Label="Manfredd the Accursed" State="false" />
14+
<Setting Id="boss_12" Label="Cold One Beast" State="false" />
15+
<Setting Id="boss_13" Label="Leena" State="false" />
16+
<Setting Id="boss_14" Label="Lord Patryck Laddak" State="false" />
17+
<Setting Id="boss_20" Label="Nyxaroth the Eldritch Wight" State="false" />
18+
<Setting Id="boss_17" Label="The Old Wymond" State="false" />
19+
<Setting Id="boss_15" Label="Annabella &amp; Caterina" State="false" />
20+
<Setting Id="boss_19" Label="Starlight Best of Illygarth" State="false" />
21+
<Setting Id="boss_18" Label="The Harbinger of Nightmare" State="false" />
22+
<Setting Id="boss_16" Label="Medeya the Cosmic Voice" State="false" />
23+
<Setting Id="boss_8" Label="AssassinMacewhip (No idea what this is)" State="false" />
24+
</Setting>
25+
<Setting Id="checkpoint" Label="Split on activating a checkpoint altar" State="false">
26+
<Setting Id="Checkpoints/PRS4-Checkpoint-1" Label="Chapel Alcove [Temple of the Deposed Gods]" State="false" />
27+
<Setting Id="Checkpoints/LFS4-Checkpoint-0" Label="Old Ruins [Broken Pass]" State="false" />
28+
<Setting Id="Checkpoints/MGN2-Checkpoint-0" Label="Oxnevylle's Great Hall [Oxnevylle Manor]" State="false" />
29+
<Setting Id="Checkpoints/CTYZ3_2-Checkpoint-0" Label="Mythringal West District [City of Mythringal]" State="false" />
30+
<Setting Id="Checkpoints/CTYZ3_13-Checkpoint-0" Label="Mythringal East District [City of Mythringal]" State="false" />
31+
<Setting Id="Checkpoints/HML1-Checkpoint-0" Label="Inquisition Foyer [Federal Inquisition]" State="false" />
32+
<Setting Id="Checkpoints/HML9-Checkpoint-0" Label="Inquisition Inner Sanctum [Federal Inquisition]" State="false" />
33+
<Setting Id="Checkpoints/CAV5-Checkpoint-0" Label="Crypt Entrance [Site Cave]" State="false" />
34+
<Setting Id="Checkpoints/DCR30-Checkpoint-0" Label="Chasm of the Fallen [Drowned Crypt]" State="false" />
35+
<Setting Id="Checkpoints/SWP1-Checkpoint-0" Label="Sodden Refuge [Marshland of Shadows]" State="false" />
36+
<Setting Id="Checkpoints/SWP3-Checkpoint-1" Label="Coven's Mound [Marshland of Shadows]" State="false" />
37+
<Setting Id="Checkpoints/ERL2-Checkpoint-0" Label="Gates of Erlim [City of Erlim]" State="false" />
38+
<Setting Id="Checkpoints/ESK1-Checkpoint-1" Label="Hall of Mirrors [The Esk Mansion]" State="false" />
39+
<Setting Id="Checkpoints/DPF2 ExternalCutsceneInDifferentSceneWithEventTrigger-Checkpoint-1" Label="Old Churchyard [Liturgical Pass]" State="false" />
40+
<Setting Id="Checkpoints/DPF18-Checkpoint-0" Label="Outside the Great Church [Liturgical Pass]" State="false" />
41+
<Setting Id="Checkpoints/SNP3-Checkpoint-0" Label="Ruined Outpost [Damned Ruins of Osseus Fortress]" State="false" />
42+
<Setting Id="Checkpoints/SNP16-Checkpoint-0" Label="Telwynill Bridge [Damned Ruins of Osseus Fortress]" State="false" />
43+
<Setting Id="Checkpoints/SNP19-Checkpoint-0" Label="Frozen Caverns [Damned Ruins of Osseus Fortress]" State="false" />
44+
<Setting Id="Checkpoints/FZV7-Checkpoint-1" Label="Regent's Gate [Telwynill Village]" State="false" />
45+
<Setting Id="Checkpoints/MNF9-Checkpoint-0" Label="Ordens Shrine [Ordens Regnant Palace]" State="false" />
46+
<Setting Id="Checkpoints/MNF18-Checkpoint-0" Label="The Clocktower [Ordens Regnant Palace]" State="false" />
47+
<Setting Id="Checkpoints/BRG3-Checkpoint-0" Label="Mythringal Upper District [High walls of Mythringal]" State="false" />
48+
<Setting Id="Checkpoints/BRG9-Checkpoint-0" Label="Mythringal Hoily District [High walls of Mythringal]" State="false" />
49+
<Setting Id="Checkpoints/BRG23-Checkpoint-0" Label="Caterina's Church [High walls of Mythringal]" State="false" />
50+
<Setting Id="Checkpoints/GCT5-Checkpoint-0" Label="Altar of the Verb of Junas [The Junas Ministry]" State="false" />
51+
<Setting Id="Checkpoints/MDY1-Checkpoint-0" Label="Wonder of Illygarth's Hall [Wonder of Illygarth]" State="false" />
52+
</Setting>
53+
</Settings>

The Last Faith/thelastfaith.asl

+172
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
state("The Last Faith") { }
2+
3+
startup
4+
{
5+
Assembly.Load(File.ReadAllBytes("Components/asl-help")).CreateInstance("Unity");
6+
vars.Helper.GameName = "The Last Faith";
7+
vars.Helper.LoadSceneManager = true;
8+
vars.Helper.Settings.CreateFromXml("Components/TheLastFaith.Settings.xml");
9+
10+
vars.Watch = (Action<IDictionary<string, object>, IDictionary<string, object>, string>)((oldLookup, currentLookup, key) =>
11+
{
12+
var oldValue = oldLookup[key];
13+
var currentValue = currentLookup[key];
14+
if (oldValue != null && currentValue != null && !oldValue.Equals(currentValue))
15+
vars.Log(key + ": " + oldValue + " -> " + currentValue);
16+
});
17+
18+
vars.CompletedSplits = new HashSet<string>();
19+
20+
vars.Helper.AlertRealTime();
21+
}
22+
23+
/* Todo
24+
* - find a thing to measure the start point
25+
* - get something for when boss fights start
26+
* - picking up items (weapons, key items, etc)
27+
*/
28+
init
29+
{
30+
vars.Helper.TryLoad = (Func<dynamic, bool>)(mono =>
31+
{
32+
// I don't know why this is needed. asl-help reads all offsets as 0x10 earlier than they
33+
// actually are. (huge pain to figure out why this wasn't working)
34+
var OFFSET = 0x10;
35+
// var UIPlayerController = mono["UIPlayerController"];
36+
// var UiManager = mono["UiManager"];
37+
// var UIPanel = mono["UIPanel"];
38+
39+
// vars.Helper["hudStatus"] = UIPlayerController.Make<bool>("Instance", UIPlayerController["uiManager"] + 0x10, UiManager["currentTopHudStatus"] + 0x10);
40+
// vars.Helper["hud"] = UIPlayerController.Make<int>("Instance", UIPlayerController["uiManager"] + 0x10, UiManager["hud"] + 0x10, UIPanel["priority"] + 0x10);
41+
// vars.Helper["blackScreen"] = UIPlayerController.Make<int>("Instance", UIPlayerController["blackScreen"] + 0x10);
42+
// vars.Helper["showUIPC"] = UIPlayerController.Make<bool>("Show");
43+
44+
// var BaseController2D = mono["BaseController2D"];
45+
// var BaseHealth2D = mono["BaseHealth2D"];
46+
// vars.Helper["healthActive"] = BaseController2D.Make<bool>("Instance", BaseController2D["Health"] + 0x10, BaseHealth2D["HealthPrefab"] + 0x10, 0x57);
47+
// vars.Log("HA " + vars.Helper["healthActive"]);
48+
49+
var UIPlayerController = mono["UIPlayerController"];
50+
var DeveloperBossControllerConsole = mono["DeveloperBossControllerConsole"];
51+
var BossFightController = mono["BossFightController"];
52+
var BaseBossController = mono["BaseBossController"];
53+
var EnemyHealth = mono["EnemyHealth"];
54+
55+
vars.Helper["boss"] = UIPlayerController.Make<int>(
56+
"Instance",
57+
UIPlayerController["bossConsole"] + OFFSET,
58+
DeveloperBossControllerConsole["fightControllerScript"] + OFFSET,
59+
BossFightController["bossName"] + OFFSET
60+
);
61+
62+
vars.Helper["bossIsDead"] = UIPlayerController.Make<bool>(
63+
"Instance",
64+
UIPlayerController["bossConsole"] + OFFSET,
65+
DeveloperBossControllerConsole["fightControllerScript"] + OFFSET,
66+
BossFightController["Boss"] + OFFSET,
67+
BaseBossController["enemyHealth"] + OFFSET,
68+
EnemyHealth["isDead"] + OFFSET
69+
);
70+
// Other fun paths
71+
// 0x24
72+
// 0x40, 0x420, 0x21A // Boss, enemyHealth, isDead
73+
// 0x40, 0x420, 0x28, 0x2c // Boss, enemyHealth, health, value
74+
// 0x2F8 fightStarted
75+
76+
// (working)
77+
var CurrentActiveCheckPoint = mono["CurrentActiveCheckPoint"];
78+
var CheckPoint = mono["CheckPoint"];
79+
var PersistentObject = mono["PersistentObject"];
80+
var PersistentObjectPath = mono["PersistentObjectPath"];
81+
82+
vars.Helper["checkpoint"] = CurrentActiveCheckPoint.MakeString(
83+
"checkPoint",
84+
CheckPoint["persistentObject"] + OFFSET, // 0xC8
85+
PersistentObject["path"] + OFFSET, // 0x18,
86+
PersistentObjectPath["path"] + OFFSET // 0x10
87+
);
88+
89+
vars.Helper["checkpointInMenu"] = CurrentActiveCheckPoint.Make<bool>(
90+
"checkPoint",
91+
CheckPoint["inMenu"] + OFFSET // 0xD0
92+
);
93+
94+
return true;
95+
});
96+
97+
// this function is a helper for checking splits that may or may not exist in settings,
98+
// and if we want to do them only once
99+
vars.CheckSplit = (Func<string, bool>)(key => {
100+
// if the split doesn't exist, or it's off, or we've done it already
101+
if (!settings.ContainsKey(key)
102+
|| !settings[key]
103+
|| !vars.CompletedSplits.Add(key)
104+
) {
105+
return false;
106+
}
107+
108+
vars.Log("Completed: " + key);
109+
return true;
110+
});
111+
}
112+
113+
update
114+
{
115+
current.activeScene = vars.Helper.Scenes.Active.Name ?? current.activeScene;
116+
current.loadingScene = vars.Helper.Scenes.Loaded[0].Name ?? current.loadingScene;
117+
118+
vars.Watch(old, current, "activeScene");
119+
vars.Watch(old, current, "loadingScene");
120+
if (old.checkpoint != current.checkpoint) {
121+
vars.Log("checkpoint: " + old.checkpoint + " -> " + current.checkpoint);
122+
// vars.Log("<Setting Id=\"cp_" + current.checkpoint + "\" Label=\"\" State=\"false\">");
123+
}
124+
vars.Watch(old, current, "checkpointInMenu");
125+
126+
vars.Watch(old, current, "boss");
127+
vars.Watch(old, current, "bossIsDead");
128+
129+
// vars.Watch(old, current, "showUIPC");
130+
// vars.Watch(old, current, "healthActive");
131+
132+
// vars.Watch(old, current, "boss");
133+
}
134+
135+
onStart
136+
{
137+
// refresh all splits when we start the run, none are yet completed
138+
vars.CompletedSplits.Clear();
139+
140+
vars.Log(current.activeScene);
141+
vars.Log(current.checkpoint);
142+
vars.Log(current.checkpointInMenu);
143+
144+
vars.Log(current.boss);
145+
vars.Log(current.bossIsDead);
146+
// vars.Log(current.hudStatus);
147+
// vars.Log(current.hud);
148+
// vars.Log(current.healthActive);
149+
}
150+
151+
isLoading
152+
{
153+
return current.loadingScene != current.activeScene;
154+
}
155+
156+
split
157+
{
158+
if (settings["checkpoint"]
159+
&& !old.checkpointInMenu && current.checkpointInMenu
160+
&& vars.CheckSplit(current.checkpoint)
161+
) {
162+
return true;
163+
}
164+
165+
166+
if (settings["boss_death"]
167+
&& !old.bossIsDead && current.bossIsDead
168+
&& vars.CheckSplit("boss_" + current.boss)
169+
) {
170+
return true;
171+
}
172+
}

0 commit comments

Comments
 (0)