Conquering Ciros
Conquering Ciros is an action rogue-lite with a twist of strategy. As Nilvor, the reborn lich prince, you must collect the power of the Crystals, and harness them skillfully in order to reclaim your kingdom. Unleash vengeance and build your power through permanent upgrades, new skills, new crystals, and more!
Contributions:
- UI/UX Design and System Implementation
- Input System (Keyboard, Mouse, and Controller Input for UI and Gameplay)
- CSV Importer for Narrative Data
UI + Input System
In Game UI Demonstration (Controller/Keyboard and Mouse)
Buff Placement
Menu UI Demonstration
Crystal Placement/Swapping
In Game Movement Demonstration
The UI + Input System consist of the Main Menu UI, In Game Player Movement, and In Game UI. Using a combination of the legacy and new Unity Input systems, this system is managed simplistically and modularly. The most complex of the 3 is the In Game UI System, taking advantage of the legacy and new Input systems at the same time. It mainly operates the Level Up and Crystal Pick-up functionality, but there many options available to the player. The basic functions the player can perform with the crystals and buffs on the menu:
When leveling up — place a buff on a current crystal, swap crystal(s) locations within the player’s sigil, and trash a crystal (if more than 1 is present in the sigil).
When picking up a crystal — place a crystal into an empty sigil slot, swap crystal(s) locations (including with the newly picked-up crystal), supercharge a crystal, and trash a crystal (if more than 1 is present in the sigil).
The In Game UI/Input System has 3 main parts.
The first uses legacy Unity UI to use button transitions for controller UI navigation. When a Button UI Component is added to a Unity Game Object, Unity’s legacy input system automatically generates transitions for directional input movement between any other button objects currently active in the same scene. When spawning in buffs and crystals, a button component is added to the object to handle the navigation.
This is also how the Main Menu UI navigation is operated.
The last part uses the events from the Input System package to consolidate the processing of all the unique input methods. The primary function used for the In Game UI is the Submit function. This handles each of the functionalities listed above for both mouse drag and drop and controller selection. Within each commented “if-block” is a helper function that performs the actual action necessary.
Crystal Trashing
Unity UI Button Transition Visualization
The next part uses the new Unity Input System package to have seamless controls across all control schemes (Keyboard and Mouse + most standard controller types). Using the Input Action Asset provided as part of the package, the basic necessary actions are defined. Unity’s package handles the default controller mapping - which mimics a standard gamepad (ex. a PlayStation or Xbox controller). Whenever a new input is needed, it can easily be defined in the Input Action Asset. Each Action is an event in code, so in the UI Manager script each action has a correlating function subscribed to it. Some actions, like Mouse Dragging, are not available by default in the package, so I added a composite script to allow for it. The system is now set up and easily modified.
The player movement is also operated using the Input System Package — the actions for movement are subscribed to their corresponding function within the Player script.
An End Game Run Stats screen being saved to the Journal for later viewing
Save and Load System
Using JSON serialization, many pieces of info are saved to a hidden file. This includes if the tutorial has been completed, the number of unlocked crystals, the types of enemies encountered, etc. Saving is performed at the end of every run, and upon exiting the permanent upgrades menu (if a change was made).
Each run specific stats such as the enemy that killed the player, the player’s final crystals, time elapsed, total kills, and more, are also saved for future viewing within the Journal. The code to the left shows the save data storage format for all of the Run Stats from every run.
CSV Importer
The CSV Importer takes each spreadsheet of narrative data and converts it to a Scriptable Object. The importer can both write and overwrite info. With the use of an editor button I added, the data importing is easily processed once a new CSV is added to the repository. That data is then easily accessible for display in engine/code.
Import of a brand new BeastiaryEntries (Narrative Data) Scriptable Object
Per-run
Buff Placement
Crystal Placement
The Permanent Upgrade System allows the player to increase their base overall stats like health and move speed as well as gain special skills like Dashing and HP recovery. Permanent Upgrades are purchased with Crystal Shards earned through breaking Crystal Deposits in-run. Upgrades get more expensive with each level. In the Upgrade Menu, players have the option to refund their lifetime spendings to redistribute it as they see necessary. The system was implemented before any of the upgrades themselves were designed. As such, the system uses Reflection to find and apply and of the necessary upgrades to the player each run. The Reflection only runs once (during a loading period), so it is not an issue to performance. Through the use of Reflection, however, it allows the Upgrades to be easily modified, added, or removed without changing more than one line of code. Using an Upgrade class to store the data for each one, the code finds the associated variable of each upgrade through name comparison, then applies the correct modification to that variable, if needed. The permanent upgrades are saved as part of the Save and Load System (the save is triggered upon leaving the Upgrade Menu on the Main Menu, if a change was made).
Upgrade Systems
Permanent and Per-run
The Per-run Upgrade System consists of two main parts — Buffs and Crystals. Buffs are boosts to the stats of individual crystals, such as Damage, Range, and Cooldown. Buffs can be applied an infinite amount of times, but provide a diminishing return they are percentage based. Buffs are available to the player upon each level up. Levels are gained by killing enemies and collecting the XP shards they drop. Crystals are the core aspect of the game — the unique offensive, defensive, or supportive ability of each provides a new strength and potential powerful synergies to every run. Crystals are obtained by defeating large-sized enemies know as Mini-bosses. A player may only have as many crystals as is the size of their sigil. As a player progresses, they unlock new crystals and sigils, allowing them to have both more crystals in their arsenal at once and more powerful crystals all together. Lastly, if a player trashes a set number of crystals, they gain the ability to Supercharge a crystal in their sigil. This provides an extreme buff based on the class of main character chosen (Melee — Damage Increase, Ranged — Range Increase, Support — Cooldown Decrease).
Permanent
A short example of Pre-Upgrades and Post-Upgrades (Upgrades in Gif: Dash, Move Speed, Greed, and Experience Increase)
Game State System
The Game State System informs all other scripts of the current game state so they can perform any actions necessary to the current state. Using an Enum and Events, the system sends a message upon a Game State change or the stored Game State Enum is checked when validation is required.
The states include Menu states, In-Game States such as Pause and Play, as well as Saving and Loading, and a few other common game states that occur within the game.
An efficient and effective Game State System helps prevent excess code from running at unrequired times.