Corndog Chronicles was inspired by a narrative idea I had in mind. The protagonist is a sausage, and they are being oppressed by a corndog regime. The protagonist decided to rise up and murder corndog soldiers. However after some rampage, he discovered that the corndogs are also sausages inside....
The gameplay is inspired by Enter the Gungeon. We wanted to create a rouge-lite top down shooter. The game progression is influenced by Slay the Spire. That game forces players to have an adaptive play style through RNG, while allowing the player to build up their arsenal through loot drop options and different path.
We decided that the player would have limited option in their weapons. However, they would be able to build up their weapons through weapon attachments. Those range from normal stats upgrade such as increase fire rate to unique mods such as increasing player's weapon damage whenever they missed. This would allow the player build up a weapon according to its inherit strength as well as synergy with unique mods. For example, one of the unique mods is explosive shot for the last round in the magazine. This proved to be very powerful for double barrel shotgun, as every other shot would be explosive.
At the beginning of the game, the player has the option between two weapons. They also has the option between two rooms. Upon completing each room, they get a loot box in which they can select one of the reward. The more difficult a room is, the more option the player would get.
We ended up with a mechanically engaging game, as each play through would be different from the last one, but each play through is still very engaging due to the build up of the player weapon. Each attachment that the player pick up would be represented visually. If the player pick up an accuracy mod, they would get a scope on their gun. If they pick up an extended magazine mod, they would get a magazine attached to their magazine. If they pick up another accuracy mod, they would have another scope attached to their first scope. As a result we would end up with some insane looking weapons that are fun to shoot and fun to look at.
I was one of the design lead of the game. I was the programmer for the player character. I designed and programmed the entirety of the weapon attachment system.
Austin Edwards - Level designer, Game designer, Programmer
Chris Schickler - Game designer, Programmer
Drew DiCenso - Artist
Parker Daniels - Artist
All the weapons share the same parent class. Everything weapon related is handled by the parent blueprint: Spawning projectiles, reload, attaching attachments, interactions with unique attachments etc.
The weapon blueprint is designed to handle having 10 different stats affecting its function: Full auto boolean, Explosive boolean, Damage, FireRate, Multishot, Magazine size, Reload Time, Accuracy, Projectile Speed, Character Movement Speed. All these can be modified by the attachments that the player pick up.
In total we have 10 weapons in the game.
Below is the event graph of the parent gun.
The weapon blueprint has a section of modifier variables. When creating a new weapon, designers only have to change these variables. These modifiers include basic stats of the weapon, custom projectile mesh for weapons like rocket launcher, and custom weapon firing sound. The majority of the stats are stored in a stats struct array. Each item contain the stats type, default value, and current value. The values are then extracted and used to set variables that would be used by the blueprint, such as accuracy, damage etc.
Attachment System Overview
The attachment system has three main components : Parent attachment system, Unique attachments, and Attachment mesh actors.
Attachments are divided into two main category : Normal and Unique. Normal attachment is a simple stats upgrade to the player weapon, such as increasing damage or accuracy. It will also attach a mesh actor to the player weapon.
The attachment parent blueprint is very simple. This is used for normal attachment. It has basic functions such as being able to be picked up by the player. The player weapon will communicate with the attachment when they are picked up. The weapon will get whether it is an unique attachment, and its stats buff if it is a normal attachment.
The unique attachments however are more complex. They have very specific functions and interactions. For example, making the last round of the weapon explosive, or increasing weapon damage every time the player hit or kill somebody. These attachments has to somehow attach a function to the weapon itself.
I ended up using an interface for this. Every tick, the weapon would be casting a interface message to all unique attachments. The event within the unique attachment will obtain the reference to the gun and interact with the weapon actor accordingly.
Below is the event graph of the unique attachment : Last shot explosive
Attachment Stats System
Whenever the player picked up an attachment, this following functions would run. The attachment mesh system would be covered in the next section. Right now I am focusing on the update of weapon stats.
Below is the Update Att Stats function and Refresh Stat
The Update Att Stats first adds all the stats struct into the Upgrade Stats array. The struct contains the attachment type and the buff value. Then the Refresh Stats function would read the type of the Upgrade Stats item, then add the buff value to the weapon stats struct. All values are additive except for the accuracy.
Attachment Mesh System
Each normal attachment comes with a mesh. Each stats has its own corresponding mesh. For accuracy it is a scope, for projectile speed it is extended barrel, for player movement speed it is a balloon.
I wanted to make these attachment stack on each other. For example if the player keep on picking up extended barrel, the barrel should keep extending. As a result, I created attachment mesh actors.
The attachment actors themselves do not have any static mesh component attached on them. Instead they have a mesh child actor attached to them, with a mesh actor corresponding to the attachment's stat boost. That actor is the mesh that you see spinning on the ground.
The attachment mesh actors are all child blueprint of the BP_Parent_AttMesh. The parent mesh actor is very simple, it has a static mesh, an arrow that indicates the next stacking position, and a forward direction error just for reference in editor.
This needs to be a separate actor because they have multiple components, and this also allows certain attachment meshes to be more complex, such as the balloon with spring arm and cable.
One thing to note is that, for example when the player pick up a projectile speed attachment (extended barrel), the extended barrel you see on the weapon afterwards is not from the attachment actor that was spinning on the ground. Instead, the extended barrel (mesh actor) is spawned by the gun itself. The mesh actor on the attachment actor (the spinning mesh) is destroyed the moment it was picked up.
This allow me to spawn multiple mesh actors of the same type on a single weapon. For example this is useful for extended barrel for double barrel shotguns. With this system I can spawn two extended barrel for each barrel of the shotgun. This gets particularly interesting for the minigun, where I can spawn 6 extended barrel for each barrel on the weapon.
Weapon Attachment Sockets
So the run down for the entire system is like this:
First off, sockets need to be placed on the weapon blueprints. There are sockets inherited from the parent weapon blueprint. For most weapons, I simply have to re-position the sockets. I've created a visualization tool so that I can preview how the gun would look like with 1 attachment of each type. The spawned mesh actors would be destroyed at begin play.
The parent gun has a struct array called AttData. Each item contains the attachment type, the class reference of the mesh actor, all sockets of the attachment type, and a relative transform information that is not being used for now.
Below is the construction script of the parent gun. This contains the code of the attachment visualization.
Note that the Get Att Table is a global function that calls to get a data table that contains the information of what mesh actor correspond to each attachment type. This would serve as the default AttData array. Also all those NewEnumerator would be attachment type. The enum failed to import to the blueprint embed.
Below are the functions AddAttSocket and SpawnTempAttMesh. These are all within the parent gun blueprint.
AddAttSocket manually adds the socket component to the Att Data array. Each attachment type would have their own Att Data item that contains all the sockets in an array.
SpawnTempAttMesh is the function that spawn child mesh actor to the socket locations. This makes placing and positioning the sockets much easier.
For child weapons, inherited sockets can be removed and new sockets can be added. For the minigun, all barrel attachments sockets (multishot barrel, extended barrel and bayonet) need to be replaced because they need to be child component of the spinning barrel. Also the weapon has 6 barrels, meaning it needs 6 sockets for each barrel attachment.
First new sockets are added
Then, the inherited sockets would need to be removed from the AttData array, new sockets would need to be added, and the mesh actors would need to respawn. All these would be in the construction script of the child weapon.
Spawning Attachment Mesh
When the player pick up a new attachment, these following functions would run :
Here I will be covering the Att Meshes functions, Update Att Stats is covered above.
Reset Att Meshes would delete all spawned mesh actors.
For example, when the player pick up an extended barrel, this would attach to the socket on the gun itself. The 2nd one would attach to the socket on the 1st one, this process would repeat, allowing the barrel to grow longer.
This is where the Att Sockets Map comes in. This map is used to determine where the mesh actors are going to spawn. The key of the map are all the attachment sockets of the gun. The value is the next socket for the next mesh actor to spawn in. At first, the value is the same as its key, since the first mesh actor would be spawned at the base socket locations of the gun.
The Value Socket would update every time it is occupied. It would call the occupying mesh actor for the next socket, then set it as the new Value Socket. Then the next mesh actor would spawn on the new Value Socket and the process would repeat.
This system allows the attachments to stack on each other, and it works regardless of how many sockets are on the gun, such as the minigun with its high amount of sockets.
Below is the Update Att Mesh. For each attachments, it would get all weapon sockets of its type, and spawn a attachment mesh.
The attachment and its mesh generation also transfer between weapons.