# Modding Shweet's Sim Want to add characters or modify existing ones or mod Shweet's Sim in general or otherwise want to know how the game works? Here's how. # Animation Format Shweet's Sim uses ".anm2" files for tweened character animations, sourced from spritesheets. The format comes from the game _The Binding of Isaac: Rebirth_ (a game I mod on my own time), but the game reads the JSON flavor of it saved by my own animation editor, [Anm2Ed](https://github.com/ShweetsStuff/anm2ed). In Anm2Ed, turn on Save as JSON (Settings → Configure → Serialization), or convert an existing file with `anm2ed convert file.anm2 --format json`. Keep the `.anm2` extension. Isaac's own editor can't open these. Anm2Ed has "Regions", which let you set spritesheet regions (areas in the spritesheet that can be repurposed) to quickly reference in animations; previously, one would have to manually create a perfectly spaced spritesheet and then manually set values; this is no longer the case, so using "Regions" is recommended. My process for making characters is that they're typically comprised of many "cells" (small graphics). I make these cells their own file, and then in the editor, I drag them onto "Spritesheets" and then right click -> merge them, with the "Make Spritesheet Regions" option enabled. Then, right click -> Pack on a spritesheet to optimize it all nice for one big spritesheet atlas with everything in one place. It won't produce a very comprehensible spritesheet, but it works just fine (not my problem). Make sure to save the spritesheets you're using once you're done. You can sort regions around by clicking, holding and moving them around. If you'd like a quick primer on how to use the editor, check either of [these](https://www.youtube.com/watch?v=qU_GMo2l7NY) [videos](https://www.youtube.com/watch?v=QiXVM6Gwzlw) out. They're a little out of date, but much of it still applies. The game plays spritesheets, regions, layers, nulls, layer groups, events, trigger sounds, and the position, crop, pivot, scale, rotation, tint, color offset, visibility and easing of keyframes. It doesn't play skew, depth, blur, custom shaders or animation layers. Animation groups (the editor's folders) are fine; the game just looks animations up by name, so keep those unique. Stage-specific character animations are controlled by `animationSuffix` on each stage in `character.json`. The base stage uses no suffix. Later stages append that stage's suffix. Example: - stage 1: `Look` - stage 2 with `"animationSuffix": "Stage2"`: `LookStage2` - stage 5 with `"animationSuffix": "Stage5"`: `LookStage5` Animation names in the JSON files should still use just the base name like `Look`, `Neutral`, or `Eat`. The game appends the current stage's suffix automatically. Know that despite Anm2Ed supporting sounds for animations, don't expect these to work in context based on names; use the JSON sound lists when applicable. You can add sounds for fluff, though (trigger sounds play). # Resources There's two folders inside resources; "characters" and "font". "font" is just a font containing the font used in the selection screen. That's literally it. EVERYTHING ELSE is stored inside character folders in the "characters" folder; one folder per character, named however you like (the folder name is also the name of its save file). This has all data associated with characters. Think of characters more as tailored game experiences rather than literally being just the characters. Not only is there the character graphics, but backgrounds, items, parameters, etc. These are intensely customizable to suit whatever experience you'd like (within the confines of the engine, of course). Shweet's Sim uses [JSON](https://en.wikipedia.org/wiki/JSON) files for its data; make sure to brush up on the format. A character folder holds these files: - character.json - items.json - dialogue.json `character.json` is required; a folder without one isn't listed. The other two are optional, but most real characters will want both. Every path in these files is relative to the character's folder (e.g. `"sfx/blip.ogg"` or `"gfx/items/apple.png"`). Paths inside an .anm2 are relative to the .anm2. Anything left out takes its default, so only write what you need. Wherever sounds are listed, one is picked at random each time. If you're making your own character, your best bet would probably be just to copy the Snivy character and edit it based on your needs, just as a helpful start. # character.json This is the main character file where much of the functionality is stored. ```json { "name": "Snivy", "anm2": "gfx/character/snivy.anm2", "weight": 8.1, "stages": [{"weight": 10, "dialoguePool": "Stage2", "animationSuffix": "Stage2"}], "animations": {"start": "Appear", "idle": "Neutral", "idleFull": "NeutralFull", "stageUp": "StageUp"}, "sounds": {"digest": ["sfx/digest1.ogg"], "gurgle": ["sfx/gurgle1.ogg", "sfx/gurgle2.ogg"]} } ``` | Key | Type | Meaning | |---|---|---| | `name` | string | Name of the character; will appear in dialogue, stats, etc. Defaults to the folder name. | | `description` | string | A general description of the character; will show in the Select screen. | | `credits` | string | Credits text shown in the Select screen's Credits tab. | | `render` | path | Texture for the character's "render" (i.e., a typical full-body display), will show in the Select screen. | | `portrait` | path | Texture for the character's "portrait" (i.e., a cropped profile view), will show in the Select screen. | | `anm2` | path | The character's anm2 file; should have all the character's animations. | | `color` | [r, g, b], 0-1 | UI accent color for the character. | | `weight` | float, kg | The character's starting weight. | | `weightMax` | float, kg | Maximum weight the character can reach. | | `capacity` | float, kcal | The character's starting capacity. | | `capacityMin`, `capacityMax` | float, kcal | The range capacity stays within. | | `overstuffedMultiplier` | float | The character can eat past capacity up to capacity times this. | | `overstuffedDigestBonus` | float | Additional capacity gained on digest when the character was over capacity (scaled by how far over). | | `caloriesToKilogram` | float | How many kilograms each calorie digested becomes. | | `digestionRate` | float, %/second | The base digestion rate. | | `digestionRateMin`, `digestionRateMax` | float, %/second | The range the digestion rate stays within. | | `digestionTime` | int, ticks | When digesting, the digestion bar will count down, and then when it hits 0, the current calories will be digested. This determines how long this takes. | | `blinkChance` | float, % | Chance each tick to blink. | | `gurgleChance` | float | How often the character will gurgle (see `sounds`) per tick, scaled by how full they are. | | `gurgleCapacityMultiplier` | float | Multiplies the gurgle chance at full capacity. Higher capacity = higher gurgle chance. | | `dialoguePool` | string | The character's base dialogue pool for "How are you feeling?". This is effectively "Stage 1"'s dialogue; each stage should have its own dialogue pool. | ### alternate The alternate spritesheet of the character, if applicable (in Pokemon terms, the "shiny"). | Key | Type | Meaning | |---|---|---| | `texture` | path | The alternate spritesheet texture. | | `sound` | path | Plays when the spritesheet is set to alternate (either on new game, or with an item that has `isToggleSpritesheet`). | | `spritesheet` | int | The spritesheet of the character's anm2 it replaces. Defaults to 0. | | `chance` | float, % | Chance of rolling the alternate spritesheet when starting a new game. | ### stages A "stage" represents each visual change of the character as the weight increases. By default, there's always one stage; each entry in this list adds another. | Key | Type | Meaning | |---|---|---| | `weight` | float, kg | The weight threshold to reach this stage. | | `dialoguePool` | string | The stage's dialogue pool for "How are you feeling?". | | `animationSuffix` | string | Suffix appended to base animation names while this stage is active. Usually `Stage2`, `Stage3`, etc. | | `area` | int | Switches to this area (from `areas.list`) from this stage on. | ### animations The character's animations. Know that a lot of character animations are typically easily played through dialogue; this is just for animations that aren't reliant on that system. These are just the base names. | Key | Meaning | |---|---| | `start` | Plays first when starting a new game; used for like a character's introduction. | | `idle` | The idle animation that the character will regularly return to. | | `idleFull` | When over capacity, this idle animation will be used instead. | | `stageUp` | When going to a new stage after digestion goes over a stage's threshold, this animation will play. | ### talk, blink "talk" and "blink" are animations tweaked by the game for effect. Typically, each animation will have an invisible blinking/talking layer (just the graphic that blinks), which will change when called for. All that's sourced is just the spritesheet crop in these cases; so don't worry about how the blink/talk layers are set up. | Key | Meaning | |---|---| | `source` | The layer in the animation which will be sourced. | | `destination` | The layer in the animation which the source will be applied to. | ### eatAreas An "eat area" is where the food should be dragged to. I'm pretty much expecting this to only be a mouth for most characters but hey maybe you want the character to also eat through their butt or something. | Key | Meaning | |---|---| | `null` | The null in the animation where food will be checked for. | | `animation` | The animation that will play when food is dragged to it. | | `event` | The event that will be checked for, determining the time the food is actually eaten/chewed. | ### expandAreas The areas which will expand based on how full the character is and their progress to the next stage (50/50); usually a stomach. This adds scale onto a layer and a null of every animation. | Key | Meaning | |---|---| | `layer` | The layer that will expand. | | `null` | The null that will expand. | | `scaleMax` | The scale (in percent) that will be added at maximum. Know that a scale of 100 is the normal scale of an animation. | ### interactTypes, interactAreas `interactTypes` is an object of interaction types by name (each gets a button in the tools bar), giving each type's defaults. `interactAreas` is a list of the concrete areas on a character which can be interacted with; usually for belly rubs, kisses, etc. Each area names its `type` and takes all of that type's settings, changing whichever it gives itself. | Key | Type | Meaning | |---|---|---| | `type` | string | (Areas only) The interaction type to use. | | `null` | string | (Areas) The null in which the interact area can be triggered. | | `layer` | string | The layer that the scale effect (e.g. smacks) applies to. | | `glyph` | string | The icon-font glyph used for this type in the tools bar. | | `isHold` | bool | If true, the interaction is held rather than clicked once. | | `cursorHover` | string | The animation the cursor will play when hovering over the interact area. | | `cursorActive` | string | The animation the cursor will play when interacting. | | `animation` | string | A character animation to play on interacting, when the area has no dialogue pool. | | `idleOnEnd` | string | The idle animation the character uses after interacting (e.g. turning around). | | `dialoguePool` | string | The dialogue pool which will be drawn from when interacting. | | `dialoguePoolFull` | string | Dialogue pool used when the character is over capacity. | | `dialogueCooldown` | int, ticks | Ticks before interacting can start new dialogue again. | | `digestionClick` | float, % | Digestion added each click. | | `digestionHover` | float, % | Digestion added each tick the cursor moves while held. | | `scaleAmplitude` | float, % | Size of the scale effect on clicking. | | `scaleCycles` | float | How many oscillations the scale effect performs. Defaults to 1. | | `scaleTime` | float, ticks | How long the scale effect lasts. Defaults to 20. | | `sounds` | paths | Sounds played when interacting. | | `particles` | strings | Particles (see `particles`) spawned when interacting. | ### sounds | Key | Meaning | |---|---| | `digest` | Plays when the character begins digesting (digestion bar full). | | `gurgle` | Ambient sounds that play randomly based on capacity; see `gurgleChance`. | ### areas "Areas" refers to the backgrounds of the game. Stages can switch between them (see `stages`). | Key | Type | Meaning | |---|---|---| | `anm2` | path | The anm2 the areas use. | | `boundsNull` | string | The null setting the world's bounds. Defaults to `Bounds`. | | `spawnNull` | string | The null items spawn at random points within. If omitted or missing, `boundsNull` is used. | | `list` | list | The areas. Each can set its own `anm2`, its `gravity` (applied to items' velocities per tick), `friction` (applied when items are grounded or hit walls) and `airResistance`. | ### cursor Determines the cursor appearance and behavior. Without one, the system cursor is used. | Key | Meaning | |---|---| | `anm2` | The anm2 file the cursor will use. | | `animations` | `idle`, `click`, `hover` (over an item), `grab` (an item), `pan` (with middle mouse), `zoom` (with the mouse wheel) and `dispose` (right clicking an item). | | `sounds` | `grab` (grabbing an item), `release` (letting go) and `throw` (letting go while dragging quickly). | | `particles` | `grab`: particles spawned when grabbing an item. | ### menu Determines menu and general UI appearance and behavior. | Key | Meaning | |---|---| | `font` | The font the menu will use. | | `iconsFont` | The font holding the tools bar's glyphs. | | `rounding` | The rounding of corners the UI will use. | | `homeGlyph` | The glyph of the tools bar's Home button. | | `sounds` | `open` and `close` (a sliding panel), `hover` and `select` (a widget), and `cheats` (after entering a special code to activate cheats). | ### particles An object of particles by name, each with the `anm2` and `animation` it plays once where spawned. # items.json Has all items and their parameters, alongside additional behavior. ```json { "anm2": "gfx/items/item.anm2", "spawnDelay": 600, "categories": {"Food": "edible", "Tool": "tool"}, "rarities": {"Common": {"weight": 1, "sound": "sfx/common.ogg"}}, "items": [ {"name": "Apple", "texture": "gfx/items/apple.png", "category": "Food", "rarity": "Common", "calories": 95} ] } ``` | Key | Type | Meaning | |---|---|---| | `anm2` | path | The base anm2 file that items will use. | | `spritesheet` | int | The spritesheet of the anm2 that an item's `texture` replaces. Defaults to 0. | | `spawnDelay` | int, ticks | Base cooldown before another item can be spawned. | | `spawnDelayMultiplier` | float | Multiplies the spawn delay once per character stage. Values below `1.0` make item spawning faster as stage increases. | | `spawnLimit` | int | Maximum number of items in the world at once. | | `sounds` | | `bounce` (an item hitting a floor/wall/ceiling), `dispose` (an item disposed of), `summon` (an item spawned) and `newItem` (an item found for the first time). | | `particles` | | `dispose` and `summon`. | | `categories` | object | The kinds of items, by name; will appear in Catalog tooltips. Each says how its items are used: `edible` (food that can be eaten) or `tool`. | | `rarities` | object | Rarities, by name. Each has a `weight` (relative chance of spawning) and a `sound` that plays when one spawns. | ### items | Key | Type | Meaning | |---|---|---| | `name` | string | The name of the item. Saves keep items by name. | | `description` | string | Flavor text for the item. | | `texture` | path | The texture the item uses. | | `anm2` | path | The item's own anm2, if needed. | | `category` | string | The item's category. | | `rarity` | string | The item's rarity. | | `flavor` | string | Flavor text (for food); honestly has no meaning but whatever. | | `calories` | float | The amount of calories the item has (if food). | | `capacityBonus` | float | Capacity increase granted as the item is eaten. | | `digestionBonus` | float, %/second | The digestion rate added as the item is eaten. | | `gravity` | float | The item's gravity; will use the area's if not given. | | `color` | [r, g, b], 0-1 | Optional UI color for the item. | | `isToggleSpritesheet` | bool | When used as a tool on the character, will toggle the character's spritesheet (in Pokemon terms, toggling normal/shiny palettes). | # dialogue.json The collection of character dialogue; likely the biggest file, depending on your needs. ```json { "delay": 2, "blipDelay": 2, "blip": ["sfx/blip.ogg"], "pauses": {".": {"delay": 5}}, "hooks": {"Start": "Start", "Eat": "Eat"}, "pools": {"Eat": ["Eat1", "Eat2"]}, "entries": { "Start": { "text": "Hey there, human!", "animation": "Smug", "choices": [{"text": "Hi!", "next": "Start2"}], "effects": [{"type": "shake", "start": 4, "end": 9}] } } } ``` | Key | Type | Meaning | |---|---|---| | `delay` | int, ticks | How many ticks pass before the next dialogue character is revealed. | | `blipDelay` | int | How many displayed dialogue characters pass between blip sounds. `3` means every third displayed character. | | `blip` | paths | Dialogue blip sounds, played periodically while text reveals. | | `pauses` | object | Extra `delay` (in ticks) after particular characters. With `isSilent`, talking and blips also pause during it. | | `hooks` | object | Connects gameplay events to a pool (or else an entry) by name. The hook names are `Start`, `End`, `Help`, `StageUp`, `Random`, `Feed`, `FeedFull`, `Eat`, `EatFull`, `Full`, `Throw`, `LowCapacity`, `Digest`, `FoodTaken` and `FoodTakenFull`. `Random` and `Help` add the "Let's chat!" and "Help" buttons. | | `pools` | object | A "pool" of dialogue is a list of entry labels, one picked at random when used. | | `entries` | object | Each bit of dialogue is referred to as an "entry", by its label. | ### entries | Key | Type | Meaning | |---|---|---| | `text` | string | The actual dialogue content of the entry. Supports Unicode, provided the font contains the characters. An entry without text just plays its animation. | | `animation` | string | A character animation that will play at the beginning of the dialogue. Again, just the base name for the animation, no stage numbers. | | `next` | string | The label of the entry that will follow this one. If no next entry, the text will not continue. Make sure to connect these. | | `choices` | list | Dialogue can be branching; each choice has its `text` (shown as a button) and the `next` entry it leads to. | | `effects` | list | Effects over the text, each with a `type`, and a `start` and `end` (the characters it covers, from `start` up to `end`). | ### effects | Type | Meaning | |---|---| | `color` | Colors the text, by `color` ([r, g, b], 0-1). | | `big`, `small` | Fixed text scales. | | `oscillation`, `shake` | Moves the text, with engine defaults. | | `silent` | Suppresses blips and character talking for its range. | | `screenshake` | Shakes the screen when its `start` comes up. | | `sound` | Plays its `sound` (a path) when its `start` comes up. | | `animation` | Plays its `animation` when its `start` comes up. | | `delay` | Changes the reveal speed to its `delay` (in ticks) from its `start` on. | | `scene` | Hides windows and items and disables interaction until the dialogue chain reaches and finishes its last entry. If another scene appears while one is active, it is ignored. | # Saves Outside of resources, Shweet's Sim also has a few files it writes outside of the game. You will find these in %AppData%/shweets-sim on Windows and ~/.local/share/shweets-sim on Linux. Each is a plain text file of `key=value` lines. ## settings.txt Stores general game settings and configuration; beyond individual characters. | Key | Meaning | |---|---| | `measurement` | `0` for metric (kg/g), `1` for imperial (lb/oz). | | `volume` | Master volume, in percent. | | `mute` | `1` if all audio is muted. | | `color` | Red, green and blue (0-1) of the menu color. | | `character_color` | `1` to use the character's color while playing. | | `width`, `height` | Window size. | | `x`, `y` | Window position. | | `last_character` | The character being played at exit, which the game continues on start. | | `console` | `1` enables the developer console (the grave key). | ## saves/.txt A character's progress: their weight, calories, capacity, digestion, totals and playtime, the camera, and the items found (`discovered=` lines) and lying in the world (`item=` lines, as position, velocity, rotation and name).