Need help? I generally respond to PMs within a day or two, but please do me a favor and see if this documentation covers your question first. If all else fails, I encourage you to shamelessly copy from the example mods!
Carmel Modding Framework, v0.01
by Anunnaki
===What is Carmel?===
The Carmel Modding Framework is intended to be a flexible, modular method for non-destructively modifying SugarCube stories. In plain English, it lets you create mods for Twine games without editing the original game's file - so you can run as many mods as you want at once, and they'll (most likely, but see below) continue to work for future releases of that game.
It's called "Carmel" because it's multiple SugarCubes melted together!
===Sounds good, how do I use it?===
Drop a mod's HTML file, and the folder with the same name, into your SMVA_Data/mods folder. That's it! The mod will automatically be loaded when you start the game.
===I want to write my own mod!===
Great! See the example mod for a good starting point. In general, there are four stages to developing a Carmel mod:
1) Write the Twine story
Carmel mods are basically Twine stories like any other, and you'll create them the same way. Start up Twine, create a new story, and write any new Passages you'd like to add to the game. Passages inside a Carmel mod can freely reference variables, macros, widgets, and <<include>>s from the base game. For SMVA in particular, there are a number of these you'll need to include at the right place in your passages in order for the game's digestion mechanics to function properly. Check out the predator and prey scenes in the example mod if your scenes aren't behaving as expected. If your Passage needs to define widgets or run startup code, you'll need to give it the appropriate tags as usual.
2) Modify the base game
At this point, your new Passages aren't connected to the main game. Let's fix that. Carmel uses a special markup called CMOD, which looks something like this:
CMOD|September 1st- Arrival|InsertAfter|off towards the sports complex instead.|DOMC
That's an ugly block of text, but we'll go over it piece by piece. CMOD at the beginning and DOMC at the end signal to the framework that this Passage is intended to modify something about the base game. The next chunk of text after the | delimiter is the name of a Passage you'd like to modify in the base game - in this case, the player's arrival on campus. The third bit of text, InsertAfter, tells Carmel what kind of change you want to make. We'll see a full list later - for now, this just inserts the rest of your new Passage into the base game's "September 1st- Arrival" passage immediately after the phrase "off towards the sports complex instead."
In the example mod, this CMOD block is used to give the player a new option upon arriving at the school - to investigate the protest behind her, which leads into the rest of the mod's content. Check out Appendix A for the full list of CMOD commands.
You can export your Twine story to HTML now! Place it in the SMVA_Data/mods folder.
3) Design your girls
SMVA's visuals are created using Kisekae. You can find a number of tutorials online, so here we'll just focus on getting your work in-game. For certain poses, you'll want my modified version of Kisekae which adds vore bellies (linked in the first page of the topic). Once you've designed your girl and gotten her into the pose you want, move her to exactly 500 horizontal units. For all poses except the prey struggling animations, you'll want to use the following settings:
Quality 5/5
Bounding box 300, 37, 200, 440
Transparent background
Export as PNG
Extremely tall girls may need larger bounding boxes - use your best judgment, keep the aspect ratio the same, and the program should be able to accommodate it. For the prey struggle images, you'll want to use the following settings:
Quality 5/5
Bounding box 335, 228, 128, 256
Transparent background
Export as PNG
For these, you'll definitely want to keep the size to 128x256 - don't worry if part of the girl gets cut off, it looks natural through the viewport.
Place the images in SMVA_Data/mods/<your mod's HTML file's name>/girls/<girl id>/. Note that girl IDs need to be unique across mods and the base game or unexpected behavior will result - it might be a good idea to name a girl MyModAnna instead of just Anna. These IDs will never actually show up in game. The wrapper will load poses with the following names:
annoyed
face
happy
neutral
scared
sit
unhappy
vomit
yum
Any of these poses can be freely used in the editor (see below) - despite the names, they're really just Pose 1, Pose 2, etc. No need to include more than you intend to use. There are also special poses associated with a character's prey scenes (again, only needed if she actually has such a scene):
internal
internal1
internal2
internal3
internalbrapanty
internal1brapanty
internal2brapanty
internal3brapanty
internalnaked
internal1naked
internal2naked
internal3naked
Finally, if a character has a pred scene and you want to give her the struggling-belly effect, you can give her the following:
full1
full2
fullmassage1
fullmassage2
fullouch1
fullouch2
fullsqueeze1
fullsqueeze2
The "1" and "2" images are closely related. You'll want to give her the full belly for each pose's "2" images, then remove the belly for the "1" images - while changing nothing else about the girl or her pose. The first time you encounter the girl during Step 4 below, the editor will automatically compare pixels between the two images and generate the "moving belly" texture.
It's not technically girls, but it fits with this step - you can also provide static images by adding a "backgrounds" folder: SMVA_Data/mods/<your mod's HTML file's name>/backgrounds/ and audio files by adding an "audio" folder: SMVA_Data/mods/<your mod's HTML file's name>/audio
4) Keyframe scenes
Now that you've got your text and your girls, all that remains is putting them together! Launch the game and navigate to your new or changed scenes, then press Tab. A slightly intimidating editor bar will appear. Don't worry, we'll go through it one tool at a time, but first some keyboard commands:
Q/E: Select next/previous girl.
WASD: Move currently selected girl.
F: Remove selected girl from scene.
X/Z: Scale selected girl up/down.
V/C: Rotate selected girl right/left.
It is critically important that the "Record to mod" box remains checked, and that the corresponding mod name matches your mod's HTML filename.
The text in the top-left indicates which Passage you're currently reading and which girl is currently selected. The color is important. If it's green, the currently-displayed paragraph is what's called a keyframe - a text paragraph linked to some change in the scene's visual elements. If it's yellow, the scene exists in memory but this particular paragraph is not a keyframe. If it's red, this particular scene has no keyframes at all yet. By clicking the "Keyframe" button, you will either delete the current keyframe if one already exists, or record the current setup (background, girl position/scale/rotation/pose, options, etc.) to a new keyframe if one doesn't.
To place a girl, or reset one's position/scale/rotation, select her ID in the dropdown menu and click "Place Girl." You can cycle her pose with the "Pose <" and "Pose >" buttons - don't worry if you pass through a blank white rectangle for certain poses, that just means you (or I) didn't provide an image for that particular pose, keep moving to the one you want. The next dropdown lets you select a background for the keyframe.
Now for the advanced stuff. "Start digestion of" does exactly what it says - it tells the game to display the stomach-cam view with a particular character as the prey. "Second prey" designates this as a multi-prey scene. "Play sound"... plays a sound. Finally, "Outfit" switches a player's outfit. The largest dropdown is simply a convenient way to jump between the base game's Passages.
One final thing to note: keyframe hashes are based on the TEXT of a scene, not its paragraph number. What this means for you, the modder, is that two paragraphs that the game has parsed differently (say, an if statement that gives different text depending on whether Mandy is alive) need two separate keyframes. You may need to play through a scene multiple times in order to see, and keyframe, all of its different forms.
Remember to click "Save" regularly while working! Click it twice, or three times, if it makes you feel more comfortable. You'll notice a new file called scenes.json in the mod's folder.
===I'm done! How do I distribute my mod?===
Just zip up your mod's html file and the associated folder from SMVA_Data/mods/.
===You're awesome. Can I buy you a beer?===
I really appreciate the sentiment! I'm lucky enough to be in a very stable financial situation, but if you have some spare cash you should consider OsmiumOrchid's Patreon. This project would not exist without SMVA!
===Appendix A: CMOD opcodes===
Please remember that any reference to "base passage text" below refers to the UNPARSED text you see in the Twine editor. Unfortunately, you can't use macros or markups in this, making it sometimes difficult to find the right insertion point. There are a number of CMOD opcodes for just this situation, though, such as needed to insert text after a macro.
AddOpt: At the very end of the base passage, adds a link to this passage. The link's text is given as the third parameter.
Replace: Replace all occurrences of the third parameter in the base passage's text with the contents of this passage.
InsertAfter: Insert this passage's contents after the third parameter in the base passage's text.
InsertBefore: Insert this passage's contents before the third parameter in the base passage's text.
InsertAfterMacro: Insert this passage's contents after a macro with the given contents in the base passage.
InsertBeforeMacro: Insert this passage's contents before a macro with the given contents in the base passage.
InsertAfterInclude: Insert this passage's contents after an include with the given name in the base passage.
InsertBeforeInclude: Insert this passage's contents before an include with the given name in the base passage.
InsertAfterLink: Insert this passage's contents after a link with the given contents in the base passage.
InsertBeforeLink: Insert this passage's contents before a link with the given contents in the base passage.
InsertBeforeIf: Insert this passage's contents before an if statement with the given contents in the base passage.
InsertFromStart: Insert this passage's contents a certain distance from the beginning of the base passage, determined by the (integer) third parameter.
InsertFromEnd: Insert this passage's contents a certain distance from the end of the base passage, determined by the (integer) third parameter.
InsertAtEnd: Insert this passage's contents at the very end of the base passage.