Newer
Older
/**
* Example model, a 'xray-vaginal' and small part of 'close-vaginal' slots of sex animation.
* See game/03-JavaScript/canvasmodel.js for API reference
* and canvasmodel-example.twee for test passage (accessible in Debug/Main menu).
name: "sexdemo", // For debugging
width: 768,
height: 256,
frames: 8, // For CSS animation only. JS animations can have as many frames as needed
/**
* List of names of generated options, for debugging & tooling.
* All possible options should be initialised to some non-crashing values here.
* Global animation speed, "" (no animation) | "slow" | "mid" | "fast" | "vfast".
*/
close_vagina_speed: "",
/**
* Penetration state, "" (none) | "entrance" | "imminent" | "penetrated"
* NOT the equivalent of $vaginastate, tentacles share entrance/imminent/penetrated
* and $vaginastate="tentacledeep" should set options.vaginacumming=true.
* Penetrator type, "" (empty) | "penis" (human) | "beast" | "tentacle" | "machine".
*/
vagina_penetrator: "",
/**
* Penetrator subtype, options depend on vagina_penetrator:
* - for "human": NPC skin colour
* - for "beast": beast type
* User-supplied filters go here; typically this is empty in default options.
},
/**
* This function is called before compiling layers for rendering or animation.
* Generated options and filters implementations go here.
if (!options.xray_vaginal_speed) {
// "" means use global
options.xray_vaginal_speed = options.animation_speed;
}
if (!options.close_vagina_speed) {
// "" means use global
options.close_vagina_speed = options.animation_speed;
}
if (options.worn.under_lower) {
const record = setup.colours.clothes_map[options.worn.under_lower.colour];
console.error("Unknown under_lower colour " + options.worn.under_lower.colour);
}
}
// Despite the name, filters can have any layer properties, including those affectign composition
};
},
/**
* The meat.
* Key is layer name, value is layer definition.
* Rendering order is guaranteed only via `z` property.
*/
layers: {
},
/**
* This option is required because layer takes small part of the resulting image.
* Without it, the 2048 pixel wide image would be treated as 3-frame animation (=2048/768).
*/
width: 256,
/**
* As this layer has `showfn`, it will be displayed automatically when needed,
* without <<showlayer "xray_vaginal">>.
* You'll need <<set _modeloptions.xray_vaginal_show = true>> instead.
* Not much difference but it makes more sense when you toggle multiple layers with one option.
*/
showfn(options) {
return options.xray_vaginal_show && options.vagina_state === "penetrated";
},
srcfn(options) {
switch (options.vagina_penetrator) {
case "machine":
return "img/sex/machine/vaginal/xray_vaginal.png";
case "beast":
switch (options.vagina_penetrator_subtype) {
case "horse":
}
case "penis":
switch (options.vagina_penetrator_subtype) {
case "black":
* Returns name of animation, or empty string if none.
*
* @param options
* We use the fact that option values and animation names are same.
return options.xray_vaginal_speed ? "sex-8f-" + options.xray_vaginal_speed : "";
},
},
srcfn(options) {
if (options.vagina_state === "penetrated") {
return options.vagina_penetrator === "beast" && options.vagina_penetrator_size >= 5
? "img/sex/close/" + options.position + "/vaginapenetratebig.png"
: "img/sex/close/" + options.position + "/vaginapenetrate.png";
return options.vagina_aroused
? "img/sex/close/" + options.position + "/vaginaaroused.png"
: "img/sex/close/" + options.position + "/vagina.png";
return "img/sex/close/" + options.position + "/vaginaaroused.png";
z: 252,
showfn(options) {
/**
* Only exact 'false' would hide the layer (undefined etc won't),
* so cast non-boolean options to boolean via double negation.
*/
return "img/sex/close/" + options.position + "/" + (options.balls ? "futavagina.png" : "futavaginanoballs.png");
return options.close_vagina_show && !!options.worn.under_lower.index && options.worn.under_lower.state === "totheside";
return "img/sex/close/" + options.position + "/vaginatotheside.png";
return options.close_vagina_show && !!options.vagina_state && !!options.vagina_penetrator;
},
srcfn(options) {
switch (options.vagina_state) {
case "penetrated":
switch (options.vagina_penetrator) {
case "tentacle":
return "img/sex/close/" + options.position + "/vaginatentaclepenetrated.png";
return "img/sex/close/machine/vaginal/" + options.position + "/penetrated_close.png";
case "beast":
if (options.vagina_penetrator_subtype === "horse" || options.vagina_penetrator_subtype === "centaur") {
return "img/sex/close/" + options.position + "/vaginapenetratedbeast.png";
return "img/sex/close/" + options.position + "/vaginapenetrated.png";
}
case "imminent":
case "entrance":
switch (options.vagina_penetrator) {
case "tentacle":
return "img/sex/close/" + options.position + "/vaginatentacleentrance.png";
return "img/sex/machine/vaginal/" + options.position + "/entrance_close.png";
case "beast":
if (options.vagina_penetrator_subtype === "horse" || options.vagina_penetrator_subtype === "centaur") {
return "img/sex/close/" + options.position + "/vaginaentrancebeast.png";
return "img/sex/close/" + options.position + "/vaginaentrance.png";