Browse Source

Stop passing the state around manually

It was a nice idea to explicitly pass state to everything,
but it didn't really provide any benefits (we only ever have one
game going at once), the rule was already violated (some places
used the global instance of state), and it added a lot of clutter.
Also removed the unused entity.js file.
tags/v0.1.3
Fen Dweller 5 years ago
parent
commit
a36d966d3f
7 changed files with 151 additions and 152 deletions
  1. +0
    -0
      entity.js
  2. +9
    -9
      game.js
  3. +0
    -1
      satiate.html
  4. +6
    -6
      satiate.js
  5. +19
    -19
      stories/demo.js
  6. +97
    -97
      stories/fen-snack.js
  7. +20
    -20
      world.js

+ 0
- 0
entity.js View File


+ 9
- 9
game.js View File

@@ -1,6 +1,6 @@
stories = []; stories = [];


function initGame(story, state) {
function initGame(story) {
state.info = {}; state.info = {};
state.info.time = { state.info.time = {
id: "time", id: "time",
@@ -50,16 +50,16 @@ function createStatDisplays(stats, statType) {
} }
}); });
} }
function initGamePostSetup(state) {
function initGamePostSetup() {
createStatDisplays(state.info, "world"); createStatDisplays(state.info, "world");
createStatDisplays(state.player.stats, "player"); createStatDisplays(state.player.stats, "player");
} }


function getStat(stat, state) {
function getStat(stat) {
return state.player.stats[stat].value; return state.player.stats[stat].value;
} }


