Bläddra i källkod

Merge pull request #2 from chemicalcrux/master

Bringing changes on main repo into branch
master
jsb5468 GitHub 5 år sedan
förälder
incheckning
cbc92ecd75
Ingen känd nyckel hittad för denna signaturen i databasen GPG-nyckel ID: 4AEE18F83AFDEB23
9 ändrade filer med 1447 tillägg och 252 borttagningar
  1. +72
    -56
      features.js
  2. +202
    -70
      game.js
  3. +21
    -1
      migrations.js
  4. +746
    -17
      presets.js
  5. +280
    -38
      recursive-desc.js
  6. +12
    -13
      recursive-macro.js
  7. +26
    -23
      stroll.html
  8. +43
    -19
      style.css
  9. +45
    -15
      units.js

+ 72
- 56
features.js Visa fil

@@ -558,7 +558,7 @@ options = [
"name": "Hand length",
"id": "baseHandLength",
"type": "float",
"default": "0.25",
"default": "0.2",
"unit": "length"
},
{
@@ -572,7 +572,7 @@ options = [
"name": "Ass area",
"id": "baseAssArea",
"type": "float",
"default": "0.2",
"default": "0.1",
"unit": "area"
},
{
@@ -646,7 +646,6 @@ options = [
"type": "radio",
"id": "difficulty",
"default": "0",
"tooltip": "Grow how you want, when you want.",
"choices":
[
{
@@ -663,24 +662,23 @@ options = [
},
{
"name": "Automatic Growth",
"id": "automaticGrowth",
"id": "automaticGrowthEnabled",
"type": "subcategory",
"entries":
[
{
"name": "Automatic growth",
"id": "automaticGrowthEnabled",
"type": "checkbox",
"default": false,
"warning": "Automatic Growth is enabled",
"tooltip": "When checked, you will automaically grow by ingesting/absorbing mass.",
"name": "Help",
"id": "",
"type": "label",
"tooltip": "When checked, you will automaically grow by ingesting/absorbing mass."
},
{
"name": "Prey growth factor",
"id": "basePreyGrowthFactor",
"type": "float",
"default": "0.8",
"tooltip": "How much of what you eat gets automatically added to your body. Setting this to [0] disables it. To add half of your prey mass to your own, set to [.5]."
"default": "80",
"unit": "percentage",
"tooltip": "How much of what you eat gets automatically added to your body. Setting this to 0% disables it. To add half of your prey mass to your own, set to 50%."
},
{
"name": "Scale growth with size",
@@ -782,22 +780,26 @@ options = [
[
{
"name": "Non-fatal",
"value": "0"
"value": "0",
"tooltip": "All actions are explicitly safe."
},
{
"name": "Fatal",
"value": "1",
"warning": "Fatal actions are enabled"
"warning": "Fatal actions are enabled",
"tooltip": "Actions can have fatal consequences, but don't go into detail."
},
{
"name": "Gory",
"value": "2",
"warning": "Gory actions are enabled"
"warning": "Gory actions are enabled",
"tooltip": "Descriptions are violent, but not excessively so."
},
{
"name": "Sadistic",
"value": "3",
"warning": "Brutal actions are enabled"
"warning": "Brutal actions are enabled",
"tooltip": "Cronch."
},
]
}
@@ -888,7 +890,7 @@ options = [
"name": "Anus diameter",
"id": "baseAnalVoreDiameter",
"type": "float",
"default": "0.2",
"default": "0.1",
"unit": "length"
},
{
@@ -910,8 +912,9 @@ options = [
"name": "Anal autogrowth factor",
"id": "assGrowthFactor",
"type": "float",
"default": "0.01",
"tooltip": "How much this part grows during part specific digestion. This is relative to overall growth, [1]:all mass goes to this part [.2]:20% part growth-80% overall growth."
"default": "1",
"unit": "percentage",
"tooltip": "How much this part grows during part specific digestion. This is relative to overall growth, 100%:all mass goes to this part 20%:20% part growth-80% overall growth."
},
{
"name": "Manual digestion",
@@ -1089,8 +1092,9 @@ options = [
"name": "Tail autogrowth factor",
"id": "tailGrowthFactor",
"type": "float",
"default": "0.01",
"tooltip": "How much this part grows during part specific digestion. This is relative to overall growth, [1]:all mass goes to this part [.2]:20% part growth-80% overall growth."
"default": "1",
"unit": "percentage",
"tooltip": "How much this part grows during part specific digestion. This is relative to overall growth, 100%:all mass goes to this part 20%:20% part growth-80% overall growth."
},
{
"name": "Automatic Digestion",
@@ -1192,9 +1196,9 @@ options = [
"name": "Passive cum production",
"id": "baseCumProduction",
"type": "float",
"default": "0.01",
"unit": "volume",
"tooltip": "The fraction of your maximum capacity produced every second"
"default": "1",
"unit": "percentage",
"tooltip": "How much you fill up every second"
},
{
"name": "Cum storage factor",
@@ -1206,15 +1210,17 @@ options = [
"name": "Cock autogrowth factor",
"id": "cockGrowthFactor",
"type": "float",
"default": "0.01",
"tooltip": "How much this part grows during part specific digestion. This is relative to overall growth, [1]:all mass goes to this part [.2]:20% part growth-80% overall growth."
"default": "1",
"unit": "percentage",
"tooltip": "How much this part grows during part specific digestion. This is relative to overall growth, 100%:all mass goes to this part 20%:20% part growth-80% overall growth."
},
{
"name": "Balls autogrowth factor",
"id": "ballGrowthFactor",
"type": "float",
"default": "0.01",
"tooltip": "How much this part grows during part specific digestion. This is relative to overall growth, [1]:all mass goes to this part [.2]:20% part growth-80% overall growth."
"default": "1",
"unit": "percentage",
"tooltip": "How much this part grows during part specific digestion. This is relative to overall growth, 100%:all mass goes to this part 20%:20% part growth-80% overall growth."
},
{
"name": "Cock Vore",
@@ -1304,6 +1310,7 @@ options = [
"name": "Musk",
"id": "maleMuskEnabled",
"type": "subcategory",
"parts": ["musk"],
"entries":
[
{
@@ -1357,9 +1364,9 @@ options = [
"name": "Passive femcum production",
"id": "baseFemcumProduction",
"type": "float",
"default": "0.01",
"unit": "volume",
"tooltip": "The fraction of your maximum capacity produced every second"
"default": "1",
"unit": "percentage",
"tooltip": "How much you fill up every second"
},
{
"name": "Femcum storage factor",
@@ -1390,15 +1397,17 @@ options = [
"name": "Vagina autogrowth factor",
"id": "vaginaGrowthFactor",
"type": "float",
"default": "0.01",
"tooltip": "How much this part grows during part specific digestion. This is relative to overall growth, [1]:all mass goes to this part [.2]:20% part growth-80% overall growth."
"default": "1",
"unit": "percentage",
"tooltip": "How much this part grows during part specific digestion. This is relative to overall growth, 100%:all mass goes to this part 20%:20% part growth-80% overall growth."
},
{
"name": "Womb autogrowth factor",
"id": "wombGrowthFactor",
"type": "float",
"default": "0.01",
"tooltip": "How much this part grows during part specific digestion. This is relative to overall growth, [1]:all mass goes to this part [.2]:20% part growth-80% overall growth."
"default": "1",
"unit": "percentage",
"tooltip": "How much this part grows during part specific digestion. This is relative to overall growth, 100%:all mass goes to this part 20%:20% part growth-80% overall growth."
},
{
"name": "Automatic Digestion",
@@ -1439,6 +1448,7 @@ options = [
"name": "Musk",
"id": "femaleMuskEnabled",
"type": "subcategory",
"parts": ["musk"],
"entries":
[
{
@@ -1486,9 +1496,9 @@ options = [
"name": "Passive milk production",
"id": "baseLactationProduction",
"type": "float",
"default": "0.001",
"unit": "volume",
"tooltip": "The fraction of your maximum capacity produced every second"
"default": "0.1",
"unit": "percentage",
"tooltip": "How much you fill up every second"
},
{
"name": "Milk storage scale",
@@ -1521,8 +1531,9 @@ options = [
"name": "Breast autogrowth factor",
"id": "breastGrowthFactor",
"type": "float",
"default": "0.01",
"tooltip": "How much this part grows during part specific digestion. This is relative to overall growth, [1]:all mass goes to this part [.2]:20% part growth-80% overall growth."
"default": "1",
"unit": "percentage",
"tooltip": "How much this part grows during part specific digestion. This is relative to overall growth, 100%:all mass goes to this part 20%:20% part growth-80% overall growth."
},
{
"name": "Automatic Digestion",
@@ -1565,6 +1576,7 @@ options = [
"id": "stenchEnabled",
"optional": true,
"warning": "Stench is enabled",
"parts": ["stench"],
"entries":
[
{
@@ -1618,9 +1630,9 @@ options = [
"name": "Passive gas production",
"id": "baseGasProduction",
"type": "float",
"default": "0.01",
"unit": "volume",
"tooltip": "The fraction of your maximum capacity produced every second"
"default": "1",
"unit": "percentage",
"tooltip": "How much you fill up every second"
},
{
"name": "Gas storage scale",
@@ -1655,7 +1667,8 @@ options = [
"name": "Souls autogrowth factor",
"id": "soulGrowthFactor",
"type": "float",
"default": "0.25",
"default": "25",
"unit": "percentage",
"tooltip": "How much you grow when absorbing souls. [1]-you will gain equal mass to the souls you absorb. [.01]- you will grow by 1% of the mass of the souls you absorb. This does not stack with Prey growth factor"
},
{
@@ -1716,9 +1729,9 @@ options = [
"name": "Passive piss production",
"id": "basePissProduction",
"type": "float",
"default": "0.01",
"unit": "volume",
"tooltip": "The fraction of your maximum capacity produced every second"
"default": "1",
"unit": "percentage",
"tooltip": "How much you fill up every second"
},
{
"name": "Piss storage scale",
@@ -1809,9 +1822,9 @@ options = [
"name": "Passive scat production",
"id": "baseScatProduction",
"type": "float",
"default": "0.001",
"unit": "volume",
"tooltip": "The fraction of your maximum capacity produced every second"
"default": "0.1",
"unit": "percentage",
"tooltip": "How much you fill up every second"
},
{
"name": "Scat storage scale",
@@ -1845,7 +1858,8 @@ options = [
"name": "Goo autogrowth factor",
"id": "gooGrowthFactor",
"type": "float",
"default": "0.8",
"default": "80",
"unit": "percentage",
"tooltip": "How much you grow when absorbing people via goo. [1]-you will gain equal mass to the souls you absorb. [.01]- you will grow by 1% of the mass of the souls you absorb. This does not stack with Prey growth factor"
},
{
@@ -1883,8 +1897,9 @@ options = [
"name": "Paw autogrowth factor",
"id": "pawGrowthFactor",
"type": "float",
"default": "0.01",
"tooltip": "How much this part grows during part specific digestion. This is relative to overall growth, [1]:all mass goes to this part [.2]:20% part growth-80% overall growth."
"default": "1",
"unit": "percentage",
"tooltip": "How much this part grows during part specific digestion. This is relative to overall growth, 100%:all mass goes to this part 20%:20% part growth-80% overall growth."
},
{
"name": "Automatic Digestion",
@@ -2038,7 +2053,7 @@ options = [
"id": "hasWings",
"optional": true,
"panels": ["misc"],
//"parts": ["wings"],
"parts": ["wings"],
"buttons": ["wings_flap"],
"entries":
[
@@ -2073,8 +2088,9 @@ options = [
"name": "Wing autogrowth factor",
"id": "wingGrowthFactor",
"type": "float",
"default": "0.01",
"tooltip": "How much this part grows during part specific digestion. This is relative to overall growth, [1]:all mass goes to this part [.2]:20% part growth-80% overall growth."
"default": "1",
"unit": "percentage",
"tooltip": "How much this part grows during part specific digestion. This is relative to overall growth, 100%:all mass goes to this part 20%:20% part growth-80% overall growth."
},
{
"name": "Automatic Digestion",


+ 202
- 70
game.js Visa fil

@@ -3,7 +3,7 @@
/*jshint browser: true*/
/*jshint devel: true*/

let version = "v1.0.1";
let version = "v1.1.1";

let errored = false;

@@ -19,6 +19,8 @@ window.onerror = function(msg, source, lineno, colno, error) { //opens a popup i
//generates initial conditions and sets up variables
let started = false;

const fillPeriod = 1000 / 60;

const strollingEnum = {
Standing: 0,
Strolling: 1,
@@ -90,6 +92,9 @@ let macro = //macro controls every customizable part of the players body
"wombScale": 1,
"breastScale": 1,
"tailScale": 1,
"wingScale": 1,
"muskScale": 1,
"stenchScale": 1,

"tailDensity": 1000,
"dickDensity": 1000,
@@ -113,8 +118,8 @@ let macro = //macro controls every customizable part of the players body
get handWidth() { return this.scaling(this.baseHandWidth, this.scale, 1); },
get handArea() { return this.handLength * this.handWidth },

get wingLength() { return this.scaling(this.baseWingLength, this.scale, 1); },
get wingWidth() { return this.scaling(this.baseWingWidth, this.scale, 1); },
get wingLength() { return this.scaling(this.baseWingLength, this.scale * this.wingScale, 1); },
get wingWidth() { return this.scaling(this.baseWingWidth, this.scale * this.wingScale, 1); },
get wingArea() { return this.wingLength * this.wingWidth; },

"footOnlyDesc": function(plural=false,capital=false) {
@@ -1336,23 +1341,21 @@ let macro = //macro controls every customizable part of the players body
},

"fillCum": function(self) {
self.cumStorage.amount += self.scaling(self.baseCumProduction / 10 / 1000, self.scale * self.ballScale, 3);
self.cumStorage.amount += self.cumStorage.limit * self.baseCumProduction * fillPeriod / 1000;
if (self.cumStorage.amount > self.cumStorage.limit)
self.arouse(1 * (self.cumStorage.amount / self.cumStorage.limit - 1));
setTimeout(function () { self.fillCum(self); }, 100);
update();
setTimeout(function () { self.fillCum(self); }, fillPeriod);
},

"fillFemcum": function(self) {
self.femcumStorage.amount += self.scaling(self.baseFemcumProduction / 10 / 1000, self.scale * self.wombScale, 3);
self.femcumStorage.amount += self.femcumStorage.limit * self.baseFemcumProduction * fillPeriod / 1000;
if (self.femcumStorage.amount > self.femcumStorage.limit)
self.arouse(1 * (self.femcumStorage.amount / self.femcumStorage.limit - 1));
setTimeout(function () { self.fillFemcum(self); }, 100);
update();
setTimeout(function () { self.fillFemcum(self); }, fillPeriod);
},

"fillBreasts": function(self) {
self.milkStorage.amount += self.scaling(self.baseLactationProduction / 10 / 1000, self.scale * self.breastScale, 3);
self.milkStorage.amount += self.milkStorage.limit * self.baseLactationProduction * fillPeriod / 1000;

if (self.milkStorage.amount > self.milkStorage.limit) {
breast_milk(self.milkStorage.amount - self.milkStorage.limit/2);
@@ -1361,12 +1364,11 @@ let macro = //macro controls every customizable part of the players body
if (self.milkStorage.amount > self.milkStorage.limit) {
self.milkStorage.amount = self.milkStorage.limit;
}
setTimeout(function () { self.fillBreasts(self); }, 100);
update();
setTimeout(function () { self.fillBreasts(self); }, fillPeriod);
},

"fillGas": function(self) {
self.gasStorage.amount += self.scaling(self.baseGasProduction / 10 / 1000, self.scale, 3);
self.gasStorage.amount += self.gasStorage.limit * self.baseGasProduction * fillPeriod / 1000;

let ratio = self.gasStorage.amount / self.gasStorage.limit;

@@ -1384,8 +1386,7 @@ let macro = //macro controls every customizable part of the players body
}

}
setTimeout(function () { self.fillGas(self); }, 100);
update();
setTimeout(function () { self.fillGas(self); }, fillPeriod);
},

get urethraDiameter() {
@@ -1399,21 +1400,19 @@ let macro = //macro controls every customizable part of the players body
},

"fillPiss": function(self) {
self.pissStorage.amount += self.scaling(self.basePissProduction / 10 / 1000, self.scale, 3);
self.pissStorage.amount += self.pissStorage.limit * self.basePissProduction * fillPeriod / 1000;

if (self.pissStorage.amount > self.pissStorage.limit * 2)
piss(self.pissStorage.amount, false);
setTimeout(function () { self.fillPiss(self); }, 100);
update();
setTimeout(function () { self.fillPiss(self); }, fillPeriod);
},

"fillScat": function(self) {
self.scatStorage.amount += self.scaling(self.baseScatProduction / 10 / 1000, self.scale, 3);
self.scatStorage.amount += self.scatStorage.limit * self.baseScatProduction * fillPeriod / 1000;

if (self.scatStorage.amount > self.scatStorage.limit * 2)
scat(self.scatStorage.amount, false);
setTimeout(function () { self.fillScat(self); }, 100);
update();
setTimeout(function () { self.fillScat(self); }, fillPeriod);
},

"cumStorage": {
@@ -1460,11 +1459,11 @@ let macro = //macro controls every customizable part of the players body
},

get pawStenchArea() {
return this.pawArea * this.basePawStenchArea;
return this.pawArea * this.basePawStenchArea * this.stenchScale;
},

get assStenchArea() {
return this.assArea * this.baseAssStenchArea;
return this.assArea * this.baseAssStenchArea * this.stenchScale;
},

get gasDigestFactor() {
@@ -1527,7 +1526,6 @@ let macro = //macro controls every customizable part of the players body
this.arousal = 0;
this.afterglow = false;
}
update();
},

"quenchExcess": function(self) {
@@ -1550,7 +1548,6 @@ let macro = //macro controls every customizable part of the players body
female_spurt(macro.femcumVolume * (0.1 + Math.random() / 10), false);
self.femaleSpurt = 0;
}
update();
} else if (self.orgasm) {
self.quench(1);
} else if (self.afterglow) {
@@ -2114,9 +2111,9 @@ function getWeights(region, area) {

if (area > things["Planet"].area) {
weights = {
"Planet": 1.47e-10,
"Star": 1.7713746e-12,
"Solar System": 4e-10,
"Planet": 1.47e-3,
"Star": 1.7713746e-3,
"Solar System": 4e-4,
"Galaxy": 0.1,
"Cluster": 0.5,
"Universe": 1,
@@ -2186,7 +2183,7 @@ function getWeights(region, area) {
}
}
if (macro.victimsMicros) {
weights["Micro"] = 1;
weights["Micro"] = 0.001;
}

if (macro.victimsMacros) {
@@ -2402,7 +2399,8 @@ function drool()

update([sound,line,linesummary,newline]);
}
function stomp()

function stomp(active=true)
{
if (macro.gooMolten && !macro.footShoeWorn && !macro.footSockWorn) {
stomp_goo();
@@ -2412,7 +2410,7 @@ function stomp()
let area = macro.pawArea;
let prey = getPrey(biome, area, macro.sameSizeStomp);
let line = describe("stomp", prey, macro, verbose, flat);
let linesummary = summarize(prey.sum(), false);
let linesummary = summarize(prey.sum(), true);

let people = get_living_prey(prey.sum());

@@ -2422,20 +2420,20 @@ function stomp()

add_victim_people("stomped",prey);

update([sound,line,linesummary,newline]);
update([sound,line,linesummary,newline], active);

updateBiome(false);

macro.arouse(5);

stomp_wedge();
stomp_wedge(active);

if (macro.stenchEnabled && macro.basePawStenchArea > 0) {
paw_stench();
paw_stench(active);
}
}

function stomp_wedge() {
function stomp_wedge(active=true) {
if (macro.footType == "hoof")
return;

@@ -2466,14 +2464,14 @@ function stomp_wedge() {

add_victim_people("stomped",prey);

update([sound,line,linesummary,newline]);
update([sound,line,linesummary,newline], active);
}

function stomp_goo() {
let area = macro.pawArea;
let prey = getPrey(biome, area, macro.sameSizeStomp);
let line = describe("stomp-goo", prey, macro, verbose, flat);
let linesummary = summarize(prey.sum(), true);
let linesummary = summarize(prey.sum(), false);

let people = get_living_prey(prey.sum());

@@ -2553,7 +2551,7 @@ function paw_stench() {
macro.arouse(5);
}

function grind()
function grind(active=true)
{
let area = macro.assArea / 2;

@@ -2578,9 +2576,17 @@ function grind()
update([sound,line,linesummary,newline]);

macro.arouse(20);

if (macro.maleMuskEnabled) {
male_musk(area * macro.baseMaleMuskArea * macro.muskScale / 2, active);
}

if (macro.femaleMuskEnabled) {
female_musk(area * macro.baseFemaleMuskArea * macro.muskScale, active);
}
}

function ass_grind()
function ass_grind(active=true)
{
let area = macro.assArea / 2;

@@ -2600,6 +2606,14 @@ function ass_grind()
update([sound,line,linesummary,newline]);

macro.arouse(15);

if (macro.maleMuskEnabled) {
male_musk(area * macro.baseMaleMuskArea * macro.muskScale / 2, active);
}

if (macro.femaleMuskEnabled) {
female_musk(area * macro.baseFemaleMuskArea * macro.muskScale, active);
}
}

function anal_vore()
@@ -3101,7 +3115,7 @@ function foreskin_absorb()
macro.arouse(45);
}

function cockslap()
function cockslap(active=true)
{
let area = macro.dickArea;
let prey = getPrey(biome, area);
@@ -3118,9 +3132,13 @@ function cockslap()
update([sound,line,linesummary,newline]);

macro.arouse(15);

if (macro.maleMuskEnabled) {
male_musk(area * macro.baseMaleMuskArea * macro.muskScale / 2, active);
}
}

function cock_vore()
function cock_vore(active=true)
{
let area = macro.dickStretchGirth;
let prey = getPrey(biome, area, macro.sameSizeCockVore);
@@ -3139,9 +3157,13 @@ function cock_vore()
update([sound,line,linesummary,newline]);

macro.arouse(20);

if (macro.maleMuskEnabled) {
male_musk(area * macro.baseMaleMuskArea * macro.muskScale / 2, active);
}
}

function ball_smother()
function ball_smother(active=true)
{
let area = macro.ballArea * 2;
let prey = getPrey(biome, area);
@@ -3158,6 +3180,27 @@ function ball_smother()
update([sound,line,linesummary,newline]);

macro.arouse(10);

if (macro.maleMuskEnabled) {
male_musk(area * macro.baseMaleMuskArea * macro.muskScale, active);
}
}

function male_musk(area, active=true) {
let prey = getPrey(biome, area);
let line = describe("male-musk", prey, macro, verbose, flat);
let linesummary = summarize(prey.sum(), true);

let people = get_living_prey(prey.sum());

if (get_living_prey(prey.sum()) == 0)
return;

let preyMass = prey.sum_property("mass");

add_victim_people("male-musk",prey);

update([line,linesummary,newline], active);
}

function male_spurt(vol, active=true)
@@ -3179,7 +3222,7 @@ function male_spurt(vol, active=true)
update([sound,line,linesummary,newline], active);

if (macro.maleMuskEnabled) {
male_spurt_musk(area * macro.baseMaleMuskArea, active);
male_spurt_musk(area * macro.baseMaleMuskArea * macro.muskScale, active);
}
}

@@ -3197,7 +3240,7 @@ function male_spurt_musk(area, active=true) {

add_victim_people("male-spurt-musk",prey);

update([line,linesummary,newline]);
update([line,linesummary,newline], active);

macro.arouse(5);
}
@@ -3221,7 +3264,7 @@ function male_orgasm(vol, active=true)
update([sound,line,linesummary,newline], active);

if (macro.maleMuskEnabled) {
male_orgasm_musk(area * macro.baseMaleMuskArea, active);
male_orgasm_musk(area * macro.baseMaleMuskArea * macro.muskScale, active);
}
}

@@ -3244,6 +3287,25 @@ function male_orgasm_musk(area, active=true) {
macro.arouse(5);
}

function female_musk(area, active=true) {
let prey = getPrey(biome, area);
let line = describe("female-musk", prey, macro, verbose, flat);
let linesummary = summarize(prey.sum(), true);

let people = get_living_prey(prey.sum());

if (get_living_prey(prey.sum()) == 0)
return;

let preyMass = prey.sum_property("mass");

add_victim_people("female-musk",prey);

update([line,linesummary,newline], active);

macro.arouse(5);
}

function female_spurt(vol, active=true)
{
let area = Math.pow(vol, 2/3);
@@ -3263,7 +3325,7 @@ function female_spurt(vol, active=true)
update([sound,line,linesummary,newline], active);

if (macro.femaleMuskEnabled) {
female_spurt_musk(area * macro.baseFemaleMuskArea, active);
female_spurt_musk(area * macro.baseFemaleMuskArea * macro.muskScale, active);
}
}

@@ -3305,7 +3367,7 @@ function female_orgasm(vol, active=true)
update([sound,line,linesummary,newline], active);

if (macro.femaleMuskEnabled) {
female_orgasm_musk(area * macro.baseFemaleMuskArea, active);
female_orgasm_musk(area * macro.baseFemaleMuskArea * macro.muskScale, active);
}
}

@@ -3798,7 +3860,7 @@ function piss(vol, active=true) {
macro.arouse(20);

if (macro.stenchEnabled && macro.basePissStenchArea > 0) {
piss_stench(area * macro.basePissStenchArea, active);
piss_stench(area * macro.basePissStenchArea * macro.stenchScale, active);
}
}

@@ -3868,7 +3930,7 @@ function scat(vol, active=true) {
macro.arouse(50);

if (macro.stenchEnabled && macro.baseScatStenchArea > 0) {
scat_stench(area*macro.baseScatStenchArea, active);
scat_stench(area * macro.baseScatStenchArea * macro.stenchScale, active);
}
}

@@ -4355,9 +4417,9 @@ function cooldown_end(category) {
});
}

function transformNumbers(line)
function transformNumbers(line, fixed=undefined)
{
return line.toString().replace(/[0-9]+(\.[0-9]+)?(e\+[0-9]+)?/g, function(text) { return number(text, numbers); });
return line.toString().replace(/[0-9]+(\.[0-9]+)?(e\+[0-9]+)?/g, function(text) { return number(text, numbers, fixed); });
}

function update(lines = [], active=true)
@@ -4416,7 +4478,7 @@ function applyPercentage(name, meterPos) {
}

function stylePercentage(name, storage) {
document.getElementById(name).innerHTML = name + ": " + transformNumbers(volume(storage.amount,unit,false));
document.getElementById(name).innerHTML = name + ": " + transformNumbers(volume(storage.amount,unit,false), 2);
let meterPos = 150 - storage.amount / storage.limit * 150;
applyPercentage(name, meterPos);
}
@@ -4448,7 +4510,7 @@ function pick_move()
return;
}

stomp();
stomp(false);
}
//Growth
//Automatic Growth
@@ -4512,9 +4574,8 @@ function grow_part_pick(id) {
}

function grow_pick(times) {

let button = document.querySelector(".growth-part-active");

const select = document.querySelector("#growth-part-select");
const chosenPart = select.value;
if (macro.difficulty > 0 && macro.growthPoints < (times - 1) * 10) {
update(["You need " + times*10 + " growth points to grow that much.",newline]);
} else {
@@ -4524,7 +4585,7 @@ function grow_pick(times) {

times /= 10;

switch (button.id.replace("button-growth-", "")) {
switch (chosenPart) {
case "body": grow(times); break;
case "paws": grow_paws(times); break;
case "tail": grow_tail(times); break;
@@ -4535,6 +4596,8 @@ function grow_pick(times) {
case "womb": grow_womb(times); break;
case "breasts": grow_breasts(times); break;
case "wings": grow_wings(times); break;
case "musk": grow_musk(times); break;
case "stench": grow_stench(times); break;
}
}
}
@@ -4721,14 +4784,44 @@ function grow_wings(factor, simpleCalc=true){
let oldLength = macro.wingLength;

if (simpleCalc == true){
macro.pawScale *= factor;
macro.wingScale *= factor;
} else {
macro.wingScale = (macro.wingScale + (factor/macro.mass))
}

let lengthDelta = macro.wingLength - oldLength;

update([pickString("Power surges through you","Energy flows into you","Your back muscles fight for space","Your muscles tense","A crackeling fills the air","Your balance shifts","You feel a buzz of power","A warm sensation fills you") + " as your " + macro.wingDesc(true) + " grow, gaining " + length(2 * lengthDelta, unit, false) + " of wingspan.",newline]);
update([pickString("Power surges through you","Energy flows into you","Your back muscles fight for space","Your muscles tense","A crackeling fills the air","Your balance shifts","You feel a buzz of power","A warm sensation fills you") + " as your " + macro.wingDesc + " wings grow, gaining " + length(2 * lengthDelta, unit, false) + " of wingspan.",newline]);
}

function grow_musk(factor, simpleCalc=true){

let oldScale = macro.muskScale;

if (simpleCalc == true){
macro.muskScale *= factor;
} else {
macro.muskScale = (macro.muskScale + (factor/Math.pow(macro.mass, 1/3)))
}

let scaleDelta = macro.muskScale - oldScale;

update([pickString("Power surges through you","Energy flows into you","A crackeling fills the air","Your balance shifts","You feel a buzz of power","A warm sensation fills you") + " as your musk thickens, growing more potent.",newline]);
}

function grow_stench(factor, simpleCalc=true){

let oldScale = macro.muskScale;

if (simpleCalc == true){
macro.stenchScale *= factor;
} else {
macro.stenchScale = (macro.stenchScale + (factor/Math.pow(macro.mass, 1/3)))
}

let scaleDelta = macro.stenchScale - oldScale;

update([pickString("Power surges through you","Energy flows into you","A crackeling fills the air","Your balance shifts","You feel a buzz of power","A warm sensation fills you") + " as your stench thickens, growing more potent.",newline]);
}

function resetSettings() {
@@ -4825,8 +4918,15 @@ function generateSettings(diff=false) {
let value = form[i].value == "" ? form[i].placeholder : form[i].value;
if (form[i].type == "text")
settings[form[i].name] = value;
else if (form[i].type == "number")
settings[form[i].name] = parseFloat(value);
else if (form[i].type == "number") {
if (form[i].dataset.unit == "percentage") {
settings[form[i].name] = parseFloat(value) / 100;
} else if (form[i].dataset.unit == "volume") {
settings[form[i].name] = parseFloat(value) / 1000;
} else {
settings[form[i].name] = parseFloat(value);
}
}
else if (form[i].type == "checkbox") {
settings[form[i].name] = form[i].checked;

@@ -4879,8 +4979,20 @@ function recurseDeletePanel(settings, panel) {
delete settings[option.id];
} else if (option.type == "checkbox" && !settings[option.id] && option.default === undefined) {
delete settings[option.id];
} else if (settings[option.id] == option.default && option.id != "name") {
delete settings[option.id];
} else {
if (option.unit == "percentage") {
if (settings[option.id] * 100 == option.default)
delete settings[option.id];
}

else if (option.unit == "volume") {
if (settings[option.id] * 1000 == option.default)
delete settings[option.id];
}
else if (settings[option.id] == option.default && option.id != "name") {
delete settings[option.id];
}
}
})

@@ -5003,8 +5115,16 @@ function loadSettings(settings = null) {
if (settings[form[i].name] != undefined) {
if (form[i].type == "text")
form[i].value = settings[form[i].name];
else if (form[i].type == "number")
form[i].value = settings[form[i].name];
else if (form[i].type == "number") {
if (form[i].dataset.unit == "percentage") {
form[i].value = settings[form[i].name] * 100;
} else if (form[i].dataset.unit == "volume") {
form[i].value = settings[form[i].name] * 1000;
} else {
form[i].value = settings[form[i].name];
}
}
else if (form[i].type == "checkbox") {
form[i].checked = settings[form[i].name];
} else if (form[i].type == "radio") {
@@ -5027,8 +5147,6 @@ function add_victim_people(category, prey) {
victims[category]["people"] += get_living_prey(prey.sum());

macro.growthPoints += get_living_prey(prey.sum()) * 100 / (1 + Math.log10(macro.scale));

update();
}

function enable_victim(category) {
@@ -5054,7 +5172,7 @@ function enable_stat(name) {
}

function enable_growth_part(name) {
document.querySelector("#button-growth-" + name).style.display = 'block';
document.querySelector("#option-growth-" + name).style.display = 'block';
}

function disable_button(name) {
@@ -5233,10 +5351,16 @@ function startGame(e) {
document.getElementById("actions-body").style.display = 'flex';
document.getElementById("stat-container").style.display = 'flex';

repeatUpdate();

window.scroll(0,0);
}

function repeatUpdate() {
update();
setTimeout(repeatUpdate, fillPeriod);
}

function actionTab(e) {
let name = e.target.id;

@@ -5355,7 +5479,8 @@ function updatePreview(name) {
result = volume(value * scale * scale * scale / 1000, unit);
else if (unitType == "mass")
result = mass(value * scale * scale * scale, unit);

else if (unitType == "percentage")
result = value + "%";
document.getElementById(name + "Preview").innerHTML = result;
}

@@ -5455,7 +5580,7 @@ window.addEventListener('load', function(event) {

document.getElementById("button-dark-mode-options").addEventListener("click",toggleDarkMode);
document.querySelectorAll(".growth-part").forEach(function (button) {
button.addEventListener("click", function() { grow_part_pick(button.id); });
button.addEventListener("select", function() { grow_part_pick(button.id); });
});

document.getElementById("button-growth-1.1").addEventListener("click",function() { grow_pick(11); });
@@ -5577,6 +5702,13 @@ function render_radio_option(options_div, option) {
label.setAttribute("for", option.id + "-" + choice.value);
label.innerText = choice.name;

label.classList.add("solo")

if (choice.tooltip) {
label.classList.add("has-tooltip")
label.title = choice.tooltip;
}

attach_form_data(input, choice);

li.appendChild(input);


+ 21
- 1
migrations.js Visa fil

@@ -6,6 +6,7 @@ migrations = [
// does nothing
save => {
},

// 1 -> 2

// automatic digestion is now a subcategory, so anyone with
@@ -35,8 +36,27 @@ migrations = [
save.cropTransferAuto = false;
if (save.wingDigestTime == 0)
save.wingDigestAuto = false;
}
},

// 2 -> 3

// passive production is now written as percentage points;
// old values won't make sense anymore, so we'll just
// erase them
save => {
if (save.baseCumProduction)
delete save.baseCumProduction;
if (save.baseFemcumProduction)
delete save.baseFemcumProduction;
if (save.baseLactationProduction)
delete save.baseLactationProduction;
if (save.baseGasProduction)
delete save.baseGasProduction;
if (save.basePissProduction)
delete save.basePissProduction;
if (save.baseScatProduction)
delete save.baseScatProduction;
}
];

function migrate(save, target=null) {


+ 746
- 17
presets.js Visa fil

@@ -1,19 +1,748 @@
let presets = [
{"version":1,"name":"Fen","priority": 1,"brutality":"2","oralVore":true,"analVore":true,"analVoreToStomach":true,"hasTail":true,"tailType":"twisted","baseTailLength":2,"baseTailDiameter":0.4},
{"version":1,"name":"Mech","baseHeight":3.7,"baseMass":500,"basePawLength":0.8,"basePawWidth":0.5,"baseHandLength":0.4,"baseHandWidth":0.2,"baseAssArea":1,"species":"Dragon","brutality":"2","victimsHuman":true,"victimsMilitary":true,"victimsMacros":true,"oralVore":true,"oralDigestTime":5,"analVore":true,"baseAnalVoreDiameter":0.4,"analVoreToStomach":true,"arousalEnabled":true,"hasTail":true,"tailType":"meaty","baseTailLength":2.5,"baseTailDiameter":0.6,"maleParts":true,"baseDickLength":0.9,"baseDickDiameter":0.2,"dickType":"hefty","baseBallDiameter":0.19,"baseCumVolume":2,"cockVoreEnabled":true,"cockDigestTime":5,"basePissProduction":0.001,"baseScatDigestFactor":0.3,"scatStorageScale":1.5,"scatScaleWithSize":true,"magicEnabled":true},
{"version":1,"name":"Goathias","scale":3,"species":"Goat","footType":"hoof","difficulty":"1","brutality":"3","victimsHuman":true,"victimsMilitary":true,"oralVore":true,"vomitEnabled":true,"analVore":true,"arousalEnabled":true,"maleParts":true,"cockVoreEnabled":true,"cumScaleWithSize":true,"maleMuskEnabled":true,"hasBreasts":true,"lactationEnabled":true,"breastVore":true,"milkScaleWithSize":true,"stenchEnabled":true,"gasEnabled":true,"belchEnabled":true,"fartEnabled":true,"gasScaleWithSize":true,"pissEnabled":true,"bladderVore":true,"pissScaleWithSize":true,"scatEnabled":true,"scatScaleWithSize":true,"breathEnabled":true,"breathFoul":true,"droolEnabled":true,"magicEnabled":true},
{"version":1,"name":"Arokha","scale":10,"baseHeight":1.67,"baseMass":50,"baseAssArea":0.25,"species":"kitsune","victimsMicros":true,"oralVore":true,"oralDigestTime":5,"analVore":true,"baseAnalVoreDiameter":0.1,"analDigestTime":5,"analVoreToStomach":true,"footSockEnabled":true,"footShoeEnabled":true,"arousalEnabled":true,"hasTail":true,"tailCount":2,"tailMaw":true,"tailStretchiness":1,"tailDigestTime":5,"tailVoreToStomach":true,"dickStretchiness":1,"hasSheath":true,"femaleParts":true,"baseVaginaLength":0.12,"vaginaStretchiness":2,"femcumScaleWithSize":true,"hasBreasts":true,"lactationEnabled":true,"breastStretchiness":1,"baseAssStenchArea":2,"baseScatStenchArea":1.5,"gasEnabled":true,"belchEnabled":true,"fartEnabled":true,"gasScaleWithSize":true,"soulVoreEnabled":true,"soulDigestTime":5,"pissEnabled":true,"scatEnabled":true,"scatScaleWithSize":true,"gooDigestion":true},
{"version":1,"name":"Aronai","scale":10,"baseHeight":1.8,"baseMass":86,"baseAssArea":0.25,"sameSizeStomp":true,"species":"synthfox","brutality":"0","victimsMacros":true,"victimsMicros":true,"oralVore":true,"analVore":true,"baseAnalVoreDiameter":0.1,"footSockEnabled":true,"footShoeEnabled":true,"arousalEnabled":true,"hasTail":true,"tailType":"floofy","tailStretchiness":1,"tailVoreToStomach":true,"dickStretchiness":1,"hasSheath":true,"femaleParts":true,"baseVaginaLength":0.12,"vaginaStretchiness":2,"femcumScaleWithSize":true,"breastStretchiness":1,"baseAssStenchArea":2,"baseScatStenchArea":1.5,"gasEnabled":true,"belchEnabled":true,"fartEnabled":true,"gasScaleWithSize":true,"soulVoreEnabled":true,"soulDigestTime":10,"soulVoreType":"release","pissEnabled":true,"scatEnabled":true,"scatScaleWithSize":true,"gooDigestion":true},
{"version":1,"name":"Dissy","scale":450,"baseHeight":3,"baseMass":55,"baseAssArea":5,"species":"stallion","footType":"hoof","brutality":"3","victimsHuman":true,"victimsMilitary":true,"victimsMacros":true,"victimsMicros":true,"oralVore":true,"oralDigestTime":0,"vomitEnabled":true,"analVore":true,"baseAnalVoreDiameter":1,"analDigestTime":0,"analVoreToStomach":true,"footSockEnabled":true,"footShoe":"sandal","arousalEnabled":true,"arousalFactor":2,"hasTail":true,"tailType":"floofy","baseTailDiameter":2,"tailMaw":true,"tailStretchiness":5,"tailVoreToStomach":true,"maleParts":true,"baseDickLength":4,"baseDickDiameter":2,"dickType":"horse","baseBallDiameter":7,"cumStorageScale":9,"dickStretchiness":1,"hasSheath":true,"vaginaStretchiness":1,"lactationEnabled":true,"breastVore":true,"breastStretchiness":1,"stenchEnabled":true,"basePawStenchArea":4,"baseAssStenchArea":4,"basePissStenchArea":4,"baseScatStenchArea":4,"gasEnabled":true,"belchEnabled":true,"fartEnabled":true,"baseGasDigestFactor":4,"soulVoreType":"release","pissEnabled":true,"scatEnabled":true,"baseScatDigestFactor":3,"scatStorageScale":5,"gooDigestion":true,"pawDigestTime":0},
{"version":1,"name":"Elijah","baseHeight":1.77,"baseMass":63,"baseAssArea":0.15,"sameSizeStomp":true,"species":"Blue Jay","footType":"avian","jawType":"beak","brutality":"3","victimsHuman":true,"oralVore":true,"analVore":true,"baseAnalVoreDiameter":0.08,"footWear":true,"footShoeEnabled":true,"footShoe":"sandal","arousalEnabled":true,"edgeFactor":3,"hasTail":true,"tailType":"Feathered","baseTailLength":0.8,"baseTailDiameter":0.2,"tailStretchiness":1,"tailVoreToStomach":true,"maleParts":true,"baseDickLength":0.18,"dickType":"Avian","dickStretchiness":1,"cockDigestTime":20,"cumScaleWithSize":true,"hasSheath":true,"vaginaStretchiness":1,"breastStretchiness":1,"baseAssStenchArea":2,"baseScatStenchArea":1.5,"belchEnabled":true,"soulVoreType":"release","gooDigestion":true,"cropEnabled":true,"cropTransferTime":30,"droolBaseVolume":0.0001},
{"version":1,"name":"Famis","scale":155,"baseHeight":1.52,"baseAssArea":0.25,"sameSizeStomp":true,"difficulty":"1","victimsHuman":true,"victimsMilitary":true,"victimsMacros":true,"victimsMicros":true,"oralVore":true,"oralDigestTime":30,"analVore":true,"baseAnalVoreDiameter":0.1,"analDigestTime":30,"analVoreToStomach":true,"footWear":true,"arousalEnabled":true,"hasTail":true,"tailType":"slinky","tailMaw":true,"tailStretchiness":50,"tailVoreToStomach":true,"maleParts":true,"dickStretchiness":15,"cockDigestTime":45,"cumScaleWithSize":true,"hasSheath":true,"maleMuskEnabled":true,"baseMaleMuskArea":5,"vaginaStretchiness":1,"breastStretchiness":1,"stenchEnabled":true,"basePawStenchArea":4,"baseAssStenchArea":0,"basePissStenchArea":0,"baseScatStenchArea":0,"soulVoreEnabled":true,"soulDigestTime":60,"gooEnabled":true,"gooDigestion":true,"gooDigestTime":20,"pawVoreEnabled":true,"pawDigestTime":45,"cropTransferTime":15,"droolEnabled":true,"droolBaseVolume":0.0001},
{"version":1,"name":"Jaredin","scale":2,"baseHeight":3.7,"baseMass":907,"baseAssArea":0.4,"species":"cybernetic armoured dragon","victimsMilitary":true,"victimsMacros":true,"victimsMicros":true,"oralVore":true,"analVore":true,"baseAnalVoreDiameter":0.1,"footShoe":"trainer","arousalEnabled":true,"hasTail":true,"tailType":"thick armour plated","baseTailLength":1.5,"baseTailDiameter":0.5,"tailStretchiness":1,"hasPouch":true,"maleParts":true,"baseDickLength":1,"baseDickDiameter":0.3,"dickType":"draconic","baseBallDiameter":0.08,"dickStretchiness":1,"hasSheath":true,"vaginaStretchiness":1,"lactationEnabled":true,"breastVore":true,"breastStretchiness":1,"baseAssStenchArea":1,"belchEnabled":true,"soulVoreEnabled":true},
{"version":1,"name":"Kanosint","baseHeight":1.48,"baseMass":54,"baseAssArea":0.5,"species":"rakshasa","victimsMilitary":true,"victimsMacros":true,"victimsMicros":true,"oralVore":true,"analVore":true,"baseAnalVoreDiameter":0.15,"analVoreToStomach":true,"footWear":true,"footSockEnabled":true,"arousalEnabled":true,"arousalFactor":0.8,"hasTail":true,"tailType":"serpentine","baseTailLength":1.5,"baseTailDiameter":0.4,"tailStretchiness":1,"maleParts":true,"baseDickLength":0.2,"dickType":"feline","baseBallDiameter":0.04,"dickStretchiness":0.8,"hasSheath":true,"vaginaStretchiness":1,"lactationEnabled":true,"breastStretchiness":1,"stenchEnabled":true,"basePawStenchArea":0.7,"baseAssStenchArea":0.5,"gasEnabled":true,"belchEnabled":true,"fartEnabled":true,"baseGasDigestFactor":1.2,"gasScaleWithSize":true,"soulVoreEnabled":true,"pissEnabled":true,"bladderVore":true,"baseUrethraDiameter":0.04,"urethraStretchiness":0.8,"scatEnabled":true,"gooEnabled":true},
{"version":1,"name":"Kassy","baseHeight":1.7,"baseMass":90,"baseAssArea":0.25,"sameSizeStomp":true,"species":"Ram","footType":"foot","brutality":"3","victimsMilitary":true,"victimsMacros":true,"victimsMicros":true,"oralVore":true,"oralDigestTime":25,"analVore":true,"baseAnalVoreDiameter":0.1,"analDigestTime":20,"footWear":true,"footShoeEnabled":true,"footShoe":"sandal","arousalEnabled":true,"hasTail":true,"tailType":"Wooly","baseTailLength":0.1,"tailStretchiness":1,"tailVoreToStomach":true,"maleParts":true,"dickType":"Human","dickStretchiness":1,"cumScaleWithSize":true,"maleMuskEnabled":true,"baseMaleMuskArea":0.1,"vaginaStretchiness":1,"breastStretchiness":1,"baseAssStenchArea":2,"baseScatStenchArea":1.5,"gasEnabled":true,"belchEnabled":true,"gasScaleWithSize":true,"soulVoreType":"release","gooDigestion":true,"cropTransferTime":15,"droolEnabled":true,"droolBaseVolume":0.00001},
{"version":1,"name":"Mekuto","baseHeight":1.778,"baseMass":66,"baseAssArea":0.25,"species":"wahsune","oralVore":true,"analVore":true,"baseAnalVoreDiameter":0.1,"analVoreToStomach":true,"arousalEnabled":true,"hasTail":true,"tailCount":5,"tailType":"ravenous","baseTailLength":1.9,"baseTailDiameter":0.15,"tailMaw":true,"maleParts":true,"baseDickLength":0.15,"baseDickDiameter":0.05,"baseBallDiameter":0.03,"dickStretchiness":3,"hasSheath":true,"vaginaStretchiness":1,"lactationEnabled":true,"breastVore":true,"breastStretchiness":1},
{"version":1,"name":"Noma","baseHeight":8,"baseMass":4800,"baseAssArea":2,"sameSizeStomp":true,"species":"Lynxcoon","victimsMilitary":true,"victimsMacros":true,"victimsMicros":true,"oralVore":true,"baseAnalVoreDiameter":0.1,"footWear":true,"footSockEnabled":true,"footShoeEnabled":true,"footShoe":"boot","hasTail":true,"tailType":"fluffy coon ","baseTailLength":8,"baseTailDiameter":2,"tailMaw":true,"tailStretchiness":2,"tailVoreToStomach":true,"maleParts":true,"baseDickLength":2,"baseDickDiameter":0.5,"dickType":"feline","baseBallDiameter":2,"cumStorageScale":2,"dickStretchiness":1,"baseCumDigestFactor":2,"cumScaleWithSize":true,"hasSheath":true,"vaginaStretchiness":1,"lactationEnabled":true,"breastVore":true,"breastStretchiness":1,"baseAssStenchArea":1,"baseScatStenchArea":1.5,"gasEnabled":true,"belchEnabled":true,"gasStorageScale":2,"gasScaleWithSize":true,"soulVoreEnabled":true,"gooEnabled":true,"gooDigestion":true,"pawVoreEnabled":true},
{"version":1,"name":"Ona","baseMass":125,"baseAssArea":0.45,"sameSizeStomp":true,"species":"Raven","footType":"avian","jawType":"beak","brutality":"2","victimsMilitary":true,"victimsMacros":true,"oralVore":true,"analVore":true,"baseAnalVoreDiameter":0.1,"footWear":true,"footShoeEnabled":true,"footShoe":"sandal","arousalEnabled":true,"tailType":"slinky","tailStretchiness":1,"dickStretchiness":1,"hasSheath":true,"femaleParts":true,"baseVaginaLength":0.2,"baseVaginaWidth":0.1,"vaginaStretchiness":2,"hasBreasts":true,"lactationEnabled":true,"breastVore":true,"breastStretchiness":1,"baseAssStenchArea":1,"belchEnabled":true,"soulVoreEnabled":true,"soulVoreType":"oblivion"},
{"version":1,"name":"Rain Fallen","scale":54.22,"baseAssArea":0.4,"sameSizeStomp":true,"species":"Wolf Demon","brutality":"3","victimsMilitary":true,"victimsMacros":true,"victimsMicros":true,"oralVore":true,"analVore":true,"baseAnalVoreDiameter":0.1,"footSockEnabled":true,"footShoeEnabled":true,"arousalEnabled":true,"hasTail":true,"tailType":"Wolf","baseTailLength":1.8,"tailMaw":true,"tailStretchiness":1,"maleParts":true,"baseDickLength":0.4,"baseDickDiameter":0.09,"baseBallDiameter":0.12,"dickStretchiness":1,"cumScaleWithSize":true,"hasSheath":true,"vaginaStretchiness":1,"lactationEnabled":true,"breastStretchiness":1,"stenchEnabled":true,"baseAssStenchArea":1,"gasEnabled":true,"belchEnabled":true,"fartEnabled":true,"gasScaleWithSize":true,"soulVoreEnabled":true},
{"version":1,"name":"Ralerin","baseHeight":2.2,"baseMass":140,"baseAssArea":0.4,"species":"pangolin","victimsMilitary":true,"victimsMacros":true,"oralVore":true,"analVore":true,"baseAnalVoreDiameter":0.1,"footWear":true,"footShoeEnabled":true,"footShoe":"sandal","arousalEnabled":true,"hasTail":true,"tailType":"Scaled","baseTailLength":1.66,"baseTailDiameter":0.33,"tailStretchiness":1,"maleParts":true,"baseDickLength":0.4,"baseDickDiameter":0.12,"dickType":"pangolin","baseBallDiameter":0.09,"dickStretchiness":1.1,"hasSheath":true,"vaginaStretchiness":1,"lactationEnabled":true,"breastVore":true,"breastStretchiness":1,"baseAssStenchArea":1,"belchEnabled":true,"soulVoreEnabled":true,"soulVoreType":"release","bladderVore":true},
{"version":1,"name":"Vulpes","baseHeight":2,"baseMass":73,"species":"fox","brutality":"2","victimsMacros":true,"oralVore":true,"analVore":true,"baseAnalVoreDiameter":0.1,"analVoreToStomach":true,"arousalEnabled":true,"hasTail":true,"baseTailLength":1.3,"tailStretchiness":1,"maleParts":true,"baseDickLength":0.25,"baseDickDiameter":0.1,"dickType":"sheathed","baseBallDiameter":0.04,"dickStretchiness":2,"hasSheath":true,"vaginaStretchiness":1,"lactationEnabled":true,"breastVore":true,"breastStretchiness":1,"soulVoreEnabled":true}
{
"version": 3,
"name": "Fen",
"priority": 1,
"brutality": "2",
"oralVore": true,
"analVore": true,
"analVoreToStomach": true,
"hasTail": true,
"tailType": "twisted",
"baseTailLength": 2,
"baseTailDiameter": 0.4
},
{
"version": 3,
"name": "Arokha",
"scale": 10,
"baseHeight": 1.67,
"baseMass": 50,
"baseAssArea": 0.25,
"species": "kitsune",
"victimsMicros": true,
"oralVore": true,
"oralDigestTime": 5,
"analVore": true,
"baseAnalVoreDiameter": 0.1,
"analDigestTime": 5,
"analVoreToStomach": true,
"footSockEnabled": true,
"footShoeEnabled": true,
"arousalEnabled": true,
"hasTail": true,
"tailCount": 2,
"tailMaw": true,
"tailStretchiness": 1,
"tailDigestTime": 5,
"tailVoreToStomach": true,
"dickStretchiness": 1,
"hasSheath": true,
"femaleParts": true,
"baseVaginaLength": 0.12,
"vaginaStretchiness": 2,
"femcumScaleWithSize": true,
"hasBreasts": true,
"lactationEnabled": true,
"breastStretchiness": 1,
"baseAssStenchArea": 2,
"baseScatStenchArea": 1.5,
"gasEnabled": true,
"belchEnabled": true,
"fartEnabled": true,
"gasScaleWithSize": true,
"soulVoreEnabled": true,
"soulDigestTime": 5,
"pissEnabled": true,
"scatEnabled": true,
"scatScaleWithSize": true,
"gooDigestion": true
},
{
"version": 3,
"name": "Aronai",
"scale": 10,
"baseHeight": 1.8,
"baseMass": 86,
"baseAssArea": 0.25,
"sameSizeStomp": true,
"species": "synthfox",
"brutality": "0",
"victimsMacros": true,
"victimsMicros": true,
"oralVore": true,
"analVore": true,
"baseAnalVoreDiameter": 0.1,
"footSockEnabled": true,
"footShoeEnabled": true,
"arousalEnabled": true,
"hasTail": true,
"tailType": "floofy",
"tailStretchiness": 1,
"tailVoreToStomach": true,
"dickStretchiness": 1,
"hasSheath": true,
"femaleParts": true,
"baseVaginaLength": 0.12,
"vaginaStretchiness": 2,
"femcumScaleWithSize": true,
"breastStretchiness": 1,
"baseAssStenchArea": 2,
"baseScatStenchArea": 1.5,
"gasEnabled": true,
"belchEnabled": true,
"fartEnabled": true,
"gasScaleWithSize": true,
"soulVoreEnabled": true,
"soulDigestTime": 10,
"soulVoreType": "release",
"pissEnabled": true,
"scatEnabled": true,
"scatScaleWithSize": true,
"gooDigestion": true
},
{
"version": 3,
"name": "Dissy",
"scale": 450,
"baseHeight": 3,
"baseMass": 55,
"baseAssArea": 5,
"species": "stallion",
"footType": "hoof",
"brutality": "3",
"victimsHuman": true,
"victimsMilitary": true,
"victimsMacros": true,
"victimsMicros": true,
"oralVore": true,
"oralDigestTime": 0,
"vomitEnabled": true,
"analVore": true,
"baseAnalVoreDiameter": 1,
"analDigestTime": 0,
"analVoreToStomach": true,
"footSockEnabled": true,
"footShoe": "sandal",
"arousalEnabled": true,
"arousalFactor": 2,
"hasTail": true,
"tailType": "floofy",
"baseTailDiameter": 2,
"tailMaw": true,
"tailStretchiness": 5,
"tailVoreToStomach": true,
"maleParts": true,
"baseDickLength": 4,
"baseDickDiameter": 2,
"dickType": "horse",
"baseBallDiameter": 7,
"cumStorageScale": 9,
"dickStretchiness": 1,
"hasSheath": true,
"vaginaStretchiness": 1,
"lactationEnabled": true,
"breastVore": true,
"breastStretchiness": 1,
"stenchEnabled": true,
"basePawStenchArea": 4,
"baseAssStenchArea": 4,
"basePissStenchArea": 4,
"baseScatStenchArea": 4,
"gasEnabled": true,
"belchEnabled": true,
"fartEnabled": true,
"baseGasDigestFactor": 4,
"soulVoreType": "release",
"pissEnabled": true,
"scatEnabled": true,
"baseScatDigestFactor": 3,
"scatStorageScale": 5,
"gooDigestion": true,
"pawDigestTime": 0,
"oralDigestAuto": false,
"analDigestAuto": false,
"pawDigestAuto": false
},
{
"version": 3,
"name": "Elijah",
"baseHeight": 1.77,
"baseMass": 63,
"baseAssArea": 0.15,
"sameSizeStomp": true,
"species": "Blue Jay",
"footType": "avian",
"jawType": "beak",
"brutality": "3",
"victimsHuman": true,
"oralVore": true,
"analVore": true,
"baseAnalVoreDiameter": 0.08,
"footWear": true,
"footShoeEnabled": true,
"footShoe": "sandal",
"arousalEnabled": true,
"edgeFactor": 3,
"hasTail": true,
"tailType": "Feathered",
"baseTailLength": 0.8,
"baseTailDiameter": 0.2,
"tailStretchiness": 1,
"tailVoreToStomach": true,
"maleParts": true,
"baseDickLength": 0.18,
"dickType": "Avian",
"dickStretchiness": 1,
"cockDigestTime": 20,
"cumScaleWithSize": true,
"hasSheath": true,
"vaginaStretchiness": 1,
"breastStretchiness": 1,
"baseAssStenchArea": 2,
"baseScatStenchArea": 1.5,
"belchEnabled": true,
"soulVoreType": "release",
"gooDigestion": true,
"cropEnabled": true,
"cropTransferTime": 30,
"droolBaseVolume": 0.0001
},
{
"version": 3,
"name": "Famis",
"scale": 155,
"baseHeight": 1.52,
"baseAssArea": 0.25,
"sameSizeStomp": true,
"difficulty": "1",
"victimsHuman": true,
"victimsMilitary": true,
"victimsMacros": true,
"victimsMicros": true,
"oralVore": true,
"oralDigestTime": 30,
"analVore": true,
"baseAnalVoreDiameter": 0.1,
"analDigestTime": 30,
"analVoreToStomach": true,
"footWear": true,
"arousalEnabled": true,
"hasTail": true,
"tailType": "slinky",
"tailMaw": true,
"tailStretchiness": 50,
"tailVoreToStomach": true,
"maleParts": true,
"dickStretchiness": 15,
"cockDigestTime": 45,
"cumScaleWithSize": true,
"hasSheath": true,
"maleMuskEnabled": true,
"baseMaleMuskArea": 5,
"vaginaStretchiness": 1,
"breastStretchiness": 1,
"stenchEnabled": true,
"basePawStenchArea": 4,
"baseAssStenchArea": 0,
"basePissStenchArea": 0,
"baseScatStenchArea": 0,
"soulVoreEnabled": true,
"soulDigestTime": 60,
"gooEnabled": true,
"gooDigestion": true,
"gooDigestTime": 20,
"pawVoreEnabled": true,
"pawDigestTime": 45,
"cropTransferTime": 15,
"droolEnabled": true,
"droolBaseVolume": 0.0001
},
{
"version": 3,
"name": "Goathias",
"scale": 3,
"species": "Goat",
"footType": "hoof",
"difficulty": "1",
"brutality": "3",
"victimsHuman": true,
"victimsMilitary": true,
"oralVore": true,
"vomitEnabled": true,
"analVore": true,
"arousalEnabled": true,
"maleParts": true,
"cockVoreEnabled": true,
"cumScaleWithSize": true,
"maleMuskEnabled": true,
"hasBreasts": true,
"lactationEnabled": true,
"breastVore": true,
"milkScaleWithSize": true,
"stenchEnabled": true,
"gasEnabled": true,
"belchEnabled": true,
"fartEnabled": true,
"gasScaleWithSize": true,
"pissEnabled": true,
"bladderVore": true,
"pissScaleWithSize": true,
"scatEnabled": true,
"scatScaleWithSize": true,
"breathEnabled": true,
"breathFoul": true,
"droolEnabled": true,
"magicEnabled": true
},
{
"version": 3,
"name": "Jaredin",
"scale": 2,
"baseHeight": 3.7,
"baseMass": 907,
"baseAssArea": 0.4,
"species": "cybernetic armoured dragon",
"victimsMilitary": true,
"victimsMacros": true,
"victimsMicros": true,
"oralVore": true,
"analVore": true,
"baseAnalVoreDiameter": 0.1,
"footShoe": "trainer",
"arousalEnabled": true,
"hasTail": true,
"tailType": "thick armour plated",
"baseTailLength": 1.5,
"baseTailDiameter": 0.5,
"tailStretchiness": 1,
"hasPouch": true,
"maleParts": true,
"baseDickLength": 1,
"baseDickDiameter": 0.3,
"dickType": "draconic",
"baseBallDiameter": 0.08,
"dickStretchiness": 1,
"hasSheath": true,
"vaginaStretchiness": 1,
"lactationEnabled": true,
"breastVore": true,
"breastStretchiness": 1,
"baseAssStenchArea": 1,
"belchEnabled": true,
"soulVoreEnabled": true
},
{
"version": 3,
"name": "Kanosint",
"baseHeight": 1.48,
"baseMass": 54,
"baseAssArea": 0.5,
"species": "rakshasa",
"victimsMilitary": true,
"victimsMacros": true,
"victimsMicros": true,
"oralVore": true,
"analVore": true,
"baseAnalVoreDiameter": 0.15,
"analVoreToStomach": true,
"footWear": true,
"footSockEnabled": true,
"arousalEnabled": true,
"arousalFactor": 0.8,
"hasTail": true,
"tailType": "serpentine",
"baseTailLength": 1.5,
"baseTailDiameter": 0.4,
"tailStretchiness": 1,
"maleParts": true,
"baseDickLength": 0.2,
"dickType": "feline",
"baseBallDiameter": 0.04,
"dickStretchiness": 0.8,
"hasSheath": true,
"vaginaStretchiness": 1,
"lactationEnabled": true,
"breastStretchiness": 1,
"stenchEnabled": true,
"basePawStenchArea": 0.7,
"baseAssStenchArea": 0.5,
"gasEnabled": true,
"belchEnabled": true,
"fartEnabled": true,
"baseGasDigestFactor": 1.2,
"gasScaleWithSize": true,
"soulVoreEnabled": true,
"pissEnabled": true,
"bladderVore": true,
"baseUrethraDiameter": 0.04,
"urethraStretchiness": 0.8,
"scatEnabled": true,
"gooEnabled": true
},
{
"version": 3,
"name": "Kassy",
"baseHeight": 1.7,
"baseMass": 90,
"baseAssArea": 0.25,
"sameSizeStomp": true,
"species": "Ram",
"footType": "foot",
"brutality": "3",
"victimsMilitary": true,
"victimsMacros": true,
"victimsMicros": true,
"oralVore": true,
"oralDigestTime": 25,
"analVore": true,
"baseAnalVoreDiameter": 0.1,
"analDigestTime": 20,
"footWear": true,
"footShoeEnabled": true,
"footShoe": "sandal",
"arousalEnabled": true,
"hasTail": true,
"tailType": "Wooly",
"baseTailLength": 0.1,
"tailStretchiness": 1,
"tailVoreToStomach": true,
"maleParts": true,
"dickType": "Human",
"dickStretchiness": 1,
"cumScaleWithSize": true,
"maleMuskEnabled": true,
"baseMaleMuskArea": 0.1,
"vaginaStretchiness": 1,
"breastStretchiness": 1,
"baseAssStenchArea": 2,
"baseScatStenchArea": 1.5,
"gasEnabled": true,
"belchEnabled": true,
"gasScaleWithSize": true,
"soulVoreType": "release",
"gooDigestion": true,
"cropTransferTime": 15,
"droolEnabled": true,
"droolBaseVolume": 0.00001
},
{
"version": 3,
"name": "Mech",
"baseHeight": 3.7,
"baseMass": 500,
"basePawLength": 0.8,
"basePawWidth": 0.5,
"baseHandLength": 0.4,
"baseHandWidth": 0.2,
"baseAssArea": 1,
"species": "Dragon",
"brutality": "2",
"victimsHuman": true,
"victimsMilitary": true,
"victimsMacros": true,
"oralVore": true,
"oralDigestTime": 5,
"analVore": true,
"baseAnalVoreDiameter": 0.4,
"analVoreToStomach": true,
"arousalEnabled": true,
"hasTail": true,
"tailType": "meaty",
"baseTailLength": 2.5,
"baseTailDiameter": 0.6,
"maleParts": true,
"baseDickLength": 0.9,
"baseDickDiameter": 0.2,
"dickType": "hefty",
"baseBallDiameter": 0.19,
"baseCumVolume": 2,
"cockVoreEnabled": true,
"cockDigestTime": 5,
"baseScatDigestFactor": 0.3,
"scatStorageScale": 1.5,
"scatScaleWithSize": true,
"magicEnabled": true
},
{
"version": 3,
"name": "Mekuto",
"baseHeight": 1.778,
"baseMass": 66,
"baseAssArea": 0.25,
"species": "wahsune",
"oralVore": true,
"analVore": true,
"baseAnalVoreDiameter": 0.1,
"analVoreToStomach": true,
"arousalEnabled": true,
"hasTail": true,
"tailCount": 5,
"tailType": "ravenous",
"baseTailLength": 1.9,
"baseTailDiameter": 0.15,
"tailMaw": true,
"maleParts": true,
"baseDickLength": 0.15,
"baseDickDiameter": 0.05,
"baseBallDiameter": 0.03,
"dickStretchiness": 3,
"hasSheath": true,
"vaginaStretchiness": 1,
"lactationEnabled": true,
"breastVore": true,
"breastStretchiness": 1
},
{
"version": 3,
"name": "Noma",
"baseHeight": 8,
"baseMass": 4800,
"baseAssArea": 2,
"sameSizeStomp": true,
"species": "Lynxcoon",
"victimsMilitary": true,
"victimsMacros": true,
"victimsMicros": true,
"oralVore": true,
"baseAnalVoreDiameter": 0.1,
"footWear": true,
"footSockEnabled": true,
"footShoeEnabled": true,
"footShoe": "boot",
"hasTail": true,
"tailType": "fluffy coon ",
"baseTailLength": 8,
"baseTailDiameter": 2,
"tailMaw": true,
"tailStretchiness": 2,
"tailVoreToStomach": true,
"maleParts": true,
"baseDickLength": 2,
"baseDickDiameter": 0.5,
"dickType": "feline",
"baseBallDiameter": 2,
"cumStorageScale": 2,
"dickStretchiness": 1,
"baseCumDigestFactor": 2,
"cumScaleWithSize": true,
"hasSheath": true,
"vaginaStretchiness": 1,
"lactationEnabled": true,
"breastVore": true,
"breastStretchiness": 1,
"baseAssStenchArea": 1,
"baseScatStenchArea": 1.5,
"gasEnabled": true,
"belchEnabled": true,
"gasStorageScale": 2,
"gasScaleWithSize": true,
"soulVoreEnabled": true,
"gooEnabled": true,
"gooDigestion": true,
"pawVoreEnabled": true
},
{
"version": 3,
"name": "Ona",
"baseMass": 125,
"baseAssArea": 0.45,
"sameSizeStomp": true,
"species": "Raven",
"footType": "avian",
"jawType": "beak",
"brutality": "2",
"victimsMilitary": true,
"victimsMacros": true,
"oralVore": true,
"analVore": true,
"baseAnalVoreDiameter": 0.1,
"footWear": true,
"footShoeEnabled": true,
"footShoe": "sandal",
"arousalEnabled": true,
"tailType": "slinky",
"tailStretchiness": 1,
"dickStretchiness": 1,
"hasSheath": true,
"femaleParts": true,
"baseVaginaLength": 0.2,
"baseVaginaWidth": 0.1,
"vaginaStretchiness": 2,
"hasBreasts": true,
"lactationEnabled": true,
"breastVore": true,
"breastStretchiness": 1,
"baseAssStenchArea": 1,
"belchEnabled": true,
"soulVoreEnabled": true,
"soulVoreType": "oblivion"
},
{
"version": 3,
"name": "Rain Fallen",
"scale": 54.22,
"baseAssArea": 0.4,
"sameSizeStomp": true,
"species": "Wolf Demon",
"brutality": "3",
"victimsMilitary": true,
"victimsMacros": true,
"victimsMicros": true,
"oralVore": true,
"analVore": true,
"baseAnalVoreDiameter": 0.1,
"footSockEnabled": true,
"footShoeEnabled": true,
"arousalEnabled": true,
"hasTail": true,
"tailType": "Wolf",
"baseTailLength": 1.8,
"tailMaw": true,
"tailStretchiness": 1,
"maleParts": true,
"baseDickLength": 0.4,
"baseDickDiameter": 0.09,
"baseBallDiameter": 0.12,
"dickStretchiness": 1,
"cumScaleWithSize": true,
"hasSheath": true,
"vaginaStretchiness": 1,
"lactationEnabled": true,
"breastStretchiness": 1,
"stenchEnabled": true,
"baseAssStenchArea": 1,
"gasEnabled": true,
"belchEnabled": true,
"fartEnabled": true,
"gasScaleWithSize": true,
"soulVoreEnabled": true
},
{
"version": 3,
"name": "Ralerin",
"baseHeight": 2.2,
"baseMass": 140,
"baseAssArea": 0.4,
"species": "pangolin",
"victimsMilitary": true,
"victimsMacros": true,
"oralVore": true,
"analVore": true,
"baseAnalVoreDiameter": 0.1,
"footWear": true,
"footShoeEnabled": true,
"footShoe": "sandal",
"arousalEnabled": true,
"hasTail": true,
"tailType": "Scaled",
"baseTailLength": 1.66,
"baseTailDiameter": 0.33,
"tailStretchiness": 1,
"maleParts": true,
"baseDickLength": 0.4,
"baseDickDiameter": 0.12,
"dickType": "pangolin",
"baseBallDiameter": 0.09,
"dickStretchiness": 1.1,
"hasSheath": true,
"vaginaStretchiness": 1,
"lactationEnabled": true,
"breastVore": true,
"breastStretchiness": 1,
"baseAssStenchArea": 1,
"belchEnabled": true,
"soulVoreEnabled": true,
"soulVoreType": "release",
"bladderVore": true
},
{
"version": 3,
"name": "Vulpes",
"baseHeight": 2,
"baseMass": 73,
"species": "fox",
"brutality": "2",
"victimsMacros": true,
"oralVore": true,
"analVore": true,
"baseAnalVoreDiameter": 0.1,
"analVoreToStomach": true,
"arousalEnabled": true,
"hasTail": true,
"baseTailLength": 1.3,
"tailStretchiness": 1,
"maleParts": true,
"baseDickLength": 0.25,
"baseDickDiameter": 0.1,
"dickType": "sheathed",
"baseBallDiameter": 0.04,
"dickStretchiness": 2,
"hasSheath": true,
"vaginaStretchiness": 1,
"lactationEnabled": true,
"breastVore": true,
"breastStretchiness": 1,
"soulVoreEnabled": true
},
{
"version": 3,
"name": "Cinnamon",
"baseHeight": 1.25,
"baseMass": 100,
"baseAssArea": 1,
"species": "Dragon",
"automaticGrowth": true,
"automaticGrowthEnabled": true,
"basePreyGrowthFactor": 1,
"growthScaleWithSize": true,
"biomes": true,
"changingBiomes": true,
"defaultBiome": "Downtown",
"ruralEnabled": false,
"brutality": "3",
"oralVore": true,
"arousalEnabled": true,
"maleParts": true,
"baseDickLength": 1.25,
"baseDickDiameter": 0.3,
"dickType": "equine",
"baseBallDiameter": 0.3,
"baseCumVolume": 1892.71,
"cockGrowthFactor": 1,
"ballGrowthFactor": 1,
"cockVoreEnabled": true,
"dickStretchiness": 25,
"cumScaleWithSize": true,
"maleMuskEnabled": true,
"baseMaleMuskArea": 1,
"droolEnabled": true
},
{
"version": 3,
"name": "Rai",
"scale": 1.65,
"baseMass": 33,
"basePawLength": 0.19,
"basePawWidth": 0.19,
"baseHandLength": 0.2,
"baseHandWidth": 0.2,
"baseAssArea": 1,
"species": "Wolf",
"victimsHuman": true,
"victimsMilitary": true,
"victimsMicros": true,
"oralVore": true,
"analVoreToStomach": true,
"hasTail": true,
"tailType": "Fluffy",
"hasBreasts": true,
"baseBreastDiameter": 0.12,
"soulVoreEnabled": true,
"soulVoreType": "oblivion",
"breathEnabled": true,
"breathElectric": true,
"droolEnabled": true,
"magicEnabled": true
}
]

+ 280
- 38
recursive-desc.js Visa fil

@@ -5,10 +5,25 @@
var rules = {};
var defaults = {};

const synonyms = {
heavy: ["heavy", "weighty"],
huge: ["huge", "massive", "gigantic", "large"],
cosmic: ["cosmic", "utterly colossal", "star-spanning"],
gulp: ["gulp", "gluk", "glrk", "glp"],
swallow: ["swallow", "gulp"],
looming: ["looming", "imposing", "awe-inspiring", "menacing"],
putrid: ["putrid", "foul", "wretched", "choking", "rancid", "utterly foul", "miasma-shrouded", "eye-wateringly foul"],
moan: ["moan", "gasp", "growl"]
}

function plural(quantity, singular, plural) {
return quantity > 1 ? plural : singular;
}

function capitalize(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}

function getDefault(name) {
let tokens = name.split("-");
for (let i=0; i<tokens.length; i++) {
@@ -31,9 +46,9 @@ function getDefaultVictim(name) {
return window[funcName];
}

var action_keys = ["eat","chew","vomit","stomp","stomp-wedge","flex-toes","kick","anal-vore","ass-crush","ass-grind","tail-slap","tail-vore","tails-vore","cleavage-stuff","cleavage-crush","cleavage-drop","cleavage-absorb","breast-crush","breast-vore","breast-milk","unbirth","sheath-stuff","sheath-clench","sheath-crush","sheath-absorb","foreskin-stuff","foreskin-clench","foreskin-crush","foreskin-absorb","cock-vore","cockslap","ball-smother","male-spurt","male-orgasm","female-spurt","female-orgasm","grind","pouch-stuff","pouch-rub","pouch-eat","pouch-absorb","soul-vore","soul-absorb-paw","paw-stench","ass-stench","piss-stench","scat-stench","male-orgasm-musk","female-orgasm-musk","male-spurt-musk","female-spurt-musk","belch","fart","stomach","tail","tail-to-stomach","womb","balls","bowels","bowels-to-stomach","breasts","bladder","soul-digest","wings","wings-to-stomach","wear-shoe","remove-shoe","wear-sock","remove-sock","stuff-shoe","dump-shoe","stuff-sock","dump-sock","piss","bladder-vore","scat","sheath-toy","foreskin-toy","slit-toy","breast-toy","melt","solidify","flood","stomp-goo","goo-digest","ass-goo","goo-stomach-pull","goo-stomach-push","goo-bowels-pull","goo-bowels-push","goo-womb-pull","goo-womb-push","goo-balls-pull","goo-balls-push","goo-breasts-pull","goo-breasts-push","goo-tail-pull","goo-tail-push","goo-paws-pull","goo-paws-push","paw-vore","paw-vore-toes","paws","crop-swallow","crop-transfer","breath-fire","breath-ice","breath-electric","breath-smoke","breath-radiation","breath-foul","drool","magic-shrink","magic-hypnotize","wings-flap","wings-vore"];
var action_keys = ["eat","chew","vomit","stomp","stomp-wedge","flex-toes","kick","anal-vore","ass-crush","ass-grind","tail-slap","tail-vore","tails-vore","cleavage-stuff","cleavage-crush","cleavage-drop","cleavage-absorb","breast-crush","breast-vore","breast-milk","unbirth","sheath-stuff","sheath-clench","sheath-crush","sheath-absorb","foreskin-stuff","foreskin-clench","foreskin-crush","foreskin-absorb","cock-vore","cockslap","ball-smother","male-spurt","male-orgasm","female-spurt","female-orgasm","grind","pouch-stuff","pouch-rub","pouch-eat","pouch-absorb","soul-vore","soul-absorb-paw","paw-stench","ass-stench","piss-stench","scat-stench","male-musk","female-musk","male-orgasm-musk","female-orgasm-musk","male-spurt-musk","female-spurt-musk","belch","fart","stomach","tail","tail-to-stomach","womb","balls","bowels","bowels-to-stomach","breasts","bladder","soul-digest","wings","wings-to-stomach","wear-shoe","remove-shoe","wear-sock","remove-sock","stuff-shoe","dump-shoe","stuff-sock","dump-sock","piss","bladder-vore","scat","sheath-toy","foreskin-toy","slit-toy","breast-toy","melt","solidify","flood","stomp-goo","goo-digest","ass-goo","goo-stomach-pull","goo-stomach-push","goo-bowels-pull","goo-bowels-push","goo-womb-pull","goo-womb-push","goo-balls-pull","goo-balls-push","goo-breasts-pull","goo-breasts-push","goo-tail-pull","goo-tail-push","goo-paws-pull","goo-paws-push","paw-vore","paw-vore-toes","paws","crop-swallow","crop-transfer","breath-fire","breath-ice","breath-electric","breath-smoke","breath-radiation","breath-foul","drool","magic-shrink","magic-hypnotize","wings-flap","wings-vore"];

var victim_keys = ["victim-cum-flood", "victim-femcum-flood", "victim-stomped", "victim-flex-toes", "victim-eaten", "victim-ass-crush", "victim-ass-ground", "victim-humped", "victim-vomit", "victim-chew", "victim-drool", "victim-anal-vore", "victim-tail-slap", "victim-tail-vore", "victim-cock-slap", "victim-cock-vore", "victim-ball-smother", "victim-sheath-crush", "victim-sheath-absorb", "victim-foreskin-crush", "victim-foreskin-absorb", "victim-cum-flood", "victim-male-spurt-musk", "victim-male-orgasm-musk", "victim-unbirth", "victim-femcum-flood", "victim-female-spurt-musk", "victim-female-orgasm-musk", "victim-breast-crush", "victim-cleavage-crush", "victim-cleavage-absorb", "victim-cleavage-drop", "victim-milk-flood", "victim-breast-vore", "victim-pouch-absorb", "victim-soul-digest", "victim-soul-paw", "victim-paw-stench", "victim-ass-stench", "victim-gas-belch", "victim-gas-fart", "victim-piss", "victim-bladder-vore", "victim-piss-stench", "victim-scat", "victim-scat-stench", "victim-goo", "victim-paw-vore", "victim-breath-fire", "victim-breath-ice", "victim-breath-electric", "victim-breath-smoke", "victim-breath-radiation", "victim-breath-foul", "victim-wings-flap", "victim-wings-vore"]
var victim_keys = ["victim-cum-flood", "victim-femcum-flood", "victim-stomped", "victim-flex-toes", "victim-eaten", "victim-ass-crush", "victim-ass-ground", "victim-humped", "victim-vomit", "victim-chew", "victim-drool", "victim-anal-vore", "victim-tail-slap", "victim-tail-vore", "victim-cock-slap", "victim-cock-vore", "victim-ball-smother", "victim-sheath-crush", "victim-sheath-absorb", "victim-foreskin-crush", "victim-foreskin-absorb", "victim-cum-flood", "victim-male-musk", "victim-male-spurt-musk", "victim-male-orgasm-musk", "victim-unbirth", "victim-femcum-flood", "victim-female-musk", "victim-female-spurt-musk", "victim-female-orgasm-musk", "victim-breast-crush", "victim-cleavage-crush", "victim-cleavage-absorb", "victim-cleavage-drop", "victim-milk-flood", "victim-breast-vore", "victim-pouch-absorb", "victim-soul-digest", "victim-soul-paw", "victim-paw-stench", "victim-ass-stench", "victim-gas-belch", "victim-gas-fart", "victim-piss", "victim-bladder-vore", "victim-piss-stench", "victim-scat", "victim-scat-stench", "victim-goo", "victim-paw-vore", "victim-breath-fire", "victim-breath-ice", "victim-breath-electric", "victim-breath-smoke", "victim-breath-radiation", "victim-breath-foul", "victim-wings-flap", "victim-wings-vore"]

for (let i=0; i<action_keys.length; i++) {
rules[action_keys[i]] = [];
@@ -130,12 +145,12 @@ function describe(action, container, macro, verbose=true, flat=false, extra1=0)
container = flatten(container);
}

if (options.length > 0 && Math.random() > (1 / (2 + rules[action].length))) {
if (options.length > 0 && Math.random() > (1 / (2 + options.length))) {
let choice = Math.floor(Math.random() * options.length);
return options[choice](container, macro, extra1);
return options[choice](container, macro, verbose, flat, extra1);
}
else {
return getDefault(action)(container, macro, extra1);
return getDefault(action)(container, macro, verbose, flat, extra1);
}
}

@@ -148,13 +163,37 @@ function pickString(...array){
var pick = strings[~~(Math.random() * strings.length)];
return pick;
}

function pickStringChance(chance, ...array) {
if (Math.random() < chance) {
return pickString(...array);
} else {
return ""
}
}

// DEFAULTS

function defaultEat(container, macro, verbose, flat) {
console.log(verbose);
if (container.count == 0)
return "You reach down for a delicious treat and grab - oh, nothing.";
else
return "You scoop up " + container.describe(verbose) + " and swallow " + (container.count > 1 ? "them" : "it") + " whole.";
return pickString([
"You",
pickString("snatch up", "grab", "pluck up", "seize", "catch"),
container.describe(verbose) + ",",
"then",
pickString("swallow", "devour", "consume"),
(container.count > 1 ? "them" : "it"),
"whole."
], [
"Your maw envelops",
container.describe(verbose),
"in a tight embrace of flesh.",
(container.count > 1 ? "They sink" : "Your victim sinks"),
"down deep with a little <i>gulp</i>."
]).join(" ");
}

function defaultChew(container, macro, verbose, flat) {
@@ -190,21 +229,43 @@ function defaultStomp(container, macro, verbose, flat) {
else if (isSadistic(macro))
return "Your " + macro.footDesc(false) + " comes down on " + container.describe(verbose) + ", crushing your prey into gore and rubble with ease as your " + macro.toeDesc(true) + " shear bone and snap metal.";
else if (isFatal(macro))
return "You crush " + container.describe(verbose) + " under" + macro.footDesc(false,false,true) + ".";
return pickString([
"You",
pickString("crush", "smash", "flatten"),
container.describe(verbose),
pickString("under", "beneath", "with"),
"your",
(macro.stenchEnabled ? pickString(...synonyms.putrid) + "," : ""),
pickStringChance(0.4, ...synonyms.looming),
macro.footDesc(false,false,true) + "."
], [
capitalize(container.describe(verbose)),
(container.count > 1 ? "are" : "is"),
pickString("crushed", "flattened"),
pickString("under", "beneath"),
"your",
(macro.stenchEnabled ? pickString(...synonyms.putrid) : pickString("heavy", "weighty", "powerful")),
macro.footDesc(false,false,true) + "."
], [
"A swift stroke of your",
macro.footDesc(false,false,true),
pickString("crushes", "smashes", "flattens"),
container.describe(verbose)
]).filter(Boolean).join(" ");
else
return "You step on " + container.describe(verbose) + ".";
}

function defaultStompWedge(container, macro, verbose, flat) {
if (container.count == 1) {
let line = container.describe(verbose);
line = line.charAt(0).toUpperCase() + line.slice(1);
return line + " is wedged in your " + macro.toeDesc(true);
} else {
let line = container.describe(verbose);
line = line.charAt(0).toUpperCase() + line.slice(1);
return line + " are wedged in your " + macro.toeDesc(true);
}
return [
capitalize(container.describe(verbose)),
(container.count > 1 ? "are" : "is"),
pickString("wedged", "trapped", "left stuck", "jammed"),
pickString("in", "between", "within"),
"your",
(macro.stenchEnabled ? pickString(...synonyms.putrid) : ""),
macro.toeDesc(true)
].filter(Boolean).join(" ")
}

function defaultFlexToes(container, macro, verbose, flat) {
@@ -242,7 +303,20 @@ function defaultAnalVore(container, macro, verbose, flat) {
if (container.count == 0)
return "You're pretty sure you just sat on a rock.";
else
return "You sit yourself down on " + container.describe(false) + ". " + (container.count > 1 ? "They slide" : "It slides") + " inside with ease.";
return pickString([
"You sit yourself down on",
container.describe(false) + ". ",
(container.count > 1 ? "They slide" : "It slides"),
"inside with ease."
], [
"You grab",
container.describe(false) + ",",
"shoving",
(container.count > 1 ? "your victims" : "your victim"),
"right up your rear with a muffled <i>shlrkh</i>."
]
).join(" ");

}

function defaultAssCrush(container, macro, verbose, flat) {
@@ -278,7 +352,7 @@ function defaultTailSlap(container, macro, verbose, flat) {

function defaultTailVore(container, macro, verbose, flat) {
if (container.count == 0)
return "Your drooling tail swings to and fro";
return "Your drooling tail lashes about, but can't seem to chow down on anyone...";
else if (isFatal(macro))
return "Your tail lunges, maw agape, at " + container.describe(verbose) +
". It scarfs down everything in seconds, gulping forcefully to drag your prey into your sloppy confines.";
@@ -336,18 +410,52 @@ function defaultCleavageAbsorb(container, macro, verbose, flat) {

function defaultBreastCrush(container, macro, verbose, flat) {
if (container.count == 0)
return "Your thump your breasts against the ground.";
return "Your let your breasts thump against the ground.";
else if (isFatal(macro))
return "Your heavy breasts obliterate " + container.describe(verbose) + ". ";
return [
"You let your breasts drop,",
pickString("crushing", "smashing", "burying", "smothering"),
container.describe(verbose),
"beneath those",
length(macro.breastDiameter, unit, true) + "-wide",
pickString("knockers", "tits", "boobs") + ".",
pickStringChance(0.5, (macro.lactationEnabled ? "A spray of milk spurts from your nipples." : ""))
].filter(Boolean).join(" ");
else
return "You smoosh " + container.describe(verbose) + " with your breasts.";
return "You smoosh " + container.describe(verbose) + " beneath your breasts.";
}

function defaultBreastVore(container, macro, verbose, flat) {
let prey = new Container();
macro.breasts.contents.forEach(function(x) {
prey = prey.merge(x);
});

if (container.count == 0)
return "It'd be pretty hot to stick someone in your breasts. Shame you can't right now.";
else
return "Your nipples envelop " + container.describe(verbose) + ", pulling them into your breasts. ";
return pickString([
"Your breasts squish against",
container.describe(verbose),
"as",
(container.count > 1 ? "they're" : "it's"),
"forced right into your nipples! They stretch and",
pickString("envelop", "consume", "suck in"),
"your prey,",
pickStringChance(0.5, "swiftly", "easily"),
"burying them in those warm,",
(macro.lactationEnabled ? "milky" : "heavy"),
"mounds."
], [
capitalize(container.describe(verbose)),
(container.count > 1 ? "are" : "is"),
pickStringChance(0.35, "abruptly", "swiftly"),
pickString("stuffed", "slipped"),
"into your breasts",
(container.count > 1 ? "their" : "its"),
"form lost within your bosom.",
(prey.count > 0 ? (prey.count > 1 ? "The " + prey.describe(false) : capitalize(prey.describe(true))) + " within " + (prey.count > 1 ? "slosh" : "sloshes") + " about as " + (prey.count > 1 ? "they're" : "it's") + " joined by fresh prey." : "")
]).filter(Boolean).join(" ")
}


@@ -363,8 +471,32 @@ function defaultBreastMilk(container, macro, verbose, flat) {
function defaultUnbirth(container, macro, verbose, flat) {
if (container.count == 0)
return "You grab " + (macro.victimsHuman ? new Human(1).describe(verbose) : new Person(1).describe(verbose)) + " and grind them against your slit...but they won't fit.";
else
return "You gasp as you slide " + container.describe(verbose) + " up your slit. ";
else {
return pickString([
"You",
pickString(...synonyms.moan),
"as",
container.describe(verbose),
(container.count > 1 ? "spread" : "spreads"),
"open your",
pickString("sex", macro.describeVagina + " slit") + ",",
pickString("swallowed", "sucked", "drawn"),
pickString("within", "inside", "down deep"),
"by",
pickString("tender", "sensuous", "lustful"),
pickString("folds", "muscle") + "."
], [
capitalize(container.describe(verbose)),
"fall prey to your",
pickString("sex", macro.describeVagina + " slit"),
"with a messy",
pickString("<i>SQUELCH</i>,", "<i>SQUISH</i>,"),
"vanishing into your womb and sending a",
pickString("jolt", "surge", "shock"),
"of ecstasy up your spine."
]).filter(Boolean).join(" ");
}
}

function defaultSheathStuff(container, macro, verbose, flat) {
@@ -677,6 +809,26 @@ function defaultScatStench(container, macro, verbose, flat) {
return "Your stinky scat overwhelms " + (sum > 1 ? sum + " people" : "a person") + " with your scent!";
}

function defaultMaleMusk(container, macro, verbose, flat) {
let sum = get_living_prey(container.sum());
if (isSadistic(macro))
return "Waves of corrosive musk waft from your shaft, the bitter cloud liquefying the flesh of " + (sum > 1 ? numberRough(sum,"of") + " people" : "a person") + " as it dissolves " + container.describeSimple(flat) + ".";
if (isFatal(macro))
return "Powerful musk wafts from your shaft, choking the life from " + (sum > 1 ? sum + " people." : "a person.");
else
return "Your masculine musk overwhelms " + (sum > 1 ? sum + " people" : "a person") + " with your scent!";
}

function defaultFemaleMusk(container, macro, verbose, flat) {
let sum = get_living_prey(container.sum());
if (isSadistic(macro))
return "Waves of corrosive musk waft from your slit, the bitter cloud liquefying the flesh of " + (sum > 1 ? numberRough(sum,"of") + " people" : "a person") + " as it dissolves " + container.describeSimple(flat) + ".";
if (isFatal(macro))
return "Powerful musk wafts from your slit, choking the life from " + (sum > 1 ? sum + " people." : "a person.");
else
return "Your feminine musk overwhelms " + (sum > 1 ? sum + " people" : "a person") + " with your scent!";
}

function defaultMaleSpurtMusk(container, macro, verbose, flat) {
let sum = get_living_prey(container.sum());
if (isSadistic(macro))
@@ -743,13 +895,41 @@ function defaultFart(container, macro, verbose, flat) {

function defaultStomach(container, macro, verbose, flat) {
if (isSadistic(macro))
return "Your churning guts crushes your prey into a gory paste, annihilating " + container.describeSimple(flat) + " and reducing everything to rancid chyme.";
return [
"Your",
pickString("churning gut", "graveyard of a stomach", "fatal belly"),
pickString("crushes", "grinds", "mulches"),
"your prey into a gory paste,",
pickStringChance(0.5, "utterly", "completely"),
"annihilating",
container.describeSimple(flat),
"and",
pickStringChance(0.5, "swiftly"),
"reducing everything within to",
pickString("rancid", "putrid", "horrifying"),
pickString("sludge.", "slop.")
].filter(Boolean).join(" ");
else if (isGory(macro))
return "Your caustic stomach grinds " + container.describeSimple(flat) + " to a gory pulp.";
return [
"Your caustic stomach",
pickString("crushes", "grinds"),
container.describeSimple(flat),
"to a gory pulp."
].filter(Boolean).join(" ");
else if (isFatal(macro))
return "Your stomach gurgles as it digests " + container.describeSimple(flat) + ".";
return [
"Your stomach",
pickString("gurgles", "snarls", "sloshes"),
"as it digests",
container.describeSimple(flat) + "."
].filter(Boolean).join(" ");
else
return "Your stomach groans and abosrbs " + container.describeSimple(flat) + ".";
return [
"Your stomach",
pickString("squeezes", "groans", "shifts"),
"and absorbs",
container.describeSimple(flat) + "."
].filter(Boolean).join(" ");
}

function defaultTail(container, macro, verbose, flat) {
@@ -1501,15 +1681,27 @@ function defaultVictimCumFlood(macro) {
}
}

function defaultVictimMaleMusk(macro) {
if (isSadistic(macro)) {
return "reduced to slurry by corrosive masculine musk";
} else if (isGory(macro)) {
return "suffocated by masculine musk";
} else if (isFatal(macro)) {
return "snuffed out by masculine musk";
} else if (isNonFatal(macro)) {
return "dazed by masculine musk";
}
}

function defaultVictimMaleSpurtMusk(macro) {
if (isSadistic(macro)) {
return "dissolved in a tide of slick, musky precum";
return "corroded by your caustic, overwhelming masculine musk";
} else if (isGory(macro)) {
return "drowned in your slick precum";
return "snuffed out by your masculine musk";
} else if (isFatal(macro)) {
return "washed away by precum";
return "overwhelmed by masculine musk";
} else if (isNonFatal(macro)) {
return "flooded with your precum";
return "dazed by masculine musk";
}
}

@@ -1549,15 +1741,27 @@ function defaultVictimFemcumFlood(macro) {
}
}

function defaultVictimFemaleMusk(macro) {
if (isSadistic(macro)) {
return "dissolved to slurry by feminine musk";
} else if (isGory(macro)) {
return "suffocated by feminine musk";
} else if (isFatal(macro)) {
return "snuffed out by feminine musk";
} else if (isNonFatal(macro)) {
return "dazed by feminine musk";
}
}

function defaultVictimFemaleSpurtMusk(macro) {
if (isSadistic(macro)) {
return "suffocated by a spurt of corrosive feminine precum";
return "corroded by your caustic, overwhelming feminine musk";
} else if (isGory(macro)) {
return "snuffed out by a splatter of feminine fluid";
return "snuffed out by your feminine musk";
} else if (isFatal(macro)) {
return "flooded by your spurting precum";
return "overwhelmed by feminine musk";
} else if (isNonFatal(macro)) {
return "soaked with your feminine precum";
return "dazed by feminine musk";
}
}

@@ -1987,6 +2191,33 @@ rules["eat"].push({
}
});

rules["eat"].push({
test: (container, macro) => {
return hasExactly(container, "Planet", 1) && nothingLarger(container, "Planet");
},
desc: (container, macro, verbose, flat) => {
return [
"Your colossal",
macro.jawDesc(true),
"yawn wide as you drift towards the planet, blotting out the sun in the shadow of your terrifying maw. Your tongue curls along the underside of your snack's crust, slathering it in drool and gently tugging it towards you. Cracks and quakes rock the fragile crust; your body's overwhelming gravity alone is enough to stretch and warp the planet. Before long, it is entombed within your",
macro.jawDesc(true),
"and, a heartbeat later, a massive GLURKH drags it into your gullet."
].join(" ")
}
})

rules["eat"].push({
test: (container, macro) => hasAtleast(container, "Planet", 3) && hasLessThan(container, "Planet", 15) && nothingLarger(container, "Planet"),
desc: (container, macro, verbose, flat) => [
"You scoop up a plethora of planets, popping them into your",
macro.jawDesc(true),
"like the finger-food they've become, tugging each one into your gullet - and on an irreversible one-way journey to your gut - with little gluks and gulps, sealing away all",
container.contents["Planet"].count,
"of them within your cosmic body."
].join(" ")
});


// CHEWING

rules["chew"].push({
@@ -2025,6 +2256,17 @@ rules["chew"].push({
}
});

rules["chew"].push({
test: (container, macro) => hasExactly(container, "Planet", 1) && nothingLarger(container, "Planet") && isFatal(macro),
desc: (container, macro, verbose, flat) => [
"A shadow falls over your next meal - your ",
macro.jawDesc(true),
"closing around the rocky sphere like bolt cutters around a chain-link...and then, with a sharp clench, they split the planet in twain. The heat of the planet's core spills out, the homeworld of billions rent asunder by your almighty",
macro.jawDesc(true) + ".",
"A few more chews and crunches reduce it to chunky, glowing rubble...and with a flick of your head, the planet's remains are lost to your hunger."
].join(" ")
});

// STOMPING

rules["stomp"].push({
@@ -2240,7 +2482,7 @@ rules["stomp"].push({
macro.pawArea > 50 &&
isGory(macro);
}, "desc": function(container, macro, verbose, flat) {
return "You bring your " + length(macro.pawWidth, unit, true) + " wide " + macro.footDesc() + " " + macro.footDesc() + " down on " + container.describe(verbose) + ". As your " + macro.footDesc() + " impacts its target, you feel its weight sink through buildings and into the \
return "You bring your " + length(macro.pawWidth, unit, true) + " wide " + macro.footDesc() + " down on " + container.describe(verbose) + ". As your " + macro.footDesc() + " impacts its target, you feel its weight sink through buildings and into the \
ground. After you lift your " + macro.soleDesc() + ", a deep indent full of rubble and mangled corpses is revealed.";
}
});
@@ -4052,4 +4294,4 @@ rules["male-spurt"].push({

//powerplants factories

//anal vore test "ring seals to the ground and pulls in" usde weight of rear to pull in more mass
//anal vore test "ring seals to the ground and pulls in" usde weight of rear to pull in more mass

+ 12
- 13
recursive-macro.js Visa fil

@@ -463,7 +463,7 @@ var clusters =
"Person": 5,
"Human": 5,
"Cow": 15,
"Micro": 10,
"Micro": 50,
"Macro": 0,
//Vehicles
"Car": 3,
@@ -482,7 +482,7 @@ var clusters =
"Town": 5,
"City": 1,
"Continent": 5,
"Planet": 1,
"Planet": 9,
"Star": 1,
"Solar System": 1,
"Galaxy": 1,
@@ -511,7 +511,7 @@ var cluster_chances =
"Person": 0.8,
"Human": 0.8,
"Cow": 0.5,
"Micro": 10,
"Micro": 1,
"Macro": 0,
//Vehicles
"Car": 0.5,
@@ -702,10 +702,10 @@ function fill_area(area, weights, variance=0.15)
continue;

var max = Math.floor(area / candidate.area);
var limit = Math.min(max, 100);
var limit = Math.min(max, 1000);

var count = 0;
var loopvar = limit;
var loopvar = 0;

// for small amounts, actually do the randomness

@@ -713,17 +713,13 @@ function fill_area(area, weights, variance=0.15)

// if we have nothing at all, it's even better!

if (limit > 0 && result.length == 0) {
++count;
++loopvar;
}

while (loopvar < limit) {
if (loopvar <= clusters[candidate.name] && loopvar == 0 && Math.random() < cluster_chances[candidate.name]) {
if (loopvar == 0 && result.length == 0) {
++count;
}
else if (loopvar <= clusters[candidate.name]) {
if (Math.random() < candidate.weight ? 1 : 0 || Math.random() < 0.75 * cluster_chances[candidate.name]) {
if (Math.random() < candidate.weight ? 1 : Math.random() < cluster_chances[candidate.name]) {
++count;
}
}
@@ -733,8 +729,11 @@ function fill_area(area, weights, variance=0.15)
++loopvar;
}

// if we're doing more than the limit, then we just add on the rest, with some variance

if (limit < max) {
count += Math.round((max-limit) * candidate.weight);
const base = (max-limit) * candidate.weight;
count += Math.round(base - base / 10 + base * Math.random() / 5);
}

area -= count * candidate.area;


+ 26
- 23
stroll.html Visa fil

@@ -166,21 +166,24 @@
<div class="stat-line-hidden" id="piss"></div>
<div class="stat-line-hidden" id="scat"></div>
</div>
<div class="stat-header-self">Growth</div>

<div class="growth-box">
<div id="growth-box-left">
<button class="growth-part growth-part-active" id="button-growth-body">Body</button>
<button class="growth-part" id="button-growth-paws">Paws</button>
<button class="growth-part" id="button-growth-tail">Tail</button>
<button class="growth-part" id="button-growth-ass">Ass</button>
<button class="growth-part" id="button-growth-dick">Cock</button>
<button class="growth-part" id="button-growth-balls">Balls</button>
<button class="growth-part" id="button-growth-slit">Slit</button>
<button class="growth-part" id="button-growth-womb">Womb</button>
<button class="growth-part" id="button-growth-breasts">Breasts</button>
</div>
<div id="growth-box-right">
<div class="stat-header-self">Growth</div>
<select id="growth-part-select">
<option class="growth-part growth-part-active" id="option-growth-body" value="body">Body</option>
<option class="growth-part" id="option-growth-paws" value="paws">Paws</option>
<option class="growth-part" id="option-growth-tail" value="tail">Tail</option>
<option class="growth-part" id="option-growth-ass" value="ass">Ass</option>
<option class="growth-part" id="option-growth-dick" value="dick">Cock</option>
<option class="growth-part" id="option-growth-balls" value="balls">Balls</option>
<option class="growth-part" id="option-growth-slit" value="slit">Slit</option>
<option class="growth-part" id="option-growth-womb" value="womb">Womb</option>
<option class="growth-part" id="option-growth-breasts" value="breasts">Breasts</option>
<option class="growth-part" id="option-growth-wings" value="wings">Wings</option>
<option class="growth-part" id="option-growth-musk" value="musk">Musk</option>
<option class="growth-part" id="option-growth-stench" value="stench">Stench</option>
</select>
<button class="growth-amount" id="button-growth-1.1">1.1x</button>
<button class="growth-amount" id="button-growth-1.5">1.5x</button>
<button class="growth-amount" id="button-growth-2">2x</button>
@@ -188,19 +191,23 @@
<button class="growth-amount" id="button-growth-20">20x</button>
<button class="growth-amount" id="button-growth-100">100x</button>
</div>
<div id="growth-box-right">
</div>
</div>
</div>
<div id="log-area">
<div class="log" id="log">
<div>Welcome to Stroll</div>
<br>
<div>&nbsp;</div>
<div class="version"></div>
<br>
<div>&nbsp;</div>
<div><b>This game features 18+ content</b></div>
<div>&nbsp;</div>
</div>
<div class="log" id="react-log">
<div>It's a nice day for a walk</div>
<div>It's a nice day for a walk.</div>
<div>&nbsp;</div>
<div>This log will show automatic actions.</div>
<div>&nbsp;</div>
</div>
</div>
@@ -218,11 +225,7 @@

<p>Stroll is a text-based macro game. Stomp things, eat things, abuse things - then grow larger and do it all over again.</p>

<p><b>Stroll is designed for modern browsers. Chrome, Firefox, or Edge are suggested. Older browsers will likely fail to run the game. Mobile should work fine.</b></p>

<p>Leave a box empty for a sane default value</p>
<p>Lengths in meters, areas in square meters, masses in kilograms, times in seconds</p>
<p>(but you can preview the customary value)</p>
<p>Leave a box empty for a sane default value. Units are metric, but you can preview other unit systems.</p>
<p>Click on boxed titles to enable and disable features.</p>
<p class="has-tooltip" title="uwu">Underlined options have tooltips</p>
</div>
@@ -282,9 +285,9 @@
<div class="custom-category">
<p>Or export/import your character to text here. Copy and paste to share.</p>
<div class>
<button type="button" class="option-button" id="button-export-clear">Clear Space</button>
<button type="button" class="option-button" id="button-export-preset">Export Your Character</button>
<button type="button" class="option-button" id="button-import-preset">Import Your Character</button>
<button type="button" class="option-button" id="button-export-clear">Clear</button>
<button type="button" class="option-button" id="button-export-preset">Export</button>
<button type="button" class="option-button" id="button-import-preset">Import</button>

<p><input autocomplete="off" type="text" id="export-area" placeholder="Paste character data here..."></p>
</div>


+ 43
- 19
style.css Visa fil

@@ -58,7 +58,7 @@ body.dark div {

@media (max-aspect-ratio: 1/1){
.game-area {
width: 100%
width: 100%;
height: 60%;
}
#stat-container {
@@ -72,36 +72,38 @@ body.dark div {
position: fixed;
right: 0%;
top: 0%;
max-width: 33%;
max-width: 50%;
max-height: 50%;
}
#log {
position: fixed;
left: 0%;
bottom: 0%;
width: 50%;
width: 48%;
height: 50%;
max-height: 50%;
margin: 0 0 1vh 0;
margin-left: 1vw;
}
#react-log {
position: fixed;
right: 0%;
bottom: 0%;
width: 50%;
width: 48%;
height: 50%;
max-height: 50%;
margin: 1vh 0 0 0;
height: 40vh;
margin-right: 1vw;
}
.growth-part {
width: 100px !important;
}
#growth-part-select {
width: 100px !important;
}
.growth-amount {
width: 100px !important;
}
.action-part-button {
width: 100px !important;
width: 33% !important;
}
.action-button {
width: 100px !important;
@@ -388,7 +390,7 @@ body.dark .custom-header-static {
display: inline-block;
border-style: dotted;
border-width: 1px;
border-length: 5px;
border-radius: 5px;
}

.custom-category-sub .custom-header {
@@ -420,7 +422,6 @@ body.light input[type="checkbox"]:checked+
.custom-header {
color: #000;
border-style: solid;
margin: 10px;
background-color: rgba(230, 230, 230, 0.3);
}

@@ -428,7 +429,6 @@ body.dark input[type="checkbox"]:checked+
.custom-header {
color: #fff;
border-style: solid;
margin: 10px;
background-color: rgba(0, 0, 0, 0.3);
}

@@ -481,6 +481,9 @@ body.light .flex-outer input[type="checkbox"]:checked + label:not(.custom-header
background: #afa;
}

.flex-outer {
user-select: none;
}
.flex-outer label {
flex: 0 1 40%;
text-align: right;
@@ -513,24 +516,32 @@ body.light .flex-outer input[type="checkbox"]:checked + label:not(.custom-header
width: 90%;
}

body.light .flex-outer-sub {
background: #c8c8c8;
}

body.light .flex-outer-sub .flex-outer-sub {
background: #c0c0c0;
}

body.dark .flex-outer-sub {
background: #181818;
}

body.dark .flex-outer-sub .flex-outer-sub {
background: #222;
background: #202020;
}

body.light .has-tooltip {
position: relative;
display: inline-block;
border-bottom: 1px dotted black;
border-bottom: 1px dotted #777;
}

body.dark .has-tooltip {
position: relative;
display: inline-block;
border-bottom: 1px dotted white;
border-bottom: 1px dotted #777;
}

body.light a {
@@ -596,10 +607,20 @@ ul {
display: none;
}

.action-part-button.active {
background: #555;
@media (max-aspect-ratio: 1) {
.action-part-button {
width: 33%;
}
}


body.light .action-part-button.active {
background: #ccc;
}

body.dark .action-part-button.active {
background: #555;
}
/* SRC: https://stackoverflow.com/questions/29738787/filling-water-animation/29740828 */

.meter {
@@ -613,7 +634,7 @@ ul {
}

body.light .meter {
background: #ddd !important;
background: #ccc !important;
}

body.dark .meter {
@@ -739,6 +760,7 @@ body.dark .meterLabel {
display: flex;
flex-wrap: wrap;
flex-direction: column;
text-align: left;
flex: 0 1 400px;
}

@@ -752,8 +774,10 @@ body.dark .meterLabel {
height: 100%;
}

#growth-box-right {
height: 100%;
#growth-part-select {
display: block;
height: 100px;
font-size: 20px;
}

.growth-part {


+ 45
- 15
units.js Visa fil

@@ -40,24 +40,32 @@ function numberRough(value,suffix="") {
}
}
}
function number(value, type="full", precision=3) {

function fixedIfDecimal(num, fixed) {
if (fixed === undefined)
return num.toString();
else;
return num.toFixed(fixed);
}

function number(value, type="full", fixed) {
var val = parseFloat(value);
switch(type) {
case "full":
if (Math.log(value) / Math.log(10) < 10) {
return val.toString();
return fixedIfDecimal(val, fixed);
}

case "scientific": return val.toExponential(precision).toString();
case "words": return number_words_repeated(val);
case "prefix": return number_prefix(val);
case "scientific": return val.toExponential(3, fixed).toString();
case "words": return number_words_repeated(val, fixed);
case "prefix": return number_prefix(val, fixed);
}
}

function number_words(value) {
var scale = Math.floor(Math.log(value) / Math.log(1000));
if (scale < 0) {
return value.toString();
return fixedIfDecimal(value, fixed);
}
switch(scale) {
case 0: return value.toString();
@@ -85,14 +93,14 @@ function number_words(value) {
}
}

function number_words_repeated(value) {
function number_words_repeated(value, fixed) {
if (value == Infinity)
return "a lot of";
var scale = Math.floor(Math.log(value) / Math.log(1000));
if (scale < 0)
return value.toString();
return fixedIfDecimal(value, fixed);
switch(scale) {
case 0: return value.toString();
case 0: return fixedIfDecimal(value, fixed);
case 1: return Math.round(value / 1e3).toString() + " thousand";
case 2: return Math.round(value / 1e6).toString() + " million";
case 3: return Math.round(value / 1e9).toString() + " billion";
@@ -108,12 +116,12 @@ function number_words_repeated(value) {
}
}

function number_prefix(value) {
function number_prefix(value, fixed) {
var scale = Math.floor(Math.log(value) / Math.log(1000));
if (scale < 0)
return value.toString();
return fixedIfDecimal(value, fixed);
switch(scale) {
case 0: return value.toString();
case 0: return fixedIfDecimal(value, fixed);
case 1: return Math.round(value / 1e3).toString() + "K";
case 2: return Math.round(value / 1e6).toString() + "M";
case 3: return Math.round(value / 1e9).toString() + "G";
@@ -434,6 +442,28 @@ function customarySymArea(m2, singular=false) {
}
}

function approxArea(m2, singular=false) {
if (m2 < 20000) {
let area = round(m2/5341.85,1);
return area + (singular || area == 1 ? " football field" : " football fields");
} else if (m2 < 9.36e+15) {
let area = round(m2/10117.1,1);
return area + (singular || area == 1 ? " block" : " blocks");
} else if (m2 < 3.7920361e+13) {
let area = round(m2/9.36e+8,1);
return area + (singular || area == 1 ? " city" : " cities");
} else if (m2 < 9.4800902e+18) {
let area = round(m2/9.4800902e+12,1);
return area + (singular || area == 1 ? " moon" : " moons");
} else if (m2 < 2.8118957330513e+42) {
let area = round(m2/6.4900004e+28,1);
return area + (singular || area == 1 ? " solar system" : " solar systems");
} else {
let area = round(m2/2.8118957330513e+42,1);
return area + (singular || area == 1 ? " milky way" : " milky ways");
}
}

function metricVolume(m3, singular=false) {
if (m3 < 1/1000) {
let volume = round(m3*1e6, 0);
@@ -462,13 +492,13 @@ function metricSymVolume(m3, singular=false) {
return volume + " L";
} else if (m3 < 1000000) {
let volume = round(m3, 0);
return volume + " m" + "3".sup();
return volume + " m" + "³";
} else if (m3 < 1e12){
let volume = round(m3/1e9, 3);
return volume + " km" + "3".sup();
return volume + " km" + "³";
} else {
let volume = round(m3/1e9, 0);
return volume + " km" + "3".sup();
return volume + " km" + "³";
}
}



Laddar…
Avbryt
Spara