diff --git a/mod-list.html b/mod-list.html index e2bc7bd2..f8bd6318 100644 --- a/mod-list.html +++ b/mod-list.html @@ -376,6 +376,7 @@ allliquids.jsMade all elements liquidsOrchid amogus.jsSmall Among Us structureAlice bfdi.jsSeveral references to Battle for Dream IslandTaterbob + chess.jsPlay chess in Sandboxels [Press U to start game]ggod citybuilding.jsSeeds that create miniature buildings and other city-related itemsSquareScreamYT collab_mod.jsCreated by multiple people, adds random thingsmrapple, ilikepizza, stefanblox cubesstuff.jsSome random stuff like Disco Ball, Pyrite, and Nordic GoldCube14yt diff --git a/mods/PRNGworldgenlib.js b/mods/PRNGworldgenlib.js index 48d5d0e8..68f221a6 100644 --- a/mods/PRNGworldgenlib.js +++ b/mods/PRNGworldgenlib.js @@ -520,7 +520,7 @@ elements.RandomGen = { elements.view_seed = { category: "edit", onSelect: function(){ - alert(seed); - selectElement("dirt"); + promptText(seed, undefined, "Seed"); + selectElement(prevElement); } } diff --git a/mods/a_mod_by_alice.js b/mods/a_mod_by_alice.js index 9e9840e3..9318325d 100644 --- a/mods/a_mod_by_alice.js +++ b/mods/a_mod_by_alice.js @@ -44986,7 +44986,6 @@ maxPixels (default 1000): Maximum amount of pixels/changes (if xSpacing and ySpa function editDistance(s1, s2) {s1 = s1.toLowerCase();s2 = s2.toLowerCase();var costs = new Array();for (var i = 0; i <= s1.length; i++) {var lastValue = i;for (var j = 0; j <= s2.length; j++) {if (i == 0)costs[j] = j;else {if (j > 0) {var newValue = costs[j - 1];if (s1.charAt(i - 1) != s2.charAt(j - 1))newValue = Math.min(Math.min(newValue, lastValue),costs[j]) + 1;costs[j - 1] = lastValue;lastValue = newValue;}}}if (i > 0)costs[s2.length] = lastValue;}return costs[s2.length];} function similarity(s1, s2) {var longer = s1;var shorter = s2;if (s1.length < s2.length) {longer = s2;shorter = s1;}var longerLength = longer.length;if (longerLength == 0) {return 1.0;}return (longerLength - editDistance(longer, shorter)) / parseFloat(longerLength);} function mostSimilarElement(s) { - delete elements; var max = 0; var maxElement = ""; for (var e in elements) { diff --git a/mods/bananas.js b/mods/bananas.js index be11cf0f..7f6bea83 100644 --- a/mods/bananas.js +++ b/mods/bananas.js @@ -1,139 +1,347 @@ var modName = "mods/bananas.js"; var onTryMoveIntoMod = "mods/onTryMoveInto.js"; var libraryMod = "mods/code_library.js"; +function scale (number, inMin, inMax, outMin, outMax) { + return (number - inMin) * (outMax - outMin) / (inMax - inMin) + outMin; +} -if(enabledMods.includes(onTryMoveIntoMod) && enabledMods.includes(libraryMod)) { - randomNumberFromOneToThree = function() { - return 1 + Math.floor(Math.random() * 3) - }; - - debugSpeedGrowth = false; - logLeaves = false; - bananaAttachWhitelist = ["banana_pseudostem","banana_peduncle_1","banana_peduncle_2","petal","banana_leaf","banana_plant_top","banana"]; - - bananaDirtElements = ["dirt","mud","sand","wet_sand","clay_soil","mycelium","grass"]; +randomNumberFromOneToThree = function() { + return 1 + Math.floor(Math.random() * 3) +}; - function logPixelCoords(pixel) { - return `(${pixel.x}, ${pixel.y})` - }; +debugSpeedGrowth = false; +logLeaves = false; +bananaAttachWhitelist = ["banana_pseudostem","banana_peduncle_1","banana_peduncle_2","petal","banana_leaf","banana_plant_top","banana"]; - function hasPixel(x,y,elementInput) { - if(isEmpty(x,y,true)) { //if empty, it can't have a pixel - return false; +bananaDirtElements = ["dirt","mud","sand","wet_sand","clay_soil","mycelium","grass"]; + +function logPixelCoords(pixel) { + return `(${pixel.x}, ${pixel.y})` +}; + +function hasPixel(x,y,elementInput) { + if(isEmpty(x,y,true)) { //if empty, it can't have a pixel + return false; + } else { + if(elementInput.includes(",")) { //CSTA + elementInput = elementInput.split(","); + }; + if(Array.isArray(elementInput)) { //if element list + return elementInput.includes(pixelMap[x][y].element); + } else { //if single element + return pixelMap[x][y].element === elementInput; + }; + }; +}; + +elements.banana_seed = { + color: "#3b3b2e", + tick: function(pixel) { + if(pixel.bananaRange === null) { + pixel.bananaRange = randomNumberFromOneToThree(); + }; + + if (isEmpty(pixel.x,pixel.y+1)) { + movePixel(pixel,pixel.x,pixel.y+1); } else { - if(elementInput.includes(",")) { //CSTA - elementInput = elementInput.split(","); - }; - if(Array.isArray(elementInput)) { //if element list - return elementInput.includes(pixelMap[x][y].element); - } else { //if single element - return pixelMap[x][y].element === elementInput; - }; - }; - }; - - elements.banana_seed = { - color: "#3b3b2e", - tick: function(pixel) { - if(pixel.bananaRange === null) { - pixel.bananaRange = randomNumberFromOneToThree(); - }; - - if (isEmpty(pixel.x,pixel.y+1)) { - movePixel(pixel,pixel.x,pixel.y+1); - } else { - if (Math.random() < (debugSpeedGrowth ? 0.09 : 0.03) && pixel.age > (debugSpeedGrowth ? 20 : 50) && pixel.temp < 100) { - if (!outOfBounds(pixel.x,pixel.y+1)) { - var dirtPixel = pixelMap[pixel.x][pixel.y+1]; - if (bananaDirtElements.includes(dirtPixel.element)) { - changePixel(dirtPixel,"root"); - }; + if (Math.random() < (debugSpeedGrowth ? 0.09 : 0.03) && pixel.age > (debugSpeedGrowth ? 20 : 50) && pixel.temp < 100) { + if (!outOfBounds(pixel.x,pixel.y+1)) { + var dirtPixel = pixelMap[pixel.x][pixel.y+1]; + if (bananaDirtElements.includes(dirtPixel.element)) { + changePixel(dirtPixel,"root"); }; - if (isEmpty(pixel.x,pixel.y-1)) { - movePixel(pixel,pixel.x,pixel.y-1); - createPixel("banana_pseudostem",pixel.x,pixel.y+1); - pixelMap[pixel.x][pixel.y+1].bananaRange = pixel.bananaRange; //pass banana range down to pseudostem - }; - } else if (pixel.age > (debugSpeedGrowth ? 500 : 1000)) { - changePixel(pixel,"banana_plant_top"); }; - pixel.age++; - }; - if(Math.random() < 0.01 && pixel.age > 200) { + if (isEmpty(pixel.x,pixel.y-1)) { + movePixel(pixel,pixel.x,pixel.y-1); + createPixel("banana_pseudostem",pixel.x,pixel.y+1); + pixelMap[pixel.x][pixel.y+1].bananaRange = pixel.bananaRange; //pass banana range down to pseudostem + }; + } else if (pixel.age > (debugSpeedGrowth ? 500 : 1000)) { changePixel(pixel,"banana_plant_top"); }; - doDefaults(pixel); - }, - properties: { - "age": 0, - //"bananaRange": null, //apparently this is suddenly, in an illogical, never-before-seen, completely new, unprecedented incident of bad behavior, evaluated before being put into the property database, so RNG has to be done in tick - "bananaRange": null, - }, - tempHigh: 100, - stateHigh: "dead_plant", - tempLow: -2, - stateLow: "frozen_plant", - burn: 5, - burnInto: ["steam", "ash"], - burnTime: 600, - category: "life", - state: "solid", - density: 1500, - cooldown: defaultCooldown, - }; + pixel.age++; + }; + if(Math.random() < 0.01 && pixel.age > 200) { + changePixel(pixel,"banana_plant_top"); + }; + doDefaults(pixel); + }, + properties: { + "age": 0, + //"bananaRange": null, //apparently this is suddenly, in an illogical, never-before-seen, completely new, unprecedented incident of bad behavior, evaluated before being put into the property database, so RNG has to be done in tick + "bananaRange": null, + }, + tempHigh: 100, + stateHigh: "dead_plant", + tempLow: -2, + stateLow: "frozen_plant", + burn: 5, + burnInto: ["steam", "ash"], + burnTime: 600, + category: "life", + state: "solid", + density: 1500, + cooldown: defaultCooldown, +}; - elements.banana_pseudostem = { - hidden: true, - color: "#d5e39f", - tick: function(pixel) { - if(pixel.bananaRange === null) { - pixel.bananaRange = randomNumberFromOneToThree(); +elements.banana_pseudostem = { + hidden: true, + color: "#d5e39f", + tick: function(pixel) { + if(pixel.bananaRange === null) { + pixel.bananaRange = randomNumberFromOneToThree(); + }; + + if (pixel.age > 60 && pixel.temp < 100 && !pixel.grewPeduncle) { + var peduncleOffsets = [-1, 1]; //placed to the left, placed to the right + for(i = 0; i < peduncleOffsets.length; i++) { + if (isEmpty(pixel.x+peduncleOffsets[i],pixel.y,false)) { + if (Math.random() < 0.005) { + createPixel("banana_peduncle_1",pixel.x+peduncleOffsets[i],pixel.y); + pixelMap[pixel.x+peduncleOffsets[i]][pixel.y].dir = Math.sign(peduncleOffsets[i]); + pixelMap[pixel.x+peduncleOffsets[i]][pixel.y].bananaRange = pixel.bananaRange; //pass banana range down to peduncle + if(Math.random() < 0.8) { pixel.grewPeduncle = true; } //20% chance to not mark as true, allowing for a chance to try another peduncle + }; + }; }; + }; + pixel.age++; + doDefaults(pixel); + }, + properties: { + "age": 0, + "grewPeduncle": false, + "bananaRange": null, + }, + tempHigh: 100, + stateHigh: "dead_plant", + tempLow: -2, + stateLow: "frozen_plant", + burn: 5, + burnInto: ["steam", "ash"], + burnTime: 600, + category: "life", + state: "solid", + density: 1500, +}; - if (pixel.age > 60 && pixel.temp < 100 && !pixel.grewPeduncle) { - var peduncleOffsets = [-1, 1]; //placed to the left, placed to the right - for(i = 0; i < peduncleOffsets.length; i++) { - if (isEmpty(pixel.x+peduncleOffsets[i],pixel.y,false)) { - if (Math.random() < 0.005) { - createPixel("banana_peduncle_1",pixel.x+peduncleOffsets[i],pixel.y); - pixelMap[pixel.x+peduncleOffsets[i]][pixel.y].dir = Math.sign(peduncleOffsets[i]); - pixelMap[pixel.x+peduncleOffsets[i]][pixel.y].bananaRange = pixel.bananaRange; //pass banana range down to peduncle - if(Math.random() < 0.8) { pixel.grewPeduncle = true; } //20% chance to not mark as true, allowing for a chance to try another peduncle +elements.banana = { + color: "#ede84c", + tick: function(pixel) { + if(pixel.attached) { + var attachCoords = [pixel.x+Math.sign(pixel.attachDirection), pixel.y]; + if(isEmpty(attachCoords[0],attachCoords[1],false)) { + pixel.attached = false; + }; + } else { //Move if not attached + if (!tryMove(pixel, pixel.x, pixel.y+1)) { + if(Math.random() < 0.9) { + if (Math.random() < 0.5) { + if (!tryMove(pixel, pixel.x+1, pixel.y+1)) { + tryMove(pixel, pixel.x-1, pixel.y+1); + }; + } else { + if (!tryMove(pixel, pixel.x-1, pixel.y+1)) { + tryMove(pixel, pixel.x+1, pixel.y+1); }; }; }; }; - pixel.age++; - doDefaults(pixel); - }, - properties: { - "age": 0, - "grewPeduncle": false, - "bananaRange": null, - }, - tempHigh: 100, - stateHigh: "dead_plant", - tempLow: -2, - stateLow: "frozen_plant", - burn: 5, - burnInto: ["steam", "ash"], - burnTime: 600, - category: "life", - state: "solid", - density: 1500, - }; - - elements.banana = { - color: "#ede84c", - tick: function(pixel) { - if(pixel.attached) { - var attachCoords = [pixel.x+Math.sign(pixel.attachDirection), pixel.y]; - if(isEmpty(attachCoords[0],attachCoords[1],false)) { - pixel.attached = false; + }; + doDefaults(pixel); + var shouldSpoil = true; //spoil by default + if(pixel.attached) { //if it's attached + if(!isEmpty(attachCoords[0],attachCoords[1],true)) { //if the attachment coords are a pixel and not OOB + var attachPixel = pixelMap[attachCoords[0]][attachCoords[1]]; + var attachElement = attachPixel.element; + if(bananaAttachWhitelist.includes(attachElement)) {//if the element is a whitelisted "don't spoil" element + shouldSpoil = false; //then don't spoil }; - } else { //Move if not attached + }; + }; + if(shouldSpoil) { //spoil if not attached + if(pixel.temp > -14 && pixel.temp <= 4) { //(no spoiling below 14C) + pixel.spoilage += Math.max(Math.min(scale(pixel.temp,-14,4,0,9),9),0) + } else if(pixel.temp > 4) { + pixel.spoilage += Math.max(Math.min(scale(pixel.temp,4,20,9,30),40),0) + }; + }; + if(pixel.spoilage > 14400) { //3600 = 120 ticks at 20C + if(Math.random() < 0.05) { + changePixel(pixel,"spoiled_banana"); + }; + }; + }, + properties: { + "spoilage":0, + "attached": false, + "attachDirection": (!Math.floor(Math.random() * 2)) ? 1 : -1, + }, + burn: 5, + burnInto: ["steam", "ash"], + burnTime: 600, + tempHigh: 200, + stateHigh: ["steam", "ash"], + onMoveInto: function(pixel,otherPixel) { + var otherInfo = elements[otherPixel.element] + if(typeof(otherInfo.state) === "string" && otherInfo.state !== "gas") { + pixel.attached = false; + }; + }, + category: "food" +}; + +elements.banana_peduncle_1 = { + hidden: true, + name: "banana peduncle (offshoot)", + color: "#acb55b", + tick: function(pixel) { + if(pixel.bananaRange === null) { + pixel.bananaRange = randomNumberFromOneToThree(); + }; + + if (pixel.age > 20 && pixel.temp < 100) { + var peduncleCoords1 = [pixel.x + pixel.dir, pixel.y]; + var peduncleCoords2 = [pixel.x + pixel.dir, pixel.y + 1]; + if(isEmpty(peduncleCoords1[0],peduncleCoords1[1],false) && isEmpty(peduncleCoords2[0],peduncleCoords2[1],false)) { + if(Math.random() < 0.5) { + createPixel(pixel.element,peduncleCoords1[0],peduncleCoords1[1]); + pixelMap[peduncleCoords1[0]][peduncleCoords1[1]].dir = pixel.dir; + pixelMap[peduncleCoords1[0]][peduncleCoords1[1]].bananaRange = pixel.bananaRange; //pass banana range down to next pixel of peduncle horizontal + } else { + createPixel("banana_peduncle_2",peduncleCoords2[0],peduncleCoords2[1]); + pixelMap[peduncleCoords2[0]][peduncleCoords2[1]].bananaRange = pixel.bananaRange; //pass banana range down to diagonal offshoot + }; + }; + }; + pixel.age++; + doDefaults(pixel); + }, + properties: { + "dir": (!Math.floor(Math.random() * 2)) ? 1 : -1, + "age": 0, + //"bananaRange": (1 + (Math.floor(Math.random() * 3))), //1-3 + "bananaRange": null, + }, + tempHigh: 100, + stateHigh: "dead_plant", + tempLow: -2, + stateLow: "frozen_plant", + burn: 5, + burnInto: ["steam", "ash"], + burnTime: 600, + category: "life", + state: "solid", + density: 1500, +}; + +elements.banana_peduncle_2 = { + hidden: true, + name: "banana peduncle (hanging)", + color: "#9bad51", + tick: function(pixel) { + if(pixel.bananaRange === null) { + pixel.bananaRange = randomNumberFromOneToThree(); + }; + + // Grow/Flower + if (pixel.age > 20 && pixel.temp < 100) { + var growthCoords = [pixel.x, pixel.y + 1]; + if(isEmpty(...growthCoords)) { + if(Math.random() < 0.9) { + createPixel(pixel.element,...growthCoords); + pixelMap[growthCoords[0]][growthCoords[1]].bananaRange = pixel.bananaRange; //pass banana range down to next pixel of peduncle vertical + } else { + createPixel("petal",...growthCoords); //the sexual dimorphism of the banana plant has zonked me + }; + }; + }; + + //Make bananas + if (pixel.age > 40 && pixel.temp < 100) { + var bananaOffsets = [-1, 1]; //placed to the left, placed to the right + for(i = 0; i < bananaOffsets.length; i++) { + //console.log(`Looping through left and right positions: ${bananaOffsets}`); + for(j = 1; j < pixel.bananaRange + 1; j++) { //for max banana distance, using the banana range + //console.log(`Looping through banana offset multipliers: ${j}`); + if (isEmpty(pixel.x+(j * bananaOffsets[i]),pixel.y,false)) { //if there's an empty space + //console.log(`Banana position is empty: [${j * bananaOffsets[i]}, 0]\nTrying banana at (${pixel.x+(j * bananaOffsets[i])},${pixel.y})`); + if (Math.random() < (debugSpeedGrowth ? 0.05 : 0.005)) { //try to place the banana + //console.log(`Placing banana`); + createPixel("banana",pixel.x+(j * bananaOffsets[i]),pixel.y); + pixelMap[pixel.x+(j * bananaOffsets[i])][pixel.y].attached = true; + pixelMap[pixel.x+(j * bananaOffsets[i])][pixel.y].attachDirection = -1 * Math.sign(bananaOffsets[i]); //attach dir is the opposite of placement dir so it attaches towards the stem + } else { + //console.log(`NOT placing banana`); + }; + //console.log(`Banana tried, stopping iteration`); + break; //and then stop iteration + } else { + //console.log(`Banana position is NOT empty: [${j * bananaOffsets[i]}, 0]\nSkipping this offset`); + continue; //if not empty, skip that pixel and move on the next distance + }; + //console.log(`====End of side try====`); + }; + //console.log(`####End of side iterator####`); + }; + //console.log(`>>>>End of banana iterator<<<<`); + }; + pixel.age++; + doDefaults(pixel); + //console.log(`\nEnd of peduncle tick\n`); + }, + properties: { + "age": 0, + //"bananaRange": (1 + (Math.floor(Math.random() * 3))), //1-3 + "bananaRange": null, + }, + tempHigh: 100, + stateHigh: "dead_plant", + tempLow: -2, + stateLow: "frozen_plant", + burn: 5, + burnInto: ["steam", "ash"], + burnTime: 600, + category: "life", + state: "solid", + density: 1500, +}; + +elements.spoiled_banana = { + hidden: true, + color: "#594b29", + behavior: [ + "XX|CR:stench,fly%0.1|XX", + "M2%0.5|CH:dirty_water,fly,fly%0.007|M2%0.5", + "M2|M1|M2" + ], + stain: 0.01, + burn: 5, + burnInto: ["steam", "ash"], + burnTime: 600, + tempHigh: 200, + stateHigh: ["steam", "ash"], +}; + +elements.fly.reactions.spoiled_banana = { "elem2":null, chance:0.15, func:behaviors.FEEDPIXEL }; + +elements.banana_leaf = { + hidden: true, + color: "#9df24e", + tick: function(pixel) { + if(pixel.bananaRange === null) { + pixel.bananaRange = randomNumberFromOneToThree(); + }; + + if(pixel.attached) { + var attachCoords = [pixel.x + pixel.attachOffsets[0], pixel.y + pixel.attachOffsets[1]]; + if(isEmpty(attachCoords[0],attachCoords[1],false)) { //consider OOB full + pixel.attached = false; + }; + } else { //Move if not attached + if(Math.random() < 0.2) { if (!tryMove(pixel, pixel.x, pixel.y+1)) { - if(Math.random() < 0.9) { + if(Math.random() < 0.4) { if (Math.random() < 0.5) { if (!tryMove(pixel, pixel.x+1, pixel.y+1)) { tryMove(pixel, pixel.x-1, pixel.y+1); @@ -146,398 +354,192 @@ if(enabledMods.includes(onTryMoveIntoMod) && enabledMods.includes(libraryMod)) { }; }; }; - doDefaults(pixel); - var shouldSpoil = true; //spoil by default - if(pixel.attached) { //if it's attached - if(!isEmpty(attachCoords[0],attachCoords[1],true)) { //if the attachment coords are a pixel and not OOB - var attachPixel = pixelMap[attachCoords[0]][attachCoords[1]]; - var attachElement = attachPixel.element; - if(bananaAttachWhitelist.includes(attachElement)) {//if the element is a whitelisted "don't spoil" element - shouldSpoil = false; //then don't spoil - }; + }; + doDefaults(pixel); + }, + properties: { + "attached": false, + "attachOffsets": [(!Math.floor(Math.random() * 2)) ? 1 : -1, 0], + "bananaRange": null, + }, + burn: 5, + burnInto: ["steam", "ash"], + burnTime: 600, + tempHigh: 200, + stateHigh: ["steam", "ash"], + onMoveInto: function(pixel,otherPixel) { //Move through + var otherElement = otherPixel.element; //var element for readability + + var otherInfo = elements[otherElement]; //var info + + var otherState = "solid"; //consider things solid by default + if(typeof(otherInfo.state) === "string") { + otherState = otherInfo.state; //get actual state if it exists + }; + + var otherDensity = 1000; //consider density 1000 by default + if(typeof(otherInfo.density) === "number") { + otherDensity = otherInfo.density; //get actual density if it exists + }; + + var react = false; //default to no reaction + if(typeof(otherInfo.reactions) === "object") { //look for reactions + if(typeof(otherInfo.reactions[pixel.element]) === "object") { //look for reactions involving this element + react = true; //if there are any, set reaction flag to true + }; + }; + + if(otherElement.endsWith("head") || otherElement.endsWith("body")) { + //i don't want to make general MPL handling so I'll just try to exclude them; + if(otherElement !== "antibody") { + //exclude antibody from exclusion + return false; + }; + }; + + if(otherElement !== pixel.element) { //allow this element from piling on itself + if(logLeaves) { console.log("Other element is not banana leaves") }; //yes, this code is for banana leaves + if(react) { //if there was a reaction in that previous step + if(logLeaves) { console.log("Reacting pixels") }; + reactPixels(otherPixel,pixel); //react + } else { //if no such reaction existed, move through + if(logLeaves) { console.log("Moving pixels") }; + if((otherState !== "solid") || (otherState === "solid" && otherDensity > 100)) { //admit any non-solid, or any solid with a density over 100 + var pX = pixel.x; //var pixel coords for no particular reason + var pY = pixel.y; + var oX = otherPixel.x; //var other pixel's coords for no particular reason + var oY = otherPixel.y; + if(logLeaves) { console.log(`${otherElement} pixel (${oX},${oY}) trying to move info leaf block (${pX},${pY})`) }; + var dX = oX - pX; //get the difference between this's X and other's X; if the other pixel is moving from the space immediately to the right, this dX value should be 1 + var dY = oY - pY; + var iDX = -1 * dX; //get the additive inverse; if we want to move such a pixel from the right to the left, we would change its +1 X offset to a -1 X offset for the coord sto move it to + var iDY = -1 * dY; + if(logLeaves) { console.log(`Old offset (relative to leaf): [${dX},${dY}], new offset [${iDX},${iDY}]`) }; + var fX = pX + iDX; //combine this pixel's X with the inverted offset we just made; + //assuming this pixel is (23,31) and the other pixel is trying to move in to the left into this from (24,31), + //the dX would be [1, 0], signifying that the other pixel is 1 pixel to the right of this + //the space to the left of this, where it would go, is (22,31), and the offset for that pixel relative to this is [-1, 0] + //to get the [-1, 0], we'd need to flip that [1, 0] offset (lmao flip that the song by loona), hence the inverse + var fY = pY + iDY; + if(logLeaves) { console.log(`Calculated final position: (${fX},${fY}), moving other pixel from (${oX},${oY})`) }; + tryMove(otherPixel,fX,fY); }; }; - if(shouldSpoil) { //spoil if not attached - if(pixel.temp > -14 && pixel.temp <= 4) { //(no spoiling below 14C) - pixel.spoilage += Math.max(Math.min(scale(pixel.temp,-14,4,0,9),9),0) - } else if(pixel.temp > 4) { - pixel.spoilage += Math.max(Math.min(scale(pixel.temp,4,20,9,30),40),0) - }; - }; - if(pixel.spoilage > 14400) { //3600 = 120 ticks at 20C - if(Math.random() < 0.05) { - changePixel(pixel,"spoiled_banana"); - }; - }; - }, - properties: { - "spoilage":0, - "attached": false, - "attachDirection": (!Math.floor(Math.random() * 2)) ? 1 : -1, - }, - burn: 5, - burnInto: ["steam", "ash"], - burnTime: 600, - tempHigh: 200, - stateHigh: ["steam", "ash"], - onTryMoveInto: function(pixel,otherPixel) { - var otherInfo = elements[otherPixel.element] - if(typeof(otherInfo.state) === "string" && otherInfo.state !== "gas") { - pixel.attached = false; - }; - }, - }; - - elements.banana_peduncle_1 = { - hidden: true, - name: "banana peduncle (offshoot)", - color: "#acb55b", - tick: function(pixel) { - if(pixel.bananaRange === null) { - pixel.bananaRange = randomNumberFromOneToThree(); - }; - - if (pixel.age > 20 && pixel.temp < 100) { - var peduncleCoords1 = [pixel.x + pixel.dir, pixel.y]; - var peduncleCoords2 = [pixel.x + pixel.dir, pixel.y + 1]; - if(isEmpty(peduncleCoords1[0],peduncleCoords1[1],false) && isEmpty(peduncleCoords2[0],peduncleCoords2[1],false)) { - if(Math.random() < 0.5) { - createPixel(pixel.element,peduncleCoords1[0],peduncleCoords1[1]); - pixelMap[peduncleCoords1[0]][peduncleCoords1[1]].dir = pixel.dir; - pixelMap[peduncleCoords1[0]][peduncleCoords1[1]].bananaRange = pixel.bananaRange; //pass banana range down to next pixel of peduncle horizontal - } else { - createPixel("banana_peduncle_2",peduncleCoords2[0],peduncleCoords2[1]); - pixelMap[peduncleCoords2[0]][peduncleCoords2[1]].bananaRange = pixel.bananaRange; //pass banana range down to diagonal offshoot - }; - }; - }; - pixel.age++; - doDefaults(pixel); - }, - properties: { - "dir": (!Math.floor(Math.random() * 2)) ? 1 : -1, - "age": 0, - //"bananaRange": (1 + (Math.floor(Math.random() * 3))), //1-3 - "bananaRange": null, - }, - tempHigh: 100, - stateHigh: "dead_plant", - tempLow: -2, - stateLow: "frozen_plant", - burn: 5, - burnInto: ["steam", "ash"], - burnTime: 600, - category: "life", - state: "solid", - density: 1500, - }; - - elements.banana_peduncle_2 = { - hidden: true, - name: "banana peduncle (hanging)", - color: "#9bad51", - tick: function(pixel) { - if(pixel.bananaRange === null) { - pixel.bananaRange = randomNumberFromOneToThree(); - }; - - // Grow/Flower - if (pixel.age > 20 && pixel.temp < 100) { - var growthCoords = [pixel.x, pixel.y + 1]; - if(isEmpty(...growthCoords)) { - if(Math.random() < 0.9) { - createPixel(pixel.element,...growthCoords); - pixelMap[growthCoords[0]][growthCoords[1]].bananaRange = pixel.bananaRange; //pass banana range down to next pixel of peduncle vertical - } else { - createPixel("petal",...growthCoords); //the sexual dimorphism of the banana plant has zonked me - }; - }; - }; - - //Make bananas - if (pixel.age > 40 && pixel.temp < 100) { - var bananaOffsets = [-1, 1]; //placed to the left, placed to the right - for(i = 0; i < bananaOffsets.length; i++) { - //console.log(`Looping through left and right positions: ${bananaOffsets}`); - for(j = 1; j < pixel.bananaRange + 1; j++) { //for max banana distance, using the banana range - //console.log(`Looping through banana offset multipliers: ${j}`); - if (isEmpty(pixel.x+(j * bananaOffsets[i]),pixel.y,false)) { //if there's an empty space - //console.log(`Banana position is empty: [${j * bananaOffsets[i]}, 0]\nTrying banana at (${pixel.x+(j * bananaOffsets[i])},${pixel.y})`); - if (Math.random() < (debugSpeedGrowth ? 0.05 : 0.005)) { //try to place the banana - //console.log(`Placing banana`); - createPixel("banana",pixel.x+(j * bananaOffsets[i]),pixel.y); - pixelMap[pixel.x+(j * bananaOffsets[i])][pixel.y].attached = true; - pixelMap[pixel.x+(j * bananaOffsets[i])][pixel.y].attachDirection = -1 * Math.sign(bananaOffsets[i]); //attach dir is the opposite of placement dir so it attaches towards the stem - } else { - //console.log(`NOT placing banana`); - }; - //console.log(`Banana tried, stopping iteration`); - break; //and then stop iteration - } else { - //console.log(`Banana position is NOT empty: [${j * bananaOffsets[i]}, 0]\nSkipping this offset`); - continue; //if not empty, skip that pixel and move on the next distance - }; - //console.log(`====End of side try====`); - }; - //console.log(`####End of side iterator####`); - }; - //console.log(`>>>>End of banana iterator<<<<`); - }; - pixel.age++; - doDefaults(pixel); - //console.log(`\nEnd of peduncle tick\n`); - }, - properties: { - "age": 0, - //"bananaRange": (1 + (Math.floor(Math.random() * 3))), //1-3 - "bananaRange": null, - }, - tempHigh: 100, - stateHigh: "dead_plant", - tempLow: -2, - stateLow: "frozen_plant", - burn: 5, - burnInto: ["steam", "ash"], - burnTime: 600, - category: "life", - state: "solid", - density: 1500, - }; - - elements.spoiled_banana = { - hidden: true, - color: "#594b29", - behavior: [ - "XX|CR:stench,fly%0.1|XX", - "M2%0.5|CH:dirty_water,fly,fly%0.007|M2%0.5", - "M2|M1|M2" - ], - stain: 0.01, - burn: 5, - burnInto: ["steam", "ash"], - burnTime: 600, - tempHigh: 200, - stateHigh: ["steam", "ash"], - }; - - elements.fly.reactions.spoiled_banana = { "elem2":null, chance:0.15, func:behaviors.FEEDPIXEL }; - - elements.banana_leaf = { - hidden: true, - color: "#9df24e", - tick: function(pixel) { - if(pixel.bananaRange === null) { - pixel.bananaRange = randomNumberFromOneToThree(); - }; - - if(pixel.attached) { - var attachCoords = [pixel.x + pixel.attachOffsets[0], pixel.y + pixel.attachOffsets[1]]; - if(isEmpty(attachCoords[0],attachCoords[1],false)) { //consider OOB full - pixel.attached = false; - }; - } else { //Move if not attached - if(Math.random() < 0.2) { - if (!tryMove(pixel, pixel.x, pixel.y+1)) { - if(Math.random() < 0.4) { - if (Math.random() < 0.5) { - if (!tryMove(pixel, pixel.x+1, pixel.y+1)) { - tryMove(pixel, pixel.x-1, pixel.y+1); - }; - } else { - if (!tryMove(pixel, pixel.x-1, pixel.y+1)) { - tryMove(pixel, pixel.x+1, pixel.y+1); - }; - }; - }; - }; - }; - }; - doDefaults(pixel); - }, - properties: { - "attached": false, - "attachOffsets": [(!Math.floor(Math.random() * 2)) ? 1 : -1, 0], - "bananaRange": null, - }, - burn: 5, - burnInto: ["steam", "ash"], - burnTime: 600, - tempHigh: 200, - stateHigh: ["steam", "ash"], - onTryMoveInto: function(pixel,otherPixel) { //Move through - var otherElement = otherPixel.element; //var element for readability - - var otherInfo = elements[otherElement]; //var info - - var otherState = "solid"; //consider things solid by default - if(typeof(otherInfo.state) === "string") { - otherState = otherInfo.state; //get actual state if it exists - }; - - var otherDensity = 1000; //consider density 1000 by default - if(typeof(otherInfo.density) === "number") { - otherDensity = otherInfo.density; //get actual density if it exists - }; - - var react = false; //default to no reaction - if(typeof(otherInfo.reactions) === "object") { //look for reactions - if(typeof(otherInfo.reactions[pixel.element]) === "object") { //look for reactions involving this element - react = true; //if there are any, set reaction flag to true - }; - }; - - if(otherElement.endsWith("head") || otherElement.endsWith("body")) { - //i don't want to make general MPL handling so I'll just try to exclude them; - if(otherElement !== "antibody") { - //exclude antibody from exclusion - return false; - }; - }; - - if(otherElement !== pixel.element) { //allow this element from piling on itself - if(logLeaves) { console.log("Other element is not banana leaves") }; //yes, this code is for banana leaves - if(react) { //if there was a reaction in that previous step - if(logLeaves) { console.log("Reacting pixels") }; - reactPixels(otherPixel,pixel); //react - } else { //if no such reaction existed, move through - if(logLeaves) { console.log("Moving pixels") }; - if((otherState !== "solid") || (otherState === "solid" && otherDensity > 100)) { //admit any non-solid, or any solid with a density over 100 - var pX = pixel.x; //var pixel coords for no particular reason - var pY = pixel.y; - var oX = otherPixel.x; //var other pixel's coords for no particular reason - var oY = otherPixel.y; - if(logLeaves) { console.log(`${otherElement} pixel (${oX},${oY}) trying to move info leaf block (${pX},${pY})`) }; - var dX = oX - pX; //get the difference between this's X and other's X; if the other pixel is moving from the space immediately to the right, this dX value should be 1 - var dY = oY - pY; - var iDX = -1 * dX; //get the additive inverse; if we want to move such a pixel from the right to the left, we would change its +1 X offset to a -1 X offset for the coord sto move it to - var iDY = -1 * dY; - if(logLeaves) { console.log(`Old offset (relative to leaf): [${dX},${dY}], new offset [${iDX},${iDY}]`) }; - var fX = pX + iDX; //combine this pixel's X with the inverted offset we just made; - //assuming this pixel is (23,31) and the other pixel is trying to move in to the left into this from (24,31), - //the dX would be [1, 0], signifying that the other pixel is 1 pixel to the right of this - //the space to the left of this, where it would go, is (22,31), and the offset for that pixel relative to this is [-1, 0] - //to get the [-1, 0], we'd need to flip that [1, 0] offset (lmao flip that the song by loona), hence the inverse - var fY = pY + iDY; - if(logLeaves) { console.log(`Calculated final position: (${fX},${fY}), moving other pixel from (${oX},${oY})`) }; - tryMove(otherPixel,fX,fY); - }; - }; - }; - }, - }; - - /*if(!elements.diamond.reactions) { //test reaction - elements.diamond.reactions = {}; - }; - - elements.diamond.reactions.banana_leaf = { "elem2": "dead_plant" };*/ - - elements.banana_plant_top = { - hidden: true, - color: "#d5e39f", - tick: function(pixel) { - if(pixel.bananaRange === null) { - pixel.bananaRange = randomNumberFromOneToThree(); - }; - - if (pixel.age > 30 && pixel.temp < 100) { - if(!pixel.grewLeftLeaves) { - for(i = (0 - pixel.leafRange); i < 0; i++) { //left half - if(i == 0) { - continue; - }; - - var leafOffset = i; //readability - var leafX = pixel.x + leafOffset; //set X to banana_plant_top pixel's X + offset/index - var leafAttachOffset = [1, 0]; //difference 1: attaches rightwards (+) for leaves left (-) of center - var leafY = pixel.y; //set Y to default banana_plant_top pixel's Y - if(Math.abs(leafOffset) == pixel.leafRange) { - leafY++; //place edge leaves 1 pixel downwards; - leafAttachOffset[1] = -1; //compensate by subtracting 1 from Y attach offset (less Y = higher position, so they attach diagonally up-right or up-left) - }; - - if(outOfBounds(leafX,leafY)) { - continue; - }; - - if (isEmpty(leafX,leafY,false)) { - createPixel("banana_leaf",leafX,leafY); - pixelMap[leafX][leafY].attached = true; //set leaf's attached to true - pixelMap[leafX][leafY].attachOffsets = leafAttachOffset; //array of 2 numbers - pixelMap[leafX][leafY].bananaRange = pixel.bananaRange; - pixel.grewLeftLeaves = true; //difference 2: separate flag for left side - } else { - break; - }; - }; - }; - - if(!pixel.grewRightLeaves) { - for(i = 1; i < (pixel.leafRange + 1); i++) { //right half - if(i == 0) { - continue; - }; - - var leafOffset = i; //readability - var leafX = pixel.x + leafOffset; //set X to banana_plant_top pixel's X + offset/index - var leafAttachOffset = [-1, 0]; //difference 1: attaches leftwards (-) for leaves right (+) of center - var leafY = pixel.y; //set Y to default banana_plant_top pixel's Y - if(Math.abs(leafOffset) == pixel.leafRange) { - leafY++; //place edge leaves 1 pixel downwards; - leafAttachOffset[1] = -1; //compensate by subtracting 1 from Y attach offset (less Y = higher position, so they attach diagonally up-right or up-left) - }; - - if(outOfBounds(leafX,leafY)) { - continue; - }; - - if (isEmpty(leafX,leafY,false)) { - createPixel("banana_leaf",leafX,leafY); - pixelMap[leafX][leafY].attached = true; //set leaf's attached to true - pixelMap[leafX][leafY].attachOffsets = leafAttachOffset; //array of 2 numbers - pixelMap[leafX][leafY].bananaRange = pixel.bananaRange; - pixel.grewRightLeaves = true; //difference 2: separate flag for right side - } else { - break; - }; - }; - }; - }; - pixel.age++; - doDefaults(pixel); - }, - properties: { - "age": 0, - "leafRange": 2 + (Math.floor(Math.random() * 3)), //2-4 - "grewLeftLeaves": false, - "grewRightLeaves": false, - "bananaRange": null, - }, - tempHigh: 100, - stateHigh: "dead_plant", - tempLow: -2, - stateLow: "frozen_plant", - burn: 5, - burnInto: ["steam", "ash"], - burnTime: 600, - category: "life", - state: "solid", - density: 1500, - }; - - - /*elements.cocoa_bean = { - color: ["#f2ede9", "#f0dfce", "#e8cfb5"], - behavior: behaviors.SOLID, - category: "liquids", - viscosity: 100000, - state: "liquid", - density: 593, - tick: functi - };*/ -} else { - enabledMods.splice(enabledMods.indexOf(modName),0,onTryMoveIntoMod); - enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod); - localStorage.setItem("enabledMods", JSON.stringify(enabledMods)); - alert(`The ${onTryMoveIntoMod} mod and ${libraryMod} mods are required and have been automatically inserted (reload for this to take effect).`); + }; + }, }; + +/*if(!elements.diamond.reactions) { //test reaction + elements.diamond.reactions = {}; +}; + +elements.diamond.reactions.banana_leaf = { "elem2": "dead_plant" };*/ + +elements.banana_plant_top = { + hidden: true, + color: "#d5e39f", + tick: function(pixel) { + if(pixel.bananaRange === null) { + pixel.bananaRange = randomNumberFromOneToThree(); + }; + + if (pixel.age > 30 && pixel.temp < 100) { + if(!pixel.grewLeftLeaves) { + for(i = (0 - pixel.leafRange); i < 0; i++) { //left half + if(i == 0) { + continue; + }; + + var leafOffset = i; //readability + var leafX = pixel.x + leafOffset; //set X to banana_plant_top pixel's X + offset/index + var leafAttachOffset = [1, 0]; //difference 1: attaches rightwards (+) for leaves left (-) of center + var leafY = pixel.y; //set Y to default banana_plant_top pixel's Y + if(Math.abs(leafOffset) == pixel.leafRange) { + leafY++; //place edge leaves 1 pixel downwards; + leafAttachOffset[1] = -1; //compensate by subtracting 1 from Y attach offset (less Y = higher position, so they attach diagonally up-right or up-left) + }; + + if(outOfBounds(leafX,leafY)) { + continue; + }; + + if (isEmpty(leafX,leafY,false)) { + createPixel("banana_leaf",leafX,leafY); + pixelMap[leafX][leafY].attached = true; //set leaf's attached to true + pixelMap[leafX][leafY].attachOffsets = leafAttachOffset; //array of 2 numbers + pixelMap[leafX][leafY].bananaRange = pixel.bananaRange; + pixel.grewLeftLeaves = true; //difference 2: separate flag for left side + } else { + break; + }; + }; + }; + + if(!pixel.grewRightLeaves) { + for(i = 1; i < (pixel.leafRange + 1); i++) { //right half + if(i == 0) { + continue; + }; + + var leafOffset = i; //readability + var leafX = pixel.x + leafOffset; //set X to banana_plant_top pixel's X + offset/index + var leafAttachOffset = [-1, 0]; //difference 1: attaches leftwards (-) for leaves right (+) of center + var leafY = pixel.y; //set Y to default banana_plant_top pixel's Y + if(Math.abs(leafOffset) == pixel.leafRange) { + leafY++; //place edge leaves 1 pixel downwards; + leafAttachOffset[1] = -1; //compensate by subtracting 1 from Y attach offset (less Y = higher position, so they attach diagonally up-right or up-left) + }; + + if(outOfBounds(leafX,leafY)) { + continue; + }; + + if (isEmpty(leafX,leafY,false)) { + createPixel("banana_leaf",leafX,leafY); + pixelMap[leafX][leafY].attached = true; //set leaf's attached to true + pixelMap[leafX][leafY].attachOffsets = leafAttachOffset; //array of 2 numbers + pixelMap[leafX][leafY].bananaRange = pixel.bananaRange; + pixel.grewRightLeaves = true; //difference 2: separate flag for right side + } else { + break; + }; + }; + }; + }; + pixel.age++; + doDefaults(pixel); + }, + properties: { + "age": 0, + "leafRange": 2 + (Math.floor(Math.random() * 3)), //2-4 + "grewLeftLeaves": false, + "grewRightLeaves": false, + "bananaRange": null, + }, + tempHigh: 100, + stateHigh: "dead_plant", + tempLow: -2, + stateLow: "frozen_plant", + burn: 5, + burnInto: ["steam", "ash"], + burnTime: 600, + category: "life", + state: "solid", + density: 1500, +}; + + +/*elements.cocoa_bean = { + color: ["#f2ede9", "#f0dfce", "#e8cfb5"], + behavior: behaviors.SOLID, + category: "liquids", + viscosity: 100000, + state: "liquid", + density: 593, + tick: functi +};*/ + +// enabledMods.splice(enabledMods.indexOf(modName),0,onTryMoveIntoMod); +// enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod); +// localStorage.setItem("enabledMods", JSON.stringify(enabledMods)); +// alert(`The ${onTryMoveIntoMod} mod and ${libraryMod} mods are required and have been automatically inserted (reload for this to take effect).`); diff --git a/mods/boiling_things.js b/mods/boiling_things.js index 635cc91e..e5606555 100644 --- a/mods/boiling_things.js +++ b/mods/boiling_things.js @@ -1,7 +1,7 @@ var modName = "mods/boiling_things.js"; var libraryMod = "mods/code_library.js"; -if(enabledMods.includes(libraryMod)) { +dependOn("code_library.js", function(){ //glass { @@ -533,8 +533,4 @@ if(enabledMods.includes(libraryMod)) { }; }); -} else { - alert(`The ${libraryMod} mod is required and has been automatically inserted (reload for this to take effect).`) - enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod) - localStorage.setItem("enabledMods", JSON.stringify(enabledMods)); -}; +}, true); \ No newline at end of file diff --git a/mods/change.js b/mods/change.js index 9511a0c4..f6bd8f26 100644 --- a/mods/change.js +++ b/mods/change.js @@ -32,7 +32,7 @@ elements.change = { tool: function(pixel) { changePixel(pixel,changeTo,true); }, - category: "tools", + category: "edit", desc: "Changes any pixels it is used on to a specified type.
Currently replacing pixels with \"" + changeTo + "\".
Press [;] or click here to open the change prompt.", }; @@ -41,7 +41,7 @@ elements.alt_change = { tool: function(pixel) { pixel.element = changeTo; }, - category: "tools", + category: "edit", desc: "Changes any pixels it is used on to a specified type, but keeping their non-element-based properties.
Currently replacing pixels with \"" + changeTo + "\".
Press [;] or click here to open the change prompt.", hidden: true, }; @@ -52,7 +52,7 @@ elements.alt_alt_change = { pixel.element = changeTo; pixel.color = pixelColorPick(pixel); }, - category: "tools", + category: "edit", desc: "Changes any pixels it is used on to a specified type, but keeping their non-element-based properties except for color.
Currently replacing pixels with \"" + changeTo + "\".
Press [;] or click here to open the change prompt.", hidden: true, }; \ No newline at end of file diff --git a/mods/cherries.js b/mods/cherries.js index 1d4b786d..aebd93e2 100644 --- a/mods/cherries.js +++ b/mods/cherries.js @@ -1,139 +1,350 @@ var modName = "mods/cherries.js"; -var onTryMoveIntoMod = "mods/onTryMoveInto.js"; -var libraryMod = "mods/code_library.js"; +// var onTryMoveIntoMod = "mods/onTryMoveInto.js"; +// var libraryMod = "mods/code_library.js"; -if(enabledMods.includes(onTryMoveIntoMod) && enabledMods.includes(libraryMod)) { - randomNumberFromOneToThree = function() { - return 1 + Math.floor(Math.random() * 3) - }; - - debugSpeedGrowth = false; - logLeaves = false; - cherryAttachWhitelist = ["cherry_log","cherry_branch_1","cherry_branch_2","blossom","cherry_leaf","cherry_plant_top","cherry"]; - - cherryDirtElements = ["dirt","mud","sand","wet_sand","clay_soil","mycelium","grass"]; +function scale (number, inMin, inMax, outMin, outMax) { + return (number - inMin) * (outMax - outMin) / (inMax - inMin) + outMin; +} - function logPixelCoords(pixel) { - return `(${pixel.x}, ${pixel.y})` - }; +randomNumberFromOneToThree = function() { + return 1 + Math.floor(Math.random() * 3) +}; - function hasPixel(x,y,elementInput) { - if(isEmpty(x,y,true)) { //if empty, it can't have a pixel - return false; +debugSpeedGrowth = false; +logLeaves = false; +cherryAttachWhitelist = ["cherry_log","cherry_branch_1","cherry_branch_2","blossom","cherry_leaf","cherry_plant_top","cherry"]; + +cherryDirtElements = ["dirt","mud","sand","wet_sand","clay_soil","mycelium","grass"]; + +function logPixelCoords(pixel) { + return `(${pixel.x}, ${pixel.y})` +}; + +function hasPixel(x,y,elementInput) { + if(isEmpty(x,y,true)) { //if empty, it can't have a pixel + return false; + } else { + if(elementInput.includes(",")) { //CSTA + elementInput = elementInput.split(","); + }; + if(Array.isArray(elementInput)) { //if element list + return elementInput.includes(pixelMap[x][y].element); + } else { //if single element + return pixelMap[x][y].element === elementInput; + }; + }; +}; + +elements.cherry_seed = { + color: "#8b4513", + tick: function(pixel) { + if(pixel.cherryRange === null) { + pixel.cherryRange = randomNumberFromOneToThree(); + }; + + if (isEmpty(pixel.x,pixel.y+1)) { + movePixel(pixel,pixel.x,pixel.y+1); } else { - if(elementInput.includes(",")) { //CSTA - elementInput = elementInput.split(","); - }; - if(Array.isArray(elementInput)) { //if element list - return elementInput.includes(pixelMap[x][y].element); - } else { //if single element - return pixelMap[x][y].element === elementInput; - }; - }; - }; - - elements.cherry_seed = { - color: "#8b4513", - tick: function(pixel) { - if(pixel.cherryRange === null) { - pixel.cherryRange = randomNumberFromOneToThree(); - }; - - if (isEmpty(pixel.x,pixel.y+1)) { - movePixel(pixel,pixel.x,pixel.y+1); - } else { - if (Math.random() < (debugSpeedGrowth ? 0.09 : 0.03) && pixel.age > (debugSpeedGrowth ? 20 : 50) && pixel.temp < 100) { - if (!outOfBounds(pixel.x,pixel.y+1)) { - var dirtPixel = pixelMap[pixel.x][pixel.y+1]; - if (cherryDirtElements.includes(dirtPixel.element)) { - changePixel(dirtPixel,"root"); - }; + if (Math.random() < (debugSpeedGrowth ? 0.09 : 0.03) && pixel.age > (debugSpeedGrowth ? 20 : 50) && pixel.temp < 100) { + if (!outOfBounds(pixel.x,pixel.y+1)) { + var dirtPixel = pixelMap[pixel.x][pixel.y+1]; + if (cherryDirtElements.includes(dirtPixel.element)) { + changePixel(dirtPixel,"root"); }; - if (isEmpty(pixel.x,pixel.y-1)) { - movePixel(pixel,pixel.x,pixel.y-1); - createPixel("cherry_log",pixel.x,pixel.y+1); - pixelMap[pixel.x][pixel.y+1].cherryRange = pixel.cherryRange; //pass cherry range down to log - }; - } else if (pixel.age > (debugSpeedGrowth ? 500 : 1000)) { - changePixel(pixel,"cherry_plant_top"); }; - pixel.age++; - }; - if(Math.random() < 0.01 && pixel.age > 200) { + if (isEmpty(pixel.x,pixel.y-1)) { + movePixel(pixel,pixel.x,pixel.y-1); + createPixel("cherry_log",pixel.x,pixel.y+1); + pixelMap[pixel.x][pixel.y+1].cherryRange = pixel.cherryRange; //pass cherry range down to log + }; + } else if (pixel.age > (debugSpeedGrowth ? 500 : 1000)) { changePixel(pixel,"cherry_plant_top"); }; - doDefaults(pixel); - }, - properties: { - "age": 0, - //"cherryRange": null, //apparently this is suddenly, in an illogical, never-before-seen, completely new, unprecedented incident of bad behavior, evaluated before being put into the property database, so RNG has to be done in tick - "cherryRange": null, - }, - tempHigh: 100, - stateHigh: "dead_plant", - tempLow: -2, - stateLow: "frozen_plant", - burn: 5, - burnInto: ["steam", "ash"], - burnTime: 600, - category: "life", - state: "solid", - density: 1500, - cooldown: defaultCooldown, - }; + pixel.age++; + }; + if(Math.random() < 0.01 && pixel.age > 200) { + changePixel(pixel,"cherry_plant_top"); + }; + doDefaults(pixel); + }, + properties: { + "age": 0, + //"cherryRange": null, //apparently this is suddenly, in an illogical, never-before-seen, completely new, unprecedented incident of bad behavior, evaluated before being put into the property database, so RNG has to be done in tick + "cherryRange": null, + }, + tempHigh: 100, + stateHigh: "dead_plant", + tempLow: -2, + stateLow: "frozen_plant", + burn: 5, + burnInto: ["steam", "ash"], + burnTime: 600, + category: "life", + state: "solid", + density: 1500, + cooldown: defaultCooldown, +}; - elements.cherry_log = { - hidden: true, - color: "#310a0b", - tick: function(pixel) { - if(pixel.cherryRange === null) { - pixel.cherryRange = randomNumberFromOneToThree(); +elements.cherry_log = { + hidden: true, + color: "#310a0b", + tick: function(pixel) { + if(pixel.cherryRange === null) { + pixel.cherryRange = randomNumberFromOneToThree(); + }; + + if (pixel.age > 60 && pixel.temp < 100 && !pixel.grewPeduncle) { + var peduncleOffsets = [-1, 1]; //placed to the left, placed to the right + for(i = 0; i < peduncleOffsets.length; i++) { + if (isEmpty(pixel.x+peduncleOffsets[i],pixel.y,false)) { + if (Math.random() < 0.005) { + createPixel("cherry_branch_1",pixel.x+peduncleOffsets[i],pixel.y); + pixelMap[pixel.x+peduncleOffsets[i]][pixel.y].dir = Math.sign(peduncleOffsets[i]); + pixelMap[pixel.x+peduncleOffsets[i]][pixel.y].cherryRange = pixel.cherryRange; //pass cherry range down to branch + if(Math.random() < 0.8) { pixel.grewPeduncle = true; } //20% chance to not mark as true, allowing for a chance to try another branch + }; + }; }; + }; + pixel.age++; + doDefaults(pixel); + }, + properties: { + "age": 0, + "grewPeduncle": false, + "cherryRange": null, + }, + tempHigh: 100, + stateHigh: "dead_plant", + tempLow: -2, + stateLow: "frozen_plant", + burn: 5, + burnInto: ["steam", "ash"], + burnTime: 600, + category: "life", + state: "solid", + density: 1500, +}; - if (pixel.age > 60 && pixel.temp < 100 && !pixel.grewPeduncle) { - var peduncleOffsets = [-1, 1]; //placed to the left, placed to the right - for(i = 0; i < peduncleOffsets.length; i++) { - if (isEmpty(pixel.x+peduncleOffsets[i],pixel.y,false)) { - if (Math.random() < 0.005) { - createPixel("cherry_branch_1",pixel.x+peduncleOffsets[i],pixel.y); - pixelMap[pixel.x+peduncleOffsets[i]][pixel.y].dir = Math.sign(peduncleOffsets[i]); - pixelMap[pixel.x+peduncleOffsets[i]][pixel.y].cherryRange = pixel.cherryRange; //pass cherry range down to branch - if(Math.random() < 0.8) { pixel.grewPeduncle = true; } //20% chance to not mark as true, allowing for a chance to try another branch +elements.cherry = { + color: "#f7022a", + tick: function(pixel) { + if(pixel.attached) { + var attachCoords = [pixel.x+Math.sign(pixel.attachDirection), pixel.y]; + if(isEmpty(attachCoords[0],attachCoords[1],false)) { + pixel.attached = false; + }; + } else { //Move if not attached + if (!tryMove(pixel, pixel.x, pixel.y+1)) { + if(Math.random() < 0.9) { + if (Math.random() < 0.5) { + if (!tryMove(pixel, pixel.x+1, pixel.y+1)) { + tryMove(pixel, pixel.x-1, pixel.y+1); + }; + } else { + if (!tryMove(pixel, pixel.x-1, pixel.y+1)) { + tryMove(pixel, pixel.x+1, pixel.y+1); }; }; }; }; - pixel.age++; - doDefaults(pixel); - }, - properties: { - "age": 0, - "grewPeduncle": false, - "cherryRange": null, - }, - tempHigh: 100, - stateHigh: "dead_plant", - tempLow: -2, - stateLow: "frozen_plant", - burn: 5, - burnInto: ["steam", "ash"], - burnTime: 600, - category: "life", - state: "solid", - density: 1500, - }; - - elements.cherry = { - color: "#f7022a", - tick: function(pixel) { - if(pixel.attached) { - var attachCoords = [pixel.x+Math.sign(pixel.attachDirection), pixel.y]; - if(isEmpty(attachCoords[0],attachCoords[1],false)) { - pixel.attached = false; + }; + doDefaults(pixel); + var shouldSpoil = true; //spoil by default + if(pixel.attached) { //if it's attached + if(!isEmpty(attachCoords[0],attachCoords[1],true)) { //if the attachment coords are a pixel and not OOB + var attachPixel = pixelMap[attachCoords[0]][attachCoords[1]]; + var attachElement = attachPixel.element; + if(cherryAttachWhitelist.includes(attachElement)) {//if the element is a whitelisted "don't spoil" element + shouldSpoil = false; //then don't spoil }; - } else { //Move if not attached + }; + }; + if(shouldSpoil) { //spoil if not attached + if(pixel.temp > -14 && pixel.temp <= 4) { //(no spoiling below 14C) + pixel.spoilage += Math.max(Math.min(scale(pixel.temp,-14,4,0,9),9),0) + } else if(pixel.temp > 4) { + pixel.spoilage += Math.max(Math.min(scale(pixel.temp,4,20,9,30),40),0) + }; + }; + if(pixel.spoilage > 14400) { //3600 = 120 ticks at 20C + if(Math.random() < 0.05) { + changePixel(pixel,"spoiled_cherry"); + }; + }; + }, + properties: { + "spoilage":0, + "attached": false, + "attachDirection": (!Math.floor(Math.random() * 2)) ? 1 : -1, + }, + burn: 5, + burnInto: ["steam", "ash"], + burnTime: 600, + tempHigh: 200, + stateHigh: ["steam", "ash"], + onMoveInto: function(pixel,otherPixel) { + var otherInfo = elements[otherPixel.element] + if(typeof(otherInfo.state) === "string" && otherInfo.state !== "gas") { + pixel.attached = false; + }; + }, + category: "food", + breakInto: "juice", + breakIntoColor: "#A20205" +}; + +elements.cherry_branch_1 = { + hidden: true, + name: "cherry branch (offshoot)", + color: "#310a0b", + tick: function(pixel) { + if(pixel.cherryRange === null) { + pixel.cherryRange = randomNumberFromOneToThree(); + }; + + if (pixel.age > 20 && pixel.temp < 100) { + var peduncleCoords1 = [pixel.x + pixel.dir, pixel.y]; + var peduncleCoords2 = [pixel.x + pixel.dir, pixel.y + 1]; + if(isEmpty(peduncleCoords1[0],peduncleCoords1[1],false) && isEmpty(peduncleCoords2[0],peduncleCoords2[1],false)) { + if(Math.random() < 0.5) { + createPixel(pixel.element,peduncleCoords1[0],peduncleCoords1[1]); + pixelMap[peduncleCoords1[0]][peduncleCoords1[1]].dir = pixel.dir; + pixelMap[peduncleCoords1[0]][peduncleCoords1[1]].cherryRange = pixel.cherryRange; //pass cherry range down to next pixel of branch horizontal + } else { + createPixel("cherry_branch_2",peduncleCoords2[0],peduncleCoords2[1]); + pixelMap[peduncleCoords2[0]][peduncleCoords2[1]].cherryRange = pixel.cherryRange; //pass cherry range down to diagonal offshoot + }; + }; + }; + pixel.age++; + doDefaults(pixel); + }, + properties: { + "dir": (!Math.floor(Math.random() * 2)) ? 1 : -1, + "age": 0, + //"cherryRange": (1 + (Math.floor(Math.random() * 3))), //1-3 + "cherryRange": null, + }, + tempHigh: 100, + stateHigh: "dead_plant", + tempLow: -2, + stateLow: "frozen_plant", + burn: 5, + burnInto: ["steam", "ash"], + burnTime: 600, + category: "life", + state: "solid", + density: 1500, +}; + +elements.cherry_branch_2 = { + hidden: true, + name: "cherry branch (hanging)", + color: "#310a0b", + tick: function(pixel) { + if(pixel.cherryRange === null) { + pixel.cherryRange = randomNumberFromOneToThree(); + }; + + // Grow/Flower + if (pixel.age > 20 && pixel.temp < 100) { + var growthCoords = [pixel.x, pixel.y + 1]; + if(isEmpty(...growthCoords)) { + if(Math.random() < 0.9) { + createPixel(pixel.element,...growthCoords); + pixelMap[growthCoords[0]][growthCoords[1]].cherryRange = pixel.cherryRange; //pass cherry range down to next pixel of branch vertical + } else { + createPixel("blossom",...growthCoords); // cherry flower + }; + }; + }; + + //Make cherries + if (pixel.age > 40 && pixel.temp < 100) { + var cherryOffsets = [-1, 1]; //placed to the left, placed to the right + for(i = 0; i < cherryOffsets.length; i++) { + //console.log(`Looping through left and right positions: ${cherryOffsets}`); + for(j = 1; j < pixel.cherryRange + 1; j++) { //for max cherry distance, using the cherry range + //console.log(`Looping through cherry offset multipliers: ${j}`); + if (isEmpty(pixel.x+(j * cherryOffsets[i]),pixel.y,false)) { //if there's an empty space + //console.log(`Cherry position is empty: [${j * cherryOffsets[i]}, 0]\nTrying cherry at (${pixel.x+(j * cherryOffsets[i])},${pixel.y})`); + if (Math.random() < (debugSpeedGrowth ? 0.05 : 0.005)) { //try to place the cherry + //console.log(`Placing cherry`); + createPixel("cherry",pixel.x+(j * cherryOffsets[i]),pixel.y); + pixelMap[pixel.x+(j * cherryOffsets[i])][pixel.y].attached = true; + pixelMap[pixel.x+(j * cherryOffsets[i])][pixel.y].attachDirection = -1 * Math.sign(cherryOffsets[i]); //attach dir is the opposite of placement dir so it attaches towards the stem + } else { + //console.log(`NOT placing cherry`); + }; + //console.log(`Cherry tried, stopping iteration`); + break; //and then stop iteration + } else { + //console.log(`Cherry position is NOT empty: [${j * cherryOffsets[i]}, 0]\nSkipping this offset`); + continue; //if not empty, skip that pixel and move on the next distance + }; + //console.log(`====End of side try====`); + }; + //console.log(`####End of side iterator####`); + }; + //console.log(`>>>>End of cherry iterator<<<<`); + }; + pixel.age++; + doDefaults(pixel); + //console.log(`\nEnd of branch tick\n`); + }, + properties: { + "age": 0, + //"cherryRange": (1 + (Math.floor(Math.random() * 3))), //1-3 + "cherryRange": null, + }, + tempHigh: 100, + stateHigh: "dead_plant", + tempLow: -2, + stateLow: "frozen_plant", + burn: 5, + burnInto: ["steam", "ash"], + burnTime: 600, + category: "life", + state: "solid", + density: 1500, +}; + +elements.spoiled_cherry = { + hidden: true, + color: "#594b29", + behavior: [ + "XX|CR:stench,fly%0.1|XX", + "M2%0.5|CH:dirty_water,fly,fly%0.007|M2%0.5", + "M2|M1|M2" + ], + stain: 0.01, + burn: 5, + burnInto: ["steam", "ash"], + burnTime: 600, + tempHigh: 200, + stateHigh: ["steam", "ash"], +}; + +elements.fly.reactions.spoiled_cherry = { "elem2":null, chance:0.15, func:behaviors.FEEDPIXEL }; + +elements.cherry_leaf = { + hidden: true, + color: "#9df24e", + tick: function(pixel) { + if(pixel.cherryRange === null) { + pixel.cherryRange = randomNumberFromOneToThree(); + }; + + if(pixel.attached) { + var attachCoords = [pixel.x + pixel.attachOffsets[0], pixel.y + pixel.attachOffsets[1]]; + if(isEmpty(attachCoords[0],attachCoords[1],false)) { //consider OOB full + pixel.attached = false; + }; + } else { //Move if not attached + if(Math.random() < 0.2) { if (!tryMove(pixel, pixel.x, pixel.y+1)) { - if(Math.random() < 0.9) { + if(Math.random() < 0.4) { if (Math.random() < 0.5) { if (!tryMove(pixel, pixel.x+1, pixel.y+1)) { tryMove(pixel, pixel.x-1, pixel.y+1); @@ -146,398 +357,193 @@ if(enabledMods.includes(onTryMoveIntoMod) && enabledMods.includes(libraryMod)) { }; }; }; - doDefaults(pixel); - var shouldSpoil = true; //spoil by default - if(pixel.attached) { //if it's attached - if(!isEmpty(attachCoords[0],attachCoords[1],true)) { //if the attachment coords are a pixel and not OOB - var attachPixel = pixelMap[attachCoords[0]][attachCoords[1]]; - var attachElement = attachPixel.element; - if(cherryAttachWhitelist.includes(attachElement)) {//if the element is a whitelisted "don't spoil" element - shouldSpoil = false; //then don't spoil - }; + }; + doDefaults(pixel); + }, + properties: { + "attached": false, + "attachOffsets": [(!Math.floor(Math.random() * 2)) ? 1 : -1, 0], + "cherryRange": null, + }, + burn: 5, + burnInto: ["steam", "ash"], + burnTime: 600, + tempHigh: 200, + stateHigh: ["steam", "ash"], + onMoveInto: function(pixel,otherPixel) { //Move through + var otherElement = otherPixel.element; //var element for readability + + var otherInfo = elements[otherElement]; //var info + + var otherState = "solid"; //consider things solid by default + if(typeof(otherInfo.state) === "string") { + otherState = otherInfo.state; //get actual state if it exists + }; + + var otherDensity = 1000; //consider density 1000 by default + if(typeof(otherInfo.density) === "number") { + otherDensity = otherInfo.density; //get actual density if it exists + }; + + var react = false; //default to no reaction + if(typeof(otherInfo.reactions) === "object") { //look for reactions + if(typeof(otherInfo.reactions[pixel.element]) === "object") { //look for reactions involving this element + react = true; //if there are any, set reaction flag to true + }; + }; + + if(otherElement.endsWith("head") || otherElement.endsWith("body")) { + //i don't want to make general MPL handling so I'll just try to exclude them; + if(otherElement !== "antibody") { + //exclude antibody from exclusion + return false; + }; + }; + + if(otherElement !== pixel.element) { //allow this element from piling on itself + if(logLeaves) { console.log("Other element is not cherry leaves") }; //yes, this code is for cherry leaves + if(react) { //if there was a reaction in that previous step + if(logLeaves) { console.log("Reacting pixels") }; + reactPixels(otherPixel,pixel); //react + } else { //if no such reaction existed, move through + if(logLeaves) { console.log("Moving pixels") }; + if((otherState !== "solid") || (otherState === "solid" && otherDensity > 100)) { //admit any non-solid, or any solid with a density over 100 + var pX = pixel.x; //var pixel coords for no particular reason + var pY = pixel.y; + var oX = otherPixel.x; //var other pixel's coords for no particular reason + var oY = otherPixel.y; + if(logLeaves) { console.log(`${otherElement} pixel (${oX},${oY}) trying to move info leaf block (${pX},${pY})`) }; + var dX = oX - pX; //get the difference between this's X and other's X; if the other pixel is moving from the space immediately to the right, this dX value should be 1 + var dY = oY - pY; + var iDX = -1 * dX; //get the additive inverse; if we want to move such a pixel from the right to the left, we would change its +1 X offset to a -1 X offset for the coord sto move it to + var iDY = -1 * dY; + if(logLeaves) { console.log(`Old offset (relative to leaf): [${dX},${dY}], new offset [${iDX},${iDY}]`) }; + var fX = pX + iDX; //combine this pixel's X with the inverted offset we just made; + //assuming this pixel is (23,31) and the other pixel is trying to move in to the left into this from (24,31), + //the dX would be [1, 0], signifying that the other pixel is 1 pixel to the right of this + //the space to the left of this, where it would go, is (22,31), and the offset for that pixel relative to this is [-1, 0] + //to get the [-1, 0], we'd need to flip that [1, 0] offset (lmao flip that the song by loona), hence the inverse + var fY = pY + iDY; + if(logLeaves) { console.log(`Calculated final position: (${fX},${fY}), moving other pixel from (${oX},${oY})`) }; + tryMove(otherPixel,fX,fY); }; }; - if(shouldSpoil) { //spoil if not attached - if(pixel.temp > -14 && pixel.temp <= 4) { //(no spoiling below 14C) - pixel.spoilage += Math.max(Math.min(scale(pixel.temp,-14,4,0,9),9),0) - } else if(pixel.temp > 4) { - pixel.spoilage += Math.max(Math.min(scale(pixel.temp,4,20,9,30),40),0) - }; - }; - if(pixel.spoilage > 14400) { //3600 = 120 ticks at 20C - if(Math.random() < 0.05) { - changePixel(pixel,"spoiled_cherry"); - }; - }; - }, - properties: { - "spoilage":0, - "attached": false, - "attachDirection": (!Math.floor(Math.random() * 2)) ? 1 : -1, - }, - burn: 5, - burnInto: ["steam", "ash"], - burnTime: 600, - tempHigh: 200, - stateHigh: ["steam", "ash"], - onTryMoveInto: function(pixel,otherPixel) { - var otherInfo = elements[otherPixel.element] - if(typeof(otherInfo.state) === "string" && otherInfo.state !== "gas") { - pixel.attached = false; - }; - }, - }; - - elements.cherry_branch_1 = { - hidden: true, - name: "cherry branch (offshoot)", - color: "#310a0b", - tick: function(pixel) { - if(pixel.cherryRange === null) { - pixel.cherryRange = randomNumberFromOneToThree(); - }; - - if (pixel.age > 20 && pixel.temp < 100) { - var peduncleCoords1 = [pixel.x + pixel.dir, pixel.y]; - var peduncleCoords2 = [pixel.x + pixel.dir, pixel.y + 1]; - if(isEmpty(peduncleCoords1[0],peduncleCoords1[1],false) && isEmpty(peduncleCoords2[0],peduncleCoords2[1],false)) { - if(Math.random() < 0.5) { - createPixel(pixel.element,peduncleCoords1[0],peduncleCoords1[1]); - pixelMap[peduncleCoords1[0]][peduncleCoords1[1]].dir = pixel.dir; - pixelMap[peduncleCoords1[0]][peduncleCoords1[1]].cherryRange = pixel.cherryRange; //pass cherry range down to next pixel of branch horizontal - } else { - createPixel("cherry_branch_2",peduncleCoords2[0],peduncleCoords2[1]); - pixelMap[peduncleCoords2[0]][peduncleCoords2[1]].cherryRange = pixel.cherryRange; //pass cherry range down to diagonal offshoot - }; - }; - }; - pixel.age++; - doDefaults(pixel); - }, - properties: { - "dir": (!Math.floor(Math.random() * 2)) ? 1 : -1, - "age": 0, - //"cherryRange": (1 + (Math.floor(Math.random() * 3))), //1-3 - "cherryRange": null, - }, - tempHigh: 100, - stateHigh: "dead_plant", - tempLow: -2, - stateLow: "frozen_plant", - burn: 5, - burnInto: ["steam", "ash"], - burnTime: 600, - category: "life", - state: "solid", - density: 1500, - }; - - elements.cherry_branch_2 = { - hidden: true, - name: "cherry branch (hanging)", - color: "#310a0b", - tick: function(pixel) { - if(pixel.cherryRange === null) { - pixel.cherryRange = randomNumberFromOneToThree(); - }; - - // Grow/Flower - if (pixel.age > 20 && pixel.temp < 100) { - var growthCoords = [pixel.x, pixel.y + 1]; - if(isEmpty(...growthCoords)) { - if(Math.random() < 0.9) { - createPixel(pixel.element,...growthCoords); - pixelMap[growthCoords[0]][growthCoords[1]].cherryRange = pixel.cherryRange; //pass cherry range down to next pixel of branch vertical - } else { - createPixel("blossom",...growthCoords); // cherry flower - }; - }; - }; - - //Make cherries - if (pixel.age > 40 && pixel.temp < 100) { - var cherryOffsets = [-1, 1]; //placed to the left, placed to the right - for(i = 0; i < cherryOffsets.length; i++) { - //console.log(`Looping through left and right positions: ${cherryOffsets}`); - for(j = 1; j < pixel.cherryRange + 1; j++) { //for max cherry distance, using the cherry range - //console.log(`Looping through cherry offset multipliers: ${j}`); - if (isEmpty(pixel.x+(j * cherryOffsets[i]),pixel.y,false)) { //if there's an empty space - //console.log(`Cherry position is empty: [${j * cherryOffsets[i]}, 0]\nTrying cherry at (${pixel.x+(j * cherryOffsets[i])},${pixel.y})`); - if (Math.random() < (debugSpeedGrowth ? 0.05 : 0.005)) { //try to place the cherry - //console.log(`Placing cherry`); - createPixel("cherry",pixel.x+(j * cherryOffsets[i]),pixel.y); - pixelMap[pixel.x+(j * cherryOffsets[i])][pixel.y].attached = true; - pixelMap[pixel.x+(j * cherryOffsets[i])][pixel.y].attachDirection = -1 * Math.sign(cherryOffsets[i]); //attach dir is the opposite of placement dir so it attaches towards the stem - } else { - //console.log(`NOT placing cherry`); - }; - //console.log(`Cherry tried, stopping iteration`); - break; //and then stop iteration - } else { - //console.log(`Cherry position is NOT empty: [${j * cherryOffsets[i]}, 0]\nSkipping this offset`); - continue; //if not empty, skip that pixel and move on the next distance - }; - //console.log(`====End of side try====`); - }; - //console.log(`####End of side iterator####`); - }; - //console.log(`>>>>End of cherry iterator<<<<`); - }; - pixel.age++; - doDefaults(pixel); - //console.log(`\nEnd of branch tick\n`); - }, - properties: { - "age": 0, - //"cherryRange": (1 + (Math.floor(Math.random() * 3))), //1-3 - "cherryRange": null, - }, - tempHigh: 100, - stateHigh: "dead_plant", - tempLow: -2, - stateLow: "frozen_plant", - burn: 5, - burnInto: ["steam", "ash"], - burnTime: 600, - category: "life", - state: "solid", - density: 1500, - }; - - elements.spoiled_cherry = { - hidden: true, - color: "#594b29", - behavior: [ - "XX|CR:stench,fly%0.1|XX", - "M2%0.5|CH:dirty_water,fly,fly%0.007|M2%0.5", - "M2|M1|M2" - ], - stain: 0.01, - burn: 5, - burnInto: ["steam", "ash"], - burnTime: 600, - tempHigh: 200, - stateHigh: ["steam", "ash"], - }; - - elements.fly.reactions.spoiled_cherry = { "elem2":null, chance:0.15, func:behaviors.FEEDPIXEL }; - - elements.cherry_leaf = { - hidden: true, - color: "#9df24e", - tick: function(pixel) { - if(pixel.cherryRange === null) { - pixel.cherryRange = randomNumberFromOneToThree(); - }; - - if(pixel.attached) { - var attachCoords = [pixel.x + pixel.attachOffsets[0], pixel.y + pixel.attachOffsets[1]]; - if(isEmpty(attachCoords[0],attachCoords[1],false)) { //consider OOB full - pixel.attached = false; - }; - } else { //Move if not attached - if(Math.random() < 0.2) { - if (!tryMove(pixel, pixel.x, pixel.y+1)) { - if(Math.random() < 0.4) { - if (Math.random() < 0.5) { - if (!tryMove(pixel, pixel.x+1, pixel.y+1)) { - tryMove(pixel, pixel.x-1, pixel.y+1); - }; - } else { - if (!tryMove(pixel, pixel.x-1, pixel.y+1)) { - tryMove(pixel, pixel.x+1, pixel.y+1); - }; - }; - }; - }; - }; - }; - doDefaults(pixel); - }, - properties: { - "attached": false, - "attachOffsets": [(!Math.floor(Math.random() * 2)) ? 1 : -1, 0], - "cherryRange": null, - }, - burn: 5, - burnInto: ["steam", "ash"], - burnTime: 600, - tempHigh: 200, - stateHigh: ["steam", "ash"], - onTryMoveInto: function(pixel,otherPixel) { //Move through - var otherElement = otherPixel.element; //var element for readability - - var otherInfo = elements[otherElement]; //var info - - var otherState = "solid"; //consider things solid by default - if(typeof(otherInfo.state) === "string") { - otherState = otherInfo.state; //get actual state if it exists - }; - - var otherDensity = 1000; //consider density 1000 by default - if(typeof(otherInfo.density) === "number") { - otherDensity = otherInfo.density; //get actual density if it exists - }; - - var react = false; //default to no reaction - if(typeof(otherInfo.reactions) === "object") { //look for reactions - if(typeof(otherInfo.reactions[pixel.element]) === "object") { //look for reactions involving this element - react = true; //if there are any, set reaction flag to true - }; - }; - - if(otherElement.endsWith("head") || otherElement.endsWith("body")) { - //i don't want to make general MPL handling so I'll just try to exclude them; - if(otherElement !== "antibody") { - //exclude antibody from exclusion - return false; - }; - }; - - if(otherElement !== pixel.element) { //allow this element from piling on itself - if(logLeaves) { console.log("Other element is not cherry leaves") }; //yes, this code is for cherry leaves - if(react) { //if there was a reaction in that previous step - if(logLeaves) { console.log("Reacting pixels") }; - reactPixels(otherPixel,pixel); //react - } else { //if no such reaction existed, move through - if(logLeaves) { console.log("Moving pixels") }; - if((otherState !== "solid") || (otherState === "solid" && otherDensity > 100)) { //admit any non-solid, or any solid with a density over 100 - var pX = pixel.x; //var pixel coords for no particular reason - var pY = pixel.y; - var oX = otherPixel.x; //var other pixel's coords for no particular reason - var oY = otherPixel.y; - if(logLeaves) { console.log(`${otherElement} pixel (${oX},${oY}) trying to move info leaf block (${pX},${pY})`) }; - var dX = oX - pX; //get the difference between this's X and other's X; if the other pixel is moving from the space immediately to the right, this dX value should be 1 - var dY = oY - pY; - var iDX = -1 * dX; //get the additive inverse; if we want to move such a pixel from the right to the left, we would change its +1 X offset to a -1 X offset for the coord sto move it to - var iDY = -1 * dY; - if(logLeaves) { console.log(`Old offset (relative to leaf): [${dX},${dY}], new offset [${iDX},${iDY}]`) }; - var fX = pX + iDX; //combine this pixel's X with the inverted offset we just made; - //assuming this pixel is (23,31) and the other pixel is trying to move in to the left into this from (24,31), - //the dX would be [1, 0], signifying that the other pixel is 1 pixel to the right of this - //the space to the left of this, where it would go, is (22,31), and the offset for that pixel relative to this is [-1, 0] - //to get the [-1, 0], we'd need to flip that [1, 0] offset (lmao flip that the song by loona), hence the inverse - var fY = pY + iDY; - if(logLeaves) { console.log(`Calculated final position: (${fX},${fY}), moving other pixel from (${oX},${oY})`) }; - tryMove(otherPixel,fX,fY); - }; - }; - }; - }, - }; - - /*if(!elements.diamond.reactions) { //test reaction - elements.diamond.reactions = {}; - }; - - elements.diamond.reactions.cherry_leaf = { "elem2": "dead_plant" };*/ - - elements.cherry_plant_top = { - hidden: true, - color: "#310a0b", - tick: function(pixel) { - if(pixel.cherryRange === null) { - pixel.cherryRange = randomNumberFromOneToThree(); - }; - - if (pixel.age > 30 && pixel.temp < 100) { - if(!pixel.grewLeftLeaves) { - for(i = (0 - pixel.leafRange); i < 0; i++) { //left half - if(i == 0) { - continue; - }; - - var leafOffset = i; //readability - var leafX = pixel.x + leafOffset; //set X to cherry_plant_top pixel's X + offset/index - var leafAttachOffset = [1, 0]; //difference 1: attaches rightwards (+) for leaves left (-) of center - var leafY = pixel.y; //set Y to default cherry_plant_top pixel's Y - if(Math.abs(leafOffset) == pixel.leafRange) { - leafY++; //place edge leaves 1 pixel downwards; - leafAttachOffset[1] = -1; //compensate by subtracting 1 from Y attach offset (less Y = higher position, so they attach diagonally up-right or up-left) - }; - - if(outOfBounds(leafX,leafY)) { - continue; - }; - - if (isEmpty(leafX,leafY,false)) { - createPixel("cherry_leaf",leafX,leafY); - pixelMap[leafX][leafY].attached = true; //set leaf's attached to true - pixelMap[leafX][leafY].attachOffsets = leafAttachOffset; //array of 2 numbers - pixelMap[leafX][leafY].cherryRange = pixel.cherryRange; - pixel.grewLeftLeaves = true; //difference 2: separate flag for left side - } else { - break; - }; - }; - }; - - if(!pixel.grewRightLeaves) { - for(i = 1; i < (pixel.leafRange + 1); i++) { //right half - if(i == 0) { - continue; - }; - - var leafOffset = i; //readability - var leafX = pixel.x + leafOffset; //set X to cherry_plant_top pixel's X + offset/index - var leafAttachOffset = [-1, 0]; //difference 1: attaches leftwards (-) for leaves right (+) of center - var leafY = pixel.y; //set Y to default cherry_plant_top pixel's Y - if(Math.abs(leafOffset) == pixel.leafRange) { - leafY++; //place edge leaves 1 pixel downwards; - leafAttachOffset[1] = -1; //compensate by subtracting 1 from Y attach offset (less Y = higher position, so they attach diagonally up-right or up-left) - }; - - if(outOfBounds(leafX,leafY)) { - continue; - }; - - if (isEmpty(leafX,leafY,false)) { - createPixel("cherry_leaf",leafX,leafY); - pixelMap[leafX][leafY].attached = true; //set leaf's attached to true - pixelMap[leafX][leafY].attachOffsets = leafAttachOffset; //array of 2 numbers - pixelMap[leafX][leafY].cherryRange = pixel.cherryRange; - pixel.grewRightLeaves = true; //difference 2: separate flag for right side - } else { - break; - }; - }; - }; - }; - pixel.age++; - doDefaults(pixel); - }, - properties: { - "age": 0, - "leafRange": 2 + (Math.floor(Math.random() * 3)), //2-4 - "grewLeftLeaves": false, - "grewRightLeaves": false, - "cherryRange": null, - }, - tempHigh: 100, - stateHigh: "dead_plant", - tempLow: -2, - stateLow: "frozen_plant", - burn: 5, - burnInto: ["steam", "ash"], - burnTime: 600, - category: "life", - state: "solid", - density: 1500, - }; - - - /*elements.cocoa_bean = { - color: ["#f2ede9", "#f0dfce", "#e8cfb5"], - behavior: behaviors.SOLID, - category: "liquids", - viscosity: 100000, - state: "liquid", - density: 593, - tick: functi - };*/ -} else { - enabledMods.splice(enabledMods.indexOf(modName),0,onTryMoveIntoMod); - enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod); - localStorage.setItem("enabledMods", JSON.stringify(enabledMods)); - alert(`The ${onTryMoveIntoMod} mod and ${libraryMod} mods are required and have been automatically inserted (reload for this to take effect).`); + }; + }, }; + +/*if(!elements.diamond.reactions) { //test reaction + elements.diamond.reactions = {}; +}; + +elements.diamond.reactions.cherry_leaf = { "elem2": "dead_plant" };*/ + +elements.cherry_plant_top = { + hidden: true, + color: "#310a0b", + tick: function(pixel) { + if(pixel.cherryRange === null) { + pixel.cherryRange = randomNumberFromOneToThree(); + }; + + if (pixel.age > 30 && pixel.temp < 100) { + if(!pixel.grewLeftLeaves) { + for(i = (0 - pixel.leafRange); i < 0; i++) { //left half + if(i == 0) { + continue; + }; + + var leafOffset = i; //readability + var leafX = pixel.x + leafOffset; //set X to cherry_plant_top pixel's X + offset/index + var leafAttachOffset = [1, 0]; //difference 1: attaches rightwards (+) for leaves left (-) of center + var leafY = pixel.y; //set Y to default cherry_plant_top pixel's Y + if(Math.abs(leafOffset) == pixel.leafRange) { + leafY++; //place edge leaves 1 pixel downwards; + leafAttachOffset[1] = -1; //compensate by subtracting 1 from Y attach offset (less Y = higher position, so they attach diagonally up-right or up-left) + }; + + if(outOfBounds(leafX,leafY)) { + continue; + }; + + if (isEmpty(leafX,leafY,false)) { + createPixel("cherry_leaf",leafX,leafY); + pixelMap[leafX][leafY].attached = true; //set leaf's attached to true + pixelMap[leafX][leafY].attachOffsets = leafAttachOffset; //array of 2 numbers + pixelMap[leafX][leafY].cherryRange = pixel.cherryRange; + pixel.grewLeftLeaves = true; //difference 2: separate flag for left side + } else { + break; + }; + }; + }; + + if(!pixel.grewRightLeaves) { + for(i = 1; i < (pixel.leafRange + 1); i++) { //right half + if(i == 0) { + continue; + }; + + var leafOffset = i; //readability + var leafX = pixel.x + leafOffset; //set X to cherry_plant_top pixel's X + offset/index + var leafAttachOffset = [-1, 0]; //difference 1: attaches leftwards (-) for leaves right (+) of center + var leafY = pixel.y; //set Y to default cherry_plant_top pixel's Y + if(Math.abs(leafOffset) == pixel.leafRange) { + leafY++; //place edge leaves 1 pixel downwards; + leafAttachOffset[1] = -1; //compensate by subtracting 1 from Y attach offset (less Y = higher position, so they attach diagonally up-right or up-left) + }; + + if(outOfBounds(leafX,leafY)) { + continue; + }; + + if (isEmpty(leafX,leafY,false)) { + createPixel("cherry_leaf",leafX,leafY); + pixelMap[leafX][leafY].attached = true; //set leaf's attached to true + pixelMap[leafX][leafY].attachOffsets = leafAttachOffset; //array of 2 numbers + pixelMap[leafX][leafY].cherryRange = pixel.cherryRange; + pixel.grewRightLeaves = true; //difference 2: separate flag for right side + } else { + break; + }; + }; + }; + }; + pixel.age++; + doDefaults(pixel); + }, + properties: { + "age": 0, + "leafRange": 2 + (Math.floor(Math.random() * 3)), //2-4 + "grewLeftLeaves": false, + "grewRightLeaves": false, + "cherryRange": null, + }, + tempHigh: 100, + stateHigh: "dead_plant", + tempLow: -2, + stateLow: "frozen_plant", + burn: 5, + burnInto: ["steam", "ash"], + burnTime: 600, + category: "life", + state: "solid", + density: 1500, +}; + + +/*elements.cocoa_bean = { + color: ["#f2ede9", "#f0dfce", "#e8cfb5"], + behavior: behaviors.SOLID, + category: "liquids", + viscosity: 100000, + state: "liquid", + density: 593, + tick: functi +};*/ + +// enabledMods.splice(enabledMods.indexOf(modName),0,onTryMoveIntoMod); +// enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod); +// localStorage.setItem("enabledMods", JSON.stringify(enabledMods)); +// alert(`The ${onTryMoveIntoMod} mod and ${libraryMod} mods are required and have been automatically inserted (reload for this to take effect).`); + diff --git a/mods/chess.js b/mods/chess.js index 83be06f1..773f7a74 100644 --- a/mods/chess.js +++ b/mods/chess.js @@ -1435,7 +1435,7 @@ runAfterLoadList.push(() => { if (!localStorage.getItem("chessjs-tutorial")) { // "might break" // i know damn well it will 100% break on mobile - alert("To start or restart chess board press 'u'. Might break on different resolutions and on mobile."); + promptText("To start or restart chess board press 'u'. Might break on different resolutions and on mobile."); localStorage.setItem("chessjs-tutorial", true); } }) diff --git a/mods/colonies.js b/mods/colonies.js index 215cb3d0..622b8bee 100644 --- a/mods/colonies.js +++ b/mods/colonies.js @@ -1,7 +1,7 @@ var modName = "mods/colonies.js"; -var exoplanetMod = "mods/exoplanet.js"; +// var exoplanetMod = "mods/exoplanet.js"; -if(enabledMods.includes(exoplanetMod)) { +dependOn("exoplanet.js", function(){ window.addEventListener("load", () => { document.getElementById("elementButton-base")?.remove() @@ -567,8 +567,4 @@ elements.arriving_rocket = { cooldown: defaultCooldown } -} else { - enabledMods.splice(enabledMods.indexOf(modName),0,exoplanetMod) - localStorage.setItem("enabledMods", JSON.stringify(enabledMods)); - alert(`The ${exoplanetMod} mod is required and has been automatically inserted (reload for this to take effect).`) -}; +}, true); \ No newline at end of file diff --git a/mods/color_tools.js b/mods/color_tools.js index a16ac231..a3abd1d1 100644 --- a/mods/color_tools.js +++ b/mods/color_tools.js @@ -1,7 +1,7 @@ var modName = "mods/color_tools.js"; var libraryMod = "mods/code_library.js"; -if(enabledMods.includes(libraryMod)) { +dependOn("code_library.js", function(){ var colorToolCounter = 0; saturationAmount = 1; saturationOp = "add"; @@ -290,8 +290,4 @@ if(enabledMods.includes(libraryMod)) { excludeRandom: true, desc: "Click here to configure the element filter (applies to all color tools).", } -} else { - enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod) - alert(`The ${libraryMod} mod is required and has been automatically inserted (reload for this to take effect).`) - localStorage.setItem("enabledMods", JSON.stringify(enabledMods)); -}; +}, true); \ No newline at end of file diff --git a/mods/delete_all_of_element.js b/mods/delete_all_of_element.js index 8080074f..670eb6e9 100644 --- a/mods/delete_all_of_element.js +++ b/mods/delete_all_of_element.js @@ -12,6 +12,6 @@ elements.delete_all_of_element = { } } }, - category: "tools", + category: "edit", excludeRandom: true, }; diff --git a/mods/drills.js b/mods/drills.js index a360c5b6..4575d2b0 100644 --- a/mods/drills.js +++ b/mods/drills.js @@ -65,19 +65,19 @@ // info element -elements.drills_info = { - color: "#000000", - name: "drills.js", - category: "Mods", - behavior: behaviors.SELFDELETE, - maxSize: 1, - tool: function(pixel) {}, - onSelect: function(pixel) { - let mod_info = "The drills.js mod adds different kinds of drills to a new 'drills' category.\n\nMod made by: Necrotic_Phantom. \n With help from: voidapex11." - alert(mod_info) - return - }, -}; +// elements.drills_info = { +// color: "#000000", +// name: "drills.js", +// category: "Mods", +// behavior: behaviors.SELFDELETE, +// maxSize: 1, +// tool: function(pixel) {}, +// onSelect: function(pixel) { +// let mod_info = "The drills.js mod adds different kinds of drills to a new 'drills' category.\n\nMod made by: Necrotic_Phantom. \n With help from: voidapex11." +// alert(mod_info) +// return +// }, +// }; diff --git a/mods/haseulite.js b/mods/haseulite.js index a326fb56..dd901f1c 100644 --- a/mods/haseulite.js +++ b/mods/haseulite.js @@ -1152,7 +1152,7 @@ if(enabledMods.includes(loonaMod) && enabledMods.includes(fireMod) && enabledMod burnTime: 600, tempHigh: 200, stateHigh: ["steam", "ash"], - onTryMoveInto: function(pixel,otherPixel) { + onMoveInto: function(pixel,otherPixel) { var otherInfo = elements[otherPixel.element] if(typeof(otherInfo.state) === "string" && otherInfo.state !== "gas") { pixel.attached = false; diff --git a/mods/human_edit.js b/mods/human_edit.js index 1cdf42b1..83a8d0c6 100644 --- a/mods/human_edit.js +++ b/mods/human_edit.js @@ -1,5 +1,4 @@ var modName = "mods/human_edit.js"; -var onTryMoveIntoMod = "mods/onTryMoveInto.js"; if(typeof(breakPixel) == "undefined") { function breakPixel(pixel,changetemp=false,defaultBreakIntoDust=false) { var info = elements[pixel.element]; @@ -33,693 +32,686 @@ function hasPixel(x,y,elementInput) { }; }; -if(enabledMods.includes(onTryMoveIntoMod)) { - elements.brain = { - color: ["#fce3e3","#deb6c5","#f5ced5","#e87b8f"], - behavior: [ - "XX|XX|XX", - "XX|CH:rotten_meat%1|XX", - "M2|M1|M2", - ], - reactions: { - "dirty_water": { "elem1":"rotten_meat", "chance":0.1 }, - "fly": { "elem1":"rotten_meat", "chance":0.2 }, - "dioxin": { "elem1":"rotten_meat", "elem2":null, "chance":0.1 }, - "uranium": { "elem1":"rotten_meat", "chance":0.1 }, - "cancer": { "elem1":"rotten_meat", "chance":0.1 }, - "plague": { "elem1":"rotten_meat", "elem2":null, "chance":0.3 }, - "ant": { "elem1":"rotten_meat", "chance":0.1 }, - "worm": { "elem1":"rotten_meat", "chance":0.1 }, - "rat": { "elem1":"rotten_meat", "chance":0.3 }, - "mushroom_spore": { "elem1":"rotten_meat", "chance":0.1 }, - "mushroom_stalk": { "elem1":"rotten_meat", "chance":0.1 }, - "mercury": { "elem1":"rotten_meat", "elem2":null, "chance":0.2 }, - "mercury_gas": { "elem1":"rotten_meat", "elem2":null, "chance":0.1 }, - "virus": { "elem1":"rotten_meat", "chance":0.1 }, - "poison": { "elem1":"rotten_meat", "elem2":null, "chance":0.5 }, - "infection": { "elem1":"rotten_meat", "elem2":null, "chance":0.1 }, - "ink": { "elem1":"rotten_meat", "elem2":null, "chance":0.1 }, - "acid": { "elem1":"rotten_meat", "elem2":null, "chance":0.5 }, - "acid_gas": { "elem1":"rotten_meat", "chance":0.4 }, - "cyanide": { "elem1":"rotten_meat", "elem2":null, "chance":0.5 }, - }, - tempHigh: 100, - stateHigh: "cooked_meat", - tempLow: -18, - stateLow: "frozen_meat", - category:"life", - hidden: true, - breakInto: ["meat", "blood"], - burn:10, - burnTime:200, - burnInto:["cooked_meat","steam","steam","salt"], - state: "solid", - density: 1081, - conduct: 1, +elements.brain = { + color: ["#fce3e3","#deb6c5","#f5ced5","#e87b8f"], + behavior: [ + "XX|XX|XX", + "XX|CH:rotten_meat%1|XX", + "M2|M1|M2", + ], + reactions: { + "dirty_water": { "elem1":"rotten_meat", "chance":0.1 }, + "fly": { "elem1":"rotten_meat", "chance":0.2 }, + "dioxin": { "elem1":"rotten_meat", "elem2":null, "chance":0.1 }, + "uranium": { "elem1":"rotten_meat", "chance":0.1 }, + "cancer": { "elem1":"rotten_meat", "chance":0.1 }, + "plague": { "elem1":"rotten_meat", "elem2":null, "chance":0.3 }, + "ant": { "elem1":"rotten_meat", "chance":0.1 }, + "worm": { "elem1":"rotten_meat", "chance":0.1 }, + "rat": { "elem1":"rotten_meat", "chance":0.3 }, + "mushroom_spore": { "elem1":"rotten_meat", "chance":0.1 }, + "mushroom_stalk": { "elem1":"rotten_meat", "chance":0.1 }, + "mercury": { "elem1":"rotten_meat", "elem2":null, "chance":0.2 }, + "mercury_gas": { "elem1":"rotten_meat", "elem2":null, "chance":0.1 }, + "virus": { "elem1":"rotten_meat", "chance":0.1 }, + "poison": { "elem1":"rotten_meat", "elem2":null, "chance":0.5 }, + "infection": { "elem1":"rotten_meat", "elem2":null, "chance":0.1 }, + "ink": { "elem1":"rotten_meat", "elem2":null, "chance":0.1 }, + "acid": { "elem1":"rotten_meat", "elem2":null, "chance":0.5 }, + "acid_gas": { "elem1":"rotten_meat", "chance":0.4 }, + "cyanide": { "elem1":"rotten_meat", "elem2":null, "chance":0.5 }, + }, + tempHigh: 100, + stateHigh: "cooked_meat", + tempLow: -18, + stateLow: "frozen_meat", + category:"life", + hidden: true, + breakInto: ["meat", "blood"], + burn:10, + burnTime:200, + burnInto:["cooked_meat","steam","steam","salt"], + state: "solid", + density: 1081, + conduct: 1, +}; + +elements.cerebrospinal_fluid = { + color: "#ced7db", + behavior: behaviors.LIQUID, + state: "liquid", + tempHigh: 100, + stateHigh: "steam", + breakInto: "steam", + reactions: JSON.parse(JSON.stringify(elements.water.reactions)), +}; + +function validatePanic(pixel) { + //console.log(`validatePanic: validatePanic called on pixel ${pixel.element} at (${pixel.x},${pixel.y}) with panic level ${pixel.panic || 0}`); + if(pixel.element.endsWith("body")) { + //console.log("validatePanic called on body pixel (panic is stored in the head)"); }; - - elements.cerebrospinal_fluid = { - color: "#ced7db", - behavior: behaviors.LIQUID, - state: "liquid", - tempHigh: 100, - stateHigh: "steam", - breakInto: "steam", - reactions: JSON.parse(JSON.stringify(elements.water.reactions)), + if(Number.isNaN(pixel.panic)) { + //console.log("NaN case: panic set to 0"); + pixel.panic = 0; }; + //console.log(`Bounding code running from value of ${pixel.panic}`); + pixel.panic = Math.max(0,Math.min(1,pixel.panic)); + //console.log(`Validation result: Panic set to ${pixel.panic}`); - function validatePanic(pixel) { - //console.log(`validatePanic: validatePanic called on pixel ${pixel.element} at (${pixel.x},${pixel.y}) with panic level ${pixel.panic || 0}`); - if(pixel.element.endsWith("body")) { - //console.log("validatePanic called on body pixel (panic is stored in the head)"); - }; - if(Number.isNaN(pixel.panic)) { - //console.log("NaN case: panic set to 0"); - pixel.panic = 0; - }; - //console.log(`Bounding code running from value of ${pixel.panic}`); - pixel.panic = Math.max(0,Math.min(1,pixel.panic)); - //console.log(`Validation result: Panic set to ${pixel.panic}`); - - if(Number.isNaN(pixel.mood)) { - //console.log("NaN case: panic set to 0"); - pixel.mood = 0; - }; - //console.log(`Bounding code running from value of ${pixel.panic}`); - pixel.mood = Math.max(-3,Math.min(3,pixel.mood)); - //console.log(`Validation result: Panic set to ${pixel.panic}`); + if(Number.isNaN(pixel.mood)) { + //console.log("NaN case: panic set to 0"); + pixel.mood = 0; }; + //console.log(`Bounding code running from value of ${pixel.panic}`); + pixel.mood = Math.max(-3,Math.min(3,pixel.mood)); + //console.log(`Validation result: Panic set to ${pixel.panic}`); +}; - goodPixels = { - silver: { panicChange: 0.01, panicChangeChance: 0.1, moodChange: 0.004 }, - gold: { panicChange: 0.02, panicChangeChance: 0.15, moodChange: 0.01 }, - diamond: { panicChange: 0.03, panicChangeChance: 0.2, moodChange: 0.02 }, - }; //effectively, the difference is that good pixels don't make the human flip direction (run away); - badPixels = { - rotten_meat: { panicChange: 0.02, panicChangeChance: 0.15, moodChange: -0.015 }, - blood: { panicChange: 0.06, panicChangeChance: 0.2, moodChange: -0.006 }, - brain: { panicChange: 0.1, panicChangeChance: 0.3, moodChange: -0.005 }, - fire: { panicChange: 0.1, panicChangeChance: 0.1, moodChange: 0 }, - poison: { panicChange: 0.2, panicChangeChance: 0.05, moodChange: -0.01 }, - grenade: { panicChange: 0.2, panicChangeChance: 0.4, moodChange: -0.3 }, - bomb: { panicChange: 0.2, panicChangeChance: 0.4, moodChange: -0.3 }, - tnt: { panicChange: 0.2, panicChangeChance: 0.4, moodChange: 0 }, - dynamite: { panicChange: 0.2, panicChangeChance: 0.4, moodChange: -0.3 }, - anti_bomb: { panicChange: 0.2, panicChangeChance: 0.4, moodChange: -0.3 }, - cluster_bomb: { panicChange: 0.2, panicChangeChance: 0.4, moodChange: -0.4 }, - landmine: { panicChange: 0.25, panicChangeChance: 0.1, moodChange: -0.3 }, - fireball: { panicChange: 0.25, panicChangeChance: 0.45, moodChange: -0.35 }, - magma: { panicChange: 0.3, panicChangeChance: 0.2, moodChange: 0 }, - plasma: { panicChange: 0.3, panicChangeChance: 0.2, moodChange: 0 }, - nuke: { panicChange: 1, panicChangeChance: 1, moodChange: -1 }, //insta-panic - cluster_nuke: { panicChange: 1, panicChangeChance: 1, moodChange: -1 }, //insta-panic - }; //testing - otherPixels = ["head","body"]; //do custom code here +goodPixels = { + silver: { panicChange: 0.01, panicChangeChance: 0.1, moodChange: 0.004 }, + gold: { panicChange: 0.02, panicChangeChance: 0.15, moodChange: 0.01 }, + diamond: { panicChange: 0.03, panicChangeChance: 0.2, moodChange: 0.02 }, +}; //effectively, the difference is that good pixels don't make the human flip direction (run away); +badPixels = { + rotten_meat: { panicChange: 0.02, panicChangeChance: 0.15, moodChange: -0.015 }, + blood: { panicChange: 0.06, panicChangeChance: 0.2, moodChange: -0.006 }, + brain: { panicChange: 0.1, panicChangeChance: 0.3, moodChange: -0.005 }, + fire: { panicChange: 0.1, panicChangeChance: 0.1, moodChange: 0 }, + poison: { panicChange: 0.2, panicChangeChance: 0.05, moodChange: -0.01 }, + grenade: { panicChange: 0.2, panicChangeChance: 0.4, moodChange: -0.3 }, + bomb: { panicChange: 0.2, panicChangeChance: 0.4, moodChange: -0.3 }, + tnt: { panicChange: 0.2, panicChangeChance: 0.4, moodChange: 0 }, + dynamite: { panicChange: 0.2, panicChangeChance: 0.4, moodChange: -0.3 }, + anti_bomb: { panicChange: 0.2, panicChangeChance: 0.4, moodChange: -0.3 }, + cluster_bomb: { panicChange: 0.2, panicChangeChance: 0.4, moodChange: -0.4 }, + landmine: { panicChange: 0.25, panicChangeChance: 0.1, moodChange: -0.3 }, + fireball: { panicChange: 0.25, panicChangeChance: 0.45, moodChange: -0.35 }, + magma: { panicChange: 0.3, panicChangeChance: 0.2, moodChange: 0 }, + plasma: { panicChange: 0.3, panicChangeChance: 0.2, moodChange: 0 }, + nuke: { panicChange: 1, panicChangeChance: 1, moodChange: -1 }, //insta-panic + cluster_nuke: { panicChange: 1, panicChangeChance: 1, moodChange: -1 }, //insta-panic +}; //testing +otherPixels = ["head","body"]; //do custom code here - var initialTransparencyArray = ["glass","water","salt_water","sugar_water","steam","oxygen","nitrogen","neon","methane","propane","anesthesia","ammonia","carbon_dioxide","helium","hydrogen","ozone","radiation","pool_water"]; - for(transparentElementIndex = 0; transparentElementIndex < initialTransparencyArray.length; transparentElementIndex++) { - var transparentElement = initialTransparencyArray[i]; - if(typeof(elements[transparentElement]) !== "undefined") { - elements[transparentElement].transparent = true; - }; +var initialTransparencyArray = ["glass","water","salt_water","sugar_water","steam","oxygen","nitrogen","neon","methane","propane","anesthesia","ammonia","carbon_dioxide","helium","hydrogen","ozone","radiation","pool_water"]; +for(transparentElementIndex = 0; transparentElementIndex < initialTransparencyArray.length; transparentElementIndex++) { + var transparentElement = initialTransparencyArray[i]; + if(typeof(elements[transparentElement]) !== "undefined") { + elements[transparentElement].transparent = true; }; +}; - elements.body.properties = { - dead: false, - dir: 1, - extremePanicStart: null, +elements.body.properties = { + dead: false, + dir: 1, + extremePanicStart: null, +}; +elements.body.tick = function(pixel) { + if(typeof(pixel.extremePanicStart) == "undefined") { + //console.log("oops"); + pixel.extremePanicStart = null }; - elements.body.tick = function(pixel) { - if(typeof(pixel.extremePanicStart) == "undefined") { - //console.log("oops"); - pixel.extremePanicStart = null - }; - if (tryMove(pixel, pixel.x, pixel.y+1)) { // Fall - if (!isEmpty(pixel.x, pixel.y-2, true)) { // Drag head down - var headpixel = pixelMap[pixel.x][pixel.y-2]; - if (headpixel.element == "head") { - if (isEmpty(pixel.x, pixel.y-1)) { - movePixel(pixelMap[pixel.x][pixel.y-2], pixel.x, pixel.y-1); - } - else { - swapPixels(pixelMap[pixel.x][pixel.y-2], pixelMap[pixel.x][pixel.y-1]); - } + if (tryMove(pixel, pixel.x, pixel.y+1)) { // Fall + if (!isEmpty(pixel.x, pixel.y-2, true)) { // Drag head down + var headpixel = pixelMap[pixel.x][pixel.y-2]; + if (headpixel.element == "head") { + if (isEmpty(pixel.x, pixel.y-1)) { + movePixel(pixelMap[pixel.x][pixel.y-2], pixel.x, pixel.y-1); + } + else { + swapPixels(pixelMap[pixel.x][pixel.y-2], pixelMap[pixel.x][pixel.y-1]); } } } - doHeat(pixel); - doBurning(pixel); - doElectricity(pixel); - if (pixel.dead) { - // Turn into rotten_meat if pixelTicks-dead > 500 - if (pixelTicks-pixel.dead > 200) { - changePixel(pixel,"rotten_meat"); + } + doHeat(pixel); + doBurning(pixel); + doElectricity(pixel); + if (pixel.dead) { + // Turn into rotten_meat if pixelTicks-dead > 500 + if (pixelTicks-pixel.dead > 200) { + changePixel(pixel,"rotten_meat"); + } + return + } + + // Find the head + if (!isEmpty(pixel.x, pixel.y-1, true) && pixelMap[pixel.x][pixel.y-1].element == "head") { + var head = pixelMap[pixel.x][pixel.y-1]; + if (head.dead) { // If head is dead, kill body + pixel.dead = head.dead; + } + } + else { var head = null } + + if (isEmpty(pixel.x, pixel.y-1)) { + // create blood if decapitated 10% chance + if (Math.random() < 0.1) { + createPixel("blood", pixel.x, pixel.y-1); + // set dead to true 15% chance + if (Math.random() < 0.15) { + pixel.dead = pixelTicks; } + } + } + if (head == null) { return }; + + if (Math.random() < (0.1 + head.panic)) { // Move 10% chance, varying depending on panic value + var movesToTry = [ + [1*pixel.dir,0], + [1*pixel.dir,-1], + ]; + // While movesToTry is not empty, tryMove(pixel, x, y) with a random move, then remove it. if tryMove returns true, break. + while (movesToTry.length > 0) { + var move = movesToTry.splice(Math.floor(Math.random() * movesToTry.length), 1)[0]; + /* + console.log(move); + console.log("Body X:", pixel.x, "to", pixel.x+move[0]); + console.log("Body Y:", pixel.y, "to", pixel.y+move[1]); + console.log("Head X:",head.x, "to", head.x+move[0]); + console.log("Head Y:", head.y, "to", head.y+move[1]); + */ + //If head coords are empty + if (isEmpty(pixel.x+move[0], pixel.y+move[1]) && isEmpty(head.x+move[0], head.y+move[1])) { + //console.log("Head target coords are empty"); + if (tryMove(pixel, pixel.x+move[0], pixel.y+move[1])) { + movePixel(head, head.x+move[0], head.y+move[1]); + //console.log(`Moved body to (${pixel.x},${pixel.y}) and head to (${head.x},${head.y})`); + //console.log(`Head-body offset (should always be [0,-1]): [${head.x-pixel.x},${head.y-pixel.y}]`) + break; + } + } + } + // 15% chance to change direction + if(!head.dirLocked) { + if (Math.random() < 0.15) { + pixel.dir *= -1; + //console.log("*turns around cutely to face ${pixel.dir < 0 ? 'left' : 'right'}*"); + }; + }; + }; + + //if not flagged for extreme panic + //extreme panic will not be flagged in good moods, just to be nice + if(pixel.extremePanicStart == null && head.panic > 0.8 && head.mood <= 0) { + //flag extreme panic + pixel.extremePanicStart = pixelTicks; + } + //if flagged for extreme panic and panic is still extreme + else if(pixel.extremePanicStart != null && (head.panic > 0.8 && head.mood <= 0)) { + //if extreme panic lasts too long + if(pixelTicks - pixel.extremePanicStart > 350) { + //random chance to die from exhaustion/a heart attack/whatever + if(Math.random() < 0.01) { + pixel.dead = true; + }; + }; + } + //if flagged for extreme panic and extreme panic is no longer extreme + else if(pixel.extremePanicStart != null && (head.panic <= 0.8 || head.mood > 0)) { + //unflag + pixel.extremePanicStart = null; + }; + +}; + +elements.body.onMoveInto = function(pixel,otherPixel) { + var pX = pixel.x; + var pY = pixel.y; + if(!pixel.dead && hasPixel(pX,pY-1,"head")) { //if this body pixel is alive and has a head + var head = pixelMap[pX][pY-1]; + var otherElement = otherPixel.element; + var oX = otherPixel.x; + var oY = otherPixel.y; + if(oY !== (pY - 1)) { //exclude the head above this body + if(otherElement === "head") { //if the pixel hitting this body is a head + if(hasPixel(oX,oY+1,"body")) { //if the pixel hitting this pixel has a body under it + var otherBody = pixelMap[oX][oY+1]; + if(otherPixel.dead || otherBody.dead) { //if either part of that human is dead + head.panic += 0.08; //being hit by a dead ******* body is terrifying + } else { + if(otherPixel.panic > 0.04 && otherPixel.mood <= 0) { head.panic += 0.04 }; //living, normal, bodied heads scare only if that incoming human is already scared + }; + } else { //if it's a severed head + if(otherPixel.dead) { //if the head is dead + head.panic += 0.08; //being hit by a /severed ******* head/ is terrifying + } else { + head.panic += 0.1; //being hit by a //******* severed head that's still alive// is even worse + }; + }; + } else if(otherElement === "body") { //if the pixel hitting this body is a body + if(hasPixel(oX,oY-1,"head")) { //if the pixel hitting this pixel has a head on it + var otherHead = pixelMap[oX][oY-1]; + if(otherPixel.dead || otherHead.dead) { //if either part of that human is dead + head.panic += 0.06; //dead whole body case + } else { + if(otherHead.panic > 0.04) { head.panic += 0.04 }; //living, normal, bodied heads scare only if that incoming human is already scared + }; + } else { //severed body case + if(otherPixel.dead) { //if the body is dead + head.panic += 0.08; //imagine being hit by a severed human without the head + } else { + head.panic += 0.1; //imagine the above but the heart is still beating + }; + }; + }; + }; + }; +}; + +elements.head.properties = { + dead: false, + dirLocked: false, + panic: 0, +}; + +elements.head.tick = function(pixel) { + doHeat(pixel); + doBurning(pixel); + doElectricity(pixel); + if (pixel.dead) { + // Turn into rotten_meat if pixelTicks-dead > 500 + if (pixelTicks-pixel.dead > 200) { + changePixel(pixel,"rotten_meat"); return } + } - // Find the head - if (!isEmpty(pixel.x, pixel.y-1, true) && pixelMap[pixel.x][pixel.y-1].element == "head") { - var head = pixelMap[pixel.x][pixel.y-1]; - if (head.dead) { // If head is dead, kill body - pixel.dead = head.dead; + // Find the body + if (!isEmpty(pixel.x, pixel.y+1, true) && pixelMap[pixel.x][pixel.y+1].element == "body") { + var body = pixelMap[pixel.x][pixel.y+1]; + if (body.dead) { // If body is dead, kill head + pixel.dead = body.dead; + } + } + else { var body = null } + + if (isEmpty(pixel.x, pixel.y+1)) { + tryMove(pixel, pixel.x, pixel.y+1); + // create blood if severed 10% chance + if (isEmpty(pixel.x, pixel.y+1) && !pixel.dead && Math.random() < 0.1) { + createPixel("blood", pixel.x, pixel.y+1); + // set dead to true 15% chance + if (Math.random() < 0.15) { + pixel.dead = pixelTicks; } } - else { var head = null } + } + + pixel.mood ??= 0; - if (isEmpty(pixel.x, pixel.y-1)) { - // create blood if decapitated 10% chance - if (Math.random() < 0.1) { - createPixel("blood", pixel.x, pixel.y-1); - // set dead to true 15% chance - if (Math.random() < 0.15) { - pixel.dead = pixelTicks; - } - } - } - if (head == null) { return }; - - if (Math.random() < (0.1 + head.panic)) { // Move 10% chance, varying depending on panic value - var movesToTry = [ - [1*pixel.dir,0], - [1*pixel.dir,-1], - ]; - // While movesToTry is not empty, tryMove(pixel, x, y) with a random move, then remove it. if tryMove returns true, break. - while (movesToTry.length > 0) { - var move = movesToTry.splice(Math.floor(Math.random() * movesToTry.length), 1)[0]; - /* - console.log(move); - console.log("Body X:", pixel.x, "to", pixel.x+move[0]); - console.log("Body Y:", pixel.y, "to", pixel.y+move[1]); - console.log("Head X:",head.x, "to", head.x+move[0]); - console.log("Head Y:", head.y, "to", head.y+move[1]); - */ - //If head coords are empty - if (isEmpty(pixel.x+move[0], pixel.y+move[1]) && isEmpty(head.x+move[0], head.y+move[1])) { - //console.log("Head target coords are empty"); - if (tryMove(pixel, pixel.x+move[0], pixel.y+move[1])) { - movePixel(head, head.x+move[0], head.y+move[1]); - //console.log(`Moved body to (${pixel.x},${pixel.y}) and head to (${head.x},${head.y})`); - //console.log(`Head-body offset (should always be [0,-1]): [${head.x-pixel.x},${head.y-pixel.y}]`) - break; - } - } - } - // 15% chance to change direction - if(!head.dirLocked) { - if (Math.random() < 0.15) { - pixel.dir *= -1; - //console.log("*turns around cutely to face ${pixel.dir < 0 ? 'left' : 'right'}*"); - }; - }; - }; - - //if not flagged for extreme panic - //extreme panic will not be flagged in good moods, just to be nice - if(pixel.extremePanicStart == null && head.panic > 0.8 && head.mood <= 0) { - //flag extreme panic - pixel.extremePanicStart = pixelTicks; - } - //if flagged for extreme panic and panic is still extreme - else if(pixel.extremePanicStart != null && (head.panic > 0.8 && head.mood <= 0)) { - //if extreme panic lasts too long - if(pixelTicks - pixel.extremePanicStart > 350) { - //random chance to die from exhaustion/a heart attack/whatever - if(Math.random() < 0.01) { - pixel.dead = true; - }; - }; - } - //if flagged for extreme panic and extreme panic is no longer extreme - else if(pixel.extremePanicStart != null && (head.panic <= 0.8 || head.mood > 0)) { - //unflag - pixel.extremePanicStart = null; - }; - - }; - - elements.body.onTryMoveInto = function(pixel,otherPixel) { + if((pixelTicks-pixel.start) % 5 === 0) { + //Vision loop var pX = pixel.x; var pY = pixel.y; - if(!pixel.dead && hasPixel(pX,pY-1,"head")) { //if this body pixel is alive and has a head - var head = pixelMap[pX][pY-1]; - var otherElement = otherPixel.element; - var oX = otherPixel.x; - var oY = otherPixel.y; - if(oY !== (pY - 1)) { //exclude the head above this body - if(otherElement === "head") { //if the pixel hitting this body is a head - if(hasPixel(oX,oY+1,"body")) { //if the pixel hitting this pixel has a body under it - var otherBody = pixelMap[oX][oY+1]; - if(otherPixel.dead || otherBody.dead) { //if either part of that human is dead - head.panic += 0.08; //being hit by a dead ******* body is terrifying - } else { - if(otherPixel.panic > 0.04 && otherPixel.mood <= 0) { head.panic += 0.04 }; //living, normal, bodied heads scare only if that incoming human is already scared - }; - } else { //if it's a severed head - if(otherPixel.dead) { //if the head is dead - head.panic += 0.08; //being hit by a /severed ******* head/ is terrifying - } else { - head.panic += 0.1; //being hit by a //******* severed head that's still alive// is even worse - }; + if(pixel.dir === -1) { + for(i = -4; i < 4+1; i++) { + var oY = i; + //console.log(`Starting row look at row ${pY+oY}`) + for(j = (-1); j > (-16 - 1); j--) { + var oX = j; + var nX = pX+oX; + var nY = pY+oY; + if(outOfBounds(nX,nY)) { + //console.log(`Stopping row look at pixel (${nX},${nY}) due to OoB`) + break; }; - } else if(otherElement === "body") { //if the pixel hitting this body is a body - if(hasPixel(oX,oY-1,"head")) { //if the pixel hitting this pixel has a head on it - var otherHead = pixelMap[oX][oY-1]; - if(otherPixel.dead || otherHead.dead) { //if either part of that human is dead - head.panic += 0.06; //dead whole body case - } else { - if(otherHead.panic > 0.04) { head.panic += 0.04 }; //living, normal, bodied heads scare only if that incoming human is already scared - }; - } else { //severed body case - if(otherPixel.dead) { //if the body is dead - head.panic += 0.08; //imagine being hit by a severed human without the head - } else { - head.panic += 0.1; //imagine the above but the heart is still beating - }; + if(isEmpty(nX,nY)) { + //console.log(`Skipping pixel (${nX},${nY}) (empty)`) + continue; }; - }; - }; - }; - }; - - elements.head.properties = { - dead: false, - dirLocked: false, - panic: 0, - }; - - elements.head.tick = function(pixel) { - doHeat(pixel); - doBurning(pixel); - doElectricity(pixel); - if (pixel.dead) { - // Turn into rotten_meat if pixelTicks-dead > 500 - if (pixelTicks-pixel.dead > 200) { - changePixel(pixel,"rotten_meat"); - return - } - } - - // Find the body - if (!isEmpty(pixel.x, pixel.y+1, true) && pixelMap[pixel.x][pixel.y+1].element == "body") { - var body = pixelMap[pixel.x][pixel.y+1]; - if (body.dead) { // If body is dead, kill head - pixel.dead = body.dead; - } - } - else { var body = null } - - if (isEmpty(pixel.x, pixel.y+1)) { - tryMove(pixel, pixel.x, pixel.y+1); - // create blood if severed 10% chance - if (isEmpty(pixel.x, pixel.y+1) && !pixel.dead && Math.random() < 0.1) { - createPixel("blood", pixel.x, pixel.y+1); - // set dead to true 15% chance - if (Math.random() < 0.15) { - pixel.dead = pixelTicks; - } - } - } - - pixel.mood ??= 0; - - if((pixelTicks-pixel.start) % 5 === 0) { - //Vision loop - var pX = pixel.x; - var pY = pixel.y; - if(pixel.dir === -1) { - for(i = -4; i < 4+1; i++) { - var oY = i; - //console.log(`Starting row look at row ${pY+oY}`) - for(j = (-1); j > (-16 - 1); j--) { - var oX = j; - var nX = pX+oX; - var nY = pY+oY; - if(outOfBounds(nX,nY)) { - //console.log(`Stopping row look at pixel (${nX},${nY}) due to OoB`) - break; - }; - if(isEmpty(nX,nY)) { - //console.log(`Skipping pixel (${nX},${nY}) (empty)`) - continue; - }; - if(!isEmpty(nX,nY,true)) { - var newPixel = pixelMap[nX][nY]; - var newElement = newPixel.element; - if(Object.keys(goodPixels).includes(newElement)) { - //no dir flip - if(Math.random() > goodPixels[newElement].panicChangeChance) { - pixel.panic += goodPixels[newElement].panicChange; - pixel.mood += goodPixels[newElement].moodChange; //like if there was a pretty painting item, it would make you feel better but you wouldn't necessarily feel the need to run towards it - }; - pixel.dirLocked = true; - } else if(Object.keys(badPixels).includes(newElement)) { - body.dir = 1; //flip dir - if(Math.random() > badPixels[newElement].panicChangeChance) { - pixel.panic += badPixels[newElement].panicChange; - pixel.mood += badPixels[newElement].moodChange; - }; - pixel.dirLocked = true; - }; //good and bad should be mutually exclusive; good will be evaulated first because one inevitably has to be considered first - if(otherPixels.includes(newElement)) { - //specific custom code - if(newElement === "head") { - if(hasPixel(nX,nY+1,"body")) { - var newBody = pixelMap[nX][nY+1]; - if(newPixel.dead || newBody.dead) { - pixel.panic += 0.02; //if it's seeing a whole human, it's likely to see the dead head and the dead body, thus double-executing - //it would be nice if there was a way to avoid double/multiple detection of the same human - if(hasPixel(pX,pY+1,"body")) { //mix error-proofing - var body = pixelMap[pX][pY+1]; - body.dir = 1; //run away - }; - } else { - if(newPixel.panic > 0.04) { - if(newPixel.panic > 0.8) { - pixel.panic += 0.015; //it will add up - } else if(newPixel.panic > 0.6) { - pixel.panic += 0.012; - } else if(newPixel.panic > 0.4) { - pixel.panic += 0.009; - } else if(newPixel.panic > 0.2) { - pixel.panic += 0.006; - } else { - pixel.panic += 0.003; - }; - - //the vision loop is in the head, and this is in the "seeing head" case, then this will happen when the head sees another head, and heads store panic; this is in the "other head" is panicking case so this will ultimately be the code that runs when its human sees another human panicking - if(Math.random() < 0.5) { - //run in same direction as panicking person - pixel.dir = newPixel.dir - }; - }; - }; - } else { //severed head - newPixel.dead ? pixel.panic += 0.03 : pixel.panic += 0.04; - if(hasPixel(pX,pY+1,"body")) { - var body = pixelMap[pX][pY+1]; - body.dir = 1; //run away - }; - }; - } else if(newElement === "body") { - if(hasPixel(nX,nY-1,"head")) { - var newHead = pixelMap[nX][nY-1]; - if(newPixel.dead || newHead.dead) { - pixel.panic += 0.02; - if(hasPixel(pX,pY+1,"body")) { - var body = pixelMap[pX][pY+1]; - body.dir = 1; //run away - }; - } else { - if(newHead.panic > 0.04) { - if(newHead.panic > 0.8) { - pixel.panic += 0.014; //it will add up - } else if(newHead.panic > 0.6) { - pixel.panic += 0.011; - } else if(newHead.panic > 0.4) { - pixel.panic += 0.008; - } else if(newHead.panic > 0.2) { - pixel.panic += 0.005; - } else { - pixel.panic += 0.002; - }; - }; - }; - } else { //severed body - newPixel.dead ? pixel.panic += 0.025 : pixel.panic += 0.035; + if(!isEmpty(nX,nY,true)) { + var newPixel = pixelMap[nX][nY]; + var newElement = newPixel.element; + if(Object.keys(goodPixels).includes(newElement)) { + //no dir flip + if(Math.random() > goodPixels[newElement].panicChangeChance) { + pixel.panic += goodPixels[newElement].panicChange; + pixel.mood += goodPixels[newElement].moodChange; //like if there was a pretty painting item, it would make you feel better but you wouldn't necessarily feel the need to run towards it + }; + pixel.dirLocked = true; + } else if(Object.keys(badPixels).includes(newElement)) { + body.dir = 1; //flip dir + if(Math.random() > badPixels[newElement].panicChangeChance) { + pixel.panic += badPixels[newElement].panicChange; + pixel.mood += badPixels[newElement].moodChange; + }; + pixel.dirLocked = true; + }; //good and bad should be mutually exclusive; good will be evaulated first because one inevitably has to be considered first + if(otherPixels.includes(newElement)) { + //specific custom code + if(newElement === "head") { + if(hasPixel(nX,nY+1,"body")) { + var newBody = pixelMap[nX][nY+1]; + if(newPixel.dead || newBody.dead) { + pixel.panic += 0.02; //if it's seeing a whole human, it's likely to see the dead head and the dead body, thus double-executing + //it would be nice if there was a way to avoid double/multiple detection of the same human if(hasPixel(pX,pY+1,"body")) { //mix error-proofing var body = pixelMap[pX][pY+1]; body.dir = 1; //run away }; - }; - }; - }; - //code outside of those three if blocks will be applied to pixels of all elements - if(!elements[newElement].transparent) { - break; //can't see through humans - }; - }; - }; - }; - } else if(pixel.dir === 1) { - for(i = -4; i < 4+1; i++) { - var oY = i; - //console.log(`Starting row look at row ${pY+oY}`) - for(j = 1; j < 16 + 1; j++) { - var oX = j; - var nX = pX+oX; - var nY = pY+oY; - if(outOfBounds(nX,nY)) { - //console.log(`Stopping row look at pixel (${nX},${nY}) due to OoB`) - break; - }; - if(isEmpty(nX,nY)) { - //console.log(`Skipping pixel (${nX},${nY}) (empty)`) - continue; - }; - if(!isEmpty(nX,nY,true)) { - var newPixel = pixelMap[nX][nY]; - var newElement = newPixel.element; - if(Object.keys(goodPixels).includes(newElement)) { - //no dir flip - if(Math.random() > goodPixels[newElement].panicChangeChance) { - pixel.panic += goodPixels[newElement].panicChange; - pixel.mood += goodPixels[newElement].moodChange; - }; - pixel.dirLocked = true; - } else if(Object.keys(badPixels).includes(newElement)) { - if(hasPixel(pX,pY+1,"body")) { - var body = pixelMap[pX][pY+1]; - body.dir = -1; //run away - }; - if(Math.random() > badPixels[newElement].panicChangeChance) { - pixel.panic += badPixels[newElement].panicChange; - pixel.mood += badPixels[newElement].moodChange; - }; - pixel.dirLocked = true; - }; //good and bad should be mutually exclusive; good will be evaulated first because one inevitably has to be considered first - if(otherPixels.includes(newElement)) { - if(newElement === "head") { - if(hasPixel(nX,nY+1,"body")) { - var newBody = pixelMap[nX][nY+1]; - if(newPixel.dead || newBody.dead) { - pixel.panic += 0.02; //if it's seeing a whole human, it's likely to see the dead head and the dead body, thus double-executing - //it would be nice if there was a way to avoid double/multiple detection of the same human - if(hasPixel(pX,pY+1,"body")) { - var body = pixelMap[pX][pY+1]; - body.dir = -1; //run away + } else { + if(newPixel.panic > 0.04) { + if(newPixel.panic > 0.8) { + pixel.panic += 0.015; //it will add up + } else if(newPixel.panic > 0.6) { + pixel.panic += 0.012; + } else if(newPixel.panic > 0.4) { + pixel.panic += 0.009; + } else if(newPixel.panic > 0.2) { + pixel.panic += 0.006; + } else { + pixel.panic += 0.003; }; - } else { - if(newPixel.panic > 0.04) { - if(newPixel.panic > 0.8) { - pixel.panic += 0.015; //it will add up - } else if(newPixel.panic > 0.6) { - pixel.panic += 0.012; - } else if(newPixel.panic > 0.4) { - pixel.panic += 0.009; - } else if(newPixel.panic > 0.2) { - pixel.panic += 0.006; - } else { - pixel.panic += 0.003; - }; + + //the vision loop is in the head, and this is in the "seeing head" case, then this will happen when the head sees another head, and heads store panic; this is in the "other head" is panicking case so this will ultimately be the code that runs when its human sees another human panicking + if(Math.random() < 0.5) { + //run in same direction as panicking person + pixel.dir = newPixel.dir }; }; - } else { //severed head - newPixel.dead ? pixel.panic += 0.03 : pixel.panic += 0.04; + }; + } else { //severed head + newPixel.dead ? pixel.panic += 0.03 : pixel.panic += 0.04; + if(hasPixel(pX,pY+1,"body")) { + var body = pixelMap[pX][pY+1]; + body.dir = 1; //run away + }; + }; + } else if(newElement === "body") { + if(hasPixel(nX,nY-1,"head")) { + var newHead = pixelMap[nX][nY-1]; + if(newPixel.dead || newHead.dead) { + pixel.panic += 0.02; if(hasPixel(pX,pY+1,"body")) { var body = pixelMap[pX][pY+1]; - body.dir = -1; //run away + body.dir = 1; //run away + }; + } else { + if(newHead.panic > 0.04) { + if(newHead.panic > 0.8) { + pixel.panic += 0.014; //it will add up + } else if(newHead.panic > 0.6) { + pixel.panic += 0.011; + } else if(newHead.panic > 0.4) { + pixel.panic += 0.008; + } else if(newHead.panic > 0.2) { + pixel.panic += 0.005; + } else { + pixel.panic += 0.002; + }; }; }; - } else if(newElement === "body") { - if(hasPixel(nX,nY-1,"head")) { - var newHead = pixelMap[nX][nY-1]; - if(newPixel.dead || newHead.dead) { - pixel.panic += 0.02; - if(hasPixel(pX,pY+1,"body")) { - var body = pixelMap[pX][pY+1]; - body.dir = -1; //run away - }; - } else { - if(newHead.panic > 0.04) { - if(newHead.panic > 0.8) { - pixel.panic += 0.014; //it will add up - } else if(newHead.panic > 0.6) { - pixel.panic += 0.011; - } else if(newHead.panic > 0.4) { - pixel.panic += 0.008; - } else if(newHead.panic > 0.2) { - pixel.panic += 0.005; - } else { - pixel.panic += 0.002; - }; - }; - }; - } else { //severed body - newPixel.dead ? pixel.panic += 0.025 : pixel.panic += 0.035; - if(hasPixel(pX,pY+1,"body")) { - var body = pixelMap[pX][pY+1]; - body.dir = -1; //run away - }; + } else { //severed body + newPixel.dead ? pixel.panic += 0.025 : pixel.panic += 0.035; + if(hasPixel(pX,pY+1,"body")) { //mix error-proofing + var body = pixelMap[pX][pY+1]; + body.dir = 1; //run away }; }; }; - //code outside of those three if blocks will be applied to pixels of all elements - if(!elements[newElement].transparent) { - break; //can't see through humans - }; + }; + //code outside of those three if blocks will be applied to pixels of all elements + if(!elements[newElement].transparent) { + break; //can't see through humans }; }; }; }; - }; - - validatePanic(pixel); - - if(Math.random() < 0.01) { //1% chance each tick to lose interest - pixel.dirLocked = false; - //console.log("Meh."); - }; - - if(Math.random() < ((pixel.panic) > 0.8 ? 0.04 : 0.02)) { //2% chance each tick to decrease panic (4% if the panic is extreme) - //console.log("Decreasing panic"); - pixel.panic < 0.05 ? pixel.panic = 0 : pixel.panic -= 0.05; - }; - - }; - elements.head.breakInto = ["bone","brain","brain","cerebrospinal_fluid","blood","blood","meat"]; - - elements.head.onTryMoveInto = function(pixel,otherPixel) { - var pX = pixel.x; - var pY = pixel.y; - if(!pixel.dead) { - var otherElement = otherPixel.element; - var oX = otherPixel.x; - var oY = otherPixel.y; - if(oY !== (pY + 1)) { //exclude the body under this head - if(otherElement === "head") { //if the pixel hitting this head is also a head - //console.log("head.onTryMoveInto: Head has tried to move into head"); - if(hasPixel(oX,oY+1,"body")) { //if the pixel hitting this pixel has a body under it - var otherBody = pixelMap[oX][oY+1]; - if(otherPixel.dead || otherBody.dead) { //if either part of that human is dead - pixel.panic += 0.08; //being hit by a dead ******* body is terrifying - //console.log("head.onTryMoveInto: panic increase, case: head hit by dead whole body (head's code branch)"); - } else { - //if(otherPixel.panic > 0.04) { pixel.panic += 0.04; console.log("head.onTryMoveInto: panic increase, case: head hit by panicked whole body (head's code branch)"); }; //living, normal, headed bodies scare only if that incoming human is already scared - }; - } else { //if it's a severed head - if(otherPixel.dead) { //if the head is dead - pixel.panic += 0.08; //being hit by a /severed ******* head/ is terrifying - //console.log("head.onTryMoveInto: panic increase, case: head hit by dead severed head"); - } else { - pixel.panic += 0.1; //being hit by a //******* severed head that's still alive// is even worse - //console.log("head.onTryMoveInto: panic increase, case: head hit by living severed head"); - }; + } else if(pixel.dir === 1) { + for(i = -4; i < 4+1; i++) { + var oY = i; + //console.log(`Starting row look at row ${pY+oY}`) + for(j = 1; j < 16 + 1; j++) { + var oX = j; + var nX = pX+oX; + var nY = pY+oY; + if(outOfBounds(nX,nY)) { + //console.log(`Stopping row look at pixel (${nX},${nY}) due to OoB`) + break; }; - } else if(otherElement === "body") { //if the pixel hitting this head is a body - if(hasPixel(oX,oY-1,"head")) { //if the body hitting this pixel has a head on it - var otherHead = pixelMap[oX][oY-1]; - if(otherPixel.dead || otherHead.dead) { //if either part of that human is dead - pixel.panic += 0.03; //dead whole body case - //console.log("head.onTryMoveInto: panic increase, case: head hit by dead whole body (body's code branch)"); - } else { - if(otherHead.panic > 0.04) { - pixel.panic += 0.03; - //console.log("head.onTryMoveInto: panic increase, case: head crushed by panicked whole body (body's code branch)"); - } else { - pixel.panic += 0.02; - //console.log("head.onTryMoveInto: panic increase, case: head crushed by whole body (body's code branch)"); + if(isEmpty(nX,nY)) { + //console.log(`Skipping pixel (${nX},${nY}) (empty)`) + continue; + }; + if(!isEmpty(nX,nY,true)) { + var newPixel = pixelMap[nX][nY]; + var newElement = newPixel.element; + if(Object.keys(goodPixels).includes(newElement)) { + //no dir flip + if(Math.random() > goodPixels[newElement].panicChangeChance) { + pixel.panic += goodPixels[newElement].panicChange; + pixel.mood += goodPixels[newElement].moodChange; }; - }; - } else { //severed body case - if(otherPixel.dead) { //if the body is dead - pixel.panic += 0.04; //imagine being hit by a severed human without the head - //console.log("head.onTryMoveInto: panic increase, case: head hit by dead severed body"); - } else { - pixel.panic += 0.05; //imagine the above but the heart is still beating - //console.log("head.onTryMoveInto: panic increase, case: head hit by living severed body"); - }; - }; - } else { - if(oX === pX && oY === pY-1) { - var otherInfo = elements[otherElement]; - var otherState; typeof(otherInfo.state) === "undefined" ? otherState = null : otherState = otherInfo.state; - var otherDensity = typeof(otherInfo.density) === "undefined" ? otherDensity = null : otherDensity = otherInfo.density; - if(otherState === "solid") { - if(otherDensity > 5000) { - var chance = (0.1 + (otherDensity/50000)) / 5; - if(Math.random() < chance) { - breakPixel(pixel); + pixel.dirLocked = true; + } else if(Object.keys(badPixels).includes(newElement)) { + if(hasPixel(pX,pY+1,"body")) { + var body = pixelMap[pX][pY+1]; + body.dir = -1; //run away + }; + if(Math.random() > badPixels[newElement].panicChangeChance) { + pixel.panic += badPixels[newElement].panicChange; + pixel.mood += badPixels[newElement].moodChange; + }; + pixel.dirLocked = true; + }; //good and bad should be mutually exclusive; good will be evaulated first because one inevitably has to be considered first + if(otherPixels.includes(newElement)) { + if(newElement === "head") { + if(hasPixel(nX,nY+1,"body")) { + var newBody = pixelMap[nX][nY+1]; + if(newPixel.dead || newBody.dead) { + pixel.panic += 0.02; //if it's seeing a whole human, it's likely to see the dead head and the dead body, thus double-executing + //it would be nice if there was a way to avoid double/multiple detection of the same human + if(hasPixel(pX,pY+1,"body")) { + var body = pixelMap[pX][pY+1]; + body.dir = -1; //run away + }; + } else { + if(newPixel.panic > 0.04) { + if(newPixel.panic > 0.8) { + pixel.panic += 0.015; //it will add up + } else if(newPixel.panic > 0.6) { + pixel.panic += 0.012; + } else if(newPixel.panic > 0.4) { + pixel.panic += 0.009; + } else if(newPixel.panic > 0.2) { + pixel.panic += 0.006; + } else { + pixel.panic += 0.003; + }; + }; + }; + } else { //severed head + newPixel.dead ? pixel.panic += 0.03 : pixel.panic += 0.04; + if(hasPixel(pX,pY+1,"body")) { + var body = pixelMap[pX][pY+1]; + body.dir = -1; //run away + }; + }; + } else if(newElement === "body") { + if(hasPixel(nX,nY-1,"head")) { + var newHead = pixelMap[nX][nY-1]; + if(newPixel.dead || newHead.dead) { + pixel.panic += 0.02; + if(hasPixel(pX,pY+1,"body")) { + var body = pixelMap[pX][pY+1]; + body.dir = -1; //run away + }; + } else { + if(newHead.panic > 0.04) { + if(newHead.panic > 0.8) { + pixel.panic += 0.014; //it will add up + } else if(newHead.panic > 0.6) { + pixel.panic += 0.011; + } else if(newHead.panic > 0.4) { + pixel.panic += 0.008; + } else if(newHead.panic > 0.2) { + pixel.panic += 0.005; + } else { + pixel.panic += 0.002; + }; + }; + }; + } else { //severed body + newPixel.dead ? pixel.panic += 0.025 : pixel.panic += 0.035; + if(hasPixel(pX,pY+1,"body")) { + var body = pixelMap[pX][pY+1]; + body.dir = -1; //run away + }; }; - } else if(otherDensity >= 500) { - pixel.panic += (0.01 * (otherDensity / 500)); - } else if(otherDensity >= 100) { - pixel.panic += (0.001 * (otherDensity / 100)); }; }; + //code outside of those three if blocks will be applied to pixels of all elements + if(!elements[newElement].transparent) { + break; //can't see through humans + }; }; }; }; }; }; - //Worldgen preset for testing + validatePanic(pixel); - worldgentypes.basalt_dirt = { - layers: [ - [0, "basalt", 0.05], - [0, "dirt"] - ] + if(Math.random() < 0.01) { //1% chance each tick to lose interest + pixel.dirLocked = false; + //console.log("Meh."); }; - kep1er = [ - ["first_impact", ["#664482","#cf4ba3","#c15ca9","#f0a669"]], - ["doublast", ["#2b98fd","#d0e26d","#e6f049","#dce4b3"]], - ["fly-up", ["#f2f2f2","#15a667","#de0180"]], - ["troubleshooter", ["#291923","#ed3fb6","#fee6f8","#64c5e0","#d6cdca","#330d25"]], - ["fly-by", ["#e7e6dd","#fcf0ef","#efa1ba","#8d7cb6","#5e74ba","#2b5db5","#e292b7"]], - ["lovestruck", ["#bfd9f0","#bfd9f0","#fef792","#c36475","#edd1d6"]], - ]; - - for(index in kep1er) { - index = parseInt(index); - var newName = kep1er[index][0]; - var newColor = kep1er[index][1]; - var newDisplayName = newName.replaceAll("_"," ").replaceAll("-"," - ").split(" ").map(x => x.substring(0,1).toUpperCase() + x.substring(1)).join(" ").replace(" - ","-"); - elements[newName] = { - name: newDisplayName, - color: newColor, - tempHigh: 200, - stateHigh: ["ash","molten_plastic"], - density: 332, //based off of First Impact: https://www.amazon.com/Kep1er-IMPACT-Contents-Tracking-Connect/dp/B09MQMNZ62 - tick: function(pixel) { - if(!(tryMove(pixel,pixel.x,pixel.y+1))) { - var directions = []; - if(isEmpty(pixel.x-1,pixel.y+1) && isEmpty(pixel.x-1,pixel.y+2)) { - directions.push(-1) - }; - if(isEmpty(pixel.x+1,pixel.y+1) && isEmpty(pixel.x+1,pixel.y+2)) { - directions.push(1) - }; - if(directions.length > 0) { - tryMove(pixel,pixel.x+directions[Math.floor(Math.random() * directions.length)],pixel.y) - }; - } - }, - reactions: { - water: { elem1: ["plastic","cellulose","cellulose"], elem2: ["water","water","cellulose",null,null], chance: 0.8 } - }, - burn: 40, - burnTime: 150, - burnInto: ["ash","molten_plastic","carbon_dioxide","smoke"], - category: "other" - }; - - goodPixels[newName] = { panicChange: 0.01, panicChangeChance: 0.2, moodChange: 0.035 }; + if(Math.random() < ((pixel.panic) > 0.8 ? 0.04 : 0.02)) { //2% chance each tick to decrease panic (4% if the panic is extreme) + //console.log("Decreasing panic"); + pixel.panic < 0.05 ? pixel.panic = 0 : pixel.panic -= 0.05; }; - -} else { - enabledMods.splice(enabledMods.indexOf(modName),0,onTryMoveIntoMod) - localStorage.setItem("enabledMods", JSON.stringify(enabledMods)); - alert(`The ${onTryMoveIntoMod} mod is required and has been automatically inserted (reload for this to take effect).`) + +}; +elements.head.breakInto = ["bone","brain","brain","cerebrospinal_fluid","blood","blood","meat"]; + +elements.head.onMoveInto = function(pixel,otherPixel) { + var pX = pixel.x; + var pY = pixel.y; + if(!pixel.dead) { + var otherElement = otherPixel.element; + var oX = otherPixel.x; + var oY = otherPixel.y; + if(oY !== (pY + 1)) { //exclude the body under this head + if(otherElement === "head") { //if the pixel hitting this head is also a head + //console.log("head.onMoveInto: Head has tried to move into head"); + if(hasPixel(oX,oY+1,"body")) { //if the pixel hitting this pixel has a body under it + var otherBody = pixelMap[oX][oY+1]; + if(otherPixel.dead || otherBody.dead) { //if either part of that human is dead + pixel.panic += 0.08; //being hit by a dead ******* body is terrifying + //console.log("head.onMoveInto: panic increase, case: head hit by dead whole body (head's code branch)"); + } else { + //if(otherPixel.panic > 0.04) { pixel.panic += 0.04; console.log("head.onMoveInto: panic increase, case: head hit by panicked whole body (head's code branch)"); }; //living, normal, headed bodies scare only if that incoming human is already scared + }; + } else { //if it's a severed head + if(otherPixel.dead) { //if the head is dead + pixel.panic += 0.08; //being hit by a /severed ******* head/ is terrifying + //console.log("head.onMoveInto: panic increase, case: head hit by dead severed head"); + } else { + pixel.panic += 0.1; //being hit by a //******* severed head that's still alive// is even worse + //console.log("head.onMoveInto: panic increase, case: head hit by living severed head"); + }; + }; + } else if(otherElement === "body") { //if the pixel hitting this head is a body + if(hasPixel(oX,oY-1,"head")) { //if the body hitting this pixel has a head on it + var otherHead = pixelMap[oX][oY-1]; + if(otherPixel.dead || otherHead.dead) { //if either part of that human is dead + pixel.panic += 0.03; //dead whole body case + //console.log("head.onMoveInto: panic increase, case: head hit by dead whole body (body's code branch)"); + } else { + if(otherHead.panic > 0.04) { + pixel.panic += 0.03; + //console.log("head.onMoveInto: panic increase, case: head crushed by panicked whole body (body's code branch)"); + } else { + pixel.panic += 0.02; + //console.log("head.onMoveInto: panic increase, case: head crushed by whole body (body's code branch)"); + }; + }; + } else { //severed body case + if(otherPixel.dead) { //if the body is dead + pixel.panic += 0.04; //imagine being hit by a severed human without the head + //console.log("head.onMoveInto: panic increase, case: head hit by dead severed body"); + } else { + pixel.panic += 0.05; //imagine the above but the heart is still beating + //console.log("head.onMoveInto: panic increase, case: head hit by living severed body"); + }; + }; + } else { + if(oX === pX && oY === pY-1) { + var otherInfo = elements[otherElement]; + var otherState; typeof(otherInfo.state) === "undefined" ? otherState = null : otherState = otherInfo.state; + var otherDensity = typeof(otherInfo.density) === "undefined" ? otherDensity = null : otherDensity = otherInfo.density; + if(otherState === "solid") { + if(otherDensity > 5000) { + var chance = (0.1 + (otherDensity/50000)) / 5; + if(Math.random() < chance) { + breakPixel(pixel); + }; + } else if(otherDensity >= 500) { + pixel.panic += (0.01 * (otherDensity / 500)); + } else if(otherDensity >= 100) { + pixel.panic += (0.001 * (otherDensity / 100)); + }; + }; + }; + }; + }; + }; +}; + +//Worldgen preset for testing + +worldgentypes.basalt_dirt = { + layers: [ + [0, "basalt", 0.05], + [0, "dirt"] + ] +}; + +kep1er = [ + ["first_impact", ["#664482","#cf4ba3","#c15ca9","#f0a669"]], + ["doublast", ["#2b98fd","#d0e26d","#e6f049","#dce4b3"]], + ["fly-up", ["#f2f2f2","#15a667","#de0180"]], + ["troubleshooter", ["#291923","#ed3fb6","#fee6f8","#64c5e0","#d6cdca","#330d25"]], + ["fly-by", ["#e7e6dd","#fcf0ef","#efa1ba","#8d7cb6","#5e74ba","#2b5db5","#e292b7"]], + ["lovestruck", ["#bfd9f0","#bfd9f0","#fef792","#c36475","#edd1d6"]], +]; + +for(index in kep1er) { + index = parseInt(index); + var newName = kep1er[index][0]; + var newColor = kep1er[index][1]; + var newDisplayName = newName.replaceAll("_"," ").replaceAll("-"," - ").split(" ").map(x => x.substring(0,1).toUpperCase() + x.substring(1)).join(" ").replace(" - ","-"); + elements[newName] = { + name: newDisplayName, + color: newColor, + tempHigh: 200, + stateHigh: ["ash","molten_plastic"], + density: 332, //based off of First Impact: https://www.amazon.com/Kep1er-IMPACT-Contents-Tracking-Connect/dp/B09MQMNZ62 + tick: function(pixel) { + if(!(tryMove(pixel,pixel.x,pixel.y+1))) { + var directions = []; + if(isEmpty(pixel.x-1,pixel.y+1) && isEmpty(pixel.x-1,pixel.y+2)) { + directions.push(-1) + }; + if(isEmpty(pixel.x+1,pixel.y+1) && isEmpty(pixel.x+1,pixel.y+2)) { + directions.push(1) + }; + if(directions.length > 0) { + tryMove(pixel,pixel.x+directions[Math.floor(Math.random() * directions.length)],pixel.y) + }; + } + }, + reactions: { + water: { elem1: ["plastic","cellulose","cellulose"], elem2: ["water","water","cellulose",null,null], chance: 0.8 } + }, + burn: 40, + burnTime: 150, + burnInto: ["ash","molten_plastic","carbon_dioxide","smoke"], + category: "other" + }; + + goodPixels[newName] = { panicChange: 0.01, panicChangeChance: 0.2, moodChange: 0.035 }; }; diff --git a/mods/life_eater.js b/mods/life_eater.js index 0ca0d1b1..7b7fd185 100644 --- a/mods/life_eater.js +++ b/mods/life_eater.js @@ -1,11 +1,7 @@ var modName = "mods/life_eater.js"; var fireMod = "mods/fire_mod.js"; -if(!enabledMods.includes(fireMod)) { - enabledMods.splice(enabledMods.indexOf(modName),0,fireMod); - localStorage.setItem("enabledMods", JSON.stringify(enabledMods)); - alert(`The ${fireMod} mod is required and has been automatically inserted (reload for this to take effect).`); -} else { +dependOn("fire_mod.js", function() { var lifeEaterCategories = ["life","auto creepers","food","fantastic creatures","fey","auto_fey"]; var lifeEaterBlacklist = ["life_eater_virus","life_eater_slurry","life_eater_infected_dirt"]; @@ -166,4 +162,4 @@ if(!enabledMods.includes(fireMod)) { stateHigh: elements.metal_scrap.stateHigh.concat("life_eater_virus","life_eater_virus","life_eater_virus"), }; -} +}, true); diff --git a/mods/metals.js b/mods/metals.js index dbabbe17..f16362a8 100644 --- a/mods/metals.js +++ b/mods/metals.js @@ -21,7 +21,7 @@ var modName = "mods/metals.js"; // var changeTempMod = "mods/changeTempReactionParameter.js"; // var runAfterAutogenMod = "mods/runAfterAutogen2.js"; var libraryMod = "mods/code_library.js"; -dependOn("library_test.js", function(){ +dependOn("code_library.js", function(){ elements.iron.hardness = 0.74 //https://www.engineeringtoolbox.com/bhn-brinell-hardness-number-d_1365.html //https://en.wikipedia.org/wiki/Hardnesses_of_the_elements_(data_page) diff --git a/mods/neutronium_compressor.js b/mods/neutronium_compressor.js index 106fb506..d8464c4d 100644 --- a/mods/neutronium_compressor.js +++ b/mods/neutronium_compressor.js @@ -1,27 +1,8 @@ -function whenAvailable(names, callback) { - var interval = 10; // ms - window.setTimeout(function() { - let bool = true; - for(let i = 0; i < names.length; i++) - { - if(!window[names[i]]) - { - bool = false; - } - } - if (bool) { - callback(); - } else { - whenAvailable(names, callback); - } - }, interval); -} var modName = "mods/neutronium_compressor.js"; -var runAfterAutogenMod = "mods/runAfterAutogen2.js"; -var libraryMod = "mods/code_library.js"; +// var runAfterAutogenMod = "mods/runAfterAutogen2.js"; +// var libraryMod = "mods/code_library.js"; -if(enabledMods.includes(runAfterAutogenMod) && enabledMods.includes(libraryMod)) { - whenAvailable(["urlParams","runAfterAutogen"], function() { +dependOn("code_library.js", function(){ var singularityColorTemplate = ["#202020", "#505050", "#b0b0b0", "#c7c7c7"]; singularityNumber = 10000; @@ -406,11 +387,5 @@ if(enabledMods.includes(runAfterAutogenMod) && enabledMods.includes(libraryMod)) }; //Post-generation tasks - - }); -} else { - if(!enabledMods.includes(runAfterAutogenMod)) { enabledMods.splice(enabledMods.indexOf(modName),0,runAfterAutogenMod) }; - if(!enabledMods.includes(libraryMod)) { enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod) }; - alert(`The "${runAfterAutogenMod}" and "${libraryMod}" mods are required; any missing mods in this list have been automatically inserted (reload for this to take effect).`) - localStorage.setItem("enabledMods", JSON.stringify(enabledMods)); -}; + +}, true); \ No newline at end of file diff --git a/mods/portal.js b/mods/portal.js index aa9caaef..f27ab076 100644 --- a/mods/portal.js +++ b/mods/portal.js @@ -1,8 +1,8 @@ var modName = "mods/portal.js"; -var onTryMoveIntoMod = "mods/onTryMoveInto.js"; +// var onTryMoveIntoMod = "mods/onTryMoveInto.js"; var libraryMod = "mods/code_library.js"; -if(enabledMods.includes(onTryMoveIntoMod) && enabledMods.includes(libraryMod)) { +dependOn("code_library.js", function(){ //https://stackoverflow.com/a/60922255 if(!enabledMods.includes("mods/mobs.js")) { headBodyObject = { @@ -17,7 +17,7 @@ if(enabledMods.includes(onTryMoveIntoMod) && enabledMods.includes(libraryMod)) { _correspondingPortals: null, }, insulate: true, - onTryMoveInto: function(pixel,otherPixel) { + onMoveInto: function(pixel,otherPixel) { if(pixel._correspondingPortals == null) { return; }; @@ -112,9 +112,8 @@ if(enabledMods.includes(onTryMoveIntoMod) && enabledMods.includes(libraryMod)) { state: "solid", insulate: true, } -} else { - if(!enabledMods.includes(libraryMod)) { enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod) }; - if(!enabledMods.includes(onTryMoveIntoMod)) { enabledMods.splice(enabledMods.indexOf(modName),0,onTryMoveIntoMod) }; - localStorage.setItem("enabledMods", JSON.stringify(enabledMods)); - alert(`The "${libraryMod}" and "${onTryMoveIntoMod}" mods are all required; any missing mods in this list have been automatically inserted (reload for this to take effect).`) -}; +}, true); + // if(!enabledMods.includes(libraryMod)) { enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod) }; + // if(!enabledMods.includes(onTryMoveIntoMod)) { enabledMods.splice(enabledMods.indexOf(modName),0,onTryMoveIntoMod) }; + // localStorage.setItem("enabledMods", JSON.stringify(enabledMods)); + // alert(`The "${libraryMod}" and "${onTryMoveIntoMod}" mods are all required; any missing mods in this list have been automatically inserted (reload for this to take effect).`) diff --git a/mods/prompt.js b/mods/prompt.js index dcfba5af..0b9596b2 100644 --- a/mods/prompt.js +++ b/mods/prompt.js @@ -3,7 +3,7 @@ var variablesMod = "mods/prop and prompt variables.js"; var promptInputNullishes = ["null","none","","n/a"]; var eightSpaces = " ".repeat(8); -if(enabledMods.includes(variablesMod)) { +dependOn("prop and prompt variables.js", function(){ commandHelpObject = { "set": "Sets properties for every pixel of a given type.\nUsage: set [property] [element] [value] \nDon't include framing characters []<>.\nThe element can be \"all\" to set the property for every pixel.\nNote: Strings can't have spaces because spaces are the separator used in the parsing split().\nArguments in [brackets] are required and ones in are optional.", @@ -1208,8 +1208,4 @@ Make sure to save your command in a file if you want to add this preset again.` desc: "Click here or press Shift+1 to open the command prompt.", category:"special", }; -} else { - alert(`The ${variablesMod} mod is required and has been automatically inserted (reload for this to take effect).`) - enabledMods.splice(enabledMods.indexOf(modName),0,variablesMod) - localStorage.setItem("enabledMods", JSON.stringify(enabledMods)); -}; +}, true); \ No newline at end of file diff --git a/mods/prop.js b/mods/prop.js index 6a3e690a..cac7a02a 100644 --- a/mods/prop.js +++ b/mods/prop.js @@ -1,7 +1,7 @@ var modName = "mods/prop.js"; var variablesMod = "mods/prop and prompt variables.js"; -if(enabledMods.includes(variablesMod)) { +dependOn("prop and prompt variables.js", function(){ propProperty = "element"; propValue = "sand"; propType = "string"; @@ -212,7 +212,7 @@ if(enabledMods.includes(variablesMod)) { }; pixelTempCheck(pixel); }, - category: "tools", + category: "edit", desc: `Sets properties of pixels.
Currently setting ${propProperty} to ${propValue} (${propType}).
Press [,] or click here to open the property tool prompt.`, }; @@ -452,15 +452,11 @@ if(enabledMods.includes(variablesMod)) { pixelTempCheck(pixel); }; }, - category: "tools", + category: "edit", desc: `Changes properties of pixels.
Currently ${numberAdjusterVerb} ${numberAdjusterValue} ${numberAdjusterPreposition} ${numberAdjusterProperty}.
Press [Shift+,] or click here to open the adjuster tool prompt.`, }; function updateNumberAdjusterDescription() { elements.number_adjuster.desc = numberAdjusterReverseOrder ? `Changes numeric properties of pixels.
Currently ${numberAdjusterVerb} ${numberAdjusterProperty} ${numberAdjusterPreposition} ${numberAdjusterValue}.
Press [Shift+,] or click here to open the adjuster tool prompt.` : `Changes numeric properties of pixels.
Currently ${numberAdjusterVerb} ${numberAdjusterValue} ${numberAdjusterPreposition} ${numberAdjusterProperty}.
Press [Shift+,] or click here to open the adjuster tool prompt.`; }; -} else { - alert(`The ${variablesMod} mod is required and has been automatically inserted (reload for this to take effect).`) - enabledMods.splice(enabledMods.indexOf(modName),0,variablesMod) - localStorage.setItem("enabledMods", JSON.stringify(enabledMods)); -}; +}, true); \ No newline at end of file diff --git a/mods/pullers.js b/mods/pullers.js index 085871ed..4b59320f 100644 --- a/mods/pullers.js +++ b/mods/pullers.js @@ -48,18 +48,18 @@ behaviors.SELFDELETE = [ pullerColour = '#e0adb6' -elements.pullersDesc = { - color: pullerColour, - name: 'pullers.js', - category: "Mods", - behavior: behaviors.SELFDELETE, - tool: function(pixel) {}, - onSelect: function(pixel) { - let info1stMod = `pullers.js is a mod made by voidapex11 that adds pullers to sandboxels` - alert(info1stMod) - return - }, -}; +// elements.pullersDesc = { +// color: pullerColour, +// name: 'pullers.js', +// category: "Mods", +// behavior: behaviors.SELFDELETE, +// tool: function(pixel) {}, +// onSelect: function(pixel) { +// let info1stMod = `pullers.js is a mod made by voidapex11 that adds pullers to sandboxels` +// alert(info1stMod) +// return +// }, +// }; // for the inator reference: if you know you know elements.immovable_inator = { diff --git a/mods/random_liquids.js b/mods/random_liquids.js index 85623c61..f824a9f2 100644 --- a/mods/random_liquids.js +++ b/mods/random_liquids.js @@ -1,7 +1,7 @@ var modName = "mods/random_liquids.js"; var libraryMod = "mods/code_library.js"; -if(enabledMods.includes(libraryMod)) { +dependOn("code_library.js", function(){ if(urlParams.get('liquidAmount') != null) { //null check liquidAmount = urlParams.get('liquidAmount') if(isNaN(liquidAmount) || liquidAmount === "" || liquidAmount === null) { //NaN check @@ -213,8 +213,4 @@ if(enabledMods.includes(libraryMod)) { if(makeLiquidString == true) { console.log(`Liquids added to liquidString (length ${liquidString.length})`) } -} else { - alert(`The ${libraryMod} mod is required and has been automatically inserted (reload for this to take effect).`) - enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod) - localStorage.setItem("enabledMods", JSON.stringify(enabledMods)); -}; +}, true); \ No newline at end of file diff --git a/mods/random_rocks.js b/mods/random_rocks.js index b2a14b1a..afddc296 100644 --- a/mods/random_rocks.js +++ b/mods/random_rocks.js @@ -1,7 +1,7 @@ var modName = "mods/random_rocks.js"; var libraryMod = "mods/code_library.js"; -if(enabledMods.includes(libraryMod)) { +dependOn("code_library.js", function(){ if(urlParams.get('rockAmount') != null) { //null check rockAmount = urlParams.get('rockAmount') if(isNaN(rockAmount) || rockAmount === "" || rockAmount === null) { //NaN check @@ -157,8 +157,4 @@ if(enabledMods.includes(libraryMod)) { if(makeRockString == true) { console.log(`Rocks added to rockString (length ${rockString.length})`) } -} else { - alert(`The ${libraryMod} mod is required and has been automatically inserted (reload for this to take effect).`) - enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod) - localStorage.setItem("enabledMods", JSON.stringify(enabledMods)); -}; +}, true); \ No newline at end of file diff --git a/mods/randomness.js b/mods/randomness.js index dcd4a053..4bfec787 100644 --- a/mods/randomness.js +++ b/mods/randomness.js @@ -1,7 +1,7 @@ var modName = "mods/randomness.js"; var libraryMod = "mods/code_library.js"; -if(enabledMods.includes(libraryMod)) { +dependOn("code_library.js", function(){ //i made some stupid things //TPT reference @@ -723,8 +723,4 @@ if(enabledMods.includes(libraryMod)) { } } }); -} else { - if(!enabledMods.includes(libraryMod)) { enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod) }; - alert(`The "${libraryMod}" mod is required and has been automatically inserted (reload for this to take effect).`) - localStorage.setItem("enabledMods", JSON.stringify(enabledMods)); -}; +}, true); \ No newline at end of file diff --git a/mods/rays.js b/mods/rays.js index 0b039664..d8ee75d2 100644 --- a/mods/rays.js +++ b/mods/rays.js @@ -1,28 +1,27 @@ -function whenAvailable(names, callback) { - var interval = 10; // ms - window.setTimeout(function() { - let bool = true; - for(let i = 0; i < names.length; i++) - { - if(!window[names[i]]) - { - bool = false; - } - } - if (bool) { - callback(); - } else { - whenAvailable(names, callback); - } - }, interval); -} +// function whenAvailable(names, callback) { +// var interval = 10; // ms +// window.setTimeout(function() { +// let bool = true; +// for(let i = 0; i < names.length; i++) +// { +// if(!window[names[i]]) +// { +// bool = false; +// } +// } +// if (bool) { +// callback(); +// } else { +// whenAvailable(names, callback); +// } +// }, interval); +// } var modName = "mods/rays.js"; -var runAfterAutogenMod = "mods/runAfterAutogen2.js"; -var libraryMod = "mods/code_library.js"; +// var runAfterAutogenMod = "mods/runAfterAutogen2.js"; +// var libraryMod = "mods/code_library.js"; -if(enabledMods.includes(runAfterAutogenMod) && enabledMods.includes(libraryMod)) { -whenAvailable(["raaLoaded","libraryLoaded"], function() { +dependOn("code_library.js", function(){ runAfterAutogen(function() { snowAndIceCache = Object.keys(elements).filter(function(name) { return name.endsWith("snow") || name.endsWith("ice") || name == "rime" @@ -455,10 +454,4 @@ whenAvailable(["raaLoaded","libraryLoaded"], function() { } } }; -}); -} else { - if(!enabledMods.includes(libraryMod)) { enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod) }; - if(!enabledMods.includes(runAfterAutogenMod)) { enabledMods.splice(enabledMods.indexOf(modName),0,runAfterAutogenMod) }; - localStorage.setItem("enabledMods", JSON.stringify(enabledMods)); - alert(`The "${runAfterAutogenMod}" and "${libraryMod}" mods are required and have been automatically inserted (reload for this to take effect).`); -}; +},true); \ No newline at end of file diff --git a/mods/replace.js b/mods/replace.js index eaf374c4..fa791b1f 100644 --- a/mods/replace.js +++ b/mods/replace.js @@ -49,7 +49,7 @@ elements.replace = { changePixel(pixel,replaceTo,true); }; }, - category: "tools", + category: "edit", desc: "Changes pixels of a specified type to another specified type.
Currently replacing \"" + replaceFrom + "\" with \"" + replaceTo + "\".
Press [\"] or click here to open the replace prompt.", }; @@ -60,7 +60,7 @@ elements.alt_replace = { pixel.element = replaceTo; }; }, - category: "tools", + category: "edit", desc: "Changes pixels of a specified type to another specified type, but keeping their non-element-based properties.
Currently replacing \"" + replaceFrom + "\" with \"" + replaceTo + "\".
Press [\"] or click here to open the replace prompt.", hidden: true, }; @@ -73,7 +73,7 @@ elements.alt_alt_replace = { pixel.color = pixelColorPick(pixel); }; }, - category: "tools", + category: "edit", desc: "Changes pixels of a specified type to another specified type, but keeping their non-element-based properties except for color.
Currently replacing \"" + replaceFrom + "\" with \"" + replaceTo + "\".
Press [\"] or click here to open the replace prompt.", hidden: true, }; diff --git a/mods/roseyiede.js b/mods/roseyiede.js index 8ea22616..2e5210da 100644 --- a/mods/roseyiede.js +++ b/mods/roseyiede.js @@ -1,7 +1,7 @@ var modName = "mods/roseyiede.js"; var libraryMod = "mods/code_library.js"; -if(enabledMods.includes(libraryMod)) { +dependOn("code_library.js", function(){ /* //arbitrarily picked binitialArrayL = ["m","n","p","t","ch","k","b","d","j","g","f","th","s","sh","h","l","r","y","w","z"] //:eggTF: @@ -356,8 +356,4 @@ if(enabledMods.includes(libraryMod)) { density: 956, temp: 120, } -} else { - alert(`The ${libraryMod} mod is required and has been automatically inserted (reload for this to take effect).`) - enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod) - localStorage.setItem("enabledMods", JSON.stringify(enabledMods)); -}; +}, true); \ No newline at end of file diff --git a/mods/solid_rock.js b/mods/solid_rock.js index c65d290b..702be315 100644 --- a/mods/solid_rock.js +++ b/mods/solid_rock.js @@ -1,74 +1,71 @@ var modName = "mods/random_rocks.js"; -var onTryMoveIntoMod = "mods/onTryMoveInto.js"; -var libraryMod = "mods/code_library.js"; +// var onTryMoveIntoMod = "mods/onTryMoveInto.js"; +// var libraryMod = "mods/code_library.js"; -if(enabledMods.includes(onTryMoveIntoMod) && enabledMods.includes(libraryMod)) { - elements.solid_rock = { - color: ["#808080","#4f4f4f","#949494"], - behavior: behaviors.WALL, - reactions: { - "water": {elem1: "wet_sand", chance: 0.00035}, - "salt_water": {elem1: "wet_sand", chance: 0.0005}, - "sugar_water": {elem1: "wet_sand", chance: 0.0004}, - "seltzer": {elem1: "wet_sand", chance: 0.0004}, - "dirty_water": {elem1: "wet_sand", chance: 0.0004}, - "soda": {elem1: "wet_sand", chance: 0.0004}, - "lichen": {elem1: "dirt", chance: 0.0025}, - "grape": {elem2: "juice", chance: 0.1, color2: "#291824"}, - "root": {elem1: "sand", chance: 0.0004}, - "wheat": {elem2: "flour"}, - "primordial_soup": {elem1: "wet_sand", chance: 0.001} - }, - onTryMoveInto: function(pixel,otherPixel) { - if(elements[otherPixel.element].category === "corruption") { - if(Math.random() < 0.05) { - changePixel(pixel,"corrupt_solid_rock"); - return; - }; - } else { - reactionStealer(pixel,otherPixel,"rock"); +dependOn("code_library.js", function(){ + +elements.solid_rock = { + color: ["#808080","#4f4f4f","#949494"], + behavior: behaviors.WALL, + reactions: { + "water": {elem1: "wet_sand", chance: 0.00035}, + "salt_water": {elem1: "wet_sand", chance: 0.0005}, + "sugar_water": {elem1: "wet_sand", chance: 0.0004}, + "seltzer": {elem1: "wet_sand", chance: 0.0004}, + "dirty_water": {elem1: "wet_sand", chance: 0.0004}, + "soda": {elem1: "wet_sand", chance: 0.0004}, + "lichen": {elem1: "dirt", chance: 0.0025}, + "grape": {elem2: "juice", chance: 0.1, color2: "#291824"}, + "root": {elem1: "sand", chance: 0.0004}, + "wheat": {elem2: "flour"}, + "primordial_soup": {elem1: "wet_sand", chance: 0.001} + }, + onMoveInto: function(pixel,otherPixel) { + if(elements[otherPixel.element].category === "corruption") { + if(Math.random() < 0.05) { + changePixel(pixel,"corrupt_solid_rock"); + return; }; - }, - tempHigh: 950, - stateHigh: "magma", - category: "land", - state: "solid", - density: 2600, - hardness: 0.55, - breakInto: "rock", - } + } else { + reactionStealer(pixel,otherPixel,"rock"); + }; + }, + tempHigh: 950, + stateHigh: "magma", + category: "land", + state: "solid", + density: 2600, + hardness: 0.55, + breakInto: "rock", +} - if(enabledMods.includes("mods/fey_and_more.js")) { - elements.corrupt_solid_rock = { - color: ["#514c78","#514c78","#2a264d","#2a264d","#514c78","#514c78"], - behavior: behaviors.WALL, - tempHigh: 1200, - category: "corruption", - state: "solid", - density: 1250, - breakInto: "corrupt_rock", - tick: function(pixel) { - var randomNeighborOffset = adjacentCoords[Math.floor(Math.random() * adjacentCoords.length)]; - var rfX = pixel.x+randomNeighborOffset[0]; - var rfY = pixel.y+randomNeighborOffset[1]; - if(!isEmpty(rfX,rfY,true)) { - var otherPixel = pixelMap[rfX][rfY]; - if(otherPixel.element === "solid_rock") { - if(Math.random() < 0.05) { - changePixel(otherPixel,"corrupt_solid_rock") - }; +if(enabledMods.includes("mods/fey_and_more.js")) { + elements.corrupt_solid_rock = { + color: ["#514c78","#514c78","#2a264d","#2a264d","#514c78","#514c78"], + behavior: behaviors.WALL, + tempHigh: 1200, + category: "corruption", + state: "solid", + density: 1250, + breakInto: "corrupt_rock", + tick: function(pixel) { + var randomNeighborOffset = adjacentCoords[Math.floor(Math.random() * adjacentCoords.length)]; + var rfX = pixel.x+randomNeighborOffset[0]; + var rfY = pixel.y+randomNeighborOffset[1]; + if(!isEmpty(rfX,rfY,true)) { + var otherPixel = pixelMap[rfX][rfY]; + if(otherPixel.element === "solid_rock") { + if(Math.random() < 0.05) { + changePixel(otherPixel,"corrupt_solid_rock") }; }; - }, - }; - - runAfterLoad(function() { - elements.corrupt_solid_rock.reactions = elements.corrupt_land.reactions; - }); - } -} else { - if(!enabledMods.includes(libraryMod)) { enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod) }; - if(!enabledMods.includes(onTryMoveIntoMod)) { enabledMods.splice(enabledMods.indexOf(modName),0,onTryMoveIntoMod) }; - localStorage.setItem("enabledMods", JSON.stringify(enabledMods)); - alert(`The "${libraryMod}" and "${onTryMoveIntoMod}" mods are all required; any missing mods in this list have been automatically inserted (reload for this to take effect).`) -}; + }; + }, + }; + + runAfterLoad(function() { + elements.corrupt_solid_rock.reactions = elements.corrupt_land.reactions; + }); +} + +},true); \ No newline at end of file diff --git a/mods/sponge_edit.js b/mods/sponge_edit.js index 8fd24da6..2672d903 100644 --- a/mods/sponge_edit.js +++ b/mods/sponge_edit.js @@ -1,8 +1,10 @@ var modName = "mods/sponge_edit.js"; -var onTryMoveIntoMod = "mods/onTryMoveInto.js"; +// var onTryMoveIntoMod = "mods/onTryMoveInto.js"; var libraryMod = "mods/code_library.js"; -if(enabledMods.includes(onTryMoveIntoMod) && enabledMods.includes(libraryMod)) { + + +dependOn("code_library.js", function(){ elements.sponge.properties ??= {}; elements.sponge.properties.maxAbsorb = 250; @@ -34,7 +36,7 @@ if(enabledMods.includes(onTryMoveIntoMod) && enabledMods.includes(libraryMod)) { }; }; - elements.sponge.onTryMoveInto = function(pixel,otherPixel) { + elements.sponge.onMoveInto = function(pixel,otherPixel) { var absorbedElements = Object.keys(pixel.absorbed); if(absorbedElements.length == 0) { return false; @@ -68,9 +70,4 @@ if(enabledMods.includes(onTryMoveIntoMod) && enabledMods.includes(libraryMod)) { }; }; }; -} else { - enabledMods.splice(enabledMods.indexOf(modName),0,onTryMoveIntoMod); - enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod); - localStorage.setItem("enabledMods", JSON.stringify(enabledMods)); - alert(`The ${onTryMoveIntoMod} mod and ${libraryMod} mods are required and have been automatically inserted (reload for this to take effect).`); -}; +}, true); \ No newline at end of file diff --git a/mods/stripe_paint.js b/mods/stripe_paint.js index 977e9544..89cb25cf 100644 --- a/mods/stripe_paint.js +++ b/mods/stripe_paint.js @@ -1,7 +1,7 @@ var modName = "mods/color_tools.js"; var libraryMod = "mods/code_library.js"; -if(enabledMods.includes(libraryMod)) { +dependOn("code_library.js", function(){ stripeFixedDefaultProperties = { color2: "rgb(0,0,0)", phase: 0, @@ -103,8 +103,4 @@ if(enabledMods.includes(libraryMod)) { }, desc: stripePaintDesc }; -} else { - alert(`The ${libraryMod} mod is required and has been automatically inserted (reload for this to take effect).`) - enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod) - localStorage.setItem("enabledMods", JSON.stringify(enabledMods)); -}; +}, true); \ No newline at end of file diff --git a/mods/structure_test.js b/mods/structure_test.js index 6d00aefe..2427268e 100644 --- a/mods/structure_test.js +++ b/mods/structure_test.js @@ -1,10 +1,7 @@ var modName = "mods/structure_test.js"; var libraryMod = "mods/code_library.js"; -if(!enabledMods.includes(libraryMod)) { - enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod); - alert(`The ${libraryMod} mod is required and has been automatically inserted (reload for this to take effect).`); -} else { +dependOn("code_library.js", function(){ arrayLoaderVoids = ["air", "null", null]; buildingOneSegmentDoor = ["concrete","wood_plank","concrete","wood_plank","concrete"]; buildingOneSegmentWindows = ["concrete","glass_pane","concrete","glass_pane","concrete"]; @@ -752,4 +749,4 @@ if(!enabledMods.includes(libraryMod)) { worldgentypes.desert.layers.shift(); }; }; -}; +}, true); \ No newline at end of file diff --git a/mods/wifi.js b/mods/wifi.js index bdc94a21..bf6e527c 100644 --- a/mods/wifi.js +++ b/mods/wifi.js @@ -1,7 +1,7 @@ var modName = "mods/wifi.js"; var libraryMod = "mods/code_library.js"; -if(enabledMods.includes(libraryMod)) { +dependOn("code_library.js", function(){ //https://stackoverflow.com/a/60922255 elements.wifi = { color: "#bfff7f", @@ -155,8 +155,4 @@ if(enabledMods.includes(libraryMod)) { state: "solid", } -} else { - if(!enabledMods.includes(libraryMod)) { enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod) }; - localStorage.setItem("enabledMods", JSON.stringify(enabledMods)); - alert(`The "${libraryMod}" mods is required; and has been automatically inserted (reload for this to take effect).`) -}; +}, true); \ No newline at end of file diff --git a/mods/wirelike_test.js b/mods/wirelike_test.js index 222099ae..447df508 100644 --- a/mods/wirelike_test.js +++ b/mods/wirelike_test.js @@ -1,7 +1,7 @@ var modName = "mods/wirelike_test.js"; var libraryMod = "mods/code_library.js"; -if(enabledMods.includes(libraryMod)) { +dependOn("code_library.js", function(){ //The CMYK is symbolic elements.start_test = { color: "#dddddd", @@ -674,8 +674,4 @@ if(enabledMods.includes(libraryMod)) { }; }, }; -} else { - alert(`The ${libraryMod} mod is required and has been automatically inserted (reload for this to take effect).`) - enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod) - localStorage.setItem("enabledMods", JSON.stringify(enabledMods)); -}; +}, true) \ No newline at end of file diff --git a/mods/yumcherries.js b/mods/yumcherries.js index 1d4b786d..6c54ead0 100644 --- a/mods/yumcherries.js +++ b/mods/yumcherries.js @@ -1,139 +1,347 @@ var modName = "mods/cherries.js"; -var onTryMoveIntoMod = "mods/onTryMoveInto.js"; -var libraryMod = "mods/code_library.js"; +// var onTryMoveIntoMod = "mods/onTryMoveInto.js"; +// var libraryMod = "mods/code_library.js"; -if(enabledMods.includes(onTryMoveIntoMod) && enabledMods.includes(libraryMod)) { - randomNumberFromOneToThree = function() { - return 1 + Math.floor(Math.random() * 3) - }; - - debugSpeedGrowth = false; - logLeaves = false; - cherryAttachWhitelist = ["cherry_log","cherry_branch_1","cherry_branch_2","blossom","cherry_leaf","cherry_plant_top","cherry"]; - - cherryDirtElements = ["dirt","mud","sand","wet_sand","clay_soil","mycelium","grass"]; +dependOn("code_library.js", function(){ +randomNumberFromOneToThree = function() { + return 1 + Math.floor(Math.random() * 3) +}; - function logPixelCoords(pixel) { - return `(${pixel.x}, ${pixel.y})` - }; +debugSpeedGrowth = false; +logLeaves = false; +cherryAttachWhitelist = ["cherry_log","cherry_branch_1","cherry_branch_2","blossom","cherry_leaf","cherry_plant_top","cherry"]; - function hasPixel(x,y,elementInput) { - if(isEmpty(x,y,true)) { //if empty, it can't have a pixel - return false; +cherryDirtElements = ["dirt","mud","sand","wet_sand","clay_soil","mycelium","grass"]; + +function logPixelCoords(pixel) { + return `(${pixel.x}, ${pixel.y})` +}; + +function hasPixel(x,y,elementInput) { + if(isEmpty(x,y,true)) { //if empty, it can't have a pixel + return false; + } else { + if(elementInput.includes(",")) { //CSTA + elementInput = elementInput.split(","); + }; + if(Array.isArray(elementInput)) { //if element list + return elementInput.includes(pixelMap[x][y].element); + } else { //if single element + return pixelMap[x][y].element === elementInput; + }; + }; +}; + +elements.cherry_seed = { + color: "#8b4513", + tick: function(pixel) { + if(pixel.cherryRange === null) { + pixel.cherryRange = randomNumberFromOneToThree(); + }; + + if (isEmpty(pixel.x,pixel.y+1)) { + movePixel(pixel,pixel.x,pixel.y+1); } else { - if(elementInput.includes(",")) { //CSTA - elementInput = elementInput.split(","); - }; - if(Array.isArray(elementInput)) { //if element list - return elementInput.includes(pixelMap[x][y].element); - } else { //if single element - return pixelMap[x][y].element === elementInput; - }; - }; - }; - - elements.cherry_seed = { - color: "#8b4513", - tick: function(pixel) { - if(pixel.cherryRange === null) { - pixel.cherryRange = randomNumberFromOneToThree(); - }; - - if (isEmpty(pixel.x,pixel.y+1)) { - movePixel(pixel,pixel.x,pixel.y+1); - } else { - if (Math.random() < (debugSpeedGrowth ? 0.09 : 0.03) && pixel.age > (debugSpeedGrowth ? 20 : 50) && pixel.temp < 100) { - if (!outOfBounds(pixel.x,pixel.y+1)) { - var dirtPixel = pixelMap[pixel.x][pixel.y+1]; - if (cherryDirtElements.includes(dirtPixel.element)) { - changePixel(dirtPixel,"root"); - }; + if (Math.random() < (debugSpeedGrowth ? 0.09 : 0.03) && pixel.age > (debugSpeedGrowth ? 20 : 50) && pixel.temp < 100) { + if (!outOfBounds(pixel.x,pixel.y+1)) { + var dirtPixel = pixelMap[pixel.x][pixel.y+1]; + if (cherryDirtElements.includes(dirtPixel.element)) { + changePixel(dirtPixel,"root"); }; - if (isEmpty(pixel.x,pixel.y-1)) { - movePixel(pixel,pixel.x,pixel.y-1); - createPixel("cherry_log",pixel.x,pixel.y+1); - pixelMap[pixel.x][pixel.y+1].cherryRange = pixel.cherryRange; //pass cherry range down to log - }; - } else if (pixel.age > (debugSpeedGrowth ? 500 : 1000)) { - changePixel(pixel,"cherry_plant_top"); }; - pixel.age++; - }; - if(Math.random() < 0.01 && pixel.age > 200) { + if (isEmpty(pixel.x,pixel.y-1)) { + movePixel(pixel,pixel.x,pixel.y-1); + createPixel("cherry_log",pixel.x,pixel.y+1); + pixelMap[pixel.x][pixel.y+1].cherryRange = pixel.cherryRange; //pass cherry range down to log + }; + } else if (pixel.age > (debugSpeedGrowth ? 500 : 1000)) { changePixel(pixel,"cherry_plant_top"); }; - doDefaults(pixel); - }, - properties: { - "age": 0, - //"cherryRange": null, //apparently this is suddenly, in an illogical, never-before-seen, completely new, unprecedented incident of bad behavior, evaluated before being put into the property database, so RNG has to be done in tick - "cherryRange": null, - }, - tempHigh: 100, - stateHigh: "dead_plant", - tempLow: -2, - stateLow: "frozen_plant", - burn: 5, - burnInto: ["steam", "ash"], - burnTime: 600, - category: "life", - state: "solid", - density: 1500, - cooldown: defaultCooldown, - }; + pixel.age++; + }; + if(Math.random() < 0.01 && pixel.age > 200) { + changePixel(pixel,"cherry_plant_top"); + }; + doDefaults(pixel); + }, + properties: { + "age": 0, + //"cherryRange": null, //apparently this is suddenly, in an illogical, never-before-seen, completely new, unprecedented incident of bad behavior, evaluated before being put into the property database, so RNG has to be done in tick + "cherryRange": null, + }, + tempHigh: 100, + stateHigh: "dead_plant", + tempLow: -2, + stateLow: "frozen_plant", + burn: 5, + burnInto: ["steam", "ash"], + burnTime: 600, + category: "life", + state: "solid", + density: 1500, + cooldown: defaultCooldown, +}; - elements.cherry_log = { - hidden: true, - color: "#310a0b", - tick: function(pixel) { - if(pixel.cherryRange === null) { - pixel.cherryRange = randomNumberFromOneToThree(); +elements.cherry_log = { + hidden: true, + color: "#310a0b", + tick: function(pixel) { + if(pixel.cherryRange === null) { + pixel.cherryRange = randomNumberFromOneToThree(); + }; + + if (pixel.age > 60 && pixel.temp < 100 && !pixel.grewPeduncle) { + var peduncleOffsets = [-1, 1]; //placed to the left, placed to the right + for(i = 0; i < peduncleOffsets.length; i++) { + if (isEmpty(pixel.x+peduncleOffsets[i],pixel.y,false)) { + if (Math.random() < 0.005) { + createPixel("cherry_branch_1",pixel.x+peduncleOffsets[i],pixel.y); + pixelMap[pixel.x+peduncleOffsets[i]][pixel.y].dir = Math.sign(peduncleOffsets[i]); + pixelMap[pixel.x+peduncleOffsets[i]][pixel.y].cherryRange = pixel.cherryRange; //pass cherry range down to branch + if(Math.random() < 0.8) { pixel.grewPeduncle = true; } //20% chance to not mark as true, allowing for a chance to try another branch + }; + }; }; + }; + pixel.age++; + doDefaults(pixel); + }, + properties: { + "age": 0, + "grewPeduncle": false, + "cherryRange": null, + }, + tempHigh: 100, + stateHigh: "dead_plant", + tempLow: -2, + stateLow: "frozen_plant", + burn: 5, + burnInto: ["steam", "ash"], + burnTime: 600, + category: "life", + state: "solid", + density: 1500, +}; - if (pixel.age > 60 && pixel.temp < 100 && !pixel.grewPeduncle) { - var peduncleOffsets = [-1, 1]; //placed to the left, placed to the right - for(i = 0; i < peduncleOffsets.length; i++) { - if (isEmpty(pixel.x+peduncleOffsets[i],pixel.y,false)) { - if (Math.random() < 0.005) { - createPixel("cherry_branch_1",pixel.x+peduncleOffsets[i],pixel.y); - pixelMap[pixel.x+peduncleOffsets[i]][pixel.y].dir = Math.sign(peduncleOffsets[i]); - pixelMap[pixel.x+peduncleOffsets[i]][pixel.y].cherryRange = pixel.cherryRange; //pass cherry range down to branch - if(Math.random() < 0.8) { pixel.grewPeduncle = true; } //20% chance to not mark as true, allowing for a chance to try another branch +elements.cherry = { + color: "#f7022a", + tick: function(pixel) { + if(pixel.attached) { + var attachCoords = [pixel.x+Math.sign(pixel.attachDirection), pixel.y]; + if(isEmpty(attachCoords[0],attachCoords[1],false)) { + pixel.attached = false; + }; + } else { //Move if not attached + if (!tryMove(pixel, pixel.x, pixel.y+1)) { + if(Math.random() < 0.9) { + if (Math.random() < 0.5) { + if (!tryMove(pixel, pixel.x+1, pixel.y+1)) { + tryMove(pixel, pixel.x-1, pixel.y+1); + }; + } else { + if (!tryMove(pixel, pixel.x-1, pixel.y+1)) { + tryMove(pixel, pixel.x+1, pixel.y+1); }; }; }; }; - pixel.age++; - doDefaults(pixel); - }, - properties: { - "age": 0, - "grewPeduncle": false, - "cherryRange": null, - }, - tempHigh: 100, - stateHigh: "dead_plant", - tempLow: -2, - stateLow: "frozen_plant", - burn: 5, - burnInto: ["steam", "ash"], - burnTime: 600, - category: "life", - state: "solid", - density: 1500, - }; - - elements.cherry = { - color: "#f7022a", - tick: function(pixel) { - if(pixel.attached) { - var attachCoords = [pixel.x+Math.sign(pixel.attachDirection), pixel.y]; - if(isEmpty(attachCoords[0],attachCoords[1],false)) { - pixel.attached = false; + }; + doDefaults(pixel); + var shouldSpoil = true; //spoil by default + if(pixel.attached) { //if it's attached + if(!isEmpty(attachCoords[0],attachCoords[1],true)) { //if the attachment coords are a pixel and not OOB + var attachPixel = pixelMap[attachCoords[0]][attachCoords[1]]; + var attachElement = attachPixel.element; + if(cherryAttachWhitelist.includes(attachElement)) {//if the element is a whitelisted "don't spoil" element + shouldSpoil = false; //then don't spoil }; - } else { //Move if not attached + }; + }; + if(shouldSpoil) { //spoil if not attached + if(pixel.temp > -14 && pixel.temp <= 4) { //(no spoiling below 14C) + pixel.spoilage += Math.max(Math.min(scale(pixel.temp,-14,4,0,9),9),0) + } else if(pixel.temp > 4) { + pixel.spoilage += Math.max(Math.min(scale(pixel.temp,4,20,9,30),40),0) + }; + }; + if(pixel.spoilage > 14400) { //3600 = 120 ticks at 20C + if(Math.random() < 0.05) { + changePixel(pixel,"spoiled_cherry"); + }; + }; + }, + properties: { + "spoilage":0, + "attached": false, + "attachDirection": (!Math.floor(Math.random() * 2)) ? 1 : -1, + }, + burn: 5, + burnInto: ["steam", "ash"], + burnTime: 600, + tempHigh: 200, + stateHigh: ["steam", "ash"], + onMoveInto: function(pixel,otherPixel) { + var otherInfo = elements[otherPixel.element] + if(typeof(otherInfo.state) === "string" && otherInfo.state !== "gas") { + pixel.attached = false; + }; + }, + category: "food", + breakInto: "juice", + breakIntoColor: "#A20205" +}; + +elements.cherry_branch_1 = { + hidden: true, + name: "cherry branch (offshoot)", + color: "#310a0b", + tick: function(pixel) { + if(pixel.cherryRange === null) { + pixel.cherryRange = randomNumberFromOneToThree(); + }; + + if (pixel.age > 20 && pixel.temp < 100) { + var peduncleCoords1 = [pixel.x + pixel.dir, pixel.y]; + var peduncleCoords2 = [pixel.x + pixel.dir, pixel.y + 1]; + if(isEmpty(peduncleCoords1[0],peduncleCoords1[1],false) && isEmpty(peduncleCoords2[0],peduncleCoords2[1],false)) { + if(Math.random() < 0.5) { + createPixel(pixel.element,peduncleCoords1[0],peduncleCoords1[1]); + pixelMap[peduncleCoords1[0]][peduncleCoords1[1]].dir = pixel.dir; + pixelMap[peduncleCoords1[0]][peduncleCoords1[1]].cherryRange = pixel.cherryRange; //pass cherry range down to next pixel of branch horizontal + } else { + createPixel("cherry_branch_2",peduncleCoords2[0],peduncleCoords2[1]); + pixelMap[peduncleCoords2[0]][peduncleCoords2[1]].cherryRange = pixel.cherryRange; //pass cherry range down to diagonal offshoot + }; + }; + }; + pixel.age++; + doDefaults(pixel); + }, + properties: { + "dir": (!Math.floor(Math.random() * 2)) ? 1 : -1, + "age": 0, + //"cherryRange": (1 + (Math.floor(Math.random() * 3))), //1-3 + "cherryRange": null, + }, + tempHigh: 100, + stateHigh: "dead_plant", + tempLow: -2, + stateLow: "frozen_plant", + burn: 5, + burnInto: ["steam", "ash"], + burnTime: 600, + category: "life", + state: "solid", + density: 1500, +}; + +elements.cherry_branch_2 = { + hidden: true, + name: "cherry branch (hanging)", + color: "#310a0b", + tick: function(pixel) { + if(pixel.cherryRange === null) { + pixel.cherryRange = randomNumberFromOneToThree(); + }; + + // Grow/Flower + if (pixel.age > 20 && pixel.temp < 100) { + var growthCoords = [pixel.x, pixel.y + 1]; + if(isEmpty(...growthCoords)) { + if(Math.random() < 0.9) { + createPixel(pixel.element,...growthCoords); + pixelMap[growthCoords[0]][growthCoords[1]].cherryRange = pixel.cherryRange; //pass cherry range down to next pixel of branch vertical + } else { + createPixel("blossom",...growthCoords); // cherry flower + }; + }; + }; + + //Make cherries + if (pixel.age > 40 && pixel.temp < 100) { + var cherryOffsets = [-1, 1]; //placed to the left, placed to the right + for(i = 0; i < cherryOffsets.length; i++) { + //console.log(`Looping through left and right positions: ${cherryOffsets}`); + for(j = 1; j < pixel.cherryRange + 1; j++) { //for max cherry distance, using the cherry range + //console.log(`Looping through cherry offset multipliers: ${j}`); + if (isEmpty(pixel.x+(j * cherryOffsets[i]),pixel.y,false)) { //if there's an empty space + //console.log(`Cherry position is empty: [${j * cherryOffsets[i]}, 0]\nTrying cherry at (${pixel.x+(j * cherryOffsets[i])},${pixel.y})`); + if (Math.random() < (debugSpeedGrowth ? 0.05 : 0.005)) { //try to place the cherry + //console.log(`Placing cherry`); + createPixel("cherry",pixel.x+(j * cherryOffsets[i]),pixel.y); + pixelMap[pixel.x+(j * cherryOffsets[i])][pixel.y].attached = true; + pixelMap[pixel.x+(j * cherryOffsets[i])][pixel.y].attachDirection = -1 * Math.sign(cherryOffsets[i]); //attach dir is the opposite of placement dir so it attaches towards the stem + } else { + //console.log(`NOT placing cherry`); + }; + //console.log(`Cherry tried, stopping iteration`); + break; //and then stop iteration + } else { + //console.log(`Cherry position is NOT empty: [${j * cherryOffsets[i]}, 0]\nSkipping this offset`); + continue; //if not empty, skip that pixel and move on the next distance + }; + //console.log(`====End of side try====`); + }; + //console.log(`####End of side iterator####`); + }; + //console.log(`>>>>End of cherry iterator<<<<`); + }; + pixel.age++; + doDefaults(pixel); + //console.log(`\nEnd of branch tick\n`); + }, + properties: { + "age": 0, + //"cherryRange": (1 + (Math.floor(Math.random() * 3))), //1-3 + "cherryRange": null, + }, + tempHigh: 100, + stateHigh: "dead_plant", + tempLow: -2, + stateLow: "frozen_plant", + burn: 5, + burnInto: ["steam", "ash"], + burnTime: 600, + category: "life", + state: "solid", + density: 1500, +}; + +elements.spoiled_cherry = { + hidden: true, + color: "#594b29", + behavior: [ + "XX|CR:stench,fly%0.1|XX", + "M2%0.5|CH:dirty_water,fly,fly%0.007|M2%0.5", + "M2|M1|M2" + ], + stain: 0.01, + burn: 5, + burnInto: ["steam", "ash"], + burnTime: 600, + tempHigh: 200, + stateHigh: ["steam", "ash"], +}; + +elements.fly.reactions.spoiled_cherry = { "elem2":null, chance:0.15, func:behaviors.FEEDPIXEL }; + +elements.cherry_leaf = { + hidden: true, + color: "#9df24e", + tick: function(pixel) { + if(pixel.cherryRange === null) { + pixel.cherryRange = randomNumberFromOneToThree(); + }; + + if(pixel.attached) { + var attachCoords = [pixel.x + pixel.attachOffsets[0], pixel.y + pixel.attachOffsets[1]]; + if(isEmpty(attachCoords[0],attachCoords[1],false)) { //consider OOB full + pixel.attached = false; + }; + } else { //Move if not attached + if(Math.random() < 0.2) { if (!tryMove(pixel, pixel.x, pixel.y+1)) { - if(Math.random() < 0.9) { + if(Math.random() < 0.4) { if (Math.random() < 0.5) { if (!tryMove(pixel, pixel.x+1, pixel.y+1)) { tryMove(pixel, pixel.x-1, pixel.y+1); @@ -146,398 +354,188 @@ if(enabledMods.includes(onTryMoveIntoMod) && enabledMods.includes(libraryMod)) { }; }; }; - doDefaults(pixel); - var shouldSpoil = true; //spoil by default - if(pixel.attached) { //if it's attached - if(!isEmpty(attachCoords[0],attachCoords[1],true)) { //if the attachment coords are a pixel and not OOB - var attachPixel = pixelMap[attachCoords[0]][attachCoords[1]]; - var attachElement = attachPixel.element; - if(cherryAttachWhitelist.includes(attachElement)) {//if the element is a whitelisted "don't spoil" element - shouldSpoil = false; //then don't spoil - }; + }; + doDefaults(pixel); + }, + properties: { + "attached": false, + "attachOffsets": [(!Math.floor(Math.random() * 2)) ? 1 : -1, 0], + "cherryRange": null, + }, + burn: 5, + burnInto: ["steam", "ash"], + burnTime: 600, + tempHigh: 200, + stateHigh: ["steam", "ash"], + onMoveInto: function(pixel,otherPixel) { //Move through + var otherElement = otherPixel.element; //var element for readability + + var otherInfo = elements[otherElement]; //var info + + var otherState = "solid"; //consider things solid by default + if(typeof(otherInfo.state) === "string") { + otherState = otherInfo.state; //get actual state if it exists + }; + + var otherDensity = 1000; //consider density 1000 by default + if(typeof(otherInfo.density) === "number") { + otherDensity = otherInfo.density; //get actual density if it exists + }; + + var react = false; //default to no reaction + if(typeof(otherInfo.reactions) === "object") { //look for reactions + if(typeof(otherInfo.reactions[pixel.element]) === "object") { //look for reactions involving this element + react = true; //if there are any, set reaction flag to true + }; + }; + + if(otherElement.endsWith("head") || otherElement.endsWith("body")) { + //i don't want to make general MPL handling so I'll just try to exclude them; + if(otherElement !== "antibody") { + //exclude antibody from exclusion + return false; + }; + }; + + if(otherElement !== pixel.element) { //allow this element from piling on itself + if(logLeaves) { console.log("Other element is not cherry leaves") }; //yes, this code is for cherry leaves + if(react) { //if there was a reaction in that previous step + if(logLeaves) { console.log("Reacting pixels") }; + reactPixels(otherPixel,pixel); //react + } else { //if no such reaction existed, move through + if(logLeaves) { console.log("Moving pixels") }; + if((otherState !== "solid") || (otherState === "solid" && otherDensity > 100)) { //admit any non-solid, or any solid with a density over 100 + var pX = pixel.x; //var pixel coords for no particular reason + var pY = pixel.y; + var oX = otherPixel.x; //var other pixel's coords for no particular reason + var oY = otherPixel.y; + if(logLeaves) { console.log(`${otherElement} pixel (${oX},${oY}) trying to move info leaf block (${pX},${pY})`) }; + var dX = oX - pX; //get the difference between this's X and other's X; if the other pixel is moving from the space immediately to the right, this dX value should be 1 + var dY = oY - pY; + var iDX = -1 * dX; //get the additive inverse; if we want to move such a pixel from the right to the left, we would change its +1 X offset to a -1 X offset for the coord sto move it to + var iDY = -1 * dY; + if(logLeaves) { console.log(`Old offset (relative to leaf): [${dX},${dY}], new offset [${iDX},${iDY}]`) }; + var fX = pX + iDX; //combine this pixel's X with the inverted offset we just made; + //assuming this pixel is (23,31) and the other pixel is trying to move in to the left into this from (24,31), + //the dX would be [1, 0], signifying that the other pixel is 1 pixel to the right of this + //the space to the left of this, where it would go, is (22,31), and the offset for that pixel relative to this is [-1, 0] + //to get the [-1, 0], we'd need to flip that [1, 0] offset (lmao flip that the song by loona), hence the inverse + var fY = pY + iDY; + if(logLeaves) { console.log(`Calculated final position: (${fX},${fY}), moving other pixel from (${oX},${oY})`) }; + tryMove(otherPixel,fX,fY); }; }; - if(shouldSpoil) { //spoil if not attached - if(pixel.temp > -14 && pixel.temp <= 4) { //(no spoiling below 14C) - pixel.spoilage += Math.max(Math.min(scale(pixel.temp,-14,4,0,9),9),0) - } else if(pixel.temp > 4) { - pixel.spoilage += Math.max(Math.min(scale(pixel.temp,4,20,9,30),40),0) - }; - }; - if(pixel.spoilage > 14400) { //3600 = 120 ticks at 20C - if(Math.random() < 0.05) { - changePixel(pixel,"spoiled_cherry"); - }; - }; - }, - properties: { - "spoilage":0, - "attached": false, - "attachDirection": (!Math.floor(Math.random() * 2)) ? 1 : -1, - }, - burn: 5, - burnInto: ["steam", "ash"], - burnTime: 600, - tempHigh: 200, - stateHigh: ["steam", "ash"], - onTryMoveInto: function(pixel,otherPixel) { - var otherInfo = elements[otherPixel.element] - if(typeof(otherInfo.state) === "string" && otherInfo.state !== "gas") { - pixel.attached = false; - }; - }, - }; - - elements.cherry_branch_1 = { - hidden: true, - name: "cherry branch (offshoot)", - color: "#310a0b", - tick: function(pixel) { - if(pixel.cherryRange === null) { - pixel.cherryRange = randomNumberFromOneToThree(); - }; - - if (pixel.age > 20 && pixel.temp < 100) { - var peduncleCoords1 = [pixel.x + pixel.dir, pixel.y]; - var peduncleCoords2 = [pixel.x + pixel.dir, pixel.y + 1]; - if(isEmpty(peduncleCoords1[0],peduncleCoords1[1],false) && isEmpty(peduncleCoords2[0],peduncleCoords2[1],false)) { - if(Math.random() < 0.5) { - createPixel(pixel.element,peduncleCoords1[0],peduncleCoords1[1]); - pixelMap[peduncleCoords1[0]][peduncleCoords1[1]].dir = pixel.dir; - pixelMap[peduncleCoords1[0]][peduncleCoords1[1]].cherryRange = pixel.cherryRange; //pass cherry range down to next pixel of branch horizontal - } else { - createPixel("cherry_branch_2",peduncleCoords2[0],peduncleCoords2[1]); - pixelMap[peduncleCoords2[0]][peduncleCoords2[1]].cherryRange = pixel.cherryRange; //pass cherry range down to diagonal offshoot - }; - }; - }; - pixel.age++; - doDefaults(pixel); - }, - properties: { - "dir": (!Math.floor(Math.random() * 2)) ? 1 : -1, - "age": 0, - //"cherryRange": (1 + (Math.floor(Math.random() * 3))), //1-3 - "cherryRange": null, - }, - tempHigh: 100, - stateHigh: "dead_plant", - tempLow: -2, - stateLow: "frozen_plant", - burn: 5, - burnInto: ["steam", "ash"], - burnTime: 600, - category: "life", - state: "solid", - density: 1500, - }; - - elements.cherry_branch_2 = { - hidden: true, - name: "cherry branch (hanging)", - color: "#310a0b", - tick: function(pixel) { - if(pixel.cherryRange === null) { - pixel.cherryRange = randomNumberFromOneToThree(); - }; - - // Grow/Flower - if (pixel.age > 20 && pixel.temp < 100) { - var growthCoords = [pixel.x, pixel.y + 1]; - if(isEmpty(...growthCoords)) { - if(Math.random() < 0.9) { - createPixel(pixel.element,...growthCoords); - pixelMap[growthCoords[0]][growthCoords[1]].cherryRange = pixel.cherryRange; //pass cherry range down to next pixel of branch vertical - } else { - createPixel("blossom",...growthCoords); // cherry flower - }; - }; - }; - - //Make cherries - if (pixel.age > 40 && pixel.temp < 100) { - var cherryOffsets = [-1, 1]; //placed to the left, placed to the right - for(i = 0; i < cherryOffsets.length; i++) { - //console.log(`Looping through left and right positions: ${cherryOffsets}`); - for(j = 1; j < pixel.cherryRange + 1; j++) { //for max cherry distance, using the cherry range - //console.log(`Looping through cherry offset multipliers: ${j}`); - if (isEmpty(pixel.x+(j * cherryOffsets[i]),pixel.y,false)) { //if there's an empty space - //console.log(`Cherry position is empty: [${j * cherryOffsets[i]}, 0]\nTrying cherry at (${pixel.x+(j * cherryOffsets[i])},${pixel.y})`); - if (Math.random() < (debugSpeedGrowth ? 0.05 : 0.005)) { //try to place the cherry - //console.log(`Placing cherry`); - createPixel("cherry",pixel.x+(j * cherryOffsets[i]),pixel.y); - pixelMap[pixel.x+(j * cherryOffsets[i])][pixel.y].attached = true; - pixelMap[pixel.x+(j * cherryOffsets[i])][pixel.y].attachDirection = -1 * Math.sign(cherryOffsets[i]); //attach dir is the opposite of placement dir so it attaches towards the stem - } else { - //console.log(`NOT placing cherry`); - }; - //console.log(`Cherry tried, stopping iteration`); - break; //and then stop iteration - } else { - //console.log(`Cherry position is NOT empty: [${j * cherryOffsets[i]}, 0]\nSkipping this offset`); - continue; //if not empty, skip that pixel and move on the next distance - }; - //console.log(`====End of side try====`); - }; - //console.log(`####End of side iterator####`); - }; - //console.log(`>>>>End of cherry iterator<<<<`); - }; - pixel.age++; - doDefaults(pixel); - //console.log(`\nEnd of branch tick\n`); - }, - properties: { - "age": 0, - //"cherryRange": (1 + (Math.floor(Math.random() * 3))), //1-3 - "cherryRange": null, - }, - tempHigh: 100, - stateHigh: "dead_plant", - tempLow: -2, - stateLow: "frozen_plant", - burn: 5, - burnInto: ["steam", "ash"], - burnTime: 600, - category: "life", - state: "solid", - density: 1500, - }; - - elements.spoiled_cherry = { - hidden: true, - color: "#594b29", - behavior: [ - "XX|CR:stench,fly%0.1|XX", - "M2%0.5|CH:dirty_water,fly,fly%0.007|M2%0.5", - "M2|M1|M2" - ], - stain: 0.01, - burn: 5, - burnInto: ["steam", "ash"], - burnTime: 600, - tempHigh: 200, - stateHigh: ["steam", "ash"], - }; - - elements.fly.reactions.spoiled_cherry = { "elem2":null, chance:0.15, func:behaviors.FEEDPIXEL }; - - elements.cherry_leaf = { - hidden: true, - color: "#9df24e", - tick: function(pixel) { - if(pixel.cherryRange === null) { - pixel.cherryRange = randomNumberFromOneToThree(); - }; - - if(pixel.attached) { - var attachCoords = [pixel.x + pixel.attachOffsets[0], pixel.y + pixel.attachOffsets[1]]; - if(isEmpty(attachCoords[0],attachCoords[1],false)) { //consider OOB full - pixel.attached = false; - }; - } else { //Move if not attached - if(Math.random() < 0.2) { - if (!tryMove(pixel, pixel.x, pixel.y+1)) { - if(Math.random() < 0.4) { - if (Math.random() < 0.5) { - if (!tryMove(pixel, pixel.x+1, pixel.y+1)) { - tryMove(pixel, pixel.x-1, pixel.y+1); - }; - } else { - if (!tryMove(pixel, pixel.x-1, pixel.y+1)) { - tryMove(pixel, pixel.x+1, pixel.y+1); - }; - }; - }; - }; - }; - }; - doDefaults(pixel); - }, - properties: { - "attached": false, - "attachOffsets": [(!Math.floor(Math.random() * 2)) ? 1 : -1, 0], - "cherryRange": null, - }, - burn: 5, - burnInto: ["steam", "ash"], - burnTime: 600, - tempHigh: 200, - stateHigh: ["steam", "ash"], - onTryMoveInto: function(pixel,otherPixel) { //Move through - var otherElement = otherPixel.element; //var element for readability - - var otherInfo = elements[otherElement]; //var info - - var otherState = "solid"; //consider things solid by default - if(typeof(otherInfo.state) === "string") { - otherState = otherInfo.state; //get actual state if it exists - }; - - var otherDensity = 1000; //consider density 1000 by default - if(typeof(otherInfo.density) === "number") { - otherDensity = otherInfo.density; //get actual density if it exists - }; - - var react = false; //default to no reaction - if(typeof(otherInfo.reactions) === "object") { //look for reactions - if(typeof(otherInfo.reactions[pixel.element]) === "object") { //look for reactions involving this element - react = true; //if there are any, set reaction flag to true - }; - }; - - if(otherElement.endsWith("head") || otherElement.endsWith("body")) { - //i don't want to make general MPL handling so I'll just try to exclude them; - if(otherElement !== "antibody") { - //exclude antibody from exclusion - return false; - }; - }; - - if(otherElement !== pixel.element) { //allow this element from piling on itself - if(logLeaves) { console.log("Other element is not cherry leaves") }; //yes, this code is for cherry leaves - if(react) { //if there was a reaction in that previous step - if(logLeaves) { console.log("Reacting pixels") }; - reactPixels(otherPixel,pixel); //react - } else { //if no such reaction existed, move through - if(logLeaves) { console.log("Moving pixels") }; - if((otherState !== "solid") || (otherState === "solid" && otherDensity > 100)) { //admit any non-solid, or any solid with a density over 100 - var pX = pixel.x; //var pixel coords for no particular reason - var pY = pixel.y; - var oX = otherPixel.x; //var other pixel's coords for no particular reason - var oY = otherPixel.y; - if(logLeaves) { console.log(`${otherElement} pixel (${oX},${oY}) trying to move info leaf block (${pX},${pY})`) }; - var dX = oX - pX; //get the difference between this's X and other's X; if the other pixel is moving from the space immediately to the right, this dX value should be 1 - var dY = oY - pY; - var iDX = -1 * dX; //get the additive inverse; if we want to move such a pixel from the right to the left, we would change its +1 X offset to a -1 X offset for the coord sto move it to - var iDY = -1 * dY; - if(logLeaves) { console.log(`Old offset (relative to leaf): [${dX},${dY}], new offset [${iDX},${iDY}]`) }; - var fX = pX + iDX; //combine this pixel's X with the inverted offset we just made; - //assuming this pixel is (23,31) and the other pixel is trying to move in to the left into this from (24,31), - //the dX would be [1, 0], signifying that the other pixel is 1 pixel to the right of this - //the space to the left of this, where it would go, is (22,31), and the offset for that pixel relative to this is [-1, 0] - //to get the [-1, 0], we'd need to flip that [1, 0] offset (lmao flip that the song by loona), hence the inverse - var fY = pY + iDY; - if(logLeaves) { console.log(`Calculated final position: (${fX},${fY}), moving other pixel from (${oX},${oY})`) }; - tryMove(otherPixel,fX,fY); - }; - }; - }; - }, - }; - - /*if(!elements.diamond.reactions) { //test reaction - elements.diamond.reactions = {}; - }; - - elements.diamond.reactions.cherry_leaf = { "elem2": "dead_plant" };*/ - - elements.cherry_plant_top = { - hidden: true, - color: "#310a0b", - tick: function(pixel) { - if(pixel.cherryRange === null) { - pixel.cherryRange = randomNumberFromOneToThree(); - }; - - if (pixel.age > 30 && pixel.temp < 100) { - if(!pixel.grewLeftLeaves) { - for(i = (0 - pixel.leafRange); i < 0; i++) { //left half - if(i == 0) { - continue; - }; - - var leafOffset = i; //readability - var leafX = pixel.x + leafOffset; //set X to cherry_plant_top pixel's X + offset/index - var leafAttachOffset = [1, 0]; //difference 1: attaches rightwards (+) for leaves left (-) of center - var leafY = pixel.y; //set Y to default cherry_plant_top pixel's Y - if(Math.abs(leafOffset) == pixel.leafRange) { - leafY++; //place edge leaves 1 pixel downwards; - leafAttachOffset[1] = -1; //compensate by subtracting 1 from Y attach offset (less Y = higher position, so they attach diagonally up-right or up-left) - }; - - if(outOfBounds(leafX,leafY)) { - continue; - }; - - if (isEmpty(leafX,leafY,false)) { - createPixel("cherry_leaf",leafX,leafY); - pixelMap[leafX][leafY].attached = true; //set leaf's attached to true - pixelMap[leafX][leafY].attachOffsets = leafAttachOffset; //array of 2 numbers - pixelMap[leafX][leafY].cherryRange = pixel.cherryRange; - pixel.grewLeftLeaves = true; //difference 2: separate flag for left side - } else { - break; - }; - }; - }; - - if(!pixel.grewRightLeaves) { - for(i = 1; i < (pixel.leafRange + 1); i++) { //right half - if(i == 0) { - continue; - }; - - var leafOffset = i; //readability - var leafX = pixel.x + leafOffset; //set X to cherry_plant_top pixel's X + offset/index - var leafAttachOffset = [-1, 0]; //difference 1: attaches leftwards (-) for leaves right (+) of center - var leafY = pixel.y; //set Y to default cherry_plant_top pixel's Y - if(Math.abs(leafOffset) == pixel.leafRange) { - leafY++; //place edge leaves 1 pixel downwards; - leafAttachOffset[1] = -1; //compensate by subtracting 1 from Y attach offset (less Y = higher position, so they attach diagonally up-right or up-left) - }; - - if(outOfBounds(leafX,leafY)) { - continue; - }; - - if (isEmpty(leafX,leafY,false)) { - createPixel("cherry_leaf",leafX,leafY); - pixelMap[leafX][leafY].attached = true; //set leaf's attached to true - pixelMap[leafX][leafY].attachOffsets = leafAttachOffset; //array of 2 numbers - pixelMap[leafX][leafY].cherryRange = pixel.cherryRange; - pixel.grewRightLeaves = true; //difference 2: separate flag for right side - } else { - break; - }; - }; - }; - }; - pixel.age++; - doDefaults(pixel); - }, - properties: { - "age": 0, - "leafRange": 2 + (Math.floor(Math.random() * 3)), //2-4 - "grewLeftLeaves": false, - "grewRightLeaves": false, - "cherryRange": null, - }, - tempHigh: 100, - stateHigh: "dead_plant", - tempLow: -2, - stateLow: "frozen_plant", - burn: 5, - burnInto: ["steam", "ash"], - burnTime: 600, - category: "life", - state: "solid", - density: 1500, - }; - - - /*elements.cocoa_bean = { - color: ["#f2ede9", "#f0dfce", "#e8cfb5"], - behavior: behaviors.SOLID, - category: "liquids", - viscosity: 100000, - state: "liquid", - density: 593, - tick: functi - };*/ -} else { - enabledMods.splice(enabledMods.indexOf(modName),0,onTryMoveIntoMod); - enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod); - localStorage.setItem("enabledMods", JSON.stringify(enabledMods)); - alert(`The ${onTryMoveIntoMod} mod and ${libraryMod} mods are required and have been automatically inserted (reload for this to take effect).`); + }; + }, }; + +/*if(!elements.diamond.reactions) { //test reaction + elements.diamond.reactions = {}; +}; + +elements.diamond.reactions.cherry_leaf = { "elem2": "dead_plant" };*/ + +elements.cherry_plant_top = { + hidden: true, + color: "#310a0b", + tick: function(pixel) { + if(pixel.cherryRange === null) { + pixel.cherryRange = randomNumberFromOneToThree(); + }; + + if (pixel.age > 30 && pixel.temp < 100) { + if(!pixel.grewLeftLeaves) { + for(i = (0 - pixel.leafRange); i < 0; i++) { //left half + if(i == 0) { + continue; + }; + + var leafOffset = i; //readability + var leafX = pixel.x + leafOffset; //set X to cherry_plant_top pixel's X + offset/index + var leafAttachOffset = [1, 0]; //difference 1: attaches rightwards (+) for leaves left (-) of center + var leafY = pixel.y; //set Y to default cherry_plant_top pixel's Y + if(Math.abs(leafOffset) == pixel.leafRange) { + leafY++; //place edge leaves 1 pixel downwards; + leafAttachOffset[1] = -1; //compensate by subtracting 1 from Y attach offset (less Y = higher position, so they attach diagonally up-right or up-left) + }; + + if(outOfBounds(leafX,leafY)) { + continue; + }; + + if (isEmpty(leafX,leafY,false)) { + createPixel("cherry_leaf",leafX,leafY); + pixelMap[leafX][leafY].attached = true; //set leaf's attached to true + pixelMap[leafX][leafY].attachOffsets = leafAttachOffset; //array of 2 numbers + pixelMap[leafX][leafY].cherryRange = pixel.cherryRange; + pixel.grewLeftLeaves = true; //difference 2: separate flag for left side + } else { + break; + }; + }; + }; + + if(!pixel.grewRightLeaves) { + for(i = 1; i < (pixel.leafRange + 1); i++) { //right half + if(i == 0) { + continue; + }; + + var leafOffset = i; //readability + var leafX = pixel.x + leafOffset; //set X to cherry_plant_top pixel's X + offset/index + var leafAttachOffset = [-1, 0]; //difference 1: attaches leftwards (-) for leaves right (+) of center + var leafY = pixel.y; //set Y to default cherry_plant_top pixel's Y + if(Math.abs(leafOffset) == pixel.leafRange) { + leafY++; //place edge leaves 1 pixel downwards; + leafAttachOffset[1] = -1; //compensate by subtracting 1 from Y attach offset (less Y = higher position, so they attach diagonally up-right or up-left) + }; + + if(outOfBounds(leafX,leafY)) { + continue; + }; + + if (isEmpty(leafX,leafY,false)) { + createPixel("cherry_leaf",leafX,leafY); + pixelMap[leafX][leafY].attached = true; //set leaf's attached to true + pixelMap[leafX][leafY].attachOffsets = leafAttachOffset; //array of 2 numbers + pixelMap[leafX][leafY].cherryRange = pixel.cherryRange; + pixel.grewRightLeaves = true; //difference 2: separate flag for right side + } else { + break; + }; + }; + }; + }; + pixel.age++; + doDefaults(pixel); + }, + properties: { + "age": 0, + "leafRange": 2 + (Math.floor(Math.random() * 3)), //2-4 + "grewLeftLeaves": false, + "grewRightLeaves": false, + "cherryRange": null, + }, + tempHigh: 100, + stateHigh: "dead_plant", + tempLow: -2, + stateLow: "frozen_plant", + burn: 5, + burnInto: ["steam", "ash"], + burnTime: 600, + category: "life", + state: "solid", + density: 1500, +}; + + +/*elements.cocoa_bean = { + color: ["#f2ede9", "#f0dfce", "#e8cfb5"], + behavior: behaviors.SOLID, + category: "liquids", + viscosity: 100000, + state: "liquid", + density: 593, + tick: functi +};*/ +}, true);