From 02327bf40bb9f6ef8d5e17fa982da70a3fe93eb4 Mon Sep 17 00:00:00 2001
From: Star Rauchenberger <fefferburbia@gmail.com>
Date: Sat, 21 Aug 2021 16:55:00 -0400
Subject: Implemented tutorialisation stuff

---
 Source/Memory.h       |  25 +++++++
 Source/Panels.h       | 150 +++++++++++++++++++++++++++++++++++++-
 Source/Randomizer.cpp | 196 +++++++++++++++++++++++++-------------------------
 Source/Randomizer.h   |   2 +-
 4 files changed, 270 insertions(+), 103 deletions(-)

(limited to 'Source')

diff --git a/Source/Memory.h b/Source/Memory.h
index 1724251..e924bb9 100644
--- a/Source/Memory.h
+++ b/Source/Memory.h
@@ -55,6 +55,31 @@ public:
     void AddSigScan(const std::vector<byte>& scanBytes, const std::function<void(int index)>& scanFunc);
     int ExecuteSigScans();
 
+    template <typename T>
+    void CopyEntityData(int fromId, int toId, int offset, int size) {
+        WriteEntityData<T>(toId, offset, ReadEntityData<T>(fromId, offset, size));
+    }
+
+    template <typename T>
+    void CopyArray(int fromId, int toId, int offset, int size) {
+        if (size == 0) {
+            WriteEntityData<uintptr_t>(toId, offset, { static_cast<uintptr_t>(0) });
+        }
+        else {
+            WriteNewArray<T>(toId, offset, ReadArray<T>(fromId, offset, size));
+        }
+    }
+
+    template <typename T>
+    void CopyArrayDynamicSize(int fromId, int toId, int arrayOffset, int sizeOffset) {
+        CopyArray<T>(fromId, toId, arrayOffset, ReadEntityData<int>(fromId, sizeOffset, sizeof(int))[0]);
+    }
+
+    template <class T>
+    void WritePanelData(int panel, int offset, const std::vector<T>& data) {
+        WriteData<T>({ GLOBALS, 0x18, panel * 8, offset }, data);
+    }
+
 private:
     template<class T>
     std::vector<T> ReadData(const std::vector<int>& offsets, size_t numItems) {
diff --git a/Source/Panels.h b/Source/Panels.h
index 4a850ee..ec1686c 100644
--- a/Source/Panels.h
+++ b/Source/Panels.h
@@ -67,6 +67,13 @@ std::vector<int> leftForwardRightPanels = {
     0x17E52, // Treehouse Green 4
 };
 
+std::vector<int> utmPerspective = {
+    0x288EA, // UTM Perspective 1
+    0x288FC, // UTM Perspective 2
+    0x289E7, // UTM Perspective 3
+    0x288AA, // UTM Perspective 4
+};
+
 std::vector<int> pillars = {
     0x0383D, // Mountain 3 Left Pillar 1
     0x0383F, // Mountain 3 Left Pillar 2
@@ -117,8 +124,8 @@ std::vector<int> mountainMultipanel = {
 };
 
 std::vector<int> squarePanels = {
-    0x00064, // Tutorial Straight
-    0x00182, // Tutorial Bend
+    //0x00064, // Tutorial Straight
+    //0x00182, // Tutorial Bend
     0x0A3B2, // Tutorial Back Right
     0x00295, // Tutorial Center Left
     0x00293, // Tutorial Front Center
@@ -433,6 +440,145 @@ std::vector<int> squarePanels = {
     0x0A16E, // UTM Challenge Entrance
     0x039B4, // Tunnels Theater Catwalk
     0x09E85, // Tunnels Town Shortcut
+
+        0x00698, // Desert Surface 1
+        0x0048F, // Desert Surface 2
+        0x09F92, // Desert Surface 3
+        0x0A036, // Desert Surface 4
+        0x09DA6, // Desert Surface 5
+        0x0A049, // Desert Surface 6
+        0x0A053, // Desert Surface 7
+        0x09F94, // Desert Surface 8
+        0x00422, // Desert Light 1
+        0x006E3, // Desert Light 2
+        0x0A02D, // Desert Light 3
+        0x00C72, // Desert Pond 1
+        0x0129D, // Desert Pond 2
+        0x008BB, // Desert Pond 3
+        0x0078D, // Desert Pond 4
+        0x18313, // Desert Pond 5
+        0x04D18, // Desert Flood 1
+        0x01205, // Desert Flood 2
+        0x181AB, // Desert Flood 3
+        0x0117A, // Desert Flood 4
+        0x17ECA, // Desert Flood 5
+        0x18076, // Desert Flood Exit
+        0x0A15C, // Desert Final Left Convex
+        0x09FFF, // Desert Final Left Concave
+        0x0A15F, // Desert Final Near
+        0x012D7, // Desert Final Far
+        0x09F7D, // Bunker Tutorial 1
+        0x09FDC, // Bunker Tutorial 2
+        0x09FF7, // Bunker Tutorial 3
+        0x09F82, // Bunker Tutorial 4
+        0x09FF8, // Bunker Tutorial 5
+        0x09D9F, // Bunker Advanced 1
+        0x09DA1, // Bunker Advanced 2
+        0x09DA2, // Bunker Advanced 3
+        0x09DAF, // Bunker Advanced 4
+    //    0x0A099, // Bunker Glass Door
+        0x0A010, // Bunker Glass 1
+        0x0A01B, // Bunker Glass 2
+        0x0A01F, // Bunker Glass 3
+        0x17E63, // Bunker Ultraviolet 1
+        0x17E67, // Bunker Ultraviolet 2
+        0x002C4, // Jungle Waves 1
+        0x00767, // Jungle Waves 2
+        0x002C6, // Jungle Waves 3
+        0x0070E, // Jungle Waves 4
+        0x0070F, // Jungle Waves 5
+        0x0087D, // Jungle Waves 6
+        0x002C7, // Jungle Waves 7
+    //    0x17CAB, // Jungle Pop-up Wall
+        0x0026D, // Jungle Dots 1
+        0x0026E, // Jungle Dots 2
+        0x0026F, // Jungle Dots 3
+        0x00C3F, // Jungle Dots 4
+        0x00C41, // Jungle Dots 5
+        0x014B2, // Jungle Dots 6
+        0x198B5, // Shadows Tutorial 1
+        0x198BD, // Shadows Tutorial 2
+        0x198BF, // Shadows Tutorial 3
+        0x19771, // Shadows Tutorial 4
+        0x0A8DC, // Shadows Tutorial 5
+        0x0AC74, // Shadows Tutorial 6
+        0x0AC7A, // Shadows Tutorial 7
+        0x0A8E0, // Shadows Tutorial 8
+        0x386FA, // Shadows Avoid 1
+        0x1C33F, // Shadows Avoid 2
+        0x196E2, // Shadows Avoid 3
+        0x1972A, // Shadows Avoid 4
+        0x19809, // Shadows Avoid 5
+        0x19806, // Shadows Avoid 6
+        0x196F8, // Shadows Avoid 7
+        0x1972F, // Shadows Avoid 8
+        0x19797, // Shadows Follow 1
+        0x1979A, // Shadows Follow 2
+        0x197E0, // Shadows Follow 3
+        0x197E8, // Shadows Follow 4
+        0x197E5, // Shadows Follow 5
+        0x19650, // Shadows Laser
+
+        0x09FCC, // Mountain 2 Multipanel 1
+        0x09FCE, // Mountain 2 Multipanel 2
+        0x09FCF, // Mountain 2 Multipanel 3
+        0x09FD0, // Mountain 2 Multipanel 4
+        0x09FD1, // Mountain 2 Multipanel 5
+        0x09FD2, // Mountain 2 Multipanel 6
+
+        0x00290, // Monastery Exterior 1
+        0x00038, // Monastery Exterior 2
+        0x00037, // Monastery Exterior 3
+    //    0x09D9B, // Monastery Bonsai
+        0x193A7, // Monastery Interior 1
+        0x193AA, // Monastery Interior 2
+        0x193AB, // Monastery Interior 3
+        0x193A6, // Monastery Interior 4
+
+
+
+            0x03629, // Tutorial Gate Open
+            
+            0x0C373, // Tutorial Patio floor
+            0x1C349, // Symmetry Island Door 2 - Collision fails here, sadly
+            
+            0x28A69, // Town Lattice
+            0x28A79, // Town Maze
+            0x28B39, // Town Red Hexagonal
+            
+            0x18590, // Town Transparent
+            0x28AE3, // Town Wire
+
+
+
+            0x0383D, // Mountain 3 Left Pillar 1
+            0x0383F, // Mountain 3 Left Pillar 2
+            0x03859, // Mountain 3 Left Pillar 3
+            0x339BB, // Mountain 3 Left Pillar 4
+     
+            0x0383A, // Mountain 3 Right Pillar 1
+            0x09E56, // Mountain 3 Right Pillar 2
+            0x09E5A, // Mountain 3 Right Pillar 3
+            0x33961, // Mountain 3 Right Pillar 4
+
+            0x09DD5, // UTM Challenge Pillar
+
+
+    0x09FD8, // Mountain 2 Rainbow 5
+            0x17CAA, // Jungle Courtyard Gate
+            0x0005C, // Glass Factory Vertical Symmetry 5
+            0x17C31, // Desert Final Transparent
+
+            0x00143, // Orchard Apple Tree 1
+            0x0003B, // Orchard Apple Tree 2
+            0x00055, // Orchard Apple Tree 3
+            0x032F7, // Orchard Apple Tree 4
+            0x032FF, // Orchard Apple Tree 5
+            0x009B8, // Symmetry Island Transparent 1
+            0x003E8, // Symmetry Island Transparent 2
+            0x00A15, // Symmetry Island Transparent 3
+            0x00B53, // Symmetry Island Transparent 4
+            0x00B8D, // Symmetry Island Transparent 5
 };
 
 std::vector<int> desertPanels = {
diff --git a/Source/Randomizer.cpp b/Source/Randomizer.cpp
index 72072a8..74166af 100644
--- a/Source/Randomizer.cpp
+++ b/Source/Randomizer.cpp
@@ -130,10 +130,18 @@ void Randomizer::Randomize() {
     MEMORY_CATCH(RandomizeChallenge());
 
     // Content swaps -- must happen before squarePanels
-    MEMORY_CATCH(Randomize(upDownPanels, SWAP::LINES | SWAP::COLORS));
-    MEMORY_CATCH(Randomize(leftForwardRightPanels, SWAP::LINES | SWAP::COLORS));
+    //MEMORY_CATCH(Randomize(upDownPanels, SWAP::LINES | SWAP::COLORS));
+    //MEMORY_CATCH(Randomize(leftForwardRightPanels, SWAP::LINES | SWAP::COLORS));
 
-    MEMORY_CATCH(Randomize(squarePanels, SWAP::LINES | SWAP::COLORS));
+    // Tutorial Bend
+    for (int panel : utmPerspective) {
+        Tutorialise(panel, 0x00182);
+    }
+    // Tutorial Straight
+    for (int panel : squarePanels) {
+        Tutorialise(panel, 0x00064);
+    }
+    //Randomize(squarePanels, SWAP::LINES | SWAP::COLORS);
 
     // Individual area modifications
     MEMORY_CATCH(RandomizeTutorial());
@@ -171,9 +179,9 @@ void Randomizer::RandomizeLasers() {
 void Randomizer::PreventSnipes()
 {
     // Distance-gate swamp snipe 1 to prevent RNG swamp snipe
-    _memory->WriteEntityData<float>(0x17C05, MAX_BROADCAST_DISTANCE, {15.0});
+    //_memory->WriteEntityData<float>(0x17C05, MAX_BROADCAST_DISTANCE, {15.0});
     // Distance-gate shadows laser to prevent sniping through the bars
-    _memory->WriteEntityData<float>(0x19650, MAX_BROADCAST_DISTANCE, {2.5});
+    //_memory->WriteEntityData<float>(0x19650, MAX_BROADCAST_DISTANCE, {2.5});
 }
 
 // Private methods
@@ -186,21 +194,21 @@ void Randomizer::RandomizeTutorial() {
 }
 
 void Randomizer::RandomizeSymmetry() {
-    std::vector<int> randomOrder(transparent.size(), 0);
+    /*std::vector<int> randomOrder(transparent.size(), 0);
     std::iota(randomOrder.begin(), randomOrder.end(), 0);
     RandomizeRange(randomOrder, SWAP::NONE, 1, 5);
-    ReassignTargets(transparent, randomOrder);
+    ReassignTargets(transparent, randomOrder);*/
 }
 
 void Randomizer::RandomizeDesert() {
-    Randomize(desertPanels, SWAP::LINES);
+    //Randomize(desertPanels, SWAP::LINES);
 
     // Turn off desert surface 8
-    _memory->WriteEntityData<float>(0x09F94, POWER, {0.0, 0.0});
+    /*_memory->WriteEntityData<float>(0x09F94, POWER, {0.0, 0.0});
     // Turn off desert flood final
     _memory->WriteEntityData<float>(0x18076, POWER, {0.0, 0.0});
     // Change desert floating target to desert flood final
-    _memory->WriteEntityData<int>(0x17ECA, TARGET, {0x18077});
+    _memory->WriteEntityData<int>(0x17ECA, TARGET, {0x18077});*/
 }
 
 void Randomizer::RandomizeQuarry() {
@@ -228,7 +236,7 @@ void Randomizer::RandomizeShadows() {
     // Change shadows avoid 8 to power shadows follow
     _memory->WriteEntityData<int>(0x1972F, TARGET, {0x1C34C});
 
-    std::vector<int> randomOrder(shadowsPanels.size(), 0);
+    /*std::vector<int> randomOrder(shadowsPanels.size(), 0);
     std::iota(randomOrder.begin(), randomOrder.end(), 0);
     RandomizeRange(randomOrder, SWAP::NONE, 0, 8); // Tutorial
     RandomizeRange(randomOrder, SWAP::NONE, 8, 16); // Avoid
@@ -237,12 +245,12 @@ void Randomizer::RandomizeShadows() {
     // Turn off original starting panel
     _memory->WriteEntityData<float>(shadowsPanels[0], POWER, {0.0f, 0.0f});
     // Turn on new starting panel
-    _memory->WriteEntityData<float>(shadowsPanels[randomOrder[0]], POWER, {1.0f, 1.0f});
+    _memory->WriteEntityData<float>(shadowsPanels[randomOrder[0]], POWER, {1.0f, 1.0f});*/
 }
 
 void Randomizer::RandomizeTown() {
     // @Hack...? To open the gate at the end
-    std::vector<int> randomOrder(orchard.size() + 1, 0);
+    /*std::vector<int> randomOrder(orchard.size() + 1, 0);
     std::iota(randomOrder.begin(), randomOrder.end(), 0);
     RandomizeRange(randomOrder, SWAP::NONE, 1, 5);
     // Ensure that we open the gate before the final puzzle (by swapping)
@@ -250,18 +258,18 @@ void Randomizer::RandomizeTown() {
     int panel4Index = find(randomOrder, 4);
     randomOrder[std::min(panel3Index, panel4Index)] = 3;
     randomOrder[std::max(panel3Index, panel4Index)] = 4;
-    ReassignTargets(orchard, randomOrder);
+    ReassignTargets(orchard, randomOrder);*/
 }
 
 void Randomizer::RandomizeMonastery() {
-    std::vector<int> randomOrder(monasteryPanels.size(), 0);
+    /*std::vector<int> randomOrder(monasteryPanels.size(), 0);
     std::iota(randomOrder.begin(), randomOrder.end(), 0);
     RandomizeRange(randomOrder, SWAP::NONE, 3, 9); // Outer 2 & 3, Inner 1-4
-    ReassignTargets(monasteryPanels, randomOrder);
+    ReassignTargets(monasteryPanels, randomOrder);*/
 }
 
 void Randomizer::RandomizeBunker() {
-    std::vector<int> randomOrder(bunkerPanels.size(), 0);
+    /*std::vector<int> randomOrder(bunkerPanels.size(), 0);
     std::iota(randomOrder.begin(), randomOrder.end(), 0);
     // Randomize Tutorial 2-Advanced Tutorial 4 + Glass 1
     // Tutorial 1 cannot be randomized, since no other panel can start on
@@ -270,16 +278,16 @@ void Randomizer::RandomizeBunker() {
     // Randomize Glass 1-3 into everything after the door/glass 1
     const size_t glass1Index = find(randomOrder, 9);
     RandomizeRange(randomOrder, SWAP::NONE, glass1Index + 1, 12);
-    ReassignTargets(bunkerPanels, randomOrder);
+    ReassignTargets(bunkerPanels, randomOrder);*/
 }
 
 void Randomizer::RandomizeJungle() {
-    std::vector<int> randomOrder(junglePanels.size(), 0);
+    /*std::vector<int> randomOrder(junglePanels.size(), 0);
     std::iota(randomOrder.begin(), randomOrder.end(), 0);
     // Waves 1 cannot be randomized, since no other panel can start on
     RandomizeRange(randomOrder, SWAP::NONE, 1, 7); // Waves 2-7
     RandomizeRange(randomOrder, SWAP::NONE, 8, 13); // Pitches 1-6
-    ReassignTargets(junglePanels, randomOrder);
+    ReassignTargets(junglePanels, randomOrder);*/
 
     // Fix the wall's target to point back to the cable, and the cable to point to the pitches panel.
     // auto wallTarget = _memory->ReadPanelData<int>(junglePanels[7], TARGET, 1);
@@ -292,10 +300,10 @@ void Randomizer::RandomizeSwamp() {
 
 void Randomizer::RandomizeMountain() {
     // Randomize multipanel
-    Randomize(mountainMultipanel, SWAP::LINES | SWAP::COLORS);
+    //Randomize(mountainMultipanel, SWAP::LINES | SWAP::COLORS);
 
     // Randomize final pillars order
-    std::vector<int> targets = {pillars[0] + 1};
+    /*std::vector<int> targets = {pillars[0] + 1};
     for (const int pillar : pillars) {
         int target = _memory->ReadEntityData<int>(pillar, TARGET, 1)[0];
         targets.push_back(target);
@@ -312,14 +320,14 @@ void Randomizer::RandomizeMountain() {
     _memory->WriteEntityData<float>(pillars[5], POWER, {0.0f, 0.0f});
     // Turn on new starting panels
     _memory->WriteEntityData<float>(pillars[randomOrder[0]], POWER, {1.0f, 1.0f});
-    _memory->WriteEntityData<float>(pillars[randomOrder[5]], POWER, {1.0f, 1.0f});
+    _memory->WriteEntityData<float>(pillars[randomOrder[5]], POWER, {1.0f, 1.0f});*/
 }
 
 void Randomizer::RandomizeChallenge() {
-    ChallengeRandomizer cr(_memory, Random::RandInt(1, 0x7FFFFFFF)); // 0 will trigger an "RNG not initialized" block
+    /*ChallengeRandomizer cr(_memory, Random::RandInt(1, 0x7FFFFFFF)); // 0 will trigger an "RNG not initialized" block
     for (int panel : challengePanels) {
         _memory->WriteEntityData<int>(panel, POWER_OFF_ON_FAIL, {0});
-    }
+    }*/
 }
 
 void Randomizer::RandomizeAudioLogs() {
@@ -338,92 +346,80 @@ void Randomizer::RandomizeRange(std::vector<int> &panels, int flags, size_t star
     if (panels.size() == 0) return;
     if (startIndex >= endIndex) return;
     if (endIndex >= panels.size()) endIndex = static_cast<int>(panels.size());
-    for (size_t i = endIndex-1; i > startIndex; i--) {
-        const int target = Random::RandInt(static_cast<int>(startIndex), static_cast<int>(i));
+    for (size_t i = 0; i < panels.size(); i++) {
+        /*const int target = Random::RandInt(static_cast<int>(startIndex), static_cast<int>(i));
         if (i != target) {
             // std::cout << "Swapping panels " << std::hex << panels[i] << " and " << std::hex << panels[target] << std::endl;
             SwapPanels(panels[i], panels[target], flags);
-            std::swap(panels[i], panels[target]); // Panel indices in the array
-        }
+            //std::swap(panels[i], panels[target]); // Panel indices in the array
+        }*/
+        
     }
 }
 
-void Randomizer::SwapPanels(int panel1, int panel2, int flags) {
-    std::map<int, int> offsets;
-
-    if (flags & SWAP::TARGETS) {
-        offsets[TARGET] = sizeof(int);
-    }
-    if (flags & SWAP::AUDIO_NAMES) {
-        offsets[AUDIO_LOG_NAME] = sizeof(void*);
-    }
-    if (flags & SWAP::COLORS) {
-        offsets[PATH_COLOR] = 16;
-        offsets[REFLECTION_PATH_COLOR] = 16;
-        offsets[DOT_COLOR] = 16;
-        offsets[ACTIVE_COLOR] = 16;
-        offsets[BACKGROUND_REGION_COLOR] = 12; // Not copying alpha to preserve transparency.
-        offsets[SUCCESS_COLOR_A] = 16;
-        offsets[SUCCESS_COLOR_B] = 16;
-        offsets[STROBE_COLOR_A] = 16;
-        offsets[STROBE_COLOR_B] = 16;
-        offsets[ERROR_COLOR] = 16;
-        offsets[PATTERN_POINT_COLOR] = 16;
-        offsets[PATTERN_POINT_COLOR_A] = 16;
-        offsets[PATTERN_POINT_COLOR_B] = 16;
-        offsets[SYMBOL_A] = 16;
-        offsets[SYMBOL_B] = 16;
-        offsets[SYMBOL_C] = 16;
-        offsets[SYMBOL_D] = 16;
-        offsets[SYMBOL_E] = 16;
-        offsets[PUSH_SYMBOL_COLORS] = sizeof(int);
-        offsets[OUTER_BACKGROUND] = 16;
-        offsets[OUTER_BACKGROUND_MODE] = sizeof(int);
-        // 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.
-        // offsets[SPECULAR_ADD] = sizeof(float);
-        // offsets[SPECULAR_POWER] = sizeof(int);
-        offsets[NUM_COLORED_REGIONS] = sizeof(int);
-        offsets[COLORED_REGIONS] = sizeof(void*);
-    }
-    if (flags & SWAP::LINES) {
-        offsets[TRACED_EDGES] = 16;
-        offsets[AUDIO_PREFIX] = sizeof(void*);
+void Randomizer::Tutorialise(int panel1, int tutorialStraight) {
+    //const int tutorialStraight = 0x00064;
+    
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, PATH_COLOR, 16);
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, REFLECTION_PATH_COLOR, 16);
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, DOT_COLOR, 16);
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, ACTIVE_COLOR, 16);
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, BACKGROUND_REGION_COLOR, 12);
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, SUCCESS_COLOR_A, 16);
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, SUCCESS_COLOR_B, 16);
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, STROBE_COLOR_A, 16);
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, STROBE_COLOR_B, 16);
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, ERROR_COLOR, 16);
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, PATTERN_POINT_COLOR, 16);
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, PATTERN_POINT_COLOR_A, 16);
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, PATTERN_POINT_COLOR_B, 16);
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, SYMBOL_A, 16);
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, SYMBOL_B, 16);
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, SYMBOL_C, 16);
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, SYMBOL_D, 16);
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, SYMBOL_E, 16);
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, PUSH_SYMBOL_COLORS, sizeof(int));
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, OUTER_BACKGROUND, 16);
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, OUTER_BACKGROUND_MODE, sizeof(int));
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, NUM_COLORED_REGIONS, sizeof(int));
+    _memory->CopyArrayDynamicSize<int>(tutorialStraight, panel1, COLORED_REGIONS, NUM_COLORED_REGIONS);
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, TRACED_EDGES, 16);
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, PATH_WIDTH_SCALE, sizeof(float));
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, STARTPOINT_SCALE, sizeof(float));
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, NUM_DOTS, sizeof(int));
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, NUM_CONNECTIONS, sizeof(int));
+    _memory->CopyArray<float>(tutorialStraight, panel1, DOT_POSITIONS, _memory->ReadEntityData<int>(tutorialStraight, NUM_DOTS, sizeof(int))[0]*2);
+    _memory->CopyArrayDynamicSize<int>(tutorialStraight, panel1, DOT_FLAGS, NUM_DOTS);
+    _memory->CopyArrayDynamicSize<int>(tutorialStraight, panel1, DOT_CONNECTION_A, NUM_CONNECTIONS);
+    _memory->CopyArrayDynamicSize<int>(tutorialStraight, panel1, DOT_CONNECTION_B, NUM_CONNECTIONS);
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, NUM_DECORATIONS, sizeof(int));
+    _memory->CopyArrayDynamicSize<int>(tutorialStraight, panel1, DECORATIONS, NUM_DECORATIONS);
+    _memory->CopyArrayDynamicSize<int>(tutorialStraight, panel1, DECORATION_FLAGS, NUM_DECORATIONS);
+    _memory->CopyArrayDynamicSize<int>(tutorialStraight, panel1, DECORATION_COLORS, NUM_DECORATIONS);
+    //_memory->CopyArrayDynamicSize<int>(tutorialStraight, panel1, REFLECTION_DATA, NUM_DOTS);
+    _memory->WritePanelData<long long>(panel1, REFLECTION_DATA, { 0 });
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, SEQUENCE_LEN, sizeof(int));
+    _memory->CopyArrayDynamicSize<int>(tutorialStraight, panel1, SEQUENCE, SEQUENCE_LEN);
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, DOT_SEQUENCE_LEN, sizeof(int));
+    _memory->CopyArrayDynamicSize<int>(tutorialStraight, panel1, DOT_SEQUENCE, DOT_SEQUENCE_LEN);
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, DOT_SEQUENCE_LEN_REFLECTION, sizeof(int));
+    _memory->CopyArrayDynamicSize<int>(tutorialStraight, panel1, DOT_SEQUENCE_REFLECTION, DOT_SEQUENCE_LEN_REFLECTION);
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, GRID_SIZE_X, sizeof(int));
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, GRID_SIZE_Y, sizeof(int));
+    _memory->CopyEntityData<byte>(tutorialStraight, panel1, STYLE_FLAGS, sizeof(int));
+
+
+
+
+        //arrays.push_back(AUDIO_PREFIX);
 //        offsets[IS_CYLINDER] = sizeof(int);
 //        offsets[CYLINDER_Z0] = sizeof(float);
 //        offsets[CYLINDER_Z1] = sizeof(float);
 //        offsets[CYLINDER_RADIUS] = sizeof(float);
