What I learned
Before you read my outdated code, these are the major things I learned after finishing the tool:
1. Blueprint Interfaces! Casting is an inefficient way to run a system like this, while I learned BPI's before, I got in a bad habit of avoiding them. I will forever focus on using BPI blueprints in all my future scripting!
2. Line Trace! We actually did this, while not documented we had a lot of trouble hitting the pieces the right way the first 10 weeks. It wasn't until week 11 we switched over everything to line traces and our inaccuracy problems vanished. Overlaps are good for many things, but not for this.
3. Instead of making a "switch on int" and killing myself writing out a child actor spawner for each integer, I could have just made an instanced array and selected the child actor I wanted to spawn. I also could have used Enum to label the type of puzzle piece in the editor. I will definitely use arrays more in the future!
The Puzzle Tool
As shown on the previous page, a puzzle can be built in seconds. The puzzle is fully functional (with some minor tweaks still needed) and allows a designer to test his or her ideas instantly in-engine.
In the puzzle blueprint are five construction scripts, one for each ring. 16 integers determine what puzzle piece will spawn at what location. Setting the integer between 1 - 6 will spawn different pieces. A unique rotation value is used for each integer, and is also reused for each ring (since the rotation values don't change). This is better explained in the diagram on the left. The letter represents the ring and the number represents the rotation location, and is coded as such.
Solving the puzzle activates a lot of different things in the environment. Because the puzzle acts as a power generator, doors, lights, and more puzzles are turned on. Solving a puzzle also increases a variable called "Aurora Power Level", a global variable that spawns different anomalies the higher the number gets. When the puzzle is solved, the central containment unit rises, getting power and shutting down the artifacts on the track.
When a player fails a puzzle or gets stuck, they can reset it using another actor. In order to make the reset look interesting and believable (since programming every move in reverse is a nightmare), we decided to make the puzzle flip upside down. While upside down, a number of actions are performed to put the puzzle back to its default state.
For each puzzle piece, their puzzle number is assigned and matched to the puzzle itself so that they snap in place. From there, the designer can set the ring number which snaps the piece location onto one of the 5 rings or locked in the center. Rotating the piece is as simple as rotating the actor.
The main piece the player pushes is called an artifact. Artifacts can have a positive, negative and "off" charge. These charges can be swapped by a "Gate" which is another piece. An artifact can not be moved when it's charge is off, and can be set to off when two artifacts of opposite charges collide. If two artifacts of the same charge collide, they bounce off each other.
The artifact is the only piece the player can interact with, and as such has a very complex network of controls. First, the artifact requires energy to be dispensed to it by the player in order to move. The player can push it clockwise, counterclockwise, or push it forward. The player can only move the piece in the directions determined by the track tile it moves on. The track tile can also tell the artifact to stop moving, or "Full Stop" if it is shutdown and the player can no longer move it. The piece can be bounced by elements in the puzzle and knocked by other artifacts. Collision logic determines what happens when two objects collide. The artifact is a component whose anchor rests at the center of the puzzle. Using the rotating component and "Move Component To", I can move the artifact around without changing its anchor point, allowing for smooth rotation and movement at all times. Setting Rotation Rate to 1 or -1 and Forward Rate to 1 or -1 gives a variable indication of where the artifact is moving so the puzzle tiles can accurately tell it what to do.
"Move Component To" moves the artifact from ring to ring. In order to know where to send it, the artifact has to know if it is moving forward or backward. Then it determines the location of the piece, and sets the integer for graph above for the lane it needs to move to.
A custom event is used to make sure the artifact is always the correct X distance away from the origin depending on the ring its on in order for it to always line up correctly with the track.
Each puzzle tile has similar logic. It contains collision boxes that determine how the player can push the artifact. When the player reaches the intersection, it takes the current Forward/Rotation value and, after a brief pause, sends the artifact once again on its way. Some tiles stop the player entirely.
The gate reverses an artifact's charge. It has 3 points of activation: between both panels and behind each panel. In the first example, the artifact passes through the center hitbox. The blueprint checks to see if the valid components have overlapped, then checks to see what charge the artifact has coming in. It then reverses that charge, swaps the artifact color and light, gets the current movement direction, and pushes the artifact in that direction.
The bouncer forces the artifacts in a chosen direction. The construction and setup follows much of the same code as the gate. An integer is set in the editor that decides the direction of the push. When the artifact passes through, it is forced to move in that direction.
The wall kills an artifact's charge on impact. When the two collide, the blueprint sets the charge to zero, killing it, removes the light, and freezes it in place.