function changeStat(stat, amount, state) {
function changeStat(stat, amount) {
let value = state.player.stats[stat].value; let value = state.player.stats[stat].value;
value += amount; value += amount;
value = Math.max(value, state.player.stats[stat].min); value = Math.max(value, state.player.stats[stat].min);
@@ -116,7 +116,7 @@ function updateStatDisplay(stats, statType) {
Returns the timeout id - but you still need to cancel it through stopTimer! Returns the timeout id - but you still need to cancel it through stopTimer!


*/ */
function startTimer(config, state) {
function startTimer(config) {
const timeout = setTimeout(() => { const timeout = setTimeout(() => {
const result = config.func(state, config); const result = config.func(state, config);
refresh(); refresh();
@@ -132,7 +132,7 @@ function startTimer(config, state) {


// you shouldn't use a delay of 0 anyway // you shouldn't use a delay of 0 anyway
if (result && config.loop) { if (result && config.loop) {
startTimer(config, state);
startTimer(config);
} }


} }
@@ -144,14 +144,14 @@ function startTimer(config, state) {
return timeout; return timeout;
} }


function stopTimer(id, state) {
function stopTimer(id) {
const matches = state.timers.filter(timer => timer.id == id); const matches = state.timers.filter(timer => timer.id == id);
matches.forEach(timer => clearTimeout(timer.timeout)); matches.forEach(timer => clearTimeout(timer.timeout));


state.timers = state.timers.filter(timer => timer.id != id); state.timers = state.timers.filter(timer => timer.id != id);
} }


function stopClassTimers(timerClass, state, inverse) {
function stopClassTimers(timerClass, inverse) {
const matches = state.timers.filter(timer => timer.classes.includes(timerClass)); const matches = state.timers.filter(timer => timer.classes.includes(timerClass));
const others = state.timers.filter(timer => !timer.classes.includes(timerClass)); const others = state.timers.filter(timer => !timer.classes.includes(timerClass));


@@ -164,7 +164,7 @@ function stopClassTimers(timerClass, state, inverse) {
} }
} }


function stopAllTimers(state) {
function stopAllTimers() {
state.timers.forEach(x => clearTimeout(x.timeout)); state.timers.forEach(x => clearTimeout(x.timeout));
state.timers = []; state.timers = [];
} }


+ 0
- 1
satiate.html View File

@@ -5,7 +5,6 @@
<title>Satiate</title> <title>Satiate</title>
<link rel="stylesheet" href="satiate.css"> <link rel="stylesheet" href="satiate.css">
<script src="audio.js"></script> <script src="audio.js"></script>
<script src="entity.js"></script>
<script src="game.js"></script> <script src="game.js"></script>
<script src="stories/demo.js"></script> <script src="stories/demo.js"></script>
<script src="stories/fen-snack.js"></script> <script src="stories/fen-snack.js"></script>


+ 6
- 6
satiate.js View File

@@ -89,18 +89,18 @@ function init(story) {
}, },
}; };


initWorld(story, state);
initGame(story, state);
initWorld(story);
initGame(story);


story.intro.setup(state);
story.intro.setup();


initGamePostSetup(state);
initGamePostSetup();


refreshHook = story.refresh; refreshHook = story.refresh;


story.intro.intro(state);
story.intro.intro();


goToRoom(story.intro.start, state);
goToRoom(story.intro.start);
} }


// set up the load screen // set up the load screen


+ 19
- 19
stories/demo.js View File

@@ -6,12 +6,12 @@ stories.push({
], ],
"intro": { "intro": {
"start": "Home", "start": "Home",
"setup": state => {
"setup": () => {
state.info.time.value = 3600; state.info.time.value = 3600;
state.player.stats.oofs = {name: "Oofs", type: "meter", value: 0, max: 10, color: "rgb(255,0,0)"}; state.player.stats.oofs = {name: "Oofs", type: "meter", value: 0, max: 10, color: "rgb(255,0,0)"};
state.player.stats.number = {name: "Number", type: "counter", value: 0, max: 10, color: "rgb(255,255,255)"}; state.player.stats.number = {name: "Number", type: "counter", value: 0, max: 10, color: "rgb(255,255,255)"};
}, },
"intro": state => {
"intro": () => {
print(["don't fall down the stairs ok"]); print(["don't fall down the stairs ok"]);
} }
}, },
@@ -31,15 +31,15 @@ stories.push({
"id": "Home", "id": "Home",
"name": "Home", "name": "Home",
"desc": "Where the wifi autoconnects", "desc": "Where the wifi autoconnects",
"move": (room, state) => {
"move": (room) => {
print(["You go back to your living room"]); print(["You go back to your living room"]);
}, },
"enter": (room, state) => {
"enter": (room) => {
print(["*sound of you entering your house*"]); print(["*sound of you entering your house*"]);


startTimer({ startTimer({
id: "room-counter", id: "room-counter",
func: state => {
func: () => {
state.world["Home"].data.stats.number.value += 1; state.world["Home"].data.stats.number.value += 1;
return true; return true;
}, },
@@ -48,18 +48,18 @@ stories.push({
classes: [ classes: [
"Home" "Home"
], ],
}, state);
});
}, },
"exit": (room, state) => {
"exit": (room) => {
print(["You are exiting your house"]); print(["You are exiting your house"]);


stopClassTimers("Home", state);
stopClassTimers("Home");
}, },
"actions": [ "actions": [
{ {
"name": "Squint", "name": "Squint",
"desc": "Squint in a very aggressive manner", "desc": "Squint in a very aggressive manner",
"execute": (room, state) => {
"execute": (room) => {
state.player.rooms[room.id].squinted = true; state.player.rooms[room.id].squinted = true;
print(["You stare at the wall and notice a secret door. But where is the key?"]); print(["You stare at the wall and notice a secret door. But where is the key?"]);
} }
@@ -67,15 +67,15 @@ stories.push({
{ {
"name": "Find Keys", "name": "Find Keys",
"desc": "Find your keys", "desc": "Find your keys",
"execute": (room, state) => {
"execute": (room) => {
state.player.items.keys.push("Locked Room"); state.player.items.keys.push("Locked Room");
print(["You found your keys under the couch cushions"]); print(["You found your keys under the couch cushions"]);
}, },
"show": [ "show": [
(room, state) => {
(room) => {
return state.player.rooms[room.id].squinted; return state.player.rooms[room.id].squinted;
}, },
(room, state) => {
(room) => {
return !state.player.items.keys.includes("Locked Room"); return !state.player.items.keys.includes("Locked Room");
} }
] ]
@@ -86,12 +86,12 @@ stories.push({
"target": "Locked Room", "target": "Locked Room",
"desc": "It's locked!", "desc": "It's locked!",
"conditions": [ "conditions": [
(room, state) => {
(room) => {
return state.player.items.keys.includes("Locked Room"); return state.player.items.keys.includes("Locked Room");
} }
], ],
"show": [ "show": [
(room, state) => {
(room) => {
return state.player.rooms[room.id].squinted; return state.player.rooms[room.id].squinted;
} }
] ]
@@ -100,7 +100,7 @@ stories.push({
"target": "Stairs", "target": "Stairs",
"desc": "Dare you go down the stairs?", "desc": "Dare you go down the stairs?",
"hooks": [ "hooks": [
(room, exit, state) => {
(room, exit) => {
console.log(state) console.log(state)
print(["You're very concerned that you'll fall down all these stairs."]); print(["You're very concerned that you'll fall down all these stairs."]);
return false; return false;
@@ -109,7 +109,7 @@ stories.push({
} }
}, },
"hooks": [ "hooks": [
(room, state) => {
(room) => {
print(["This is a test of the hooks"]); print(["This is a test of the hooks"]);
return true; return true;
@@ -125,14 +125,14 @@ stories.push({
"id": "Locked Room", "id": "Locked Room",
"name": "Locked Room", "name": "Locked Room",
"desc": "Super seecret", "desc": "Super seecret",
"move": (room, state) => {
"move": (room) => {
print(["You enter the locked room. wowie!"]); print(["You enter the locked room. wowie!"]);
}, },
"actions": [ "actions": [
{ {
name: "Oof", name: "Oof",
desc: "Oof", desc: "Oof",
execute: (room, state) => {
execute: (room) => {
state.player.stats.oofs.value += 1; state.player.stats.oofs.value += 1;


if (state.player.stats.oofs.value >= state.player.stats.oofs.max) { if (state.player.stats.oofs.value >= state.player.stats.oofs.max) {
@@ -150,7 +150,7 @@ stories.push({
"target": "Home", "target": "Home",
"desc": "Back to home", "desc": "Back to home",
"hooks": [ "hooks": [
(room, exit, state) => {
(room, exit) => {
print(["Potato"]); print(["Potato"]);
return true; return true;
} }


+ 97
- 97
stories/fen-snack.js View File

@@ -27,14 +27,14 @@ stories.push({
], ],
intro: { intro: {
start: "stomach", start: "stomach",
setup: state => {
setup: () => {
state.info.time.value = 86400 - 60 * 25 - 25; state.info.time.value = 86400 - 60 * 25 - 25;
state.player.stats.health = {name: "Health", type: "meter", value: 100, min: 0, max: 100, color: "rgb(255,0,0)"}; state.player.stats.health = {name: "Health", type: "meter", value: 100, min: 0, max: 100, color: "rgb(255,0,0)"};
state.player.stats.stamina = {name: "Stamina", type: "meter", value: 100, min: 0, max: 100, color: "rgb(100,255,0)"}; state.player.stats.stamina = {name: "Stamina", type: "meter", value: 100, min: 0, max: 100, color: "rgb(100,255,0)"};


startTimer({ startTimer({
id: "taunting", id: "taunting",
func: state => {
func: () => {
printRandom([ printRandom([
["The crux strokes over his snarling gut, enjoying your dwindling squirms."], ["The crux strokes over his snarling gut, enjoying your dwindling squirms."],
["\"Enjoying yourself, meal?\"", "Your captor's oh-so-smug voice booms in your ears."] ["\"Enjoying yourself, meal?\"", "Your captor's oh-so-smug voice booms in your ears."]
@@ -46,11 +46,11 @@ stories.push({
classes: [ classes: [
"alive" "alive"
] ]
}, state);
});
startTimer({ startTimer({
id: "movement", id: "movement",
func: state => {
func: () => {
const pinned = state.player.flags.pinned; const pinned = state.player.flags.pinned;


if (pinned) { if (pinned) {
@@ -70,25 +70,25 @@ stories.push({
classes: [ classes: [
"alive" "alive"
] ]
}, state);
});


startTimer({ startTimer({
id: "digestion", id: "digestion",
func: state => {
func: () => {
const location = state.player.location; const location = state.player.location;


let bonus = state.player.flags.submission ? 10 : 1; let bonus = state.player.flags.submission ? 10 : 1;


if (location.startsWith("stomach")) { if (location.startsWith("stomach")) {
changeStat("health", -1, state);
changeStat("health", -1);
} }


if (location.startsWith("intestines")) { if (location.startsWith("intestines")) {
changeStat("health", -0.75, state);
changeStat("health", -0.75);
} }


if (location.startsWith("bowels")) { if (location.startsWith("bowels")) {
changeStat("health", -0.5, state);
changeStat("health", -0.5);
} }




@@ -113,7 +113,7 @@ stories.push({


startTimer({ startTimer({
id: "time-text", id: "time-text",
func: state => {
func: () => {
print([time_text]); print([time_text]);
return true; return true;
}, },
@@ -122,19 +122,19 @@ stories.push({
classes: [ classes: [
] ]
}, state);
});


if (location.startsWith("stomach")) { if (location.startsWith("stomach")) {
goToRoom("digested-stomach", state);
goToRoom("digested-stomach");
} }


if (location.startsWith("intestines")) { if (location.startsWith("intestines")) {
goToRoom("digested-intestines", state);
goToRoom("digested-intestines");
} }


if (location.startsWith("bowels")) { if (location.startsWith("bowels")) {
goToRoom("digested-bowels", state);
goToRoom("digested-bowels");
} }


return false; return false;
@@ -146,24 +146,24 @@ stories.push({
classes: [ classes: [
"alive" "alive"
] ]
}, state);
});


startTimer({ startTimer({
id: "stamina-regen", id: "stamina-regen",
func: state => {
func: () => {
const location = state.player.location; const location = state.player.location;
let bonus = state.player.flags.submission ? -3 : 0; let bonus = state.player.flags.submission ? -3 : 0;
bonus += state.player.flags.pinned ? -0.5 : 0; bonus += state.player.flags.pinned ? -0.5 : 0;
if (location.startsWith("stomach")) { if (location.startsWith("stomach")) {
changeStat("stamina", 0.75 + bonus, state);
changeStat("stamina", 0.75 + bonus);
} }


if (location.startsWith("intestines")) { if (location.startsWith("intestines")) {
changeStat("stamina", 1.25 + bonus, state);
changeStat("stamina", 1.25 + bonus);
} }


if (location.startsWith("bowels")) { if (location.startsWith("bowels")) {
changeStat("stamina", -0.5 + bonus, state);
changeStat("stamina", -0.5 + bonus);
} }
return true; return true;
}, },
@@ -172,11 +172,11 @@ stories.push({
classes: [ classes: [
"alive" "alive"
] ]
}, state);
});


startTimer({ startTimer({
id: "clock", id: "clock",
func: state => {
func: () => {
state.info.time.value += 1; state.info.time.value += 1;
state.info.time.value %= 86400; state.info.time.value %= 86400;


@@ -187,14 +187,14 @@ stories.push({
classes: [ classes: [


] ]
}, state);
});
}, },
intro: state => {
intro: () => {
print(["Hot, slimy walls ripple and squeeze, the stomach of your captor stewing you in a churning bath of chyme and acid. The purple crux made a late-night meal out of you with ease. You've only been trapped under the Fen's pelt for a few minutes...but it doesn't seem like you'll make it until midnight."]); print(["Hot, slimy walls ripple and squeeze, the stomach of your captor stewing you in a churning bath of chyme and acid. The purple crux made a late-night meal out of you with ease. You've only been trapped under the Fen's pelt for a few minutes...but it doesn't seem like you'll make it until midnight."]);
playSfx("sfx/stomach-churn.ogg"); playSfx("sfx/stomach-churn.ogg");
} }
}, },
refresh: state => {
refresh: () => {
setBackgroundColor(50 - state.player.stats.health.value/2, 0, 0) setBackgroundColor(50 - state.player.stats.health.value/2, 0, 0)
}, },
world: { world: {
@@ -202,17 +202,17 @@ stories.push({
id: "stomach", id: "stomach",
name: "Stomach", name: "Stomach",
desc: "A hot, wet, steamy prison.", desc: "A hot, wet, steamy prison.",
move: (room, state) => {
move: (room) => {
print(["You slide into Fen's humid stomach."]); print(["You slide into Fen's humid stomach."]);
}, },
enter: (room, state) => {
enter: (room) => {
playLoop("loop/fen-stomach.ogg"); playLoop("loop/fen-stomach.ogg");


startTimer({ startTimer({
id: "stomach-churns", id: "stomach-churns",
func: state => {
func: () => {
if (Math.random() > 0.6) { if (Math.random() > 0.6) {
changeStat("stamina", -25, state);
changeStat("stamina", -25);
print(["The crux's stomach clenches around you, smothering you in the beast's slimy embrace."]); print(["The crux's stomach clenches around you, smothering you in the beast's slimy embrace."]);
playSfx("sfx/stomach-churn.ogg"); playSfx("sfx/stomach-churn.ogg");
} }
@@ -224,11 +224,11 @@ stories.push({
"alive", "alive",
"stomach" "stomach"
] ]
}, state);
});
}, },
exit: (room, state) => {
exit: (room) => {
stopLoop("loop/fen-stomach.ogg"); stopLoop("loop/fen-stomach.ogg");
stopClassTimers("stomach", state);
stopClassTimers("stomach");
}, },
hooks: [ hooks: [


@@ -237,17 +237,17 @@ stories.push({
{ {
name: "Rub", name: "Rub",
desc: "Knead on the muscular folds that surround your tasty little body", desc: "Knead on the muscular folds that surround your tasty little body",
execute: (room, state) => {
changeStat("stamina", -15, state);
execute: (room) => {
changeStat("stamina", -15);
print(["You rub all over your prison's walls. Fen's stomach gurgles in response."]); print(["You rub all over your prison's walls. Fen's stomach gurgles in response."]);
} }
}, },
{ {
name: "Thrash", name: "Thrash",
desc: "Kick and struggle", desc: "Kick and struggle",
execute: (room, state) => {
changeStat("health", -10, state);
changeStat("stamina", -35, state);
execute: (room) => {
changeStat("health", -10);
changeStat("stamina", -35);
print(["Your thrash and kick and punch - and, for your insolence, you are rewarded with a crushing CLENCH. Fen's grinding guts smother and squeeze your softening body, nearly popping you like a grape."]); print(["Your thrash and kick and punch - and, for your insolence, you are rewarded with a crushing CLENCH. Fen's grinding guts smother and squeeze your softening body, nearly popping you like a grape."]);
playSfx("sfx/stomach-churn.ogg"); playSfx("sfx/stomach-churn.ogg");
}, },
@@ -261,12 +261,12 @@ stories.push({
{ {
name: "Submit", name: "Submit",
desc: "Let Fen digest you", desc: "Let Fen digest you",
execute: (room, state) => {
execute: (room) => {
state.player.flags.submission = true; state.player.flags.submission = true;
print(["You slump back in the crux's stomach, allowing its powerful fluids to break you down..."]); print(["You slump back in the crux's stomach, allowing its powerful fluids to break you down..."]);
}, },
show: [ show: [
(room, state) => {
(room) => {
return !state.player.flags.submission; return !state.player.flags.submission;
} }
] ]
@@ -277,31 +277,31 @@ stories.push({
"down": { "down": {
"target": "intestines", "target": "intestines",
"desc": "Push yourself deeper into the crux", "desc": "Push yourself deeper into the crux",
move: (room, state) => {
move: (room) => {
print(["You manage to push yourself down through the valve at the base of the crux's fetid stomach."]); print(["You manage to push yourself down through the valve at the base of the crux's fetid stomach."]);
playSfx("sfx/stomach-to-intestines.ogg"); playSfx("sfx/stomach-to-intestines.ogg");
}, },
hooks: [ hooks: [
(room, exit, state) => {
(room, exit) => {
let stamina = state.player.stats.stamina.value; let stamina = state.player.stats.stamina.value;
let escape; let escape;
if (Math.random() > stamina/100) { if (Math.random() > stamina/100) {
changeStat("stamina", -50, state);
changeStat("stamina", -50);
print(["Fen's stomach clenches and ripples, smothering your face in wet flesh and keeping you nice and trapped."]); print(["Fen's stomach clenches and ripples, smothering your face in wet flesh and keeping you nice and trapped."]);
playSfx("sfx/stomach-to-intestines-fail.ogg"); playSfx("sfx/stomach-to-intestines-fail.ogg");
escape = false; escape = false;
} else { } else {
changeStat("stamina", -25, state);
changeStat("stamina", -25);
escape = true; escape = true;
} }
return escape; return escape;
} }
], ],
conditions: [ conditions: [
(room, state) => {
(room) => {
return !state.player.flags.submission; return !state.player.flags.submission;
}, },
(room, state) => {
(room) => {
return !state.player.flags.pinned; return !state.player.flags.pinned;
} }
] ]
@@ -317,30 +317,30 @@ stories.push({
id: "intestines", id: "intestines",
name: "Intestines", name: "Intestines",
desc: "Labyrinthine guts, winding on and on...", desc: "Labyrinthine guts, winding on and on...",
move: (room, state) => {
move: (room) => {
print(["Your squirming body glides into the crux's tight, snaking guts."]); print(["Your squirming body glides into the crux's tight, snaking guts."]);
}, },
enter: (room, state) => {
enter: (room) => {
playLoop("loop/fen-intestines.ogg"); playLoop("loop/fen-intestines.ogg");


startTimer({ startTimer({
id: "intestines-churns", id: "intestines-churns",
func: state => {
func: () => {
if (Math.random() > 0.5) { if (Math.random() > 0.5) {
if (state.player.stats.stamina.value > 50) { if (state.player.stats.stamina.value > 50) {
changeStat("stamina", -25, state);
changeStat("stamina", -25);
print(["Your prison's walls ripple and grind, shoving you against the valve leading to the crux's boiling stomach - but you manage to resist the powerful pull."]); print(["Your prison's walls ripple and grind, shoving you against the valve leading to the crux's boiling stomach - but you manage to resist the powerful pull."]);
playSfx("sfx/intestines-churn-stay.ogg"); playSfx("sfx/intestines-churn-stay.ogg");
} else { } else {
print(["Too exhausted to resist, your slimy body is crammed into the crux's churning stomach by a powerful wave of peristalsis."]); print(["Too exhausted to resist, your slimy body is crammed into the crux's churning stomach by a powerful wave of peristalsis."]);
playSfx("sfx/intestines-to-stomach-forced.ogg"); playSfx("sfx/intestines-to-stomach-forced.ogg");
goToRoom("stomach", state);
goToRoom("stomach");
} }
} else { } else {
changeStat("stamina", -25, state);
changeStat("stamina", -25);
print(["Overwhelming peristalsis grips your body and crams it into the beast's hot, life-sapping bowels."]); print(["Overwhelming peristalsis grips your body and crams it into the beast's hot, life-sapping bowels."]);
playSfx("sfx/intestines-to-stomach-forced.ogg"); playSfx("sfx/intestines-to-stomach-forced.ogg");
goToRoom("bowels", state);
goToRoom("bowels");
} }
return 10000 + Math.random() * 5000; return 10000 + Math.random() * 5000;
}, },
@@ -350,25 +350,25 @@ stories.push({
"alive", "alive",
"intestines" "intestines"
] ]
}, state);
});
}, },
exit: (room, state) => {
exit: (room) => {
stopLoop("loop/fen-intestines.ogg"); stopLoop("loop/fen-intestines.ogg");
stopClassTimers("intestines", state);
stopClassTimers("intestines");
}, },
exits: { exits: {
"up": { "up": {
target: "stomach", target: "stomach",
desc: "Writhe back into Fen's roiling stomach", desc: "Writhe back into Fen's roiling stomach",
move: (room, state) => {
move: (room) => {
print(["You push yourself back into the crux's fatal stomach."]); print(["You push yourself back into the crux's fatal stomach."]);
playSfx("sfx/intestines-to-stomach.ogg"); playSfx("sfx/intestines-to-stomach.ogg");
}, },
conditions: [ conditions: [
(room, state) => {
(room) => {
return !state.player.flags.submission; return !state.player.flags.submission;
}, },
(room, state) => {
(room) => {
return !state.player.flags.pinned; return !state.player.flags.pinned;
} }
] ]
@@ -376,15 +376,15 @@ stories.push({
"down": { "down": {
target: "bowels", target: "bowels",
desc: "Push yourself even deeper into your predator's body", desc: "Push yourself even deeper into your predator's body",
move: (room, state) => {
move: (room) => {
print(["You wriggle into the beast's bowels."]); print(["You wriggle into the beast's bowels."]);
playSfx("sfx/intestines-to-bowels.ogg"); playSfx("sfx/intestines-to-bowels.ogg");
}, },
conditions: [ conditions: [
(room, state) => {
(room) => {
return !state.player.flags.submission; return !state.player.flags.submission;
}, },
(room, state) => {
(room) => {
return !state.player.flags.pinned; return !state.player.flags.pinned;
} }
] ]
@@ -397,20 +397,20 @@ stories.push({
{ {
name: "Rub", name: "Rub",
desc: "Knead on the muscular folds that surround your tasty little body", desc: "Knead on the muscular folds that surround your tasty little body",
execute: (room, state) => {
changeStat("stamina", -20, state);
execute: (room) => {
changeStat("stamina", -20);
print(["You rub all over your prison's walls. Fen's intestines quiver and clench in response."]); print(["You rub all over your prison's walls. Fen's intestines quiver and clench in response."]);
} }
}, },
{ {
name: "Submit", name: "Submit",
desc: "Let Fen digest you", desc: "Let Fen digest you",
execute: (room, state) => {
execute: (room) => {
state.player.flags.submission = true; state.player.flags.submission = true;
print(["You go limp in the crux's intestines, letting the winding guts take you in..."]); print(["You go limp in the crux's intestines, letting the winding guts take you in..."]);
}, },
show: [ show: [
(room, state) => {
(room) => {
return !state.player.flags.submission; return !state.player.flags.submission;
} }
] ]
@@ -427,27 +427,27 @@ stories.push({
id: "bowels", id: "bowels",
name: "Bowels", name: "Bowels",
desc: "Cavernous bowels, rippling and squeezing over your bare skin", desc: "Cavernous bowels, rippling and squeezing over your bare skin",
move: (room, state) => {
move: (room) => {
print(["You enter the beast's humid bowels, taking shallow, stifled breaths of the musky air. The sauna-like atmosphere sucks the strength from your tired limbs."]); print(["You enter the beast's humid bowels, taking shallow, stifled breaths of the musky air. The sauna-like atmosphere sucks the strength from your tired limbs."]);
}, },
enter: (room, state) => {
enter: (room) => {
playLoop("loop/fen-bowels.ogg"); playLoop("loop/fen-bowels.ogg");


startTimer({ startTimer({
id: "bowels-churns", id: "bowels-churns",
func: state => {
func: () => {
if (state.player.stats.stamina.value > 50) { if (state.player.stats.stamina.value > 50) {
changeStat("stamina", -25, state);
changeStat("stamina", -25);
print(["Fen's bowels clench and churn, grinding you into their musky walls."]); print(["Fen's bowels clench and churn, grinding you into their musky walls."]);
playSfx("sfx/bowels-churn-safe.ogg"); playSfx("sfx/bowels-churn-safe.ogg");
} else { } else {
changeStat("stamina", -100, state);
changeStat("stamina", -100);
startTimer({ startTimer({
id: "digestion", id: "digestion",
func: state => {
func: () => {
let bonus = state.player.flags.submission ? 10 : 1; let bonus = state.player.flags.submission ? 10 : 1;


changeStat("health", -1, state);
changeStat("health", -1);
return 500 / bonus; return 500 / bonus;
}, },
delay: 1000, delay: 1000,
@@ -456,7 +456,7 @@ stories.push({
"alive", "alive",
"bowels" "bowels"
] ]
}, state);
});


print(["Drained of stamina, you can do little to resist as Fen's bowels grind you away."]); print(["Drained of stamina, you can do little to resist as Fen's bowels grind you away."]);
playSfx("sfx/bowels-churn-danger.ogg"); playSfx("sfx/bowels-churn-danger.ogg");
@@ -470,30 +470,30 @@ stories.push({
"alive", "alive",
"bowels" "bowels"
] ]
}, state);
});
}, },
exit: (room, state) => {
exit: (room) => {
stopLoop("loop/fen-bowels.ogg"); stopLoop("loop/fen-bowels.ogg");
stopClassTimers("bowels", state);
stopClassTimers("bowels");
}, },
exits: { exits: {
"up": { "up": {
target: "intestines", target: "intestines",
desc: "Squirm up higher", desc: "Squirm up higher",
move: (room, state) => {
move: (room) => {
print(["You squirm out from Fen's bowels, working your way back into his cramped guts."]); print(["You squirm out from Fen's bowels, working your way back into his cramped guts."]);
playSfx("sfx/bowels-to-intestines.ogg"); playSfx("sfx/bowels-to-intestines.ogg");
}, },
conditions: [ conditions: [
(room, state) => {
(room) => {
return !state.player.flags.submission; return !state.player.flags.submission;
}, },
(room, state) => {
(room) => {
return !state.player.flags.pinned; return !state.player.flags.pinned;
} }
], ],
hooks: [ hooks: [
(room, exit, state) => {
(room, exit) => {
if (state.player.stats.stamina.value < 25) { if (state.player.stats.stamina.value < 25) {
print(["You're too tired to move..."]); print(["You're too tired to move..."]);
playSfx("sfx/bowels-churn-safe.ogg"); playSfx("sfx/bowels-churn-safe.ogg");
@@ -510,21 +510,21 @@ stories.push({
], ],
"conditions": [ "conditions": [
(room, state) => {
(room) => {
return !state.player.flags.submission; return !state.player.flags.submission;
}, },
(room, state) => {
(room) => {
return !state.player.flags.pinned; return !state.player.flags.pinned;
}, },


(room, state) => {
(room) => {
return state.player.stats.stamina.value > 25; return state.player.stats.stamina.value > 25;
} }
], ],
"hooks": [ "hooks": [
(room, exit, state) => {
(room, exit) => {
print(["You make a desperate bid for freedom, grasping at the walls of Fen's sweltering bowels and dragging yourself forward. The predator growls in pleasure...and, after humoring your squirms for a long minute, crushes you within an inch of your life with a swift, staggeringly-strong clench. Every inch of escape is erased in a heartbeat...as is any hope of ending the evening as anything other than a permanent contribution to the crux's body."]); print(["You make a desperate bid for freedom, grasping at the walls of Fen's sweltering bowels and dragging yourself forward. The predator growls in pleasure...and, after humoring your squirms for a long minute, crushes you within an inch of your life with a swift, staggeringly-strong clench. Every inch of escape is erased in a heartbeat...as is any hope of ending the evening as anything other than a permanent contribution to the crux's body."]);
changeStat("stamina", -100, state);
changeStat("stamina", -100);
return false; return false;
} }
] ]
@@ -537,20 +537,20 @@ stories.push({
{ {
name: "Rub", name: "Rub",
desc: "Knead on the muscular folds that surround your tasty little body", desc: "Knead on the muscular folds that surround your tasty little body",
execute: (room, state) => {
changeStat("stamina", -25, state);
execute: (room) => {
changeStat("stamina", -25);
print(["You rub all over your prison's walls. Fen's bowels clench in on you as he rurrs with pleasure."]); print(["You rub all over your prison's walls. Fen's bowels clench in on you as he rurrs with pleasure."]);
} }
}, },
{ {
name: "Submit", name: "Submit",
desc: "Let Fen digest you", desc: "Let Fen digest you",
execute: (room, state) => {
execute: (room) => {
state.player.flags.submission = true; state.player.flags.submission = true;
print(["You slump back in the crux's bowels, yielding to their immense pressure..."]); print(["You slump back in the crux's bowels, yielding to their immense pressure..."]);
}, },
show: [ show: [
(room, state) => {
(room) => {
return !state.player.flags.submission; return !state.player.flags.submission;
} }
] ]
@@ -567,13 +567,13 @@ stories.push({
"id": "freedom", "id": "freedom",
"name": "Freedom", "name": "Freedom",
"desc": "A place you'll never reach!", "desc": "A place you'll never reach!",
"move": (room, state) => {
"move": (room) => {
}, },
"enter": (room, state) => {
"enter": (room) => {
}, },
"exit": (room, state) => {
"exit": (room) => {
}, },
"actions": [ "actions": [
@@ -595,11 +595,11 @@ stories.push({
id: "digested-stomach", id: "digested-stomach",
name: "Fen's Belly", name: "Fen's Belly",
desc: "You look good on him, at least~", desc: "You look good on him, at least~",
enter: (room, state) => {
enter: (room) => {
playLoop("loop/fen-intestines.ogg"); playLoop("loop/fen-intestines.ogg");
playSfx("sfx/digested-test.ogg"); playSfx("sfx/digested-test.ogg");
playSfx("sfx/bowels-churn-safe.ogg"); playSfx("sfx/bowels-churn-safe.ogg");
stopClassTimers("alive", state);
stopClassTimers("alive");
print(["You slump down in the acidic pit, curling up as it begins to churn you down to chyme. Fen's stomach snarls and bubbles for the next few minutes...and then you're gone~",newline,"Nothing's left but a bit of padding on your predator's gut..."]); print(["You slump down in the acidic pit, curling up as it begins to churn you down to chyme. Fen's stomach snarls and bubbles for the next few minutes...and then you're gone~",newline,"Nothing's left but a bit of padding on your predator's gut..."]);
}, },
"data": { "data": {
@@ -612,11 +612,11 @@ stories.push({
id: "digested-intestines", id: "digested-intestines",
name: "Fen's Belly", name: "Fen's Belly",
desc: "Just a little addition to the crux's belly - one that won't last for long.", desc: "Just a little addition to the crux's belly - one that won't last for long.",
enter: (room, state) => {
enter: (room) => {
playLoop("loop/fen-intestines.ogg"); playLoop("loop/fen-intestines.ogg");
playSfx("sfx/digested-test.ogg"); playSfx("sfx/digested-test.ogg");
playSfx("sfx/bowels-churn-safe.ogg"); playSfx("sfx/bowels-churn-safe.ogg");
stopClassTimers("alive", state);
stopClassTimers("alive");
print(["Fen's intestines clench and squeeze, melting you down into slop and soaking you up like a sponge.",newline,"Nothing's left but a bit of padding on your predator's hips..."]); print(["Fen's intestines clench and squeeze, melting you down into slop and soaking you up like a sponge.",newline,"Nothing's left but a bit of padding on your predator's hips..."]);
}, },
"data": { "data": {
@@ -629,11 +629,11 @@ stories.push({
id: "digested-bowels", id: "digested-bowels",
name: "Fen's Ass", name: "Fen's Ass",
desc: "A little extra heft on the predator's posterior.", desc: "A little extra heft on the predator's posterior.",
enter: (room, state) => {
enter: (room) => {
playLoop("loop/fen-bowels.ogg"); playLoop("loop/fen-bowels.ogg");
playSfx("sfx/digested-test.ogg"); playSfx("sfx/digested-test.ogg");
playSfx("sfx/bowels-churn-danger.ogg"); playSfx("sfx/bowels-churn-danger.ogg");
stopClassTimers("alive", state);
stopClassTimers("alive");
print(["A powerful ripple of muscle pins you in a vice-grip of flesh. Your exhausted form is molded like putty..and then, over the course of no more than seconds, Fen's bowels assimilate you. Numbness races through your body as you're absorbed like water into a sponge.",newline,"Nothing's left of you beyond some heft on his ass..."]); print(["A powerful ripple of muscle pins you in a vice-grip of flesh. Your exhausted form is molded like putty..and then, over the course of no more than seconds, Fen's bowels assimilate you. Numbness races through your body as you're absorbed like water into a sponge.",newline,"Nothing's left of you beyond some heft on his ass..."]);
}, },
"data": { "data": {


+ 20
- 20
world.js View File

@@ -19,19 +19,19 @@ actionButtons = [


] ]


function initWorld(story, state) {
function initWorld(story) {
state.world = story["world"]; state.world = story["world"];
initRoomState(state); initRoomState(state);
} }


function initRoomState(state) {
function initRoomState() {
state.player.rooms = {}; state.player.rooms = {};
Object.entries(state.world).forEach(([key, val]) => { Object.entries(state.world).forEach(([key, val]) => {
state.player.rooms[key] = {}; state.player.rooms[key] = {};
}); });
} }


function resetControls(state) {
function resetControls() {
const moveHolder = document.querySelector("#move-holder"); const moveHolder = document.querySelector("#move-holder");


moveHolder.innerHTML = ""; moveHolder.innerHTML = "";
@@ -75,13 +75,13 @@ function removeActionDescription() {
descHolder.textContent = ""; descHolder.textContent = "";
} }


function moveToRoom(src, exit, dest, state) {
function moveToRoom(src, exit, dest) {
const from = state.world[state.player.location]; const from = state.world[state.player.location];
const room = state.world[dest]; const room = state.world[dest];


if (exit.hooks) { if (exit.hooks) {
for (let hook of exit.hooks) { for (let hook of exit.hooks) {
if (!hook(room, exit, state)) {
if (!hook(room, exit)) {
return; return;
} }
} }
@@ -89,23 +89,23 @@ function moveToRoom(src, exit, dest, state) {


if (room.hooks) { if (room.hooks) {
for (let hook of room.hooks) { for (let hook of room.hooks) {
if (!hook(room, state)) {
if (!hook(room)) {
return; return;
} }
} }
} }


if (exit.move) if (exit.move)
exit.move(from, state);
exit.move(from);


if (from && from.exit) if (from && from.exit)
from.exit(from, state);
from.exit(from);


if (room.move) if (room.move)
room.move(room, state);
room.move(room);


if (room.enter) if (room.enter)
room.enter(room, state);
room.enter(room);


state.player.location = dest; state.player.location = dest;


@@ -116,23 +116,23 @@ function moveToRoom(src, exit, dest, state) {
refresh(); refresh();
} }


function goToRoom(dest, state) {
function goToRoom(dest) {
const from = state.world[state.player.location]; const from = state.world[state.player.location];
const room = state.world[dest]; const room = state.world[dest];


if (room.hooks) { if (room.hooks) {
for (let hook of room.hooks) { for (let hook of room.hooks) {
if (!hook(room, state)) {
if (!hook(room)) {
return; return;
} }
} }
} }


if (from && from.exit) if (from && from.exit)
from.exit(from, state);
from.exit(from);


if (room.enter) if (room.enter)
room.enter(state.world[dest], state);
room.enter(state.world[dest]);


state.player.location = dest; state.player.location = dest;


@@ -143,7 +143,7 @@ function goToRoom(dest, state) {
refresh(); refresh();
} }


function updateRoom(state) {
function updateRoom() {
const name = state.player.location; const name = state.player.location;
const room = state.world[name]; const room = state.world[name];


@@ -172,7 +172,7 @@ function updateRoom(state) {
// don't even show an exit if this fails! // don't even show an exit if this fails!


if (exit.show) { if (exit.show) {
if (!exit.show.every(cond => cond(room, state))) {
if (!exit.show.every(cond => cond(room))) {
return; return;
} }
} }
@@ -197,7 +197,7 @@ function updateRoom(state) {
} }


moveFunc = () => { moveFunc = () => {
moveToRoom(room, exit, exit.target, state);
moveToRoom(room, exit, exit.target);
}; };


button.addEventListener("click", moveFunc); button.addEventListener("click", moveFunc);
@@ -235,7 +235,7 @@ function updateRoom(state) {
button.textContent = action.name; button.textContent = action.name;


button.addEventListener("click", () => { button.addEventListener("click", () => {
action.execute(room, state);
action.execute(room);
refresh(); refresh();
}); });


@@ -249,7 +249,7 @@ function updateRoom(state) {
} }


if (action.show) { if (action.show) {
if (!action.show.every(cond => cond(room, state))) {
if (!action.show.every(cond => cond(room))) {
continue; continue;
} }
} }
@@ -257,7 +257,7 @@ function updateRoom(state) {
keptButtons.push(actionButtons[index]); keptButtons.push(actionButtons[index]);


if (action.conditions) { if (action.conditions) {
if (!action.conditions.every(cond => cond(room, state))) {
if (!action.conditions.every(cond => cond(room))) {
button.classList.add("disabled"); button.classList.add("disabled");
button.setAttribute("disabled", "true"); button.setAttribute("disabled", "true");
} }


Loading…
Cancel
Save