-        offsets[PATH_WIDTH_SCALE] = sizeof(float);
-        offsets[STARTPOINT_SCALE] = sizeof(float);
-        offsets[NUM_DOTS] = sizeof(int);
-        offsets[NUM_CONNECTIONS] = sizeof(int);
-        offsets[DOT_POSITIONS] = sizeof(void*);
-        offsets[DOT_FLAGS] = sizeof(void*);
-        offsets[DOT_CONNECTION_A] = sizeof(void*);
-        offsets[DOT_CONNECTION_B] = sizeof(void*);
-        offsets[DECORATIONS] = sizeof(void*);
-        offsets[DECORATION_FLAGS] = sizeof(void*);
-        offsets[DECORATION_COLORS] = sizeof(void*);
-        offsets[NUM_DECORATIONS] = sizeof(int);
-        offsets[REFLECTION_DATA] = sizeof(void*);
-        offsets[GRID_SIZE_X] = sizeof(int);
-        offsets[GRID_SIZE_Y] = sizeof(int);
-        offsets[STYLE_FLAGS] = sizeof(int);
-        offsets[SEQUENCE_LEN] = sizeof(int);
-        offsets[SEQUENCE] = sizeof(void*);
-        offsets[DOT_SEQUENCE_LEN] = sizeof(int);
-        offsets[DOT_SEQUENCE] = sizeof(void*);
-        offsets[DOT_SEQUENCE_LEN_REFLECTION] = sizeof(int);
-        offsets[DOT_SEQUENCE_REFLECTION] = sizeof(void*);
-        offsets[PANEL_TARGET] = sizeof(void*);
-        offsets[SPECULAR_TEXTURE] = sizeof(void*);
-    }
 
