From e119798ada8dff08945c20fab431887406a5d103 Mon Sep 17 00:00:00 2001 From: DCoded <dicoded@email.com> Date: Sat, 22 Oct 2022 13:44:49 -0400 Subject: [PATCH] Reverted changes to scene guide --- devNotes/scene guide.md | 361 ++++++++++++++++++---------------------- 1 file changed, 158 insertions(+), 203 deletions(-) diff --git a/devNotes/scene guide.md b/devNotes/scene guide.md index 050d9739bd9..7fa11cbd7cc 100644 --- a/devNotes/scene guide.md +++ b/devNotes/scene guide.md @@ -1,234 +1,189 @@ -# Writing interaction scenes +Most writing is basically just plain text with branches for different cases. +Important cases to remember: +-Does the slave have a dick/vagina/tits? +-Does the PC have a dick/tits/vagina? +-If the slave has a dick and you plan to use it, can they get erect on their own? +-Is the PC pregnant? +-Is the slave mindbroken? +-Is the slave blind? +-Is the slave pregnant? +-If you penetrate an orifice, is the slave a virgin in that orifice? +-Can the slave move (i.e. is the slave amputated and/or have massive tits and/or a massive dick)? +-Does the slave like/hate trust/fear you? +-Does the slave have fetishes or personality/sexual quirks/flaws that would impact how they react? -Players can directly interact with their slaves via interaction events, such as the ones found in the "Work" section of the Slave Interact menu. +It's important to handle every RELEVANT variation of the above cases. Depending on what you're writing, other cases may also warrant consideration; e.g. a breast-play scene will probably need to account for breast size and lactation a lot more than a generic fuck scene. If a scene only applies to a specific type of slave, you can restrict the cases you account for to the ones that are only possible for that type of slave. -## Examples +There are, broadly speaking, two main ways to do this: -If you would like to view examples of scenes currently in the game, there are quite a few in `src/npc/interaction`. Before you start writing anything, make sure there isn't already a similar scene. +1. Write the same big block of text and then copy/paste it into each relevant case, and tweak the wording slightly. + ++Less thinking required + --LOTS of duplicate text; if you need to change something later, you have to change it in many places +2. Decompose the scene into smaller segments or sections that can each be swapped out for the slave type in question. + ++MUCH easier maintenance + --Have to figure out how to phrase the scene in a way that can be broken down into discrete chunks -## Getting started +You can also combine the two cases. For example, you may want a complex, interleaved set of <<if>> conditions for the common cases, and then have big blobs for the corner cases that are hard to handle. -Writing a scene is similar to writing any other code for Free Cities; each scene should be a JavaScript function that returns either a `string`, `DocumentFragment`, or an `HTMLElement`. This main function can then be further broken down into subfunctions to increase readability. +It can also be easier if you split the scene into a "prep", "main", and "finish" section (these would all be the same writing block, just 2-3 <<if>> chains in sequence); that way, you could, for example, take all the various possible cases that aren't really unique, and narrate them so that, in the main section, you don't have to do so much explanatory writing for the scene to make sense overall. Then, if necessary, wrap up with the finish section. (See src/pregmod/fSlaveSelfImpreg.tw for an example of this approach) -To use a character's pronouns, you'll need to first call `getPronouns()` on that character. You can read more about that [here](Pronouns.md), but for now all you need to know is that `getPronouns()` can be used to get anyone's pronouns. +All the variables for you and the slave are, generally, held in the variables $PC and $activeSlave, respectively. When the PC and the slave have the same attributes, they usually have the same name, but exactly what they do and mean can vary a little bit. RTFM for details. To access a specific variable, you do $var.attribName, so e.g. pregnancy is checked by $activeSlave.preg or $PC.preg. In rarer cases, you'll be dealing with an indexed entry in the $slaves array; if that's the case, you'd use $slaves[_u] or $slaves[$i] (or whatever) instead of $activeSlave. If a second (or third?) slave is present, it will be stored in another variable, the name of which will depend on the scene; for example, when impregnating a slave with another slave, the sperm donor is in $impregnatrix -```js -const { he, him } = getPronouns(slave); -``` - -You can then use the pronouns in your text like so: +Conditions are usually checked by -```js -`${He} looks down at ${his} feet.`; // "She looks down at her feet" for female slaves ``` - -### Considerations - -When writing a scene, make sure you properly cover different variations of the event. Here are some things to keep in mind: - -- Does the slave have a dick/vagina/tits? -- Does the PC have a dick/tits/vagina? -- If the slave has a dick and you plan to use it, can they get erect on their own? -- Is the PC pregnant? -- Is the slave mindbroken? -- Is the slave blind? -- Is the slave pregnant? -- If you penetrate an orifice, is the slave a virgin in that orifice? -- Can the slave move (i.e. is the slave amputated and/or have massive tits and/or a massive dick)? -- Does the slave like/hate and trust/fear you? -- Does the slave have fetishes or personality/sexual quirks/flaws that would impact how they react? - -It's important to handle every *relevant* variation of the above cases. Depending on what you're writing, other cases may also warrant consideration; e.g. a breast-play scene will probably need to account for breast size and lactation a lot more than a generic sex scene. If a scene only applies to a specific type of slave, you can restrict the cases you account for to the ones that are only possible for that type of slave. - -### Structure - -Generally speaking, interaction scenes are split into 5 main sections: "intro", "setup", "consummation", "aftermath", and "cleanup". Though not strictly required, more often than not, your scene will contain at least one of these. - -#### `intro` - -This is, as you might expect, the introduction text to the scene. This can be as simple as a single line of text or as complex as you need it to be. - -```js -function intro() { - const text = []; - - text.push(`You call ${him} over so you can`); - if (!canDoVaginal(slave)) { - text.push(`use ${his} sole fuckhole.`); - } else if (slave.vagina > 3) { - text.push(`fuck ${his} gaping holes.`); - } else if (slave.vagina > 2) { - text.push(`fuck ${his} loose holes.`); - } else if (slave.vagina === 2) { - text.push(`use ${his} whorish holes.`); - } else if (slave.vagina === 1) { - text.push(`use ${his} tight holes.`); - } else if (slave.vagina === 0 || slave.anus === 0) { - text.push(`take ${his} virginity.`); - } - - return text.join(' '); -} +<<if CONDITION>> + SHOW THIS TEXT +<<elseif CONDITION2>> + SHOW THIS TEXT INSTEAD +<<else>> + IF NEITHER CONDITION IS MET, SHOW THIS +<</if>> ``` -<sup>From `src/npc/interaction/fButt.js`</sup> - -#### `setup` +Conditions are usually comparative (i.e. $a < $b or $b == 5 or $c != $d.e) and can be chained together with && (and) or || (or) and grouped with parentheses () - for example: +`<<if($a > 1 || ($b == 2 && $c != $a))>>` +lets you check that either variable A is greater than one, or both B equals two and C is not equal to A. +There are also a few misc functions that let you check things like whether a slave can get pregnant or whether two slaves are mutually fertile -This is where you can add "flavor" text to the intro, such as the slave's reaction, for example. +Variable names are interpolated straight into the text, so if you have a slave named "Beth" then the text +"You fuck $activeSlave.slaveName" becomes "You fuck Beth" +You can also explicitly print a variable by doing <<print _varName>> (for temp variables) or <<print $varName>> (for global variables) which can be useful in various situations; it also lets you print the output of code expressions, like <<print $someNumericVar * 10>>. +If you want to change a variable, you do something like +`<<set $activeSlave.devotion += 5>>` +Which would, in this case, give a devotion increase of 5. -```js -function setup() { - const text = []; +Color is changed with YOUR @@.colorname;COLORED TEXT@@ HERE - if (slave.vagina !== -1) { - if (slave.vaginaTat === "tribal patterns") { - text.push(`The tattoos on ${his} abdomen certainly draw attention there.`); - } else if (slave.vaginaTat === "scenes") { - text.push(`The tattoos on ${his} abdomen nicely illustrate what you mean to do to ${him}.`); - } else if (slave.vaginaTat === "degradation") { - text.push(`The tattoos on ${his} abdomen are asking you to, after all.`); - } else if (slave.vaginaTat === "lewd crest") { - text.push(`The crest on ${his} abdomen screams debauchery and implores you to use ${him}.`); - } - } +So a random (really stupid) example might be: - // ... - - return text.join(' '); -} ``` - -<sup>From `src/npc/interaction/fButt.js`</sup> - -#### `consummation` - -This is where the "action" happens. - -```js -function consummation() { - const text = []; - - if (slave.anus === 0) { - if (slave.devotion > 20) { - text.push(`${He} accepts your orders without comment and presents ${his} virgin anus for defloration. You`); - if (V.PC.dick === 0) { - text.push(`don a strap-on and`); - } - text.push(`gently sodomize ${him}. You gently ease into ${his} butthole and slowly accelerate your thrusting into ${his} ass. Since ${he} is already well broken, this new connection with ${his} ${getWrittenTitle(slave)} <span class="devotion inc">increases ${his} devotion to you.</span> <span class="virginity loss">${His} tight little ass has been broken in.</span> ${He} looks forward to having ${his} asshole fucked by you again.`); - slave.devotion += 4; - } else if (slave.devotion >= -20) { - text.push(`${He} is clearly unhappy at the idea of taking a dick up ${his} butt. ${He} obeys orders anyway, and lies there wincing and moaning as you`); - if (V.PC.dick === 0) { - text.push(`don a strap-on and`); - } - text.push(`fuck ${his} ass. You gently ease into ${his} butthole and slowly accelerate your thrusting into ${his} ass. However ${he} still squeals in pain as you continue pounding. <span class="virginity loss">${His} tight little ass has been broken in,</span> and ${he} <span class="trust dec">fears further anal pain.</span>`); - slave.trust -= 5; - } else { - text.push(`${He} is appalled at the idea of taking it up the ass${(V.PC.dick === 0) ? ` and cries with fear as you don a strap-on` : ``}. ${He} does anyway though, sobbing into the cushions`); - if (hasAnyArms(slave)) { - text.push(`while you hold ${his} ${hasBothArms(slave) ? `arms` : `arm`} behind ${him}`); - } - text.push(text.pop() + `.`); - text.push(`You force yourself into ${his} butthole and continue thrusting your member into ${his} ass. ${He} sobs and cries with disgust while you pump into ${his} rear. The painful anal rape <span class="devotion dec">decreases ${his} devotion to you.</span> <span class="virginity loss">${His} tight little ass has been broken in,</span> and ${he} is <span class="trust dec">terrified of further anal pain.</span>`); - slave.devotion -= 10; - slave.trust -= 10; - } - slave.anus++; - } - - // ... - - return text.join(' '); -} +<<if $activeSlave.fetish == 'mindbroken'>> + Special big block of mindbroken text here. +<<elseif isAmputee($activeSlave)>> + Special big block of amputee text here. +<<if $PC.dick > 0>> + <<set _wasVirgin = ''>> + <<if $activeSlave.vagina > -1>> + <<set _orifice = 'vagina'>> + <<if $activeSlave.vagina == 0>> + <<set _wasVirgin = 'vaginal'>> + <</if>> + <<else>> + <<set _orifice = 'ass'>> + <<if $activeSlave.anus == 0>> + <<set _wasVirgin = "anal">> + <</if>> + <</if>> + You fuck $activeSlave.slaveName's _orifice. + <<if _wasVirgin != ''>> + <<if $activeSlave.devotion > 50>> + $He @@.hotpink;loves@@ losing $his <<print _wasVirgin>> virginity to you. + <<set $activeSlave.devotion += 5>> + <<else>> + $He @@.mediumorchid;@@dislikes losing $his <<print _wasVirgin>> virginity to you. + <<set $activeSlave.devotion -= 5>> + <</if>> + <</if>> +<<elseif $PC.vagina > 0 && $activeSlave.dick > 0>> + $activeSlave.slaveName + <<if $activeSlave.devotion > 50>> + @@.hotpink;lovingly penetrates@@ + <<set $activeSlave.devotion += 5>> + <<else>> + indifferently hammers + <</if>> + your pussy. +<<elseif $activeSlave.vagina > -1>> + Lesbian sex here. +<<else>> + ERROR - PC doesn't have dick or vagina? +<</if>> ``` -<sup>From `src/npc/interaction/fAnus.js`</sup> +If you need to set a temp variable, prefix it with _ instead of $. This way, you don't go cluttering up the world with variables that only matter inside your little writing segment. -#### `aftermath` +You can "hot-test" stuff by text editing your HTML copy of FC, but it's a little more tedious because you have to "escape" double quotes, <, >, and & with " < > and & respectively. -Here, you can add some more flavor text, as well as any effects on the slave the interaction may have had. +Some hints: -```js -function aftermath() { - const text = []; +1. Write your logic first, so you don't forget to close tags. In other words, it's better to do - if (slave.fetish === Fetish.MINDBROKEN) { - text.push(`${His} posture doesn't change. ${He} initially only reacts slightly to your physical touch but eventually ${he} relaxes in the warmth of your embrace against ${him}. You know that this may only be a physiological reaction, nothing more. For a brief moment you think you detect a spark of life in ${his} dull eyes but just as quickly, it is gone. When you stop, ${his} ${App.Desc.eyesColor(slave)} track the movements of your hands briefly but then ${he} stares blankly ahead of ${him}, not understanding what is happening.`); - } else if (slave.relationship === -2) { - text.push(`In the warmth of your embrace, ${he} turns towards you, ${his} passionate ${App.Desc.eyesColor(slave)} staring intently at your face. ${He} leans closer to you and kisses you as you hold ${him}. ${His} heart beats faster and then gradually slows as ${he} grows accustomed to your body against ${hers}. Eventually, ${he} relaxes totally and ${his} eyes gradually close, melting in your arms. When you finally stop and relax your embrace, ${his} eyes remain closed and ${his} mouth still in a rapturous shape for a moment before ${he} slowly opens ${his} eyes and smiles at you with a blissful look on ${his} face.`); - - if (hasAnyArms(slave)) { - text.push(`${His} hand reaches to your arms and ${he} strokes them longingly.`); - } +``` +<<if $cond> + TODO +<<else>> + TODO +<</if>> +``` - if (!hasAnyArms(slave) && !canTalk(slave)) { - text.push(`${He} slowly opens them and does ${his} best to communicate love with ${his} ${App.Desc.eyesColor(slave)}.`); - } else if (!canTalk(slave)) { - text.push(`${He} signs that ${he} loves you.`); - } else { - text.push(`${Spoken(slave, `"I love you, ${Master},"`)} ${he} ${say}s dreamily.`); - } +And then fill it in later than it is to end up with a situation where you have a dozen unclosed tags and you can't remember where they are or what they do. - text.push(`${He} looks at you, almost begging you with ${his} eyes that ${he} wants much more than a mere embrace.`); - } else if (slave.devotion > 50 && slave.fetish === "dom" && slave.fetishKnown === 1 && slave.fetishStrength > 60) { - // ... - } +2. For very simple stuff, it's fine to "inline" your stuff. For example, when penetrating a slave, doing `"you fuck $his <<if $activeSlave.vagina > -1>>pussy<<else>>ass<</if>>"` to show "pussy" or "ass" as necessary. However, if you need to do the same comparison a bunch of times, do something like - return text.join(' '); -} ``` +<<if $activeSlave.vagina > -1>> + <<set _targetOrifice = "vagina">> +<<else>> + <<set _targetOrifice = "asshole">> +<</if>> +``` + +And then, when you need it, do `"you fuck $his _targetOrifice"` in sixteen different places without having the pain in the ass of copy/pasting the same if/else clause every time. + +3. INDENT YOUR LOGIC. USE TABS. I'm serious. Don't question me. It will make EVERYONE hate you, when they have to deal with your code, if it's not indented properly. +This is much easier to read: -<sup>From `src/npc/interaction/fEmbrace.js`</sup> - -#### `cleanup` - -If the slave needs to clean themselves up before returning to work, put that here. - -```js -function cleanup() { - const text = []; - - if (V.PC.dick !== 0) { - if (slave.cervixImplant === 2 || slave.cervixImplant === 3) { - slave.bellyImplant += random(10, 20); - } - - if (slave.anus > 3) { - text.push(`${His} gaping hole drips your cum right out again.`); - } else if (slave.anus > 2) { - text.push(`Cum drips out of ${his} loose hole.`); - } else if (slave.anus === 2) { - text.push(`Cum drips out of ${his} loosened anus.`); - } else if (slave.anus === 1) { - text.push(`${His} still-tight ass keeps your load inside ${him}.`); - } - - if (canMove(slave) && V.postSexCleanUp > 0) { - switch (slave.assignment) { - case "whore": - text.push(`${He} heads to the bathroom to clean ${his}`); - - if (canDoVaginal(slave) && canDoAnal(slave)) { - text.push(`holes before returning to selling them publicly.`); - } else if (canDoVaginal(slave) || canDoAnal(slave)) { - text.push(`fuckhole before returning to selling it publicly.`); - } else { - text.push(`face before returning to selling ${his} mouth publicly.`); - } - break; - case "serve the public": - // ... - } - } - } - - return text.join(' '); -} +``` +<<if $cond1>> + <<if $cond2>> + whatever + <<elseif $cond3>> + whatever + <<elseif $cond4>> + <<if $cond5>> + whatever + <<else>> + <<if $cond6>> + whatever + <</if>> + <</if>> + <<else>> + whatever + <<if $cond7>> + <<if $cond8>> + whatever + <</if>> + <</if>> + <</if>> +<</if>> ``` -<sup>From `src/npc/interaction/fButt.js`</sup> +than this: -## Tips +``` +<<if $cond1>> +<<if $cond2>> +whatever +<<elseif $cond3>> +whatever +<<elseif $cond4>> +<<if $cond5>> +whatever +<<else>> +<<if $cond6>> +whatever +<</if>> +<</if>> +<<else>> +whatever +<<if $cond7>> +<<if $cond8>> +whatever +<</if>> +<</if>> +<</if>> +<</if>> +``` -- Make sure you proofread before committing your changes. Many text editors nowadays have plugins you can use to catch spelling and grammar mistakes as you write, which can be a huge help. +4. Proof-read your shit before posting it. Spell-check wouldn't hurt. -- GitLab