30 KiB
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 a semi-proprietary format called ".anm2" for tweened character animations, sourced from a spritesheet. This file format comes from the game The Binding of Isaac: Rebirth (a game I mod on my own time) for animations.
You can either use my own animation editor for that game and this one (recommended), Anm2Ed, or if you have that game on Steam, you can find that game's own proprietary animation editor in that game's Steam folder and then in tools/IsaacAnimationEditor. I can't guarantee the stability or perfect efficacy of either, but Anm2Ed has crash mitigations and autosave (but of course, save often, for whatever you do).
Anm2Ed has slightly more extensions to the base format; in particular, something called "Regions", which allows you to 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. For the leanest files, in Anm2Ed, go to Settings -> Configure -> File -> Compatibility, and set it to "Anm2Ed Limited".
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 either program, check either of these videos out. Much of the information is interchangeable between the programs, though both are a little out of date on their current version.
Stage-specific character animations are controlled by AppendStringForAnimations on each stage in character.xml. The base stage uses no suffix. Later stages append that stage's configured suffix.
Example:
- stage 1:
Look - stage 2 with
AppendStringForAnimations="Stage2":LookStage2 - stage 5 with
AppendStringForAnimations="Stage5":LookStage5
Animation references in XML 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 .xml sound attributes when applicable. You can add sounds for fluff, though.
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. This technically isn't needed; Dear ImGui has its own font that will be used if this font is missing.
EVERYTHING ELSE is stored inside bespoke character archives (.zips) in the "characters" folder. 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 a collection of XML files to parse data; make sure to brush up on the format. A character archive can contain these files in its root:
- areas.xml
- character.xml
- cursor.xml
- dialogue.xml
- items.xml
- menu.xml
- strings.xml
The game currently expects character.xml. The rest are optional in the sense that the loader will warn and continue if some are missing, but most real characters will want nearly all of them.
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
areas.xml
"Areas" refers to the backgrounds of the game. I'd planned for the game to dynamically switch areas based on stage (in case you want a character to become a blob that grows bigger than a city or whatever) but this isn't implemented. I'd just have one entry in here for the game's background.
Areas
TextureRootPath (path)
Working folder/directory of textures the areas will use.
Anm2RootPath (path)
Working folder/directory of anm2 files the areas will use. If omitted, TextureRootPath is used.
Area
Texture (path)
The file path of the area's texture (background).
Anm2 (path)
The file path of the area's animated background. If this is set, it is used instead of Texture.
Gravity (float)
Gravity the area has; applies to items' velocities per tick.
Friction (float)
Friction of the area; applies to items' velocities when grounded or hitting walls.
character.xml
This is the main character file where much of the functionality is stored.
Character
Name (string)
Name of the character; will appear in dialogue, stats, etc.
TextureRootPath (path)
Working folder/directory of where used textures will be contained within.
SoundRootPath (path)
Working folder/directory of where used sounds will be contained within.
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)
Character's "anm2" file (uses TextureRootPath); should have all the character's animations.
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.
WeightKilograms (double)
The character's starting weight, in kilograms.
WeightMaxKilograms (double)
Maximum weight the character can reach.
CapacityCalories (double)
The character's starting capacity, in calories.
CapacityMinCalories (double)
The character's minimum capacity, in calories.
CapacityMaxCalories (double)
Maximum base capacity.
CapacityOverstuffedMultiplier (double)
Multiplier used when computing the effective full threshold from current base capacity.
CapacityIfOverStuffedOnDigestBonus (double, multiplier)
Additional capacity gained on digest when the character was over base capacity.
CaloriesToKilogram (double)
Determines how many calories become a kilogram (1 cal -> X kg).
DigestionRatePerSecond (double, percent/second)
The base digestion rate, in percent per second.
DigestionRatePerSecondMin (double, percent/second)
The minimum digestion rate for the character, in percent per second.
DigestionRatePerSecondMax (double, percent/second)
The maximum digestion rate for the character, in percent per second.
DigestionTimerMax (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, in ticks.
EatSpeedMultiplier (double)
A multiplier that speeds/slows down the eating animation, at base.
EatSpeedMinMultiplier (double)
Determines the minimum eating speed multiplier.
EatSpeedMaxMultiplier (double)
Determines the maximum eating speed multiplier.
BlinkChance (double, percent)
Chance each tick to trigger a blink override.
GurgleChance (double, percent)
Determines how often the character will gurgle (see the Gurgle sounds later) per tick.
GurgleChanceFromCapacityMultiplier (double)
Per the character's capacity, multiplies the character's gurgle chance based on the percent of capacity filled (based on max capacity). Higher capacity = higher gurgle chance, using this number at maximum.
DialoguePool (string)
Determines the character's base dialogue options (for the "How are you feeling?" option in Chat). This is effectively "Stage 1"'s dialogue; each stage should have its own dialogue pool (see later). Also see dialogue.xml for how "Pools" work.
ColorR, ColorG, ColorB (float, 0-1)
UI accent color for the character.
AlternateSpritesheet
Determines the alternate spritesheet of the character, if applicable (in Pokemon terms, the "shiny").
Texture (path)
The alternate spritesheet texture; uses TextureRootPath.
Sound (path)
The sound that will play when the spritesheet is set to alternate (either on new game, or with an item that has IsToggleSpritesheet; see items.xml); uses SoundRootPath.
ID (int)
ID of spritesheet that the alternate spritesheet will replace in the character's .anm2.
ChanceOnNewGame (float, percent)
Chance of rolling for the alternate spritesheet on starting a new game, in percent.
Stages
A "stage" represents each visual change of the character as the weight increases. By default, there's always one stage; adding more here will add additional stages.
ThresholdKilograms (float)
The weight threshold to reach this stage, in kilograms.
AreaID (int)
Reserved for background switching. Parsed, but not currently used by gameplay.
DialoguePool (string)
Determines the stage's dialogue options (for the "How are you feeling?" option in Chat). Also see dialogue.xml for how "Pools" work.
AppendStringForAnimations (string)
Suffix appended to base animation names while this stage is active. Usually Stage2, Stage3, etc.
Animations
The character's animations. Know that a lot of character animations are typically easily played/activated through Dialogue; this is just for animations that aren't reliant on that system. Know that these animations should just be the base name; all animations are expected to have a stage number after them, so don't include the number for these.
Start
The animation name that will first play 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 and going over a stage's threshold, this animation will play.
Animation
The name of the animation to be used for each of these.
AnimationOverrides
"AnimationOverrides" are the term I use for when some animations will be tweaked by the game engine for effect (blinking and talking being the ones used). There are two elements; "Talk" and "Blink" for this. Typically, how this is handled is that each animation with have an invisible blinking/talking layer (just the graphic that blinks), which will change when called for. Again, review the .anm2 format for what a "layer" is. 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.
Talk / Blink
LayerSource (string)
The layer in the animation which will be sourced for the override.
LayerDestination (string)
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. Again, not something that's well-developed at the moment.
EatArea
Null (string)
The null area in the animation where food will be checked for. Again, review the .anm2 format.
Animation (string)
The animation that will play when food is dragged to it.
EventToActivate (string)
The event that will be checked for, detrermining the time the food is actually eaten/chewed. Again, review the .anm2 format.
ExpandAreas
The areas which will expand based on capacity percent; usually a stomach. This adds additional scale onto the layer of an animation. This also can scale a null as well. ExpandAreas are presently hardcoded to scale with both capacity and weight at a 50/50 ratio; this could be changed in the future for custom ratios.
ExpandArea
Layer (string)
The layer of the animation that will expand.
Null (string)
The null of the animation that will expand.
ScaleMultiplierMaximum (float, percent)
The scale that will be added at maximum. Know that scale is a percent; a {100, 100} scale is the default and is the normal scale of an animation.
InteractAreaTypes
Default behavior for each interaction type. These entries should not have Null; they define shared cursor animations, sounds, particles, and bonuses for concrete InteractAreas.
InteractArea
Type (string)
The interaction type name. Concrete interact areas with the same Type inherit unspecified values from this definition.
GlyphFromIconFont (string)
The icon-font glyph used for this interaction in the tools bar.
IsHold (bool)
If true, the interaction is held rather than clicked once.
AnimationCursorHover (string)
The animation the cursor will play when hovering over the interact area.
AnimationCursorActive (string)
The animation the cursor will play when holding down click over the interact area.
DigestionBonusOnHover (float)
Digestion bonus applied repeatedly while hovering with a held interaction.
DigestionBonusOnClick (float)
Digestion bonus applied when a click-based interaction lands.
TimeTicks (float)
Used by click effects such as smacks. If omitted, the engine uses a short default duration.
TimeToActivateNewDialogueTicks (int)
Ticks that must pass without this interact area being interacted with before it can start a new dialogue.
ScaleEffectAmplitude (float)
Visual scale effect amount for click interactions.
ScaleEffectCycles (float)
How many oscillations the scale effect performs.
InteractAreas
The concrete areas on a character which can be interacted with; usually for belly rubs, kisses, etc.
InteractArea
Type (string)
The interaction type to use. This should match one of the entries in InteractAreaTypes.
Null (string)
The null in which the interact area can be triggered. Again, review the .anm2 format.
Layer (string; optional)
Layer used for scale-effect interactions such as smacks.
DialoguePool (string)
The dialogue pool which will be drawn from when activating an interact area (see dialogue.xml).
DialoguePoolFull (string)
Dialogue pool used when the character is over capacity.
Sound
An interact area can play multiple sounds when interacting; add additional Sound elements to achieve this. Don't worry about repeatedly-loaded sounds; the game will cache them beforehand for efficiency.
Path (path)
The path of the sound being used.
Particle
An interact area can trigger multiple particle effects.
Type (string)
The particle type from particles.xml.
Actions
Sounds that play in character-level contexts. Each action can contain multiple Sound elements.
Digest
Sounds that will play when the character begins digesting (digestion bar full).
Gurgle
Ambient sounds that will play randomly based on capacity; see GurgleChance and GurgleChanceFromCapacityMultiplier above.
Sound
Path (path)
The path of the sound for the specific action.
cursor.xml
Determines the cursor appearance and behavior.
TextureRootPath (path)
Working folder/directory of textures the cursor will use.
SoundRootPath (path)
Working folder/directory of sounds the cursor will use.
Anm2 (path)
The anm2 file the cursor will use (depends on TextureRootPath).
Animations
Idle
The cursor's default idle animation.
Hover
The cursor's hover animation, when hovering over an item.
Grab
The cursor's grab animation, when grabbing an item.
Pan
The cursor's pan animation, when panning with middle mouse button.
Zoom
The cursor's zoom animation, when zooming in/out with the mouse wheel.
Return
The cursor's return animation, when holding right click to return an item to the inventory (or to dispose of it if chewed.)
Animation (string)
The animation the cursor will use in these contexts.
Actions
Know that multiple sounds can be defined for each action by adding Sound children.
Grab
The sound that will play when grabbing an item.
Release
The sound that will play when releasing an item.
Throw
The sound that will play when throwing an item (releasing when dragging quickly).
Sound
Path (path)
The path of the sound for these respective contexts.
dialogue.xml
The collection of character dialogue; likely the biggest file, depending on your needs.
Dialogue
SoundRootPath (path)
Working folder/directory of where dialogue sounds will be contained within.
DelayTicks (int)
How many update ticks pass before the next dialogue character is revealed.
BlipDelayTicks (int)
How many displayed dialogue characters elapse between blip sounds. 3 means every third displayed character.
TextPlayback
Groups the dialogue text reveal settings.
Blip
Dialogue blip sound. One is played periodically while text reveals. Add one or more Sound children.
Sound
Path (path)
The path to the sound that will play, based on SoundRootPath.
DelayCharacters
Groups character-specific delay rules.
DelayCharacter
Character (string)
The character that should add an extra delay while text reveals.
DelayTicks (int)
Extra update ticks to pause after this character.
IsDisableTalk (bool)
If true, the talking override pauses during this character's delay.
Entries
Entry
Each bit of dialogue is referred to as an "entry".
Label (string)
Name for the entry. Other entries will rely on this for dialogue chains.
Next (string)
The ID of the entry that will follow after this one. If no Next entry, the text will not continue. Make sure to connect these.
Text (string)
The actual dialogue content of the entry. Should support Unicode, provided the font contains the characters.
Animation (string)
A character animation that will play at the beginning of the dialogue. This may be expanded into the future to allow animations to play dynamically per dialogue index. Again, make sure it's just the base name for the animation, no stage numbers.
Effects
Dialogue effects can be added as child elements of an Entry. Small and Big are fixed text scale effects. Oscillation, Shake, and Screenshake use engine defaults for their strength/timing values; do not write Amplitude, Frequency, Period, Magnitude, or TimeTicks for those effects. Scale and Rainbow are no longer supported.
Choice
Dialogue can be branching; simply added "Choice" elements into the Entry element.
Next (string)
The dialogue the choice will lead to.
Text (string)
The text of the choice; will appear as a series of buttons in the text window.
Pools
A "pool" of dialogue refers to a collection of entries that can be randomly picked in some contexts.
Pool
Label (string)
The name of the dialogue pool; can be referenced elsewhere.
Entry
Entry (string)
The name of the entry; to be added to the pool.
Start
This dialogue will play upon a new game, once its animation has concluded.
Animation (string)
The name of the animation that will be played.
Label (string)
The name of the entry that will be played.
End
The dialogue that will play upon completion of the game (character hitting max stage).
Label (string)
The name of the entry that will be played.
Help
The dialogue that will be play when the player presses the "Help" button in "Chat".
Label (string)
The name of the entry that will be played.
StageUp
Dialogue that will play after a character undergoes a stage up.
Pool (string)
The name of the pool that entries will be drawn from.
Random
The dialogue that will be play when the player presses the "Let's chat!" button in "Chat".
Pool (string)
The name of the pool that entries will be drawn from.
Feed
The dialogue that will be play when the user begins holding a food item.
Pool (string)
The name of the pool that entries will be drawn from.
FeedFull
The dialogue that will be play when the user begins holding a food item, when the character is over capacity.
Pool (string)
The name of the pool that entries will be drawn from.
Eat
The dialogue that will be play after the character finishes a food item.
Pool (string)
The name of the pool that entries will be drawn from.
EatFull
The dialogue that will be play after the character finishes a food item, when the character is over capacity.
Pool (string)
The name of the pool that entries will be drawn from.
Full
The dialogue that will be play when the character is completely full and will deny the user feeding them.
Pool (string)
The name of the pool that entries will be drawn from.
Throw
The dialogue that will be play when the user throws food.
Pool (string)
The name of the pool that entries will be drawn from.
LowCapacity
The dialogue that will be play when the character is presented a food item completely over their maximum capacity.
Pool (string)
The name of the pool that entries will be drawn from.
Digest
The dialogue that will be play when digesting is finished.
Pool (string)
The name of the pool that entries will be drawn from.
FoodTaken
The dialogue that will play when food is removed from the null area during a character's eating animation.
Pool (string)
The name of the pool that entries will be drawn from.
FoodTakenFull
The dialogue that will play when food is removed from the null area during a character's eating animation, when the character is over capacity.
Pool (string)
The name of the pool that entries will be drawn from.
items.xml
Has all items and their parameters, alongside additional behavior.
ItemSchema
TextureRootPath (path)
Working folder/directory of where used textures will be contained within.
SoundRootPath (path)
Working folder/directory of where used sounds will be contained within.
BaseAnm2 (path)
The base anm2 file that items will use. Items can technically have their own .anm2 and animate accordingly, but I haven't tested this much.
Animations
Chew
When items are chewed, play this animation family. The game looks for Chew0, Chew1, Chew2, and so on inside the item's .anm2.
Animation (string)
The name of the animation. Only the base part ("Chew", usually)
Actions
The various item actions. Each action can contain multiple Sound elements to randomly play from a selection.
Bounce
The sound that will play when an item is bounced (hitting a floor/wall/ceiling with velocity).
Dispose
The sound that will play when an item is disposed of (when an item has chewed and is right clicked).
Summon
The sound that will play when an item is spawned (clicking on it in inventory).
Return
The sound that will play when an item is returned to inventory (right clicking on it in world).
Sound
Path (path)
The path to the sound that will play, based on SoundRootPath.
Categories
The kinds of items present. Will appear in inventory tooltips.
Category
Name (string)
The name of the category.
IsEdible (bool)
Determines if the category of item can be eaten by the character.
Flavors
Item flavors (for food). Honestly have no meaning but flavor text at the moment but whatever.
Flavor
Name (string)
Name of the flavor.
Rarities
Different rarities of item. Shows in inventory and each can have their own drop chance.
Rarity
Name (string)
Name of the rarity.
Chance (float, percent)
Relative rarity weight for item systems.
Sound (path)
Sound that will play when an item of this rarity is awarded.
IsHidden (bool)
If true, items with this rarity will not be previewed in the inventory, unlesss possessed. Assumed false if not present.
Items
TextureRootPath (path)
Working folder/directory of where used item textures will be contained within.
Durability (int)
Base durability for items.
Durability means "number of bites before deletion."
Example with Durability="3":
Chew0: untouchedChew1: after one biteChew2: after two bites- removed after the third bite
QuantityMax (int)
How many items of a type can be possessed at once.
Item
An individual item entry.
Name (string)
The name of the item.
Texture (path)
The texture the item uses; uses TextureRootPath.
Description (string)
Flavor text for the item.
Category (string)
The category the item uses; as defined in Categories.
Rarity (string)
The rarity the item uses; as defined in Rarities.
Anm2 (path; optional)
The custom anm2 the item uses, if needed.
Flavor (string; optional)
The flavor the item uses; as defined in Flavors.
Calories (float; optional)
The amount of calories in an item has (if food).
CapacityBonus (float; optional)
Capacity increase granted as the item is eaten.
DigestionBonus (float, percent; optional)
The additional digestion rate in percent the item will give if eaten.
EatSpeedBonus (float; optional)
The additional eat speed multiplier the item will give if eaten.
Gravity (float; optional)
The item's gravity; will use the default gravity if not available.
Durability (int; optional)
Custom durability override for the item.
ColorR, ColorG, ColorB (float, 0-1; optional)
Optional item UI color. Missing components default to 0 if any color component is provided.
UpgradeID (string; optional)
The name of another item that this item will be able to be upgraded to.
UpgradeCount (int; optional)
The amount of this item it will take to upgrade to the upgrade item specified in UpgradeID.
IsToggleSpritesheet (bool; optional)
When used in the inventory, will toggle the character's spritesheet (in Pokemon terms, toggling normal/shiny palettes).
strings.xml
Character-specific text strings.
See src/resource/xml/strings.hpp for how strings map to in-game displays.
menu.xml
Determines menu and general UI appearance and behavior.
Menu
SoundRootPath (path)
Working folder/directory of where used sounds will be contained within.
FontRootPath (path)
Working folder/directory of where used fonts will be contained within.
Font (path)
The font the menu will use, based on FontRootPath.
ButtonRounding (float)
The rounding of corners the UI will use.
Actions
Menu sound actions. Each action can contain one or more Sound elements.
Open
Will play when opening a sliding menu panel.
Close
Will play when closing a sliding menu panel.
Hover
Will play when hovering over a widget in a menu.
Select
Will play when clicking on a widget in a menu.
CheatsActivated
Sound that will play after entering a special code to activate cheats.
Sound
Path (path)
The sound that will play, based on SoundRootPath.
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.
settings.xml
Stores general game settings and configuration; beyond invididual characters.
MeasurementSystem ("Imperial", "Metric")
Determines measurement system (kg/lb).
Volume (int, percent)
Master volume.
IsAudioMuted (bool)
If true, all audio is muted.
ColorR, ColorG, ColorB (float, 0-1)
Red/Green/Blue components of menu color.
WindowX, WindowY (int)
Window position.
WindowW/H (int)
Window size.
*.save
Saves are per-character; will be named "[blank].save", stored in "saves" folder, from the name of the character's archive.
Save
IsPostgame (bool)
Determines if the game has been completed (character's max stage has been reached); if true, will enable cheats.
IsAlternateSpritesheet (bool)
Determines if the character's spritesheet is using the alternate version (in Pokemon, would be the "shiny" version
Character
WeightKilograms (float)
Character's current weight, in kilograms.
Calories (float)
Character's current consumed calories.
CapacityCalories (float)
Character's capacity, in calories. Remember, max capacity effectively is capacity * CapacityOverstuffedMultiplier (from character.xml)
DigestionRatePerSecond (float, percent/second)
Character's digestion rate in percent per second.
EatSpeedMultiplier (float)
Eat speed multiplier for the character's Eat animation.
IsDigesting (bool)
Determines if character is currently digesting (when the bar is going down)
DigestionProgress (float, percent)
Character's digestion progress. Digestion max is always 100%.
DigestionTimer (int)
When digestion bar is going down, this is the remaining time to 0 (in ticks)
TotalCaloriesConsumed (float)
Total calories consumed by the character, per save file.
TotalFoodItemsEaten (int)
How many food items have been completely consumed by the character, per save file.
Inventory
Items.
ID (int)
ID of item being tracked (see items.xml)
Quantity (int)
Count of the item.
Items
World items currently spawned outside the inventory.
ID (int)
Item ID from items.xml.
Durability (int)
Current bite progress for that spawned item.
PositionX, PositionY (float)
World position.
VelocityX, VelocityY (float)
World velocity.
Rotation (float)
Current rotation.
Conclusion
Hopefully this'll give you the resources you need to start making your own characters. If you need any help with this guide, or with clarification on anything, I'm available. Additionally, the game is licensed as free software, meaning if you're stuck the code should give you a clue (though I apologize for the lack of comments. Self-documenting code though, am I right? :^) )