about summary refs log tree commit diff stats
path: root/Source/Randomizer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Randomizer.cpp')
-rw-r--r--Source/Randomizer.cpp405
1 files changed, 84 insertions, 321 deletions
diff --git a/Source/Randomizer.cpp b/Source/Randomizer.cpp index c573146..d67f153 100644 --- a/Source/Randomizer.cpp +++ b/Source/Randomizer.cpp
@@ -93,7 +93,6 @@ Things to do for V2:
93*/ 93*/
94#include "pch.h" 94#include "pch.h"
95#include "Randomizer.h" 95#include "Randomizer.h"
96#include "ChallengeRandomizer.h"
97#include "Panels.h" 96#include "Panels.h"
98#include "Random.h" 97#include "Random.h"
99 98
@@ -124,344 +123,108 @@ void Randomizer::Randomize() {
124 } 123 }
125 _memory->WriteData<byte>({index}, {0xEB}); // jz -> jmp 124 _memory->WriteData<byte>({index}, {0xEB}); // jz -> jmp
126 }); 125 });
127 // Sig scans will be run during challenge randomization.
128
129 // Seed challenge first for future-proofing
130 MEMORY_CATCH(RandomizeChallenge());
131
132 // Content swaps -- must happen before squarePanels
133 MEMORY_CATCH(Randomize(upDownPanels, SWAP::LINES | SWAP::COLORS));
134 MEMORY_CATCH(Randomize(leftForwardRightPanels, SWAP::LINES | SWAP::COLORS));
135
136 MEMORY_CATCH(Randomize(squarePanels, SWAP::LINES | SWAP::COLORS));
137
138 // Individual area modifications
139 MEMORY_CATCH(RandomizeTutorial());
140 MEMORY_CATCH(RandomizeDesert());
141 MEMORY_CATCH(RandomizeQuarry());
142 MEMORY_CATCH(RandomizeTreehouse());
143 MEMORY_CATCH(RandomizeKeep());
144 MEMORY_CATCH(RandomizeShadows());
145 MEMORY_CATCH(RandomizeMonastery());
146 MEMORY_CATCH(RandomizeBunker());
147 MEMORY_CATCH(RandomizeJungle());
148 MEMORY_CATCH(RandomizeSwamp());
149 MEMORY_CATCH(RandomizeMountain());
150 MEMORY_CATCH(RandomizeTown());
151 MEMORY_CATCH(RandomizeSymmetry());
152 // RandomizeAudioLogs();
153}
154 126
155void Randomizer::AdjustSpeed() { 127 _memory->ExecuteSigScans();
156 // Desert Surface Final Control
157 _memory->WriteEntityData<float>(0x09F95, OPEN_RATE, {0.04f}); // 4x
158 // Swamp Sliding Bridge
159 _memory->WriteEntityData<float>(0x0061A, OPEN_RATE, {0.1f}); // 4x
160 // Mountain 2 Elevator
161 _memory->WriteEntityData<float>(0x09EEC, OPEN_RATE, {0.075f}); // 3x
162}
163 128
164void Randomizer::RandomizeLasers() { 129 // Tutorial Bend
165 Randomize(lasers, SWAP::TARGETS); 130 for (int panel : utmPerspective) {
166 // Read the target of keep front laser, and write it to keep back laser. 131 Tutorialise(panel, 0x00182);
167 std::vector<int> keepFrontLaserTarget = _memory->ReadEntityData<int>(0x0360E, TARGET, 1); 132 }
168 _memory->WriteEntityData<int>(0x03317, TARGET, keepFrontLaserTarget); 133 // Tutorial Straight
169} 134 for (int panel : squarePanels) {
135 Tutorialise(panel, 0x00064);
136 }
137 // Town Laser Redirect Control
138 for (int panel : treehousePivots) {
139 Tutorialise(panel, 0x09F98);
170 140
171void Randomizer::PreventSnipes() 141 // Mark the panel as pivotable.
172{ 142 int panelFlags = _memory->ReadEntityData<int>(panel, STYLE_FLAGS, 1)[0];
173 // Distance-gate swamp snipe 1 to prevent RNG swamp snipe 143 _memory->WriteEntityData<int>(panel, STYLE_FLAGS, { panelFlags | 0x8000 });
174 _memory->WriteEntityData<float>(0x17C05, MAX_BROADCAST_DISTANCE, {15.0}); 144 }
175 // Distance-gate shadows laser to prevent sniping through the bars
176 _memory->WriteEntityData<float>(0x19650, MAX_BROADCAST_DISTANCE, {2.5});
177}
178 145
179// Private methods
180void Randomizer::RandomizeTutorial() {
181 // Disable tutorial cursor speed modifications (not working?) 146 // Disable tutorial cursor speed modifications (not working?)
182 _memory->WriteEntityData<float>(0x00295, CURSOR_SPEED_SCALE, {1.0}); 147 _memory->WriteEntityData<float>(0x00295, CURSOR_SPEED_SCALE, { 1.0 });
183 _memory->WriteEntityData<float>(0x0C373, CURSOR_SPEED_SCALE, {1.0}); 148 _memory->WriteEntityData<float>(0x0C373, CURSOR_SPEED_SCALE, { 1.0 });
184 _memory->WriteEntityData<float>(0x00293, CURSOR_SPEED_SCALE, {1.0}); 149 _memory->WriteEntityData<float>(0x00293, CURSOR_SPEED_SCALE, { 1.0 });
185 _memory->WriteEntityData<float>(0x002C2, CURSOR_SPEED_SCALE, {1.0}); 150 _memory->WriteEntityData<float>(0x002C2, CURSOR_SPEED_SCALE, { 1.0 });
186}
187 151
188void Randomizer::RandomizeSymmetry() {
189 std::vector<int> randomOrder(transparent.size(), 0);
190 std::iota(randomOrder.begin(), randomOrder.end(), 0);
191 Shuffle(randomOrder, 1, 5);
192 ReassignTargets(transparent, randomOrder);
193}
194
195void Randomizer::RandomizeDesert() {
196 Randomize(desertPanels, SWAP::LINES);
197
198 // Turn off desert surface 8
199 _memory->WriteEntityData<float>(0x09F94, POWER, {0.0, 0.0});
200 // Turn off desert flood final
201 _memory->WriteEntityData<float>(0x18076, POWER, {0.0, 0.0});
202 // Change desert floating target to desert flood final
203 _memory->WriteEntityData<int>(0x17ECA, TARGET, {0x18077});
204}
205
206void Randomizer::RandomizeQuarry() {
207}
208
209void Randomizer::RandomizeTreehouse() {
210 // Ensure that whatever pivot panels we have are flagged as "pivotable" 152 // Ensure that whatever pivot panels we have are flagged as "pivotable"
211 // @Bug: Can return {}, be careful! 153 // @Bug: Can return {}, be careful!
212 int panelFlags = _memory->ReadEntityData<int>(0x17DD1, STYLE_FLAGS, 1)[0]; 154 int panelFlags = _memory->ReadEntityData<int>(0x17DD1, STYLE_FLAGS, 1)[0];
213 _memory->WriteEntityData<int>(0x17DD1, STYLE_FLAGS, {panelFlags | 0x8000}); 155 _memory->WriteEntityData<int>(0x17DD1, STYLE_FLAGS, { panelFlags | 0x8000 });
214 panelFlags = _memory->ReadEntityData<int>(0x17CE3, STYLE_FLAGS, 1)[0]; 156 panelFlags = _memory->ReadEntityData<int>(0x17CE3, STYLE_FLAGS, 1)[0];
215 _memory->WriteEntityData<int>(0x17CE3, STYLE_FLAGS, {panelFlags | 0x8000}); 157 _memory->WriteEntityData<int>(0x17CE3, STYLE_FLAGS, { panelFlags | 0x8000 });
216 panelFlags = _memory->ReadEntityData<int>(0x17DB7, STYLE_FLAGS, 1)[0]; 158 panelFlags = _memory->ReadEntityData<int>(0x17DB7, STYLE_FLAGS, 1)[0];
217 _memory->WriteEntityData<int>(0x17DB7, STYLE_FLAGS, {panelFlags | 0x8000}); 159 _memory->WriteEntityData<int>(0x17DB7, STYLE_FLAGS, { panelFlags | 0x8000 });
218 panelFlags = _memory->ReadEntityData<int>(0x17E52, STYLE_FLAGS, 1)[0]; 160 panelFlags = _memory->ReadEntityData<int>(0x17E52, STYLE_FLAGS, 1)[0];
219 _memory->WriteEntityData<int>(0x17E52, STYLE_FLAGS, {panelFlags | 0x8000}); 161 _memory->WriteEntityData<int>(0x17E52, STYLE_FLAGS, { panelFlags | 0x8000 });
220} 162}
221 163
222void Randomizer::RandomizeKeep() { 164void Randomizer::Tutorialise(int panel1, int tutorialStraight) {
223} 165 //const int tutorialStraight = 0x00064;
224 166
225void Randomizer::RandomizeShadows() { 167 _memory->CopyEntityData<byte>(tutorialStraight, panel1, PATH_COLOR, 16);
226 // Change the shadows tutorial cable to only activate avoid 168 _memory->CopyEntityData<byte>(tutorialStraight, panel1, REFLECTION_PATH_COLOR, 16);
227 _memory->WriteEntityData<int>(0x319A8, CABLE_TARGET_2, {0}); 169 _memory->CopyEntityData<byte>(tutorialStraight, panel1, DOT_COLOR, 16);
228 // Change shadows avoid 8 to power shadows follow 170 _memory->CopyEntityData<byte>(tutorialStraight, panel1, ACTIVE_COLOR, 16);
229 _memory->WriteEntityData<int>(0x1972F, TARGET, {0x1C34C}); 171 _memory->CopyEntityData<byte>(tutorialStraight, panel1, BACKGROUND_REGION_COLOR, 12);
230 172 _memory->CopyEntityData<byte>(tutorialStraight, panel1, SUCCESS_COLOR_A, 16);
231 std::vector<int> randomOrder(shadowsPanels.size(), 0); 173 _memory->CopyEntityData<byte>(tutorialStraight, panel1, SUCCESS_COLOR_B, 16);
232 std::iota(randomOrder.begin(), randomOrder.end(), 0); 174 _memory->CopyEntityData<byte>(tutorialStraight, panel1, STROBE_COLOR_A, 16);
233 Shuffle(randomOrder, 0, 8); // Tutorial 175 _memory->CopyEntityData<byte>(tutorialStraight, panel1, STROBE_COLOR_B, 16);
234 Shuffle(randomOrder, 8, 16); // Avoid 176 _memory->CopyEntityData<byte>(tutorialStraight, panel1, ERROR_COLOR, 16);
235 Shuffle(randomOrder, 16, 21); // Follow 177 _memory->CopyEntityData<byte>(tutorialStraight, panel1, PATTERN_POINT_COLOR, 16);
236 ReassignTargets(shadowsPanels, randomOrder); 178 _memory->CopyEntityData<byte>(tutorialStraight, panel1, PATTERN_POINT_COLOR_A, 16);
237 // Turn off original starting panel 179 _memory->CopyEntityData<byte>(tutorialStraight, panel1, PATTERN_POINT_COLOR_B, 16);
238 _memory->WriteEntityData<float>(shadowsPanels[0], POWER, {0.0f, 0.0f}); 180 _memory->CopyEntityData<byte>(tutorialStraight, panel1, SYMBOL_A, 16);
239 // Turn on new starting panel 181 _memory->CopyEntityData<byte>(tutorialStraight, panel1, SYMBOL_B, 16);
240 _memory->WriteEntityData<float>(shadowsPanels[randomOrder[0]], POWER, {1.0f, 1.0f}); 182 _memory->CopyEntityData<byte>(tutorialStraight, panel1, SYMBOL_C, 16);
241} 183 _memory->CopyEntityData<byte>(tutorialStraight, panel1, SYMBOL_D, 16);
242 184 _memory->CopyEntityData<byte>(tutorialStraight, panel1, SYMBOL_E, 16);
243void Randomizer::RandomizeTown() { 185 _memory->CopyEntityData<byte>(tutorialStraight, panel1, PUSH_SYMBOL_COLORS, sizeof(int));
244 // @Hack...? To open the gate at the end 186 _memory->CopyEntityData<byte>(tutorialStraight, panel1, OUTER_BACKGROUND, 16);
245 std::vector<int> randomOrder(orchard.size() + 1, 0); 187 _memory->CopyEntityData<byte>(tutorialStraight, panel1, OUTER_BACKGROUND_MODE, sizeof(int));
246 std::iota(randomOrder.begin(), randomOrder.end(), 0); 188 _memory->CopyEntityData<byte>(tutorialStraight, panel1, NUM_COLORED_REGIONS, sizeof(int));
247 Shuffle(randomOrder, 1, 5); 189 _memory->CopyArrayDynamicSize<int>(tutorialStraight, panel1, COLORED_REGIONS, NUM_COLORED_REGIONS);
248 // Ensure that we open the gate before the final puzzle (by swapping) 190 _memory->CopyEntityData<byte>(tutorialStraight, panel1, TRACED_EDGES, 16);
249 int panel3Index = find(randomOrder, 3); 191 _memory->CopyEntityData<byte>(tutorialStraight, panel1, PATH_WIDTH_SCALE, sizeof(float));
250 int panel4Index = find(randomOrder, 4); 192 _memory->CopyEntityData<byte>(tutorialStraight, panel1, STARTPOINT_SCALE, sizeof(float));
251 randomOrder[std::min(panel3Index, panel4Index)] = 3; 193 _memory->CopyEntityData<byte>(tutorialStraight, panel1, NUM_DOTS, sizeof(int));
252 randomOrder[std::max(panel3Index, panel4Index)] = 4; 194 _memory->CopyEntityData<byte>(tutorialStraight, panel1, NUM_CONNECTIONS, sizeof(int));
253 ReassignTargets(orchard, randomOrder); 195 _memory->CopyArray<float>(tutorialStraight, panel1, DOT_POSITIONS, _memory->ReadEntityData<int>(tutorialStraight, NUM_DOTS, sizeof(int))[0]*2);
254} 196 _memory->CopyArrayDynamicSize<int>(tutorialStraight, panel1, DOT_FLAGS, NUM_DOTS);
255 197 _memory->CopyArrayDynamicSize<int>(tutorialStraight, panel1, DOT_CONNECTION_A, NUM_CONNECTIONS);
256void Randomizer::RandomizeMonastery() { 198 _memory->CopyArrayDynamicSize<int>(tutorialStraight, panel1, DOT_CONNECTION_B, NUM_CONNECTIONS);
257 std::vector<int> randomOrder(monasteryPanels.size(), 0); 199 _memory->CopyEntityData<byte>(tutorialStraight, panel1, NUM_DECORATIONS, sizeof(int));
258 std::iota(randomOrder.begin(), randomOrder.end(), 0); 200 _memory->CopyArrayDynamicSize<int>(tutorialStraight, panel1, DECORATIONS, NUM_DECORATIONS);
259 Shuffle(randomOrder, 3, 9); // Outer 2 & 3, Inner 1-4 201 _memory->CopyArrayDynamicSize<int>(tutorialStraight, panel1, DECORATION_FLAGS, NUM_DECORATIONS);
260 ReassignTargets(monasteryPanels, randomOrder); 202 _memory->CopyArrayDynamicSize<int>(tutorialStraight, panel1, DECORATION_COLORS, NUM_DECORATIONS);
261} 203 if (_memory->ReadPanelData<int>(tutorialStraight, REFLECTION_DATA)) {
262 204 _memory->CopyArrayDynamicSize<int>(tutorialStraight, panel1, REFLECTION_DATA, NUM_DOTS);
263void Randomizer::RandomizeBunker() {
264 std::vector<int> randomOrder(bunkerPanels.size(), 0);
265 std::iota(randomOrder.begin(), randomOrder.end(), 0);
266 // Randomize Tutorial 2-Advanced Tutorial 4 + Glass 1
267 // Tutorial 1 cannot be randomized, since no other panel can start on
268 // Glass 1 will become door + glass 1, due to the targetting system
269 Shuffle(randomOrder, 1, 10);
270 // Randomize Glass 1-3 into everything after the door/glass 1
271 const size_t glass1Index = find(randomOrder, 9);
272 Shuffle(randomOrder, glass1Index + 1, 12);
273 ReassignTargets(bunkerPanels, randomOrder);
274}
275
276void Randomizer::RandomizeJungle() {
277 std::vector<int> randomOrder(junglePanels.size(), 0);
278 std::iota(randomOrder.begin(), randomOrder.end(), 0);
279 // Waves 1 cannot be randomized, since no other panel can start on
280 Shuffle(randomOrder, 1, 7); // Waves 2-7
281 Shuffle(randomOrder, 8, 13); // Pitches 1-6
282 ReassignTargets(junglePanels, randomOrder);
283
284 // Fix the wall's target to point back to the cable, and the cable to point to the pitches panel.
285 // auto wallTarget = _memory->ReadPanelData<int>(junglePanels[7], TARGET, 1);
286 // _memory->WritePanelData<int>(junglePanels[7], TARGET, {0x3C113});
287 // _memory->WritePanelData<int>(0x3C112, CABLE_TARGET_1, wallTarget);
288}
289
290void Randomizer::RandomizeSwamp() {
291}
292
293void Randomizer::RandomizeMountain() {
294 // Randomize multipanel
295 Randomize(mountainMultipanel, SWAP::LINES | SWAP::COLORS);
296
297 // Randomize final pillars order
298 std::vector<int> targets = {pillars[0] + 1};
299 for (const int pillar : pillars) {
300 int target = _memory->ReadEntityData<int>(pillar, TARGET, 1)[0];
301 targets.push_back(target);
302 } 205 }
303 targets[5] = pillars[5] + 1; 206 else {
304 207 _memory->WritePanelData<long long>(panel1, REFLECTION_DATA, { 0 });
305 std::vector<int> randomOrder(pillars.size(), 0);
306 std::iota(randomOrder.begin(), randomOrder.end(), 0);
307 Shuffle(randomOrder, 0, 4); // Left Pillars 1-4
308 Shuffle(randomOrder, 5, 9); // Right Pillars 1-4
309 ReassignTargets(pillars, randomOrder, targets);
310 // Turn off original starting panels
311 _memory->WriteEntityData<float>(pillars[0], POWER, {0.0f, 0.0f});
312 _memory->WriteEntityData<float>(pillars[5], POWER, {0.0f, 0.0f});
313 // Turn on new starting panels
314 _memory->WriteEntityData<float>(pillars[randomOrder[0]], POWER, {1.0f, 1.0f});
315 _memory->WriteEntityData<float>(pillars[randomOrder[5]], POWER, {1.0f, 1.0f});
316}
317
318void Randomizer::RandomizeChallenge() {
319 ChallengeRandomizer cr(_memory, Random::RandInt(1, 0x7FFFFFFF)); // 0 will trigger an "RNG not initialized" block
320 for (int panel : challengePanels) {
321 _memory->WriteEntityData<int>(panel, POWER_OFF_ON_FAIL, {0});
322 }
323}
324
325void Randomizer::RandomizeAudioLogs() {
326 std::vector<int> randomOrder(audiologs.size(), 0);
327 std::iota(randomOrder.begin(), randomOrder.end(), 0);
328 Shuffle(randomOrder, 0, randomOrder.size());
329 ReassignNames(audiologs, randomOrder);
330}
331
332void Randomizer::Randomize(std::vector<int>& panels, int flags) {
333 return RandomizeRange(panels, flags, 0, panels.size());
334}
335
336// Range is [start, end)
337void Randomizer::Shuffle(std::vector<int> &order, size_t startIndex, size_t endIndex) {
338 if (order.size() == 0) return;
339 if (startIndex >= endIndex) return;
340 if (endIndex >= order.size()) endIndex = static_cast<int>(order.size());
341 for (size_t i = endIndex - 1; i > startIndex; i--) {
342 const int target = Random::RandInt(static_cast<int>(startIndex), static_cast<int>(i));
343 std::swap(order[i], order[target]);
344 }
345}
346
347// Range is [start, end)
348void Randomizer::RandomizeRange(std::vector<int> panels, int flags, size_t startIndex, size_t endIndex) {
349 if (panels.size() == 0) return;
350 if (startIndex >= endIndex) return;
351 if (endIndex >= panels.size()) endIndex = static_cast<int>(panels.size());
352 for (size_t i = endIndex-1; i > startIndex; i--) {
353 const int target = Random::RandInt(static_cast<int>(startIndex), static_cast<int>(i));
354 if (i != target) {
355 // std::cout << "Swapping panels " << std::hex << panels[i] << " and " << std::hex << panels[target] << std::endl;
356 SwapPanels(panels[i], panels[target], flags);
357 std::swap(panels[i], panels[target]); // Panel indices in the array
358 }
359 } 208 }
360} 209 _memory->CopyEntityData<byte>(tutorialStraight, panel1, SEQUENCE_LEN, sizeof(int));
361 210 _memory->CopyArrayDynamicSize<int>(tutorialStraight, panel1, SEQUENCE, SEQUENCE_LEN);
362void Randomizer::SwapPanels(int panel1, int panel2, int flags) { 211 _memory->CopyEntityData<byte>(tutorialStraight, panel1, DOT_SEQUENCE_LEN, sizeof(int));
363 std::map<int, int> offsets; 212 _memory->CopyArrayDynamicSize<int>(tutorialStraight, panel1, DOT_SEQUENCE, DOT_SEQUENCE_LEN);
364 213 _memory->CopyEntityData<byte>(tutorialStraight, panel1, DOT_SEQUENCE_LEN_REFLECTION, sizeof(int));
365 if (flags & SWAP::TARGETS) { 214 _memory->CopyArrayDynamicSize<int>(tutorialStraight, panel1, DOT_SEQUENCE_REFLECTION, DOT_SEQUENCE_LEN_REFLECTION);
366 offsets[TARGET] = sizeof(int); 215 _memory->CopyEntityData<byte>(tutorialStraight, panel1, GRID_SIZE_X, sizeof(int));
367 } 216 _memory->CopyEntityData<byte>(tutorialStraight, panel1, GRID_SIZE_Y, sizeof(int));
368 if (flags & SWAP::AUDIO_NAMES) { 217 _memory->CopyEntityData<byte>(tutorialStraight, panel1, STYLE_FLAGS, sizeof(int));
369 offsets[AUDIO_LOG_NAME] = sizeof(void*); 218 _memory->WritePanelData<byte>(panel1, RANDOMISE_ON_POWER_ON, { 0 });
370 } 219
371 if (flags & SWAP::COLORS) { 220
372 offsets[PATH_COLOR] = 16; 221 //arrays.push_back(AUDIO_PREFIX);
373 offsets[REFLECTION_PATH_COLOR] = 16;
374 offsets[DOT_COLOR] = 16;
375 offsets[ACTIVE_COLOR] = 16;
376 offsets[BACKGROUND_REGION_COLOR] = 12; // Not copying alpha to preserve transparency.
377 offsets[SUCCESS_COLOR_A] = 16;
378 offsets[SUCCESS_COLOR_B] = 16;
379 offsets[STROBE_COLOR_A] = 16;
380 offsets[STROBE_COLOR_B] = 16;
381 offsets[ERROR_COLOR] = 16;
382 offsets[PATTERN_POINT_COLOR] = 16;
383 offsets[PATTERN_POINT_COLOR_A] = 16;
384 offsets[PATTERN_POINT_COLOR_B] = 16;
385 offsets[SYMBOL_A] = 16;
386 offsets[SYMBOL_B] = 16;
387 offsets[SYMBOL_C] = 16;
388 offsets[SYMBOL_D] = 16;
389 offsets[SYMBOL_E] = 16;
390 offsets[PUSH_SYMBOL_COLORS] = sizeof(int);
391 offsets[OUTER_BACKGROUND] = 16;
392 offsets[OUTER_BACKGROUND_MODE] = sizeof(int);
393 // These two control the "burn intensity", but I can't swap out burn marks in new ver, so they should probably stay tied to each frame.
394 // offsets[SPECULAR_ADD] = sizeof(float);
395 // offsets[SPECULAR_POWER] = sizeof(int);
396 offsets[NUM_COLORED_REGIONS] = sizeof(int);
397 offsets[COLORED_REGIONS] = sizeof(void*);
398 }
399 if (flags & SWAP::LINES) {
400 offsets[TRACED_EDGES] = 16;
401 offsets[AUDIO_PREFIX] = sizeof(void*);
402// offsets[IS_CYLINDER] = sizeof(int); 222// offsets[IS_CYLINDER] = sizeof(int);
403// offsets[CYLINDER_Z0] = sizeof(float); 223// offsets[CYLINDER_Z0] = sizeof(float);
404// offsets[CYLINDER_Z1] = sizeof(float); 224// offsets[CYLINDER_Z1] = sizeof(float);
405// offsets[CYLINDER_RADIUS] = sizeof(float); 225// offsets[CYLINDER_RADIUS] = sizeof(float);
406 offsets[PATH_WIDTH_SCALE] = sizeof(float);
407 offsets[STARTPOINT_SCALE] = sizeof(float);
408 offsets[NUM_DOTS] = sizeof(int);
409 offsets[NUM_CONNECTIONS] = sizeof(int);
410 offsets[DOT_POSITIONS] = sizeof(void*);
411 offsets[DOT_FLAGS] = sizeof(void*);
412 offsets[DOT_CONNECTION_A] = sizeof(void*);
413 offsets[DOT_CONNECTION_B] = sizeof(void*);
414 offsets[DECORATIONS] = sizeof(void*);
415 offsets[DECORATION_FLAGS] = sizeof(void*);
416 offsets[DECORATION_COLORS] = sizeof(void*);
417 offsets[NUM_DECORATIONS] = sizeof(int);
418 offsets[REFLECTION_DATA] = sizeof(void*);
419 offsets[GRID_SIZE_X] = sizeof(int);
420 offsets[GRID_SIZE_Y] = sizeof(int);
421 offsets[STYLE_FLAGS] = sizeof(int);
422 offsets[SEQUENCE_LEN] = sizeof(int);
423 offsets[SEQUENCE] = sizeof(void*);
424 offsets[DOT_SEQUENCE_LEN] = sizeof(int);
425 offsets[DOT_SEQUENCE] = sizeof(void*);
426 offsets[DOT_SEQUENCE_LEN_REFLECTION] = sizeof(int);
427 offsets[DOT_SEQUENCE_REFLECTION] = sizeof(void*);
428 offsets[PANEL_TARGET] = sizeof(void*);
429 offsets[SPECULAR_TEXTURE] = sizeof(void*);
430 }
431 226
432 for (auto const& [offset, size] : offsets) { 227 //arrays.push_back(PANEL_TARGET);
433 std::vector<byte> panel1data = _memory->ReadEntityData<byte>(panel1, offset, size); 228 //arrays.push_back(SPECULAR_TEXTURE);
434 std::vector<byte> panel2data = _memory->ReadEntityData<byte>(panel2, offset, size);
435 _memory->WriteEntityData<byte>(panel2, offset, panel1data);
436 _memory->WriteEntityData<byte>(panel1, offset, panel2data);
437 }
438}
439 229
440void Randomizer::ReassignTargets(const std::vector<int>& panels, const std::vector<int>& order, std::vector<int> targets) {
441 if (targets.empty()) {
442 // This list is offset by 1, so the target of the Nth panel is in position N (aka the N+1th element)
443 // The first panel may not have a wire to power it, so we use the panel ID itself.
444 targets = {panels[0] + 1};
445 for (const int panel : panels) {
446 int target = _memory->ReadEntityData<int>(panel, TARGET, 1)[0];
447 targets.push_back(target);
448 }
449 }
450
451 for (size_t i=0; i<order.size() - 1; i++) {
452 // Set the target of order[i] to order[i+1], using the "real" target as determined above.
453 const int panelTarget = targets[order[i+1]];
454 _memory->WriteEntityData<int>(panels[order[i]], TARGET, {panelTarget});
455 }
456}
457
458void Randomizer::ReassignNames(const std::vector<int>& panels, const std::vector<int>& order) {
459 std::vector<int64_t> names;
460 for (const int panel : panels) {
461 names.push_back(_memory->ReadEntityData<int64_t>(panel, AUDIO_LOG_NAME, 1)[0]);
462 }
463
464 for (int i=0; i<panels.size(); i++) {
465 _memory->WriteEntityData<int64_t>(panels[i], AUDIO_LOG_NAME, {names[order[i]]});
466 }
467} 230}