Cosmetics System
Relevant source files
The following files were used as context for generating this wiki page:- src/store/CosmeticsStore.ts
- src/screens/CosmeticsScreen.ts
- src/components/cosmeticsScreen/CosmeticsPicker.ts
- src/components/cosmeticsScreen/CosmeticsTypePicker.ts
- src/components/cosmeticsScreen/SkinColorPicker.ts
- src/components/character/CharacterBase.ts
- src/components/character/Hat.ts
- src/components/character/Shirt.ts
- src/components/character/Pants.ts
- src/Game.ts
- src/screens/StartScreen.ts
The Cosmetics System allows players to customize their in-game character's appearance. This includes changing the character's hat, shirt, pants, and skin color. Selections are persisted across browser sessions using cookies.
The system is built around a central state management store, CosmeticsStore, which acts as the single source of truth for the character's appearance. UI components on the CosmeticsScreen read from and write to this store, and the character rendering components subscribe to its state to display the chosen cosmetics.
Architecture Overview
The system's architecture is composed of three main parts: State Management, UI Components, and Character Rendering.
This diagram shows the high-level interaction between the state store, UI components, and character rendering components.
Sources: src/store/CosmeticsStore.ts, src/screens/CosmeticsScreen.ts, src/components/character/CharacterBase.ts
State Management: CosmeticsStore
The CosmeticsStore is the heart of the system, managing the state of the player's chosen cosmetics. It extends the base Store class.
Sources: src/store/CosmeticsStore.ts:117
State Structure
The store's content is defined by the CosmeticsStoreContent type, which holds the IDs for the currently selected items.
export type CosmeticsStoreContent = {
hat: Hats;
shirt: Shirts;
pants: Pants;
skinColor: SkinColors;
};
Sources: src/store/CosmeticsStore.ts:111-116
Initialization and Persistence
On instantiation, CosmeticsStore first attempts to load a saved configuration from a browser cookie named cosmetics. If a valid cookie is found, it populates the store's state. If not, it generates a random cosmetic configuration, applies it to the state, and saves it as a new cookie for future sessions.
This flow ensures that a player's customizations are remembered, while new players start with a random look.
This sequence diagram illustrates the initialization logic of CosmeticsStore.
Sources: src/store/CosmeticsStore.ts:121-131, src/store/CosmeticsStore.ts:136-140
Data Models
The available cosmetic items are defined in static arrays, with each item type having its own enum for IDs and a data interface.
| Type | Enum | Data Interface | Data Array |
|---|---|---|---|
| Hat | Hats | HatData | hatsData |
| Shirt | Shirts | ShirtData | shirtsData |
| Pants | Pants | PantsData | pantsData |
| Skin | SkinColors | (N/A) | SKIN_COLORS |
Sources: src/store/CosmeticsStore.ts:29, src/store/CosmeticsStore.ts:68, src/store/CosmeticsStore.ts:87, src/store/CosmeticsStore.ts:108
Available Items
Hats
| ID | Name | Sprite |
|---|---|---|
| 0 | None | '' |
| 1 | Cop | cop_hat.png |
| 2 | Crown | crown.png |
| 3 | Mexican | mexican_hat.png |
| 4 | Top | top_hat.png |
| Sources: src/store/CosmeticsStore.ts:33-55 |
Shirts
| ID | Name | Sprite |
|---|---|---|
| 0 | None | '' |
| 1 | White | white_shirt.png |
| 2 | Woodsman | woodsman_shirt.png |
| Sources: src/store/CosmeticsStore.ts:72-85 |
Pants
| ID | Name | Sprite |
|---|---|---|
| 0 | Blue | blue_pants.png |
| 1 | Gray | gray_pants.png |
| Sources: src/store/CosmeticsStore.ts:91-101 |
Skin Colors
There are 5 available skin colors, identified by numbers 1 through 5.
Sources: src/store/CosmeticsStore.ts:107-108
UI Components
The user interacts with the cosmetics system via the CosmeticsScreen.
Sources: src/screens/StartScreen.ts:85-91, src/Game.ts:143-147
CosmeticsScreen
This screen acts as the main container for all cosmetic-related UI. It lays out the following components:
- A
Dialogbox for the main UI frame. - A
Charactercomponent to preview the changes in real-time. - The
CosmeticsPickerfor selecting hats, shirts, and pants. - The
SkinColorPickerfor changing the character's skin tone. - A "Home" button to return to the previous screen.
Sources: src/screens/CosmeticsScreen.ts:29-73
CosmeticsPicker
This component is responsible for displaying the selectable cosmetic items.
- It contains a
CosmeticsTypePickerto let the user switch between'hat','shirt', and'pants'. - Based on the active type, it renders a list of available items using a
Repeatinglogical component. - Each item is rendered as a
Sprite. If an item has no sprite (the "None" option), an 'X' icon is shown instead. - An
EventListeneris overlaid on each sprite. When clicked, it calls the appropriate setter method on theCosmeticsStore(e.g.,cosmeticsStore.setHat(...)).
This diagram shows the flow of selecting a cosmetic item.
Sources: src/components/cosmeticsScreen/CosmeticsPicker.ts:68-96
CosmeticsTypePicker
A simple component that displays three icons (pants, shirt, hat). Each icon has an EventListener that, when clicked, executes a callback function passed from CosmeticsPicker to update the active cosmetic type.
Sources: src/components/cosmeticsScreen/CosmeticsTypePicker.ts:19-64
SkinColorPicker
This component renders a series of colored rectangles, one for each available skin tone. Each rectangle has an EventListener that calls cosmeticsStore.setSkinColor() with the corresponding color index when clicked.
Sources: src/components/cosmeticsScreen/SkinColorPicker.ts:21-31
Character Rendering
The character's appearance is a composition of several components, each responsible for a specific part. These components read their state directly from the CosmeticsStore to render the correct sprite.
CharacterBase: Renders the main body and eyes. It readscontent.skinColorfrom theCosmeticsStoreto determine which base body sprite to use.Hat: Renders the selected hat. It gets the sprite URL fromcosmeticsStore.activeHat.sprite.Shirt: Renders the selected shirt. It gets the sprite URL fromcosmeticsStore.activeShirt.sprite.Pants: Renders the selected pants. It gets the sprite URL fromcosmeticsStore.activePants.sprite.
This direct-from-store rendering approach ensures that any change in CosmeticsStore is immediately reflected on the character preview without complex prop drilling.
Sources: src/components/character/CharacterBase.ts:25-36, src/components/character/Hat.ts:15-22, src/components/character/Shirt.ts:15-22, src/components/character/Pants.ts:15-22