-    for (auto const& [offset, size] : offsets) {
-        std::vector<byte> panel1data = _memory->ReadEntityData<byte>(panel1, offset, size);
-        std::vector<byte> panel2data = _memory->ReadEntityData<byte>(panel2, offset, size);
-        _memory->WriteEntityData<byte>(panel2, offset, panel1data);
-        _memory->WriteEntityData<byte>(panel1, offset, panel2data);
-    }
+        //arrays.push_back(PANEL_TARGET);
+        //arrays.push_back(SPECULAR_TEXTURE);
+
 }
 
 void Randomizer::ReassignTargets(const std::vector<int>& panels, const std::vector<int>& order, std::vector<int> targets) {
diff --git a/Source/Randomizer.h b/Source/Randomizer.h
index bd8895b..ae89dc9 100644
--- a/Source/Randomizer.h
+++ b/Source/Randomizer.h
@@ -37,7 +37,7 @@ private:
 
     void Randomize(std::vector<int>& panels, int flags);
     void RandomizeRange(std::vector<int> &panels, int flags, size_t startIndex, size_t endIndex);
-    void SwapPanels(int panel1, int panel2, int flags);
+    void Tutorialise(int panel1, int copyFrom);
     void ReassignTargets(const std::vector<int>& panels, const std::vector<int>& order, std::vector<int> targets = {});
     void ReassignNames(const std::vector<int>& panels, const std::vector<int>& order);
 
-- 
cgit 1.4.1