-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathLiveSplit.BattleBlockTheater.asl
More file actions
211 lines (200 loc) · 7.27 KB
/
LiveSplit.BattleBlockTheater.asl
File metadata and controls
211 lines (200 loc) · 7.27 KB
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
// Animation IDs:
// 0: Standing, changing weapon
// 1: Running
// 2: Ducking
// 3: Falling after double jump
// 4: Teleporting
// 5: Falling after no jump
// 14: Wall sliding
// 15: Drowning
// 18: Water paddle
// 20: Spawning
// 21: Wailing (farting)
// 22: Sliding transition
// 24: Shoving/punching
// 25: Knockback from explosion
// 29: Frog, airplane, discus, grenade, dodgeball, boomerang
// 30: Animation fail (29?)
// 33: On pig and moving
// 34: On pig
// 39: Falling after cat lick
// 40: Landed after cat lick
// 41: Enter level door
// 45: Dodgeball dizzy
// 47: Frozen
// 48: Frozen hop
// 49: Fireball
// 50: Ice
// 51: Falling after single jump
// 53: Vacuum/Fan sustain
// 56: Vacuum/Fan windup
// 57: Sliding
// 58: Throw ready
// 68: Rail climb up
// 71: Rail climb down
// 74: Rail hold facing up
// 77: Rail hold facing down
// 82: Licked by cat
// 88: Poison bubble, dart gun
// 92: Gibbed
// 93: Enter chapter door
// 95: Spring launch
// 98: Energy ball
// 101: Air-spike
// 106: Jet pack flying
// 107: Crying
// 108: Cutscene fadeout?
// 117: Loading & in cage
// 126: Hat dance
// 127: Level loading?
// 128: Hatty cutscene
state("BattleBlockTheater") {
int deathCount : 0x30E7C4, 0x4B4;
byte level : 0x30E7D8, 0x8;
int inLobby : 0x30E7D8, 0x28C; // TODO: Improve? I tried.
byte gameActive : 0x3131A5;
int loadout : 0x30ACB0, 0x64, 0x1C0; // TODO: Improve?
byte animation : 0x315420, 0x8B;
int squareX : 0x315420, 0x270;
int squareY : 0x315420, 0x274;
/*
byte chapter : 0x30E7C0, 0x37F6;
byte gemCount : 0x30E7C0, 0x37F8;
string levelName: 0x30E7C0, 0x3860;
int gameFrames : 0x315420, 0x8;
float playerX : 0x315420, 0x50;
float playerY : 0x315420, 0x54;
byte levelWidth : 0x315420, 0x20, 0x109;
byte levelHeight: 0x315420, 0x20, 0x10A;
*/
}
startup {
// Commonly used, default to true
settings.Add("Split when completing normal levels", true);
settings.Add("Split when completing secret levels", true);
settings.Add("Split when completing finale levels", true);
settings.Add("Split when completing encore levels", true);
// Less commonly used, default to false
settings.Add("Split when completing normal levels via secret exit", false);
settings.Add("Override first text component with a Death Counter", false);
// For IL runs
settings.Add("Start when entering a chapter instead of selecting a loadout", false);
settings.Add("Reset when exiting a chapter", false);
settings.Add("Start when entering level 1 instead of selecting a loadout", false);
vars.logFilePath = Directory.GetCurrentDirectory() + "\\autosplitter_battleblock.log";
vars.log = (Action<string>)((string logLine) => {
string time = System.DateTime.Now.ToString("dd/MM/yy hh:mm:ss:fff");
// AppendAllText will create the file if it doesn't exist.
System.IO.File.AppendAllText(vars.logFilePath, time + ": " + logLine + "\r\n");
});
vars.log("Autosplitter loaded");
}
init {
vars.deathCount = current.deathCount;
vars.updateText = false;
vars.tcs = null;
if (settings["Override first text component with a Death Counter"]) {
foreach (LiveSplit.UI.Components.IComponent component in timer.Layout.Components) {
if (component.GetType().Name == "TextComponent") {
vars.tc = component;
vars.tcs = vars.tc.Settings;
vars.updateText = true;
vars.log("Found text component at " + component);
break;
}
}
}
}
update {
if (vars.tcs != null && (vars.updateText || old.deathCount != current.deathCount)) {
vars.tcs.Text1 = "Death Count:";
vars.tcs.Text2 = (current.deathCount - vars.deathCount).ToString();
}
}
start {
if (settings["Start when entering a chapter instead of selecting a loadout"]) {
// Entered a chapter from the lobby
if (current.inLobby != 0) {
if (old.animation != current.animation && current.animation == 93) {
vars.log("Started because the player entered a chapter");
vars.deathCount = current.deathCount;
return true;
}
}
} else if (settings["Start when entering level 1 instead of selecting a loadout"]) {
// If we're in the lobby (253) and standing in front of door 1
if (current.level == 253 && current.squareX >= 7 && current.squareX <= 9 && current.squareY >= 15) {
if (old.animation != current.animation && current.animation == 41) { // And we start the spinny enter door animation
vars.log("Started because the player entered a level 1");
vars.deathCount = current.deathCount;
return true;
}
}
} else {
// Selected a loadout (0 -> non-0) while the game is not active
if (old.loadout == 0 && current.loadout > 0) {
vars.deathCount = current.deathCount;
vars.log("Started because the player confirmed an initial loadout");
return true;
}
}
}
reset {
if (old.gameActive == 1 && current.gameActive == 0) {
vars.log("Reset because the player returned to the main menu");
return true;
}
if (settings["Reset when exiting a chapter"]) {
if (old.inLobby == 0 && current.inLobby != 0) {
vars.log("Reset because the player returned to the lobby");
return true;
}
}
}
split {
// Don't try to split if the game hasn't loaded in
if (current.gameActive == 0) return false;
if (current.inLobby != 0) {
if (old.animation != current.animation && (current.animation == 4 || current.animation == 126)) {
vars.log("Reached the boat (end of game)");
return true;
}
return false; // Don't try to split otherwise, since we're not in a puzzle
}
// Grabbed a key or used a teleporter -- only for finale levels because gem count will mess up the timings otherwise
if (old.animation != current.animation && (current.animation == 4 || current.animation == 126)) {
vars.log("Changed from " + old.animation + " to " + current.animation);
// Levels 9-10 (10-11) are the two finales
if (9 <= current.level && current.level <= 10) {
vars.log("Completed Finale-" + (current.level-8));
return settings["Split when completing finale levels"];
}
}
// Changed levels (farted / grabbed secret exit)
if (current.level > old.level) { // Increased avoids some odd behavior at the beginning
vars.log("Changed levels from " + (old.level+1) + " to " + (current.level+1));
// Levels 0-8 (1-9) are acts 1-3
if (0 <= old.level && old.level <= 8) {
if (current.level == 14) {
vars.log("Completed level " + (old.level+1) + " via secret exit");
return settings["Split when completing normal levels via secret exit"];
} else if (current.level == old.level + 1) {
vars.log("Completed level " + (old.level+1) + " and proceeded onto the next");
return settings["Split when completing normal levels"];
} else if (current.level == 253) {
vars.log("Completed level " + (old.level+1) + " and returned to lobby");
return settings["Split when completing normal levels"];
}
}
// Levels 11-13 (12-14) are the encores
if (11 <= old.level && old.level <= 13) {
vars.log("Completed Encore-" + (old.level-10));
return settings["Split when completing encore levels"];
}
// Level 14 (15) is the secret level
if (old.level == 14) {
vars.log("Completed secret level");
return settings["Split when completing secret levels"];
}
}
}