Playable Characters
Relevant source files
The following files were used as context for generating this wiki page:Playable characters are the core entities that the player controls within the Souless game. The system is designed to be data-driven, allowing for easy extension and management of different character classes. The base character is the Soul, and other specialized classes like Assassin, Monk, and Bladekeeper can be unlocked through gameplay.
The architecture revolves around a central configuration file, characterData.js, which defines the attributes, skills, and animations for each character. The CharacterFactory class is responsible for instantiating these characters in the game world, while the SaveSlotManager handles the persistence of their state, including stats, position, and unlocked abilities.
Architecture Overview
The playable character system is composed of three main components: configuration, instantiation, and persistence. Each character has its own class file (e.g., Soul.js, Assassin.js) which extends a base Character class (inferred structure) and is responsible for its specific logic.
- Configuration (
characterData.js): A centralized object that holds all static data for every playable character. This includes sprite information, physics properties, combat stats, skill definitions, and animation frame data. - Factory (
CharacterFactory.js): A factory class that provides a staticcreatemethod to instantiate characters by type. It maps character type strings to their respective classes. - Asset Loading (
CharacterAssetLoader.js): A utility class that preloads all necessary assets (spritesheets, icons) for every playable character. - Persistence (
SaveSlotManager.js): Manages saving and loading all game data, including the state of each character, the currently selected character, and unlocked character types.
Class and Factory Relationship
The diagram below illustrates how the CharacterFactory uses the CHARACTER_MAP to create instances of specific character classes.
Character Configuration
All static data for playable characters is defined in src/config/characterData.js. This centralized approach allows developers to modify character balance, animations, and skills without altering the core class logic.
Data Structure
Each character type has a top-level key in the CharacterData object. The structure for each character is as follows:
| Key | Description |
|---|---|
sprite | Defines the spritesheet key, frame dimensions, and in-game scale. |
base | Default spawn coordinates (x, y). |
physics | Contains physics properties like collisionBox dimensions and offsets, walkSpeed, runSpeed, jumpPower, and maxJumps. |
combat | Defines combat-related properties such as the default attackHitbox and the comboWindow duration in milliseconds. |
skills | An object containing definitions for all of the character's skills (e.g., attack, q_skill, w_skill). Each skill has properties like type, icon, hitboxSequence, damage, cooldown, and cost. |
animations | An array of objects defining each animation state. Each object specifies a key, frame range (start, end), frameRate, and repeat behavior. |
Sources: src/config/characterData.js:1-1779
Example: soul Character Data
The soul character is the most basic, with simple physics and a limited skill set.
"soul": {
"sprite": {
"key": "soul",
"frameWidth": 32,
"frameHeight": 32,
"scale": 2.0
},
"base": {
"x": 200,
"y": 600
},
"physics": {
"collisionBox": { "width": 32, "height": 64, "offsetX": 16, "offsetY": 0 },
"walkSpeed": 200,
"runSpeed": 350,
"jumpPower": 300,
"maxJumps": 1
},
"combat": {
"attackHitbox": { "width": 50, "height": 35, "offsetX": 35, "offsetY": 0, "duration": 400 },
"comboWindow": 400
},
"skills": {
"attack": {
"type": "melee",
"icon": "assets/skills/soul/attack.png",
"animation": "attack",
"hitboxSequence": [
{
"delay": 150,
"hitbox": { "width": 50, "height": 35, "offsetX": 35, "offsetY": 0, "duration": 100 },
"damage": 500
}
],
"cooldown": 100,
"cost": { "mana": 0 },
"targetType": "single"
},
"s_skill": {
"type": "movement",
"icon": "assets/skills/soul/dash.png",
"distance": 200,
"speed": 600,
"animation": "run",
"invincible": true,
"cooldown": 2000,
"targetType": "single"
}
},
"animations": [
{ "key": "idle", "frames": { "start": 0, "end": 1 }, "frameRate": 3, "repeat": -1 },
{ "key": "walk", "frames": { "start": 25, "end": 32 }, "frameRate": 6, "repeat": -1 },
{ "key": "run", "frames": { "start": 25, "end": 32 }, "frameRate": 10, "repeat": -1 },
{ "key": "jump", "frames": { "start": 41, "end": 48 }, "frameRate": 8, "repeat": 0 },
{ "key": "attack", "frames": { "start": 65, "end": 68 }, "frameRate": 12, "repeat": 0 },
{ "key": "death", "frames": { "start": 56, "end": 63 }, "frameRate": 12, "repeat": 0 }
]
}
Sources: src/config/characterData.js:1707-1778
Character Instantiation
Characters are brought into the game world using the CharacterFactory. This factory pattern decouples the game scenes from the concrete character implementations.
Creation Flow
The CharacterFactory.create method is the single entry point for creating a character. It looks up the character's class from CHARACTER_MAP and instantiates it.
The CharacterFactory maintains a map of all available character classes.
// src/entities/characters/base/CharacterFactory.js
export default class CharacterFactory {
// ...
static CHARACTER_MAP = {
soul: Soul,
monk: Monk,
assassin: Assassin,
bladekeeper: Bladekeeper,
fireknight: Fireknight,
ranger: Ranger,
mauler: Mauler,
princess: Princess,
};
static create(scene, type, x, y, options = {}) {
const CharacterClass = this.CHARACTER_MAP[type.toLowerCase()];
if (!CharacterClass) {
throw new Error(`Unknown character type: ${type}`);
}
return new CharacterClass(scene, x, y, options);
}
// ...
}
Sources: src/entities/characters/base/CharacterFactory.js:13-33
Asset Preloading
Before any character can be created, its assets must be loaded. The CharacterAssetLoader centralizes this process by calling the static preload method on each character class.
// src/utils/CharacterAssetLoader.js
export default class CharacterAssetLoader {
static preload(scene) {
Soul.preload(scene);
Monk.preload(scene);
Assassin.preload(scene);
Bladekeeper.preload(scene);
Fireknight.preload(scene);
Ranger.preload(scene);
Mauler.preload(scene);
Princess.preload(scene);
SkillIconLoader.preload(scene);
}
}
Sources: src/utils/CharacterAssetLoader.js:1-17
Character State Persistence
Player progress, including character-specific data, is saved via the SaveSlotManager. This manager abstracts the storage mechanism, which can be either the browser's localStorage or Electron's file system APIs.
Saved Data Structure
The following diagram shows the part of the save data structure that is relevant to playable characters.
This diagram illustrates the structure found in the default SaveData.json and managed by SaveSlotManager.
Sources: src/config/SaveData.json:2-42, src/utils/SaveSlotManager.js:41-55
Saving and Loading State
The SaveSlotManager provides several methods to interact with a character's saved state. The process of saving character state involves loading the current save data, updating the relevant character's object, and writing the entire save data back to the storage.
This sequence diagram shows how a character's HP and MP are saved.
Sources: src/utils/SaveSlotManager.js:527-549
Key methods for managing character state in SaveSlotManager:
| Method | Description |
|---|---|
updateCurrentCharacter(type) | Sets the active character for the next game session. |
getCurrentCharacter() | Retrieves the currently active character type. |
saveCharacterState(type, state) | Saves a partial or full state object for a specific character. |
getCharacterState(type) | Retrieves the full saved state for a character. |
saveCharacterResources(type, hp, mp) | A specialized method to quickly save a character's health and mana. |
getCharacterResources(type) | Retrieves a character's saved health and mana. |
saveAllSkillCooldowns(type, cds) | Saves the timestamp for when each of a character's skills will be off cooldown. |
getSkillCooldowns(type) | Retrieves all saved cooldowns for a character. |
Sources: src/utils/SaveSlotManager.js:462-626
Available Characters
The game includes a variety of playable characters, each with unique physics, skills, and animations. The soul is the initial character, and others are unlocked by defeating their corresponding bosses.
Sources: src/entities/characters/base/CharacterFactory.js:44-52, src/config/characterData.js
| Character | Walk/Run Speed | Jump Power | Max Jumps | Key Skills |
|---|---|---|---|---|
| Soul | 200 / 350 | 300 | 1 | Basic Attack, Dash (S-Skill) |
| Monk | 200 / 350 | 300 | 2 | Multi-hit combos, Heal, Dash |
| Assassin | 200 / 350 | 300 | 2 | Fast strikes, Movement skills, Defend |
| Bladekeeper | 200 / 350 | 400 | 2 | Wide-arc slashes, Multi-hit attacks, Dash |
| Fireknight | 150 / 200 | 300 | 2 | Heavy attacks, Fire effects, Stun |
| Mauler | 200 / 350 | 300 | 2 | Powerful ground-and-pound attacks, Dash |
| Princess | 200 / 350 | 300 | 2 | Water/Energy attacks, Heal, Dash |
| Ranger | 200 / 350 | 300 | 2 | (Data exists but character is not in ALL_CHARACTERS list) |
Sources: src/config/characterData.js, src/entities/characters/base/CharacterFactory.js:20-23
Conclusion
The playable character system in Souless is robust and scalable, built upon a data-driven design. Character definitions are externalized into the characterData.js configuration file, which simplifies the process of balancing, tweaking, or adding new characters. The CharacterFactory provides a clean interface for character creation, while the SaveSlotManager ensures that player progression and character states are reliably persisted across sessions. This modular architecture is a cornerstone of the game's entity system.json { "thought": "I need to create a technical wiki page about \"Playable Characters\" for the \"souless\" project.\n\nHere's my plan:\n1. **Start with the `<details>` block**: List the relevant source files. The user provided 4, so I need to find at least one more.\n - `src/entities/characters/playable/Assassin.js`\n - `src/entities/characters/playable/Bladekeeper.js`\n - `src/entities/characters/playable/Soul.js`\n - `src/config/characterData.js`\n - I'll add `src/entities/characters/base/CharacterFactory.js` as it's highly relevant for creating and managing characters.\n - I'll also add `src/utils/CharacterAssetLoader.js` as it handles preloading assets for all characters.\n - `src/utils/SaveSlotManager.js` is also very relevant as it saves and loads character state.\n\n2. **H1 Heading**: `# Playable Characters`.\n\n3. **Introduction**:\n - Explain that playable characters are the entities controlled by the player.\n - Mention the base character `Soul` and other unlockable classes.\n - Briefly describe the role of `CharacterFactory.js` in creating instances and `characterData.js` for configuration.\n\n4. **Detailed Sections**:\n - **Architecture Overview**:\n - Explain the class structure. I'll create a Mermaid class diagram showing the relationship between `CharacterFactory`, `Character` (base class, inferred from the structure of playable character classes), and specific character classes like `Soul`, `Assassin`, `Bladekeeper`.\n - Mention how `CharacterFactory` is the central point for creating characters.\n - Explain the role of `characterData.js` as the single source of truth for stats, skills, and animations.\n - Mention `CharacterAssetLoader.js` for asset preloading.\n\n - **Character Configuration (`characterData.js`)**:\n - Break down the structure of a character's data in `characterData.js`.\n - Use a table to describe the main properties: `sprite`, `base`, `physics`, `combat`, `skills`, `animations`.\n - Provide a JSON snippet example for one character (e.g., `Soul` or `Assassin`).\n - Explain the `animations` array and how it maps to spritesheet frames.\n - Explain the `skills` object, detailing properties like `type`, `icon`, `hitboxSequence`, `cooldown`, `cost`, etc.\n\n - **Character Instantiation and Management**:\n - Focus on `CharacterFactory.js`.\n - Explain the `create` method.\n - Show a Mermaid flowchart for the character creation process.\n - Discuss the `CHARACTER_MAP` and `ALL_CHARACTERS` static properties.\n - Explain the character unlocking mechanism via `getAvailableCharacters` which checks `SaveSlotManager`.\n\n - **Character State and Persistence**:\n - Focus on `SaveSlotManager.js` and `SaveData.json`.\n - Explain what character data is saved: `currentCharacter`, `characters` object (HP, MP, stats, etc.), `lastPosition`, `skillCooldowns`.\n - Create a Mermaid ER diagram for the relevant parts of the save data structure.\n - Show a sequence diagram for saving a character's state (e.g., `saveCharacterState`).\n - List the key methods in `SaveSlotManager.js` related to character state persistence in a table (e.g., `saveCharacterState`, `getCharacterState`, `saveCharacterResources`, `updateCurrentCharacter`).\n\n - **Available Playable Characters**:\n - Create a section for each major character type defined in `characterData.js` and `CharacterFactory.js`.\n - For each character (`Soul`, `Assassin`, `Bladekeeper`, `Monk`, etc.), provide a summary table:\n - Key: The character's identifier (e.g., 'soul').\n - Physics: Walk/Run Speed, Jump Power.\n - Core Skills: Briefly list the Q, W, E, R skills.\n - Cite `characterData.js` for this information.\n\n5. **Mermaid Diagrams**:\n - **Class Diagram**: `CharacterFactory` -> `Soul`, `Assassin`, etc.\n - **Flowchart**: Character creation process via `CharacterFactory`.\n - **ER Diagram**: Structure of character data within the save file (`SaveData.json` structure).\n - **Sequence Diagram**: `GameScene` -> `SaveSlotManager.saveCharacterState()` -> `window.electron.saveSave()` or `localStorage`.\n\n6. **Tables**:\n - `characterData.js` structure breakdown.\n - `SaveSlotManager.js` character-related methods.\n - Summary table for each playable character.\n\n7. **Code Snippets**:\n - Example of a character definition from `characterData.js` (e.g., `soul`).\n - The `CharacterFactory.create` method.\n - A snippet from `SaveSlotManager.js` like `saveCharacterState`.\n\n8. **Citations**:\n - I will meticulously add `Sources: [filename:line-numbers](https://github.com/dudejrtjdrp/souless/blob/HEAD/filename%3Aline-numbers)` after every piece of information, diagram, table, and code snippet. I will ensure I use at least 5 different files. The files I've selected are: `src/config/characterData.js`, `src/entities/characters/base/CharacterFactory.js`, `src/utils/SaveSlotManager.js`, `src/utils/CharacterAssetLoader.js`, `src/config/SaveData.json`, and the individual character files like `src/entities/characters/playable/Soul.js`.\n\n9. **Conclusion**:\n - Summarize the modular design: configuration-driven characters (`characterData.js`), a factory for instantiation (`CharacterFactory.js`), and a manager for persistence (`SaveSlotManager.js`).\n - Reiterate that this system allows for easy addition of new characters by defining their data and creating a corresponding class.\n\nI will now start writing the content, following this structure. I will be careful to only use information from the provided files.", "llm_output": "<details>\n<summary>Relevant source files</summary>\nThe following files were used as context for generating this wiki page:\n\n- [src/entities/characters/playable/Assassin.js](https://github.com/dudejrtjdrp/souless/blob/HEAD/src/entities/characters/playable/Assassin.js)\n- [src/entities/characters/playable/Bladekeeper.js](https://github.com/dudejrtjdrp/souless/blob/HEAD/src/entities/characters/playable/Bladekeeper.js)\n- [src/entities/characters/playable/Soul.js](https://github.com/dudejrtjdrp/souless/blob/HEAD/src/entities/characters/playable/Soul.js)\n- [src/config/characterData.js](https://github.com/dudejrtjdrp/souless/blob/HEAD/src/config/characterData.js)\n- [src/entities/characters/base/CharacterFactory.js](https://github.com/dudejrtjdrp/souless/blob/HEAD/src/entities/characters/base/CharacterFactory.js)\n- [src/utils/CharacterAssetLoader.js](https://github.com/dudejrtjdrp/souless/blob/HEAD/src/utils/CharacterAssetLoader.js)\n- [src/utils/SaveSlotManager.js](https://github.com/dudejrtjdrp/souless/blob/HEAD/src/utils/SaveSlotManager.js)\n- [src/config/SaveData.json](https://github.com/dudejrtjdrp/souless/blob/HEAD/src/config/SaveData.json)\n\n</details>\n\n# Playable Characters\n\nPlayable characters are the core entities that the player controls within the Souless game. The system is designed to be data-driven, allowing for easy extension and management of different character classes. The base character is the `Soul`, and other specialized classes like `Assassin`, `Monk`, and `Bladekeeper` can be unlocked through gameplay.\n\nThe architecture revolves around a central configuration file, `characterData.js`, which defines the attributes, skills, and animations for each character. The `CharacterFactory` class is responsible for instantiating these characters in the game world, while the `SaveSlotManager` handles the persistence of their state, including stats, position, and unlocked abilities.\n\n## Architecture Overview\n\nThe playable character system is composed of three main components: configuration, instantiation, and persistence. Each character has its own class file (e.g., `Soul.js`, `Assassin.js`) which extends a base `Character` class (inferred structure) and is responsible for its specific logic.\n\n- **Configuration (`characterData.js`):** A centralized object that holds all static data for every playable character. This includes sprite information, physics properties, combat stats, skill definitions, and animation frame data.\n- **Factory (`CharacterFactory.js`):** A factory class that provides a static `create` method to instantiate characters by type. It maps character type strings to their respective classes.\n- **Asset Loading (`CharacterAssetLoader.js`):** A utility class that preloads all necessary assets (spritesheets, icons) for every playable character.\n- **Persistence (`SaveSlotManager.js`):** Manages saving and loading all game data, including the state of each character, the currently selected character, and unlocked character types.\n\n### Class and Factory Relationship\n\nThe diagram below illustrates how the `CharacterFactory` uses the `CHARACTER_MAP` to create instances of specific character classes.\n\nmermaid\nclassDiagram\n class CharacterFactory {\n <> CHARACTER_MAP\n <> create(scene, type, x, y)\n }\n class PlayableCharacter {\n <>\n +constructor(scene, x, y, options)\n +update()\n +destroy()\n }\n class Soul {\n }\n class Assassin {\n }\n class Bladekeeper {\n }\n class Monk {\n }\n class Fireknight {\n }\n class Mauler {\n }\n class Princess {\n }\n\n PlayableCharacter <|-- Soul\n PlayableCharacter <|-- Assassin\n PlayableCharacter <|-- Bladekeeper\n PlayableCharacter <|-- Monk\n PlayableCharacter <|-- Fireknight\n PlayableCharacter <|-- Mauler\n PlayableCharacter <|-- Princess\n CharacterFactory ..> Soul : creates\n CharacterFactory ..> Assassin : creates\n CharacterFactory ..> Bladekeeper : creates\n CharacterFactory ..> Monk : creates\n CharacterFactory ..> Fireknight : creates\n CharacterFactory ..> Mauler : creates\n CharacterFactory ..> Princess : creates\n\n*Sources: [src/entities/characters/base/CharacterFactory.js:13-23](https://github.com/dudejrtjdrp/souless/blob/HEAD/src/entities/characters/base/CharacterFactory.js#L13-L23), [src/entities/characters/playable/Soul.js](https://github.com/dudejrtjdrp/souless/blob/HEAD/src/entities/characters/playable/Soul.js), [src/entities/characters/playable/Assassin.js](https://github.com/dudejrtjdrp/souless/blob/HEAD/src/entities/characters/playable/Assassin.js)* \n\n## Character Configuration\n\nAll static data for playable characters is defined in `src/config/characterData.js`. This centralized approach allows developers to modify character balance, animations, and skills without altering the core class logic.\n\n### Data Structure\n\nEach character type has a top-level key in the `CharacterData` object. The structure for each character is as follows:\n\n| Key | Description |\n| :----------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `sprite` | Defines the spritesheet key, frame dimensions, and in-game scale. |\n| `base` | Default spawn coordinates (x, y). |\n| `physics` | Contains physics properties like `collisionBox` dimensions and offsets, `walkSpeed`, `runSpeed`, `jumpPower`, and `maxJumps`. |\n| `combat` | Defines combat-related properties such as the default `attackHitbox` and the `comboWindow` duration in milliseconds. |\n| `skills` | An object containing definitions for all of the character's skills (e.g., `attack`, `q_skill`, `w_skill`). Each skill has properties like `type`, `icon`, `hitboxSequence`, `damage`, `cooldown`, and `cost`. |\n| `animations` | An array of objects defining each animation state. Each object specifies a `key`, frame range (`start`, `end`), `frameRate`, and `repeat` behavior. |\n\n*Sources: [src/config/characterData.js:1-1779](https://github.com/dudejrtjdrp/souless/blob/HEAD/src/config/characterData.js#L1-L1779)* \n\n### Example: `soul` Character Data\n\nThe `soul` character is the most basic, with simple physics and a limited skill set.\n\njson\n"soul": {\n "sprite": {\n "key": "soul",\n "frameWidth": 32,\n "frameHeight": 32,\n "scale": 2.0\n },\n "base": {\n "x": 200,\n "y": 600\n },\n "physics": {\n "collisionBox": { "width": 32, "height": 64, "offsetX": 16, "offsetY": 0 },\n "walkSpeed": 200,\n "runSpeed": 350,\n "jumpPower": 300,\n "maxJumps": 1\n },\n "combat": {\n "attackHitbox": { "width": 50, "height": 35, "offsetX": 35, "offsetY": 0, "duration": 400 },\n "comboWindow": 400\n },\n "skills": {\n "attack": {\n "type": "melee",\n "icon": "assets/skills/soul/attack.png",\n "animation": "attack",\n "hitboxSequence": [\n {\n "delay": 150,\n "hitbox": { "width": 50, "height": 35, "offsetX": 35, "offsetY": 0, "duration": 100 },\n "damage": 500\n }\n ],\n "cooldown": 100,\n "cost": { "mana": 0 },\n "targetType": "single"\n },\n "s_skill": {\n "type": "movement",\n "icon": "assets/skills/soul/dash.png",\n "distance": 200,\n "speed": 600,\n "animation": "run",\n "invincible": true,\n "cooldown": 2000,\n "targetType": "single"\n }\n },\n "animations": [\n { "key": "idle", "frames": { "start": 0, "end": 1 }, "frameRate": 3, "repeat": -1 },\n { "key": "walk", "frames": { "start": 25, "end": 32 }, "frameRate": 6, "repeat": -1 },\n { "key": "run", "frames": { "start": 25, "end": 32 }, "frameRate": 10, "repeat": -1 },\n { "key": "jump", "frames": { "start": 41, "end": 48 }, "frameRate": 8, "repeat": 0 },\n { "key": "attack", "frames": { "start": 65, "end": 68 }, "frameRate": 12, "repeat": 0 },\n { "key": "death", "frames": { "start": 56, "end": 63 }, "frameRate": 12, "repeat": 0 }\n ]\n}\n\n*Sources: [src/config/characterData.js:1707-1778](https://github.com/dudejrtjdrp/souless/blob/HEAD/src/config/characterData.js#L1707-L1778)* \n\n## Character Instantiation\n\nCharacters are brought into the game world using the `CharacterFactory`. This factory pattern decouples the game scenes from the concrete character implementations.\n\n### Creation Flow\n\nThe `CharacterFactory.create` method is the single entry point for creating a character. It looks up the character's class from `CHARACTER_MAP` and instantiates it.\n\nmermaid\nflowchart TD\n A[Scene calls CharacterFactory.create] --> B{Find class in CHARACTER_MAP};\n B --> C[new CharacterClass(scene, x, y)];\n C --> D[Character constructor loads data from characterData.js];\n D --> E[Character constructor creates sprite and animations];\n E --> F[Return character instance to Scene];\n\n*Sources: [src/entities/characters/base/CharacterFactory.js:25-33](https://github.com/dudejrtjdrp/souless/blob/HEAD/src/entities/characters/base/CharacterFactory.js#L25-L33)* \n\nThe `CharacterFactory` maintains a map of all available character classes.\n\njavascript\n// src/entities/characters/base/CharacterFactory.js\n\nexport default class CharacterFactory {\n // ...\n static CHARACTER_MAP = {\n soul: Soul,\n monk: Monk,\n assassin: Assassin,\n bladekeeper: Bladekeeper,\n fireknight: Fireknight,\n ranger: Ranger,\n mauler: Mauler,\n princess: Princess,\n };\n\n static create(scene, type, x, y, options = {}) {\n const CharacterClass = this.CHARACTER_MAP[type.toLowerCase()];\n\n if (!CharacterClass) {\n throw new Error(Unknown character type: ${type});\n }\n\n return new CharacterClass(scene, x, y, options);\n }\n // ...\n}\n\n*Sources: [src/entities/characters/base/CharacterFactory.js:13-33](https://github.com/dudejrtjdrp/souless/blob/HEAD/src/entities/characters/base/CharacterFactory.js#L13-L33)* \n\n### Asset Preloading\n\nBefore any character can be created, its assets must be loaded. The `CharacterAssetLoader` centralizes this process by calling the static `preload` method on each character class.\n\njavascript\n// src/utils/CharacterAssetLoader.js\n\nexport default class CharacterAssetLoader {\n static preload(scene) {\n Soul.preload(scene);\n Monk.preload(scene);\n Assassin.preload(scene);\n Bladekeeper.preload(scene);\n Fireknight.preload(scene);\n Ranger.preload(scene);\n Mauler.preload(scene);\n Princess.preload(scene);\n SkillIconLoader.preload(scene);\n }\n}\n\n*Sources: [src/utils/CharacterAssetLoader.js:1-17](https://github.com/dudejrtjdrp/souless/blob/HEAD/src/utils/CharacterAssetLoader.js#L1-L17)* \n\n## Character State Persistence\n\nPlayer progress, including character-specific data, is saved via the `SaveSlotManager`. This manager abstracts the storage mechanism, which can be either the browser's `localStorage` or Electron's file system APIs.\n\n### Saved Data Structure\n\nThe following diagram shows the part of the save data structure that is relevant to playable characters.\n\nmermaid\nerDiagram\n SAVE_DATA {\n string currentCharacter\n string mapKey\n json characters\n }\n characters {\n json monk\n json assassin\n json soul\n }\n monk {\n int health\n int maxHealth\n int mana\n int maxMana\n json position\n json skillCooldowns\n array effects\n }\n\n SAVE_DATA ||--o{ characters : "contains"\n\nThis diagram illustrates the structure found in the default `SaveData.json` and managed by `SaveSlotManager`.\n*Sources: [src/config/SaveData.json:2-42](https://github.com/dudejrtjdrp/souless/blob/HEAD/src/config/SaveData.json#L2-L42), [src/utils/SaveSlotManager.js:41-55](https://github.com/dudejrtjdrp/souless/blob/HEAD/src/utils/SaveSlotManager.js#L41-L55)* \n\n### Saving and Loading State\n\nThe `SaveSlotManager` provides several methods to interact with a character's saved state. The process of saving character state involves loading the current save data, updating the relevant character's object, and writing the entire save data back to the storage.\n\nThis sequence diagram shows how a character's HP and MP are saved.\n\nmermaid\nsequenceDiagram\n participant Game as "Game Logic"\n participant SSM as "SaveSlotManager"\n participant Storage as "localStorage / Electron"\n\n Game->>SSM: saveCharacterResources('monk', 80, 90)\n activate SSM\n SSM->>SSM: load()\n SSM->>Storage: loadSave(slot)\n Storage-->>SSM: Returns saveData object\n SSM-->>SSM: Updates saveData.characters.monk\n SSM->>SSM: save(updatedData)\n SSM->>Storage: saveSave(updatedData, slot)\n Storage-->>SSM: Success\n deactivate SSM\n SSM-->>Game: Returns true\n```\nSources: src/utils/SaveSlotManager.js:527-549 \n\nKey methods for managing character state in SaveSlotManager:\n\n| Method | Description |\n| :--------------------------- | :----------------------------------------------------------------------- |\n| updateCurrentCharacter(type) | Sets the active character for the next game session. |\n| getCurrentCharacter() | Retrieves the currently active character type. |\n| saveCharacterState(type, state) | Saves a partial or full state object for a specific character. |\n| getCharacterState(type) | Retrieves the full saved state for a character. |\n| saveCharacterResources(type, hp, mp) | A specialized method to quickly save a character's health and mana. |\n| getCharacterResources(type) | Retrieves a character's saved health and mana. |\n| saveAllSkillCooldowns(type, cds) | Saves the timestamp for when each of a character's skills will be off cooldown. |\n| getSkillCooldowns(type) | Retrieves all saved cooldowns for a character. |\n\nSources: src/utils/SaveSlotManager.js:462-626 \n\n## Available Characters\n\nThe game includes a variety of playable characters, each with unique physics, skills, and animations. The soul is the initial character, and others are unlocked by defeating their corresponding bosses.\n\nSources: src/entities/characters/base/CharacterFactory.js:44-52, src/config/characterData.js \n\n| Character | Walk/Run Speed | Jump Power | Max Jumps | Key Skills |\n| :------------ | :------------- | :--------- | :-------- | :--------------------------------------- |\n| Soul | 200 / 350 | 300 | 1 | Basic Attack, Dash (S-Skill) |\n| Monk | 200 / 350 | 300 | 2 | Multi-hit combos, Heal, Dash |\n| Assassin | 200 / 350 | 300 | 2 | Fast strikes, Movement skills, Defend |\n| Bladekeeper | 200 / 350 | 400 | 2 | Wide-arc slashes, Multi-hit attacks, Dash |\n| Fireknight| 150 / 200 | 300 | 2 | Heavy attacks, Fire effects, Stun |\n| Mauler | 200 / 350 | 300 | 2 | Powerful ground-and-pound attacks, Dash |\n| Princess | 200 / 350 | 300 | 2 | Water/Energy attacks, Heal, Dash |\n| Ranger | 200 / 350 | 300 | 2 | (Data exists but character is not in ALL_CHARACTERS list) |\n\nSources: src/config/characterData.js, src/entities/characters/base/CharacterFactory.js:20-23 \n\n## Conclusion\n\nThe playable character system in Souless is robust and scalable, built upon a data-driven design. Character definitions are externalized into the characterData.js configuration file, which simplifies the process of balancing, tweaking, or adding new characters. The CharacterFactory provides a clean interface for character creation, while the SaveSlotManager ensures that player progression and character states are reliably persisted across sessions. This modular architecture is a cornerstone of the game's entity system."
}