diff --git a/mod-list.html b/mod-list.html index 6f497af1..d68b4f26 100644 --- a/mod-list.html +++ b/mod-list.html @@ -196,7 +196,7 @@ texturepack.jsTools that let you create and share custom texture packsnousernamefound the_ground.jsSeveral rock types, worldgen settings, and gemstonesAlice worldEdit.jsSelection and editing toolsRedBirdly -worldgenlibrary.jsWorld generation libraryAdora +worldgenlibrary.jsWorld generation libraryOrchid Science & Chemistry alcohol.jsMethanol, (iso-)propanol, and butanolAlice @@ -234,7 +234,7 @@ metals.jsSeveral metalsAlice mixture.jsMany chemicals can be mixedlllllllllwith10ls more_gold.jsGreen Goldpixelegend4 -morechemistry.jsNew chemicals, compounds, and machinesAdora +morechemistry.jsNew chemicals, compounds, and machinesOrchid moreliquids.jsVarious liquidste-agma-at neutronium_compressor.jsCompressor from Minecraft's Avaritia mod that compresses 10,000 pixels of an element into a singularityAlice noblegas.jsThe missing noble gasesnousernamefound @@ -253,6 +253,7 @@ colored_lightbulbs.jsLight bulb that can be paintedguzzo86, ggod combustion.jsComponents necessary for combustion enginesuptzik conveyance.jsConveyors, operated with and without electricityMelecie +datawire.jsAdds a wire that transfers data and other operators and machines for itOrchid drill.jsDrills made out of several materialsSuss ExtraMachines.jsSensors, energy resources, materials, and moreMecoolnotcool fans.jsFansCube14yt @@ -350,7 +351,7 @@ ocean.jsMarine lifeSquareScreamYT ores.jsOre generation along with tools to mine themnousernamefound petal_dye.jsBoil petals to make dyeSuss -plants.jsWide variety of new plants and fruitsAdora +plants.jsWide variety of new plants and fruitsOrchid primordial_birthpool.jsCross between Primordial Soup and Birthpool. Requires fey_and_more.jsAlice spring.jsMany nature elements, like sakura trees, butterflies, beehives, and moreR74n the_ground_og.jsSimplified and more stable version of the_ground.jsAlice @@ -361,7 +362,7 @@ Fun & Games 10kelements.jsCustomizable amount of randomly generated elementsnousernamefound all_around_fillers.jsDirectional Filler variantsidk73248 -allliquids.jsMade all elements liquidsAdora +allliquids.jsMade all elements liquidsOrchid amogus.jsSmall Among Us structureAlice bfdi.jsSeveral references to Battle for Dream IslandTaterbob citybuilding.jsSeeds that create miniature buildings and other city-related itemsSquareScreamYT @@ -440,7 +441,7 @@ changeTempReactionParameter.jsThe changeTemp property to modded reactionsAlice code_library.jsFunctions and variables common to some other modsAlice controllable_pixel_test.jsPixel that can be controlled with the keyboard keys [More Info] [PC ONLY]Alice -customexplosion.jsAdded a custom explosion element and interface for it. check out its source code for how modders can use itAlex +customexplosion.jsAdded a custom explosion element and interface for it.Orchid date_test.jsK-pop idol birthday testing stuffAlice drawPixels_change_test.jsTest of altering drawPixels(). Gives burning pixels a red overlay similar to the yellow overlay for charged pixelsAlice example_mod.jsExample mod for new moddersR74n @@ -455,6 +456,7 @@ modlangs.jsCustomisable property in an element to allow for translations in mods. See the file for instructions on how to implementSquareScreamYT nested_for_reaction_example.jsExample of using a nested for loop to add reactions. It makes various things kill plantsAlice nv7.jsGiant Nv7 image [Large]Nv7 +orchidslibrary.jsLibrary used by morechemistry.js, plants.js, and datawire.jsOrchid place_all_elements.jsExperimental function that places every pixelAlice randomness_but_tick.jsRandom experimental elements using the tick function featureAlice randomness_but_tool.jsRandom experimental elements using the tool function featureAlice @@ -464,7 +466,7 @@ structure_test.jsTest for implementing structures into SandboxelsAlice test.jsTest that adds mayo :)R74n tool_pixel_behavior.jsGives unique behaviors to tools if placed with cheatsAlice -worldgenlibrary.jsWorld generation libraryAdora +worldgenlibrary.jsWorld generation libraryOrchid worldgen_test.jsElement that generates a save with a grass layer, dirt layer, rock layer, and a pondAlice Broken or Deprecated diff --git a/mods/datawire.js b/mods/datawire.js new file mode 100644 index 00000000..73fedd9e --- /dev/null +++ b/mods/datawire.js @@ -0,0 +1,244 @@ +/* +Version 1.0.0 +*/ +if(!enabledMods.includes("/mods/orchidslibrary.js")){ + let continueWithout = confirm("Missing dependency for datawire.js: \"orchidslibrary.js\". Continue without? (cancel will add mod and refresh the page)"); + if(!continueWithout){ + addMod("/mods/orchidslibrary.js", true); + window.location.reload(); + } +} else { + elements.data_wire = { + desc: "Transfers data.", + color: ["#6b1502", "#631402", "#6e1400", "#631200"], + properties: {cd: 0, value: null}, + tick: function(pixel){ + for(let coords of adjacentCoords){ + let x = pixel.x+coords[0], y = pixel.y+coords[1]; + let p2 = getPixel(x,y); + if(p2 != null){ + if(p2.value != null && pixel.cd == 0){ + pixel.value = p2.value; + pixel.cd = 15; + }; + pixel.value = (pixel.cd == 3) ? null : pixel.value; + if(elements[p2.element].dataInFunc != undefined && pixel.value != null){ + elements[p2.element].dataInFunc(p2, pixel.value); + } + } + } + pixel.cd -= (pixel.cd == 0) ? 0 : 1; + }, + category: "data", + behavior: behaviors.WALL, + state: "solid", + }; + elements.data_input = { + desc: "Holds a data value that can be outputted to any nearby data wire.", + color: ["#e06500", "#f57105", "#f06f05", "#e66c09"], + value: null, + onSelect: function(){ + promptInput("Enter data info", (input)=>{elements.data_input.value = input;}, "Data Input", elements.data_input.value); + }, + category: "data", + behavior: behaviors.WALL, + state: "solid", + properties: { + value:null, + }, + tick: function(pixel){ + if(pixel.value == null){ + pixel.value = elements.data_input.value; + } + for(let coords of adjacentCoords){ + let x = pixel.x+coords[0], y = pixel.y+coords[1]; + let p2 = getPixel(x,y); + if(p2 != null && elements[p2.element].dataInFunc != undefined && pixel.value != null){ + elements[p2.element].dataInFunc(p2, pixel.value); + } + } + } + } + elements.toggle_data_input = { + desc: "Holds a data value that can be outputted to any nearby data wire when toggled on.", + color: ["#6e3302", "#783905", "#823c03", "#7d3a02"], + value: null, + onSelect: function(){ + promptInput("Enter data info", (input)=>{elements.data_input.value = input;}, "Data Input", elements.data_input.value); + }, + category: "data", + behavior: behaviors.WALL, + state: "solid", + properties: { + value:null, + val: null, + toggle: false, + clickCd: 0, + }, + tick: function(pixel){ + if(pixel.val == null){ + pixel.val = elements.data_input.value; + } + pixel.value = (pixel.toggle) ? pixel.val : null; + for(let coords of adjacentCoords){ + let x = pixel.x+coords[0], y = pixel.y+coords[1]; + let p2 = getPixel(x,y); + if(p2 != null && elements[p2.element].dataInFunc != undefined && pixel.value != null){ + elements[p2.element].dataInFunc(p2, pixel.value); + } + } + pixel.clickCd -= (pixel.clickCd == 0) ? 0 : 1; + }, + onClicked: function(pixel){ + if(pixel.clickCd == 0){ + pixel.clickCd = 20; + pixel.toggle = !pixel.toggle; + if(pixel.toggle){ + pixel.color = noiseify("#edba00", 8); + } else { + pixel.color = noiseify("#6e3302", 8); + } + } + } + } + elements.join = { + desc: "Combines multiple data inputs. Click to reset value.", + color: ["#046e00", "#067a02", "#097006", "#065904", "#056602"], + properties: {val: null, clickCd: 0}, + dataInFunc: function(pixel, value){ + if(pixel.val != null && !pixel.val.includes(value)){ + pixel.val += value; + } + if(pixel.val == null){ + pixel.val = value; + } + }, + category: "data", + behavior: behaviors.WALL, + state: "solid", + tick: function(pixel){ + let p2 = getPixel(pixel.x+1, pixel.y); + if(p2 != null && p2.element == "data_wire"){ + p2.value = pixel.val; + } + pixel.clickCd -= (pixel.clickCd == 0) ? 0 : 1; + }, + onClicked: function(pixel){ + if(pixel.clickCd == 0){ + pixel.clickCd = 20; + pixel.val = null; + } + } + } + elements.data_sensor = { + desc: "Scans adjacent pixels for a target property and outputs them, uses \"element\" by default. Click on pixel to change properties.", + color: ["#3d3c28", "#4d4b32", "#4a482f", "#403e28"], + properties: { + value: null, + property: "element", + clickCd: 0, + }, + tick: function(pixel){ + for(let coords of adjacentCoords){ + let x = pixel.x+coords[0], y = pixel.y+coords[1]; + let p2 = getPixel(x,y); + if(p2 != null && !["data_wire"].includes(p2.element)){ + pixel.value = p2[pixel.property]; + } + }; + pixel.clickCd -= (pixel.clickCd == 0) ? 0 : 1; + }, + onClicked: function(pixel){ + let propertyArr = []; + for(let coords of adjacentCoords){ + let x = pixel.x+coords[0], y = pixel.y+coords[1]; + let p2 = getPixel(x,y); + if(p2 != null){ + for(let property in p2){ + if(typeof p2[property] != "function" && !propertyArr.includes(property)){ + propertyArr.push(property); + } + } + } + }; + promptChoose("Choose property this data sensor detects:", propertyArr, (input)=>{pixel.property = input || pixel.property;}, "Property to Detect"); + }, + category: "data", + behavior: behaviors.WALL, + state: "solid", + } + elements.if = { + desc: "Takes 3 inputs, conditon (1 (true) or 0 (false), x-1), ifTrue (output if true, y-1 (pixel above)), and ifFalse (output if false, y+1 (pixel below)).", + color: ["#00574b", "#005247", "#02594e", "#025c50"], + category: "data", + behavior: behaviors.WALL, + state: "solid", + tick: function(pixel){ + let conditionPixel = getPixel(pixel.x-1, pixel.y), truePixel = getPixel(pixel.x, pixel.y-1), falsePixel = getPixel(pixel.x, pixel.y+1); + let condition = (conditionPixel != null &&conditionPixel.value != undefined) ? parseInt(conditionPixel.value) : false; + let trueOut = (truePixel != null && truePixel.value != undefined) ? truePixel.value : 1; + let falseOut = (falsePixel != null && falsePixel.value != undefined) ? falsePixel.value : 0; + let outPixel = getPixel(pixel.x+1, pixel.y); + if(outPixel != null && outPixel.value !== undefined){ + outPixel.value = (condition) ? trueOut : falseOut; + } + } + } + elements.equals = { + desc: "Takes 2 inputs, A (y-1 (pixel above)) and B (y+1 (pixel below), returns 1 if they are equal and 0 if they are not.", + color: ["#12ccb3", "#15ebce", "#0bd6bb", "#14dec3"], + category: "data", + behavior: behaviors.WALL, + state: "solid", + tick: function(pixel){ + let a = getPixel(pixel.x, pixel.y-1), b = getPixel(pixel.x, pixel.y+1); + if(a != null && b != null){ + let aVal = (a.value != undefined) ? a.value : 1; + let bVal = (b.value != undefined) ? b.value : 0; + let outPixel = getPixel(pixel.x+1, pixel.y); + if(outPixel != null && outPixel.value !== undefined){ + outPixel.value = (aVal == bVal) ? 1 : 0; + } + } + } + } + elements.prop_setter = { + category: "data", + properties: { + val: null, + }, + dataInFunc: function(pixel, value){ + pixel.val = value; + }, + color: ["#deb150", "#ebba52", "#ebba52", "#e3b44d", "#dbab44"], + state: "solid", + behavior: behaviors.WALL, + tick: function(pixel){ + if(pixel.val != null){ + let valArr = pixel.val.split(":"); + let prop = valArr[0], value = valArr[1]; + for(let coords of adjacentCoords){ + let x = pixel.x+coords[0], y = pixel.y+coords[1]; + let p2 = getPixel(x,y); + if(p2 != null && p2[prop] != undefined && elements[p2.element].category != "data"){ + if(prop == "element"){ + changePixel(p2, value); + } else if (prop == "x" || prop == "y"){ + let x = (prop == "x") ? value : p2.x, y = (prop == "y") ? value : p2.y; + tryMove(p2, parseInt(x), parseInt(y), null, true); + } else { + if(typeof p2[prop] == "number"){ + p2[prop] = parseInt(value); + } else if(typeof p2[prop] == "boolean"){ + p2[prop] = value.includes("true"); + } else if(typeof p2[prop] == "string"){ + p2[prop] = value; + }; + } + } + } + } + } + }; + +} diff --git a/mods/morechemistry.js b/mods/morechemistry.js index 25221c1b..247806d1 100644 --- a/mods/morechemistry.js +++ b/mods/morechemistry.js @@ -1,960 +1,1571 @@ /* -Version 2.1.0 +Version 2.2.0 */ -function pixelToggle(pixel, multi = {r:1,g:1,b:1}){ - if(pixel.toggle != undefined){ - pixel.toggle = !pixel.toggle; - let rgb; - if(Array.isArray(elements[pixel.element].color)){ - let elemColor = elements[pixel.element].color[Math.round(Math.random()*elements[pixel.element].color.length)]; - rgb = hexToRGB(elemColor) || getRGB(elemColor); - } else { - let elemColor = elements[pixel.element].color; - rgb = hexToRGB(elemColor) || getRGB(elemColor); - } - let num = 5 - Math.round(Math.random()*10); - if(pixel.toggle){ - for(let key in rgb){ - rgb[key] += (100*multi[key]); - rgb[key] = Math.round(Math.max(Math.min(rgb[key], 255), 0)); - } - pixel.color = `rgb(${rgb.r+num},${rgb.g+num},${rgb.b+num})`; - } - else { - pixel.color = `rgb(${rgb.r+num},${rgb.g+num},${rgb.b+num})`; - } +if(!enabledMods.includes("/mods/orchidslibrary.js")){ + let continueWithout = confirm("Missing dependency for morechemistry.js: \"orchidslibrary.js\". Continue without? (cancel will add mod and refresh the page)"); + if(!continueWithout){ + addMod("/mods/orchidslibrary.js", true); + window.location.reload(); } -} -function getRGB(rgb){ - let rgb2 = rgb.replace(")", "").replace("rgb(", "").replace(/,/g, "r").split("r") - return { r: parseInt(rgb2[0]), g: parseInt(rgb2[1]), b: parseInt(rgb2[2]) }; -} -elements.cloner.keyInput = "str:clone", elements.ecloner.keyInput = "str:clone", elements.slow_cloner.keyInput = "str:clone", elements.floating_cloner.keyInput = "str:clone"; -let xDown = false; -elements.copper_sulfate = { - behavior: behaviors.POWDER, - color: ["#4391fd","#004cfe"], - reactions: { - ant: {"elem2": "dead_bug"}, - fly: {"elem2": "dead_bug"}, - firefly: {"elem2": "dead_bug"}, - stink_bug: {"elem2": "dead_bug"}, - bee: {"elem2": "dead_bug"}, - termite: {"elem2": "dead_bug"}, - spider: {"elem2": "dead_bug"}, - plant: {"elem2": "dead_plant"}, - grass: {"elem2": "dead_plant"}, - algae: {"elem2": null}, - kelp: {"elem2": "water"}, - coral: {"elem2": "water"}, - mushroom_cap: {"elem2": null}, - mushroom_stalk: {"elem2": null}, - mushroom_gill: {"elem2": null}, - mushroom_spore: {"elem2": null}, - zinc: {"stain2": "#2A1210"}, - fire: {"elem1": null,"elem2": "poison_gas","chance": 0.1}, - sugar: {"elem1": "oxidized_copper","elem2": null,"color1": ["#CB3D3D","#A6292B","#6E1B1B"]} - }, - tempHigh: 110, - fireColor: [ - "#91d106", - "#feff97", - "#248e01" - ], - state: "solid", - density: 3600, - hidden: true, - category: "powders", - id: 509, - movable: true, - properties: { - anhydrous: false - }, - tick: function(pixel){ - if(pixelTicks-pixel.start == 2 && xDown){ - pixel.anhydrous = true; - let rgb = {r: 235, g: 247, b: 250}; - let num = 6 - (Math.round(Math.random()*12)); - for(let key in rgb){ - rgb[key] += num; - } - pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; - } - let multi = (pixel.temp-70)/100; - multi = (multi < 0) ? 0 : ((multi > 1) ? 1 : multi); - if(Math.random() < 0.05*multi){ - pixel.anhydrous = true; - let rgb = {r: 235, g: 247, b: 250}; - let num = 6 - (Math.round(Math.random()*12)); - for(let key in rgb){ - rgb[key] += num; - } - pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; - } - if(pixel.anhydrous){ - let neighbors = []; - for(let coords of squareCoords){ - let x = pixel.x+coords[0], y = pixel.y+coords[1]; - neighbors[neighbors.length] = (isEmpty(x,y) && !outOfBounds(x,y)) ? "air" : (!outOfBounds(x,y)) ? pixelMap[x][y].element : undefined; - } - if(neighbors.includes("air") && pixel.temp < 50 && Math.random() < 0.00035){ - pixel.anhydrous = false; - let rgb = (Math.random() > 0.5) ? {r: 67, g: 145, b: 253} : {r: 0, g: 76, b: 254}; - let num = 6 - (Math.round(Math.random()*12)); - for(let key in rgb){ - rgb[key] += num; - } - pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; - - } else if (neighbors.includes("steam") || neighbors.includes("water") || neighbors.includes("salt_water") || neighbors.includes("sugar_water") || neighbors.includes("dirty_water") || neighbors.includes("seltzer") || neighbors.includes("pool_water") || neighbors.includes("slush")){ - pixel.anhydrous = false; - let rgb = (Math.random() > 0.5) ? {r: 67, g: 145, b: 253} : {r: 0, g: 76, b: 254}; +} else { + elements.cloner.keyInput = "str:clone", elements.ecloner.keyInput = "str:clone", elements.slow_cloner.keyInput = "str:clone", elements.floating_cloner.keyInput = "str:clone"; + let xDown = false; + elements.copper_sulfate = { + behavior: behaviors.POWDER, + color: ["#4391fd","#004cfe"], + reactions: { + ant: {"elem2": "dead_bug"}, + fly: {"elem2": "dead_bug"}, + firefly: {"elem2": "dead_bug"}, + stink_bug: {"elem2": "dead_bug"}, + bee: {"elem2": "dead_bug"}, + termite: {"elem2": "dead_bug"}, + spider: {"elem2": "dead_bug"}, + plant: {"elem2": "dead_plant"}, + grass: {"elem2": "dead_plant"}, + algae: {"elem2": null}, + kelp: {"elem2": "water"}, + coral: {"elem2": "water"}, + mushroom_cap: {"elem2": null}, + mushroom_stalk: {"elem2": null}, + mushroom_gill: {"elem2": null}, + mushroom_spore: {"elem2": null}, + zinc: {"stain2": "#2A1210"}, + fire: {"elem1": null,"elem2": "poison_gas","chance": 0.1}, + sugar: {"elem1": "oxidized_copper","elem2": null,"color1": ["#CB3D3D","#A6292B","#6E1B1B"]}, + magnesium: {elem1: "copper", elem2: "epsom_salt"}, + wood: {stain2: "#043023"}, + }, + tempHigh: 110, + fireColor: [ + "#91d106", + "#feff97", + "#248e01" + ], + state: "solid", + density: 3600, + hidden: true, + category: "powders", + id: 509, + movable: true, + properties: { + anhydrous: false + }, + tick: function(pixel){ + if(pixelTicks-pixel.start == 2 && xDown){ + pixel.anhydrous = true; + let rgb = {r: 235, g: 247, b: 250}; let num = 6 - (Math.round(Math.random()*12)); for(let key in rgb){ rgb[key] += num; } pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; } - } - } -} -elements.water.ignore = ["copper_sulphate"], elements.steam.ignore = ["copper_sulphate"], elements.pool_water.ignore = ["copper_sulphate", 'pool_ice'], elements.salt_water.ignore = ["copper_sulphate", 'salt_ice'], elements.sugar_water.ignore = ["copper_sulphate", 'sugar_ice'], elements.seltzer.ignore = ["copper_sulphate", 'seltzer_ice'], -document.addEventListener("keydown", (e)=>{xDown = (e.key.toLowerCase() == "x") ? true : xDown;}); -document.addEventListener("keyup", (e)=>{xDown = (e.key.toLowerCase() == "x") ? false : xDown;}); - -elements.toggle_cloner = { - category: "machines", - active: "#fbff03", - inactive: "#333300", - color: "#333300", - name: "ToggleableCloner", - keyInput: "chance", - insulate: 1, - properties: { - clone: null, - toggle: false, - chance: 0.0166666667, - clickCd: 0, - }, - hardness: 1, - ignore: ["drag","unknown", "cloner", "toggle_cloner", "floating_cloner", "clone_powder", "slow_cloner", "ecloner", "destroyable_cloner", "destroyable_clone_powder", "ewall", "wall"], - onClicked: function(pixel,element){ - - if(pixel.clone == null && pixel.clickCd == 0 && dragStart == null){ - pixel.clone = (elements.toggle_cloner.ignore.includes(element)) ? pixel.clone : element; - } else if (pixel.clickCd == 0 && !shiftDown) { - pixel.toggle = !pixel.toggle; - if(pixel.toggle){ - let rgb = hexToRGB(elements.toggle_cloner.active); - let num = 5 - (Math.random()*10); + let multi = (pixel.temp-70)/100; + multi = (multi < 0) ? 0 : ((multi > 1) ? 1 : multi); + if(Math.random() < 0.05*multi){ + pixel.anhydrous = true; + let rgb = {r: 235, g: 247, b: 250}; + let num = 6 - (Math.round(Math.random()*12)); for(let key in rgb){ rgb[key] += num; - rgb[key] = Math.round(Math.max(Math.min(rgb[key], 255), 0)); - } - pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; - } else { - let rgb = hexToRGB(elements.toggle_cloner.inactive); - let num = 5 - (Math.random()*10); - for(let key in rgb){ - rgb[key] += num; - rgb[key] = Math.round(Math.max(Math.min(rgb[key], 255), 0)); } pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; } + if(pixel.anhydrous){ + let neighbors = []; + for(let coords of squareCoords){ + let x = pixel.x+coords[0], y = pixel.y+coords[1]; + neighbors[neighbors.length] = (isEmpty(x,y) && !outOfBounds(x,y)) ? "air" : (!outOfBounds(x,y)) ? pixelMap[x][y].element : undefined; + } + if(neighbors.includes("air") && pixel.temp < 50 && Math.random() < 0.00035){ + pixel.anhydrous = false; + let rgb = (Math.random() > 0.5) ? {r: 67, g: 145, b: 253} : {r: 0, g: 76, b: 254}; + let num = 6 - (Math.round(Math.random()*12)); + for(let key in rgb){ + rgb[key] += num; + } + pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; + + } else if (neighbors.includes("steam") || neighbors.includes("water") || neighbors.includes("salt_water") || neighbors.includes("sugar_water") || neighbors.includes("dirty_water") || neighbors.includes("seltzer") || neighbors.includes("pool_water") || neighbors.includes("slush")){ + pixel.anhydrous = false; + let rgb = (Math.random() > 0.5) ? {r: 67, g: 145, b: 253} : {r: 0, g: 76, b: 254}; + let num = 6 - (Math.round(Math.random()*12)); + for(let key in rgb){ + rgb[key] += num; + } + pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; + } + } } - if(shiftDown && !elements.toggle_cloner.ignore.includes(element)){ - pixel.clone = element; - } - - if(pixel.clickCd == 0 && dragStart == null){ - pixel.clickCd = 20; - }; - }, - onSelect: function(){ - logMessage("Place cloner, select element to clone, click on the pixel to set the clone element, then click on it to toggle on or off. Hold shift when clicking to change the element to the selected element."); - }, - tick: function(pixel){ - if(pixel.clickCd > 0){pixel.clickCd--;} - if(![null, undefined].includes(pixel.clone) && pixel.toggle == true && Math.random() < pixel.chance){ + } + elements.water.ignore = ["copper_sulphate"], elements.steam.ignore = ["copper_sulphate"], elements.pool_water.ignore = ["copper_sulphate", 'pool_ice'], elements.salt_water.ignore = ["copper_sulphate", 'salt_ice'], elements.sugar_water.ignore = ["copper_sulphate", 'sugar_ice'], elements.seltzer.ignore = ["copper_sulphate", 'seltzer_ice'], + document.addEventListener("keydown", (e)=>{xDown = (e.key.toLowerCase() == "x") ? true : xDown;}); + document.addEventListener("keyup", (e)=>{xDown = (e.key.toLowerCase() == "x") ? false : xDown;}); + + elements.toggle_cloner = { + category: "machines", + active: "#fbff03", + inactive: "#333300", + color: "#333300", + name: "ToggleableCloner", + keyInput: "chance", + insulate: 1, + properties: { + clone: null, + toggle: false, + chance: 0.0166666667, + clickCd: 0, + }, + hardness: 1, + ignore: ["drag","unknown", "cloner", "toggle_cloner", "floating_cloner", "clone_powder", "slow_cloner", "ecloner", "destroyable_cloner", "destroyable_clone_powder", "ewall", "wall"], + onClicked: function(pixel,element){ + + if(pixel.clone == null && pixel.clickCd == 0 && dragStart == null){ + pixel.clone = (elements.toggle_cloner.ignore.includes(element)) ? pixel.clone : element; + } else if (pixel.clickCd == 0 && !shiftDown) { + pixel.toggle = !pixel.toggle; + if(pixel.toggle){ + let rgb = hexToRGB(elements.toggle_cloner.active); + let num = 5 - (Math.random()*10); + for(let key in rgb){ + rgb[key] += num; + rgb[key] = Math.round(Math.max(Math.min(rgb[key], 255), 0)); + } + pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; + } else { + let rgb = hexToRGB(elements.toggle_cloner.inactive); + let num = 5 - (Math.random()*10); + for(let key in rgb){ + rgb[key] += num; + rgb[key] = Math.round(Math.max(Math.min(rgb[key], 255), 0)); + } + pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; + } + } + if(shiftDown && !elements.toggle_cloner.ignore.includes(element)){ + pixel.clone = element; + } + + if(pixel.clickCd == 0 && dragStart == null){ + pixel.clickCd = 20; + }; + }, + onSelect: function(){ + logMessage("Place cloner, select element to clone, click on the pixel to set the clone element, then click on it to toggle on or off. Hold shift when clicking to change the element to the selected element."); + }, + tick: function(pixel){ + if(pixel.clickCd > 0){pixel.clickCd--;} + if(![null, undefined].includes(pixel.clone) && pixel.toggle == true && Math.random() < pixel.chance){ + for(let coords of adjacentCoords){ + let x = pixel.x+coords[0], y = pixel.y+coords[1]; + if(isEmpty(x,y) && !outOfBounds(x,y)){ + createPixel(pixel.clone, x, y); + pixelMap[x][y].temp = pixel.temp; + } + } + } for(let coords of adjacentCoords){ let x = pixel.x+coords[0], y = pixel.y+coords[1]; - if(isEmpty(x,y) && !outOfBounds(x,y)){ - createPixel(pixel.clone, x, y); + let p2 = getPixel(x,y); + if(p2 != null && p2.element == pixel.element && (p2.clone == null && pixel.clone != null)){ + p2.clone = pixel.clone; + } + } + }, + dataInFunc: function(pixel, value){ + if(value.includes(":")){ + let valueArr = value.split(":"); + if(Array.isArray(pixel[valueArr[0]]) && !pixel[valueArr[0]].includes(valueArr[1])){ + pixel[valueArr[0]].push(valueArr[1]); + } else { + pixel[valueArr[0]] = (Number.isInteger(pixel[valueArr[0]])) ? parseInt(valueArr[1]) : valueArr[1]; + } + } + } + }; + + elements.multi_toggle_cloner = { + category: "machines", + color: "#283300", + keyInput: "chance", + ignore: ["unknown", "cloner", "toggle_cloner", "floating_cloner", "clone_powder", "slow_cloner", "ecloner", "destroyable_cloner", "destroyable_clone_powder", "ewall", "wall"], + properties: { + cloneElems: [], + toggle: false, + clickCd: 0, + chance: 0.45, + }, + hardness: 1, + insulate: 1, + onClicked: function(pixel, element){ + if(pixel.clickCd == 0 && !shiftDown && dragStart == null){ + pixelToggle(pixel, {r:1.5,g:1.5,b:0}); + pixel.clickCd = 20; + } + if(shiftDown && !elements.multi_toggle_cloner.ignore.includes(element)){ + if(pixel.cloneElems.includes(element)){ + pixel.cloneElems.splice(pixel.cloneElems.indexOf(element), 1); + } else { + pixel.cloneElems.push(element); + } + } + }, + tick: function(pixel){ + for(let coords of adjacentCoords){ + let x = pixel.x+coords[0], y = pixel.y+coords[1]; + if(isEmpty(x,y) && !outOfBounds(x,y) && Math.random() < pixel.chance && pixel.toggle && JSON.stringify(pixel.cloneElems) != "[]"){ + elem = pixel.cloneElems[Math.round(Math.random()*pixel.cloneElems.length)]; + createPixel(elem, x, y); pixelMap[x][y].temp = pixel.temp; } } - } - for(let coords of adjacentCoords){ - let x = pixel.x+coords[0], y = pixel.y+coords[1]; - let p2 = getPixel(x,y); - if(p2 != null && p2.element == pixel.element && (p2.clone == null && pixel.clone != null)){ - p2.clone = pixel.clone; - } - } - } -}; - -elements.multi_toggle_cloner = { - category: "machines", - color: "#283300", - keyInput: "chance", - ignore: ["unknown", "cloner", "toggle_cloner", "floating_cloner", "clone_powder", "slow_cloner", "ecloner", "destroyable_cloner", "destroyable_clone_powder", "ewall", "wall"], - properties: { - cloneElems: [], - toggle: false, - clickCd: 0, - chance: 0.45, - }, - hardness: 1, - insulate: 1, - onClicked: function(pixel, element){ - if(pixel.clickCd == 0 && !shiftDown && dragStart == null){ - pixelToggle(pixel, {r:1.5,g:1.5,b:0}); - pixel.clickCd = 20; - } - if(shiftDown && !elements.multi_toggle_cloner.ignore.includes(element)){ - if(pixel.cloneElems.includes(element)){ - pixel.cloneElems.splice(pixel.cloneElems.indexOf(element), 1); - } else { - pixel.cloneElems.push(element); - } - } - }, - tick: function(pixel){ - for(let coords of adjacentCoords){ - let x = pixel.x+coords[0], y = pixel.y+coords[1]; - if(isEmpty(x,y) && !outOfBounds(x,y) && Math.random() < pixel.chance && pixel.toggle && JSON.stringify(pixel.cloneElems) != "[]"){ - elem = pixel.cloneElems[Math.round(Math.random()*pixel.cloneElems.length)]; - createPixel(elem, x, y); - pixelMap[x][y].temp = pixel.temp; - } - } - pixel.clickCd -= (pixel.clickCd == 0) ? 0 : 1; - }, - onSelect: function(){ - logMessage("Place cloner, then add elements to the clone list by selecting the element and hold down shift while clicking in it, then click on it to toggle on or off. Shift clicking with an element already found in the list will remove it."); - } -} - -elements.toggle = { - category: "machines", - active: "#b8b8b8", - inactive: "#2b2b2b", - color: "#2b2b2b", - properties: { - toggle: false, - clickCd: 0, - }, - hardness: 1, - onClicked: function(pixel){ - if(pixel.clickCd == 0 && dragStart == null){ - pixel.toggle = !pixel.toggle; - pixel.clickCd = 20; - if(pixel.toggle){ - let rgb = hexToRGB(elements.toggle.active); - let num = 5 - (Math.random()*10); - for(let key in rgb){ - rgb[key] += num; - rgb[key] = Math.round(Math.max(Math.min(rgb[key], 255), 0)); - } - pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; - } else { - let rgb = hexToRGB(elements.toggle.inactive); - let num = 5 - (Math.random()*10); - for(let key in rgb){ - rgb[key] += num; - rgb[key] = Math.round(Math.max(Math.min(rgb[key], 255), 0)); - } - pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; - } - }; - }, - tick: function(pixel){ - if(pixel.clickCd != 0){pixel.clickCd--;} - for(let coords of adjacentCoords){ - let x = pixel.x+coords[0], y = pixel.y+coords[1]; - let p2 = getPixel(x,y); - if(p2 != null && elements[p2.element].conduct == 1 && pixel.toggle){ - p2.charge = 1; - } - } - } -} - -elements.e_temper = { - category: "machines", - color: "#ffb300", - conduct: 1, - targetTemp: 25, - hardness: 1, - onSelect: function(){ - promptInput("Enter the target temperature:", (In)=>{ - this.targetTemp = parseInt(In) || this.targetTemp; - }, "Temperature Selector", this.targetTemp); - }, - properties: { - targetTemp: null - }, - keyInput: "targetTemp", - tick: function(pixel){ - if(pixel.targetTemp == null){ - pixel.targetTemp = elements.e_temper.targetTemp; - } - - doElectricity(pixel, 1); - for(let coords of adjacentCoords){ - let x = pixel.x+coords[0], y = pixel.y+coords[1]; - let p2 = getPixel(x,y); - if(p2 != null && pixel.charge > 0){ - let difference = pixel.targetTemp-p2.temp; - p2.temp += difference/4; - } - } - } -} - -elements.toggle_temper = { - active: "#ff7b00", - inactive: "#261200", - color: "#261200", - category: "machines", - targetTemp: 25, - keyInput: "targetTemp", - hardness: 1, - properties: { - toggle: false, - clickCd: 0, - targetTemp: null, - }, - onClicked: function(pixel){ - if(pixel.clickCd == 0 && dragStart == null){ - pixel.toggle = !pixel.toggle; - pixel.clickCd = 20; - if(pixel.toggle){ - let rgb = hexToRGB(elements.toggle_temper.active); - let num = 5 - (Math.random()*10); - for(let key in rgb){ - rgb[key] += num; - rgb[key] = Math.round(Math.max(Math.min(rgb[key], 255), 0)); - } - pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; - } else { - let rgb = hexToRGB(elements.toggle_temper.inactive); - let num = 5 - (Math.random()*10); - for(let key in rgb){ - rgb[key] += num; - rgb[key] = Math.round(Math.max(Math.min(rgb[key], 255), 0)); - } - pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; - } - }; - }, - onSelect: function(){ - promptInput("Enter the target temperature:", (In)=>{ - this.targetTemp = parseInt(In) || this.targetTemp; - }, "Temperature Selector", this.targetTemp); - }, - tick: function(pixel){ - if(pixel.targetTemp == null){ - pixel.targetTemp = this.targetTemp; - } - for(let coords of adjacentCoords){ - let x = pixel.x+coords[0], y = pixel.y+coords[1]; - let p2 = getPixel(x,y); - if(p2 != null && pixel.toggle){ - let difference = pixel.targetTemp-p2.temp; - p2.temp += difference/4; - } - } - if(pixel.clickCd > 0){pixel.clickCd--;}; - }, -} - -elements.multitool = { - category: "tools", - input: 0, - onSelect: function(){ - promptInput("Multitool for morechemistry.js, changes key values for different elements added in morechemistry.js, chance for toggleable cloner, targetTemp for toggleable temper, clone for other cloners, and channel for portals.", (In)=>{ - this.input = In; - }, "Multitool Input", this.input); - }, - tool: function(pixel){ - if(elements[pixel.element].keyInput != undefined){ - let type = (elements[pixel.element].keyInput.startsWith("int:")) ? "int" : (elements[pixel.element].keyInput.startsWith("str:")) ? "string" : "int"; - let In = elements[pixel.element].keyInput.slice(elements[pixel.element].keyInput.indexOf(":")+1, elements[pixel.element].keyInput.length); - pixel[In] = (type == "int") ? parseFloat(this.input) : this.input; - } - }, - canPlace: false, -} - -class rangeTool { - constructor(color, func, properties = false, onSelect = false, onClicked = false){ - this.category = "machines"; - this.properties = (properties == false) ? { range: null } : properties; - this.color = color; - this.range = 0; - this.onSelect = (onSelect == false) ? ()=>{promptInput("Enter the range for this tool: ", (range)=>{this.range = parseInt(range);}, "Tool Range", this.range)} : onSelect; - this.onClicked = (onClicked == false) ? undefined : onClicked; - this.func = func; - } - tick = function(pixel){ - if(pixel.range == null){ - pixel.range = elements[pixel.element].range; - } else { - let pixelRange = mouseRange(pixel.x, pixel.y, pixel.range); - for(let coords of pixelRange){ - let p2 = getPixel(coords[0], coords[1]); - if(p2 != null){ - elements[pixel.element].func(p2); - } - } - } - } -} - -elements.button = { - category: "machines", - color: "#c7c7c7", - hardness: 1, - onClicked: function(pixel){ - for(let coords of adjacentCoords){ - let x = pixel.x+coords[0], y = pixel.y+coords[1]; - let p = getPixel(x,y); - if(p != null && elements[p.element].conduct){ - p.charge = 1; - } - } - } -} - -elements.toggle_mixer = new rangeTool("#212420", (pixel)=>{ - let range = mouseRange(pixel.x, pixel.y, pixel.range); - let pixels = []; - for(let coords of range){ - let p2 = getPixel(coords[0], coords[1]); - if(p2 != null && pixel.toggle){ - pixels.push(p2); - } - } - for(let p of pixels){ - if(Math.random() < pixel.chance){ - let p2 = pixels[Math.round(Math.random()*pixels.length)]; - if(p != undefined && p2 != undefined && elements[p.element].movable && elements[p2.element].movable){ - swapPixels(p, p2); - if(elements[p.element].onMix != undefined){ - elements[p.element].onMix(p); - } - if(elements[p2.element].onMix != undefined){ - elements[p2.element].onMix(p2); - } - } - } - } - if(pixel.clickCd > 0){pixel.clickCd--;} -}, {range: null, toggle: false, clickCd: 0, chance: 0.35}, false, (pixel)=>{ - if(pixel.clickCd == 0 && dragStart == null){ - pixel.toggle = !pixel.toggle; - pixel.clickCd = 20; - if(pixel.toggle){ - let rgb = hexToRGB(elements.toggle_mixer.active); - let num = 5 - (Math.random()*10); - for(let key in rgb){ - rgb[key] += num; - rgb[key] = Math.round(Math.max(Math.min(rgb[key], 255), 0)); - } - pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; - } else { - let rgb = hexToRGB(elements.toggle_mixer.inactive); - let num = 5 - (Math.random()*10); - for(let key in rgb){ - rgb[key] += num; - rgb[key] = Math.round(Math.max(Math.min(rgb[key], 255), 0)); - } - pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; - } - }; -}); -elements.toggle_mixer.inactive = "#212420", elements.toggle_mixer.active = "#93a390", elements.toggle_mixer.movable = false, elements.toggle_mixer.keyInput = "chance"; -elements.toggle_mixer.hardness = 1; - -elements.toggle_smasher = new rangeTool("#2e2726", (pixel)=>{ - let range = mouseRange(pixel.x, pixel.y, pixel.range); - for(let coords of range){ - let p2 = getPixel(coords[0], coords[1]); - if(p2 != null && pixel.toggle && Math.random() < pixel.chance && elements[p2.element].breakInto != undefined){ - let elem = (Array.isArray(elements[p2.element].breakInto)) ? elements[p2.element].breakInto[Math.round(Math.random()*elements[p2.element].breakInto.length)] : elements[p2.element].breakInto; - if(elem != undefined){ - changePixel(p2, elem); - } - } - } - if(pixel.clickCd > 0){pixel.clickCd--;} -}, {range: null, toggle: false, clickCd: 0, chance: 0.35}, false, (pixel)=>{ - if(pixel.clickCd == 0 && dragStart == null){ - pixel.toggle = !pixel.toggle; - pixel.clickCd = 20; - if(pixel.toggle){ - let rgb = hexToRGB(elements.toggle_smasher.active); - let num = 5 - (Math.random()*10); - for(let key in rgb){ - rgb[key] += num; - rgb[key] = Math.round(Math.max(Math.min(rgb[key], 255), 0)); - } - pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; - } else { - let rgb = hexToRGB(elements.toggle_smasher.inactive); - let num = 5 - (Math.random()*10); - for(let key in rgb){ - rgb[key] += num; - rgb[key] = Math.round(Math.max(Math.min(rgb[key], 255), 0)); - } - pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; - } - }; -}); -elements.toggle_smasher.inactive = "#2e2726", elements.toggle_smasher.active = "#bf9e9b", elements.toggle_smasher.movable = false, elements.toggle_smasher.keyInput = "chance"; -elements.toggle_smasher.hardness = 1; - -elements.target_toggle_smasher = new rangeTool("#332422", (pixel)=>{ - let range = mouseRange(pixel.x, pixel.y, pixel.range); - for(let coords of range){ - let p2 = getPixel(coords[0], coords[1]); - if(p2 != null && pixel.toggle && Math.random() < pixel.chance && elements[p2.element].breakInto != undefined && pixel.targetElems.includes(p2.element)){ - let elem = (Array.isArray(elements[p2.element].breakInto)) ? elements[p2.element].breakInto[Math.round(Math.random()*elements[p2.element].breakInto.length)] : elements[p2.element].breakInto; - if(elem != undefined){ - changePixel(p2, elem); - } - } - } - if(pixel.clickCd > 0){pixel.clickCd--;} -}, {range: null, toggle: false, clickCd: 0, chance: 0.35, targetElems: []}, ()=>{ - promptInput("Enter the range for this tool: ", (range)=>{ - console.log(range); - elements.target_toggle_smasher.range = parseInt(range); - logMessage("Place smasher, then add elements to the target list by selecting the element and hold down shift while clicking on the pixel, then click on it to toggle on or off. Shift clicking with an element already found in the list will remove it."); - }, "Enter range", elements.target_toggle_smasher.range); -}, (pixel, elem)=>{ - if(pixel.clickCd == 0 && dragStart == null && !shiftDown){ - pixel.toggle = !pixel.toggle; - pixel.clickCd = 20; - if(pixel.toggle){ - let rgb = hexToRGB(elements.target_toggle_smasher.active); - let num = 5 - (Math.random()*10); - for(let key in rgb){ - rgb[key] += num; - rgb[key] = Math.round(Math.max(Math.min(rgb[key], 255), 0)); - } - pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; - } else { - let rgb = hexToRGB(elements.target_toggle_smasher.inactive); - let num = 5 - (Math.random()*10); - for(let key in rgb){ - rgb[key] += num; - rgb[key] = Math.round(Math.max(Math.min(rgb[key], 255), 0)); - } - pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; - } - }; - if(shiftDown && elements[elem].breakInto != undefined){ - if(pixel.targetElems.includes(elem)){ - pixel.targetElems.splice(pixel.targetElems.indexOf(elem), 1); - } else { - pixel.targetElems.push(elem); - } - } -}); -elements.target_toggle_smasher.inactive = "#332422", elements.target_toggle_smasher.active = "#b57a72", elements.target_toggle_smasher.movable = false, elements.target_toggle_smasher.keyInput = "chance"; -elements.target_toggle_smasher.hardness = 1; - -elements.target_toggle_mixer = new rangeTool("#1f291b", (pixel)=>{ - - let range = mouseRange(pixel.x, pixel.y, pixel.range); - let pixels = []; - for(let coords of range){ - let p2 = getPixel(coords[0], coords[1]); - if(p2 != null && pixel.toggle){ - pixels.push(p2); - } - } - for(let p of pixels){ - if(Math.random() < pixel.chance){ - let p2 = pixels[Math.round(Math.random()*pixels.length)]; - if(p != undefined && p2 != undefined && elements[p.element].movable && elements[p2.element].movable && pixel.targetElems.includes(p.element) && pixel.targetElems.includes(p2.element)){ - swapPixels(p, p2); - if(elements[p.element].onMix != undefined){ - elements[p.element].onMix(p); - } - if(elements[p2.element].onMix != undefined){ - elements[p2.element].onMix(p2); - } - } - } - } - if(pixel.clickCd > 0){pixel.clickCd--;} -}, {range: null, toggle: false, clickCd: 0, chance: 0.35, targetElems: []}, ()=>{ - promptInput("Enter the range for this tool: ", (range)=>{ - console.log(range); - elements.target_toggle_mixer.range = parseInt(range); - logMessage("Place mixer, then add elements to the target list by selecting the element and hold down shift while clicking on the pixel, then click on it to toggle on or off. Shift clicking with an element already found in the list will remove it."); - }, "Enter range", elements.target_toggle_mixer.range); -}, (pixel, elem)=>{ - if(pixel.clickCd == 0 && dragStart == null && !shiftDown){ - pixel.toggle = !pixel.toggle; - pixel.clickCd = 20; - if(pixel.toggle){ - let rgb = hexToRGB(elements.target_toggle_mixer.active); - let num = 5 - (Math.random()*10); - for(let key in rgb){ - rgb[key] += num; - rgb[key] = Math.round(Math.max(Math.min(rgb[key], 255), 0)); - } - pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; - } else { - let rgb = hexToRGB(elements.target_toggle_mixer.inactive); - let num = 5 - (Math.random()*10); - for(let key in rgb){ - rgb[key] += num; - rgb[key] = Math.round(Math.max(Math.min(rgb[key], 255), 0)); - } - pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; - } - }; - if(shiftDown && elements[elem].movable){ - if(pixel.targetElems.includes(elem)){ - pixel.targetElems.splice(pixel.targetElems.indexOf(elem), 1); - } else { - pixel.targetElems.push(elem); - } - } -}); -elements.target_toggle_mixer.inactive = "#1f291b", elements.target_toggle_mixer.active = "#8cbf7a", elements.target_toggle_mixer.movable = false, elements.target_toggle_mixer.keyInput = "chance"; -elements.target_toggle_mixer.hardness = 1; -elements.target_sensor = { - color: "#afb08b", - conduct: 1, - category: "machines", - properties: { - targetElems: [], - clickCd: 0, - }, - hardness: 1, - onClicked: function(pixel, element){ - if(shiftDown && element != "unknown" && pixel.clickCd == 0){ - if(pixel.targetElems.includes(element)){ - pixel.targetElems.splice(pixel.targetElems.indexOf(element), 1); - pixel.clickCd = 20; - } else { - pixel.targetElems.push(element); - pixel.clickCd = 20; - } - } - }, - tick: function(pixel){ - for(let coords of adjacentCoords){ - let x = pixel.x+coords[0], y = pixel.y+coords[1]; - let p = getPixel(x,y); - if(p != null && pixel.targetElems.includes(p.element)){ - pixel.charge = 1; - doElectricity(pixel,1); - } - } - pixel.clickCd -= (pixel.clickCd > 0) ? 1 : 0; - } -} - -Pixel.prototype.inRange = function(range){ - res = false; - for(let coords of range){ - if(this.x == coords[0] && this.y == coords[1]){ - res = true; - } - } - return res; -} -elements.acid.ignore = elements.acid.ignore.concat(["nitric_acid", "aqua_regia", "chloroauric_acid", "nitrogen_dioxide", "nitric_acid_ice", "nitrogen_dioxide_ice", "acid", "chloroauric_acid", "magnesium_chloride", "magnesium_carbonate", "magnesium_hydroxide", "magnesium", "gallium", "gallium_chloride", "salt", "aluminum", "aluminum_chloride", "target_portal_in"]); -elements.nitric_acid = { - alias: "HNO₃", - behavior: [["XX","DB%5","XX"],["DB%5 AND M2","XX","DB%5 AND M2"],["DB%5 AND M2","DB%10 AND M1","DB%5 AND M2"]], - ignore: elements.acid.ignore, - state: "liquid", - color: ["#f5e7e1", "#f7e8e1", "#f7ebe6"], - tempLow: -42, - stateLow: "nitric_acid_ice", - reactions: { - acid: {elem1: null, elem2: "aqua_regia"}, - }, - density: 1510, - category: "liquids", - tick: function(pixel){ - for(let coords of squareCoords){ - let x = pixel.x+coords[0], y = pixel.y+coords[1]; - let p2 = getPixel(x,y); - if(p2 != null && ["light", "liquid_light", "laser"].includes(p2.element) || Math.random()<(pixel.temp-68)/53){ - let elems = ["nitrogen_dioxide","water", "oxygen"]; - let elem = elems[Math.round(Math.random()*elems.length)]; - while (elem == undefined){ - elem = elems[Math.round(Math.random()*elems.length)]; - } - changePixel(pixel, elem); - } - } - } -} -elements.nitrogen_dioxide = { - alias: "NO₂", - color: ["#6e361f", "#7d3d22", "#873f20", "#9c4935"], - behavior: behaviors.GAS, - state: "gas", - reactions: { - water: {elem1: null, elem2: "nitric_acid"}, - }, - category: "gases", - stateHigh: ["nitrogen", "oxygen"], - tempHigh: 150, - stateLow: "nitrogen_dioxide_ice", - tempLow: -11, -}; - -elements.nitrogen_dioxide_ice = { - color: ["#4f1607", "#4d1709", "#541606", "#471407"], - behavior: behaviors.WALL, - state: "solid", - category: "states", - stateHigh: "nitrogen_dioxide", - tempHigh: -10, -}; - -elements.nitric_acid_ice = { - behavior: behaviors.WALL, - color: ["#f5e7e4", "#f5efed", "#fcfafa"], - state: "solid", - category: "states", - stateHigh: "nitric_acid", - tempHigh: -41 -}; - -elements.aqua_regia = { - alias: "3HCl•HNO₃", - color:["#ffc766", "#f5c36e", "#f7c163", "#ffcd75"], - behavior: [["XX","DB%5","XX"],["DB%5 AND M2","XX","DB%5 AND M2"],["DB%5 AND M2","DB%10 AND M1","DB%5 AND M2"]], - ignore: elements.acid.ignore, - category: "liquids", - state: "liquid", - density: 1210, - reactions: { - gold: {elem1: "chloroauric_acid", elem2: null, chance: 0.15}, - gold_coin: {elem1: "chloroauric_acid", elem2: null, chance: 0.15}, - blue_gold: {elem1: ["chloroauric_acid", "gallium_chloride"], elem2: null, chance: 0.15}, - purple_gold: {elem1: ["chloroauric_acid", "chloroauric_acid", "chloroauric_acid", "aluminum_chloride"], elem2: null, chance: 0.15}, - } -}; -elements.chloroauric_acid = { - color: ["#f7bb2f", "#f5bb33", "#f5b727", "#e8ae25"], - alias: "H(AuCl₄)", - behavior: behaviors.POWDER, - category: "powders", - state: "solid", - density: 3900, - reactions: { - potassium: {elem1: "gold_coin", elem2: "potassium_salt", func: function(pixel){for(let coords of squareCoords){let x=pixel.x+coords[0],y=pixel.y+coords[1]; if(isEmpty(x,y) && !outOfBounds(x,y) && Math.random()<0.25){createPixel("hydrogen", x, y);}}}}, - sodium: {elem1: "gold_coin", elem2: "salt", func: function(pixel){for(let coords of squareCoords){let x=pixel.x+coords[0],y=pixel.y+coords[1]; if(isEmpty(x,y) && !outOfBounds(x,y) && Math.random()<0.25){createPixel("hydrogen", x, y);}}}}, - caustic_potash: {elem1: "gold_coin", elem2: "potassium_salt", func: function(pixel){for(let coords of squareCoords){let x=pixel.x+coords[0],y=pixel.y+coords[1]; if(isEmpty(x,y) && !outOfBounds(x,y) && Math.random()<0.25){createPixel("water", x, y);}}}}, - lye: {elem1: "gold_coin", elem2: "salt", func: function(pixel){for(let coords of squareCoords){let x=pixel.x+coords[0],y=pixel.y+coords[1]; if(isEmpty(x,y) && !outOfBounds(x,y) && Math.random()<0.25){createPixel("water", x, y);}}}}, - magnesium: {elem1: "gold_coin", elem2: "magnesium_chloride", func: function(pixel){for(let coords of squareCoords){let x=pixel.x+coords[0],y=pixel.y+coords[1]; if(isEmpty(x,y) && !outOfBounds(x,y) && Math.random()<0.25){createPixel("hydrogen", x, y);}}}}, - metal_scrap: {elem1: "gold_coin", elem2: "slag", func: function(pixel){for(let coords of squareCoords){let x=pixel.x+coords[0],y=pixel.y+coords[1]; if(isEmpty(x,y) && !outOfBounds(x,y) && Math.random()<0.25){createPixel("hydrogen", x, y);}}}}, - } -}; -elements.magnesium_chloride = { - alias: "MgCl₂", - category: "salts", - behavior: behaviors.POWDER, - state: "solid", - color: ["#f2f2f2", "#f5f5f5", "#ebebeb", "#e6e6e6"], - density: 2320, - reactions: { - baking_soda: {elem1: "magnesium_carbonate", elem2: "salt"}, - lye: {elem1: "magnesium_hydroxide", elem2: "salt"}, - caustic_potash: {elem1: "magnesium_hydroxide", elem2: "potassium_salt"}, - ash: {elem1: "magnesium_carbonate", elem2: ["dust","dust",null,"potassium_salt", "charcoal"]} - } -} -elements.calcium_chloride = { - alias: "CaCl₂", - category: "salts", - density: 2150, - behavior: behaviors.POWDER, - state: "solid", - color: ["#f2f2f2", "#f5f5f5", "#ebebeb", "#e6e6e6"], - density: 2320, - reactions: { - baking_soda: {elem1: "limestone", elem2: "salt"}, - lye: {elem1: "slaked_lime", elem2: "salt"}, - caustic_potash: {elem1: "slaked_lime", elem2: "potassium_salt"}, - ash: {elem1: "limestone", elem2: ["dust","dust",null,"potassium_salt", "charcoal"]}, - epsom_salt: {elem1: "hardened_gypsum", elem2: "magnesium_chloride"}, - carbon_dioxide: {elem1: "limestone", elem2: "chlorine", chance: 0.001, tempMin: 60} - } -} -elements.sodium.reactions.carbon_dioxide = {elem1: "baking_soda", elem2: null}, elements.magnesium.reactions.carbon_dioxide = {elem1: "magnesium_carbonate", elem2:null}; -elements.acid.reactions.magnesium = {elem1: "hydrogen", elem2: "magnesium_chloride"}; -elements.magnesium_carbonate = { - alias: "MgCO₃", - category: "salts", - behavior: behaviors.POWDER, - state: "solid", - color: ["#f2f2f2", "#f5f5f5", "#ebebeb", "#e6e6e6"], - density: 2960, - reactions: { - acid: {elem1: "magnesium_chloride", elem2: ["carbon_dioxide", "foam", "seltzer", "seltzer"]} - } -} -elements.magnesium_hydroxide = { - alias: "Mg(OH)₂", - category: "salts", - behavior: behaviors.POWDER, - state: "solid", - color: ["#f2f2f2", "#f5f5f5", "#ebebeb", "#e6e6e6"], - density: 2340, - reactions: { - acid: {elem1: "magnesium_chloride", elem2: "water"} - } -} -elements.hardened_gypsum = { - alias: "CaSO₄•2H₂O", - color: ["#f2f2f2", "#f5f5f5", "#ebebeb", "#e6e6e6"], - category: "solids", - state: "solid", - behavior: behaviors.WALL, - density: 2320, - breakInto: "gypsum", -} -elements.gypsum = { - alias: "CaSO₄•2H₂O", - color: ["#d1d1d1", "#d6d6d6", "#cccbca", "#cfcdca", "#bfbebb"], - category: "powders", - state: "solid", - behavior: behaviors.STURDYPOWDER, - density: 2420, - tick: function(pixel){ - let chance = (pixel.temp-18)/100*(pixel.temp/40)*((pixelTicks-pixel.start)/250); - if(Math.random(){ - elements.target_portal_in.channel = parseInt(input); - }, "Portal Channel", elements.target_portal_in.channel) - }, - tick: function(pixel){ - pixel.clickCd -= (pixel.clickCd == 0) ? 0 : 1; - if(pixel.channel == null){ - pixel.channel = elements.target_portal_in.channel; - } - if(pixel.out == null){ - for(p2 of currentPixels){ - if(p2.element == "portal_out" && p2.channel == pixel.channel){ - let adjacent = this.checkAdjacent(p2); - if(adjacent != false){ - pixel.out = p2; - break; - } + pixel[valueArr[0]] = (Number.isInteger(pixel[valueArr[0]])) ? parseInt(valueArr[1]) : valueArr[1]; } } } - for(let coords of adjacentCoords){ - let x = pixel.x+coords[0], y = pixel.y+coords[1]; - if(!isEmpty(x,y) && !outOfBounds(x,y) && elements[pixelMap[x][y].element].movable && pixel.out != undefined){ - let pixel2 = getPixel(x,y); - let spots = this.checkAdjacent(pixel.out); - if(spots != false && Array.isArray(spots)){ - let num = Math.round(Math.random()*spots.length); - while(spots[num] == undefined){ - num = Math.round(Math.random()*spots.length); + } + + elements.toggle = { + category: "machines", + active: "#b8b8b8", + inactive: "#2b2b2b", + color: "#2b2b2b", + properties: { + toggle: false, + clickCd: 0, + }, + hardness: 1, + onClicked: function(pixel){ + if(pixel.clickCd == 0 && dragStart == null){ + pixel.toggle = !pixel.toggle; + pixel.clickCd = 20; + if(pixel.toggle){ + let rgb = hexToRGB(elements.toggle.active); + let num = 5 - (Math.random()*10); + for(let key in rgb){ + rgb[key] += num; + rgb[key] = Math.round(Math.max(Math.min(rgb[key], 255), 0)); } - if(pixel.targetElems.includes(pixel2.element)){ - movePixel(pixel2, spots[num][0], spots[num][1]); + pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; + } else { + let rgb = hexToRGB(elements.toggle.inactive); + let num = 5 - (Math.random()*10); + for(let key in rgb){ + rgb[key] += num; + rgb[key] = Math.round(Math.max(Math.min(rgb[key], 255), 0)); + } + pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; + } + }; + }, + tick: function(pixel){ + if(pixel.clickCd != 0){pixel.clickCd--;} + for(let coords of adjacentCoords){ + let x = pixel.x+coords[0], y = pixel.y+coords[1]; + let p2 = getPixel(x,y); + if(p2 != null && elements[p2.element].conduct == 1 && pixel.toggle){ + p2.charge = 1; + } + } + } + } + + elements.e_temper = { + category: "machines", + color: "#ffb300", + conduct: 1, + targetTemp: 25, + hardness: 1, + onSelect: function(){ + promptInput("Enter the target temperature:", (In)=>{ + this.targetTemp = parseInt(In) || this.targetTemp; + }, "Temperature Selector", this.targetTemp); + }, + properties: { + targetTemp: null + }, + keyInput: "targetTemp", + tick: function(pixel){ + if(pixel.targetTemp == null){ + pixel.targetTemp = elements.e_temper.targetTemp; + } + + doElectricity(pixel, 1); + for(let coords of adjacentCoords){ + let x = pixel.x+coords[0], y = pixel.y+coords[1]; + let p2 = getPixel(x,y); + if(p2 != null && pixel.charge > 0){ + let difference = pixel.targetTemp-p2.temp; + p2.temp += difference/4; + } + } + }, + dataInFunc: function(pixel, value){ + if(value.includes(":")){ + let valueArr = value.split(":"); + if(Array.isArray(pixel[valueArr[0]]) && !pixel[valueArr[0]].includes(valueArr[1])){ + pixel[valueArr[0]].push(valueArr[1]); + } else { + pixel[valueArr[0]] = (Number.isInteger(pixel[valueArr[0]])) ? parseInt(valueArr[1]) : valueArr[1]; + } + } + } + } + + elements.toggle_temper = { + active: "#ff7b00", + inactive: "#261200", + color: "#261200", + category: "machines", + targetTemp: 25, + keyInput: "targetTemp", + hardness: 1, + properties: { + toggle: false, + clickCd: 0, + targetTemp: null, + }, + onClicked: function(pixel){ + if(pixel.clickCd == 0 && dragStart == null){ + pixel.toggle = !pixel.toggle; + pixel.clickCd = 20; + if(pixel.toggle){ + let rgb = hexToRGB(elements.toggle_temper.active); + let num = 5 - (Math.random()*10); + for(let key in rgb){ + rgb[key] += num; + rgb[key] = Math.round(Math.max(Math.min(rgb[key], 255), 0)); + } + pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; + } else { + let rgb = hexToRGB(elements.toggle_temper.inactive); + let num = 5 - (Math.random()*10); + for(let key in rgb){ + rgb[key] += num; + rgb[key] = Math.round(Math.max(Math.min(rgb[key], 255), 0)); + } + pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; + } + }; + }, + onSelect: function(){ + promptInput("Enter the target temperature:", (In)=>{ + this.targetTemp = parseInt(In) || this.targetTemp; + }, "Temperature Selector", this.targetTemp); + }, + tick: function(pixel){ + if(pixel.targetTemp == null){ + pixel.targetTemp = this.targetTemp; + } + for(let coords of adjacentCoords){ + let x = pixel.x+coords[0], y = pixel.y+coords[1]; + let p2 = getPixel(x,y); + if(p2 != null && pixel.toggle){ + let difference = pixel.targetTemp-p2.temp; + p2.temp += difference/4; + } + } + if(pixel.clickCd > 0){pixel.clickCd--;}; + }, + dataInFunc: function(pixel, value){ + if(value.includes(":")){ + let valueArr = value.split(":"); + if(Array.isArray(pixel[valueArr[0]]) && !pixel[valueArr[0]].includes(valueArr[1])){ + pixel[valueArr[0]].push(valueArr[1]); + } else { + pixel[valueArr[0]] = (Number.isInteger(pixel[valueArr[0]])) ? parseInt(valueArr[1]) : valueArr[1]; + } + } + } + } + + elements.multitool = { + category: "tools", + input: 0, + onSelect: function(){ + promptInput("Multitool for morechemistry.js, changes key values for different elements added in morechemistry.js, chance for toggleable cloner, targetTemp for toggleable temper, clone for other cloners, and channel for portals.", (In)=>{ + this.input = In; + }, "Multitool Input", this.input); + }, + tool: function(pixel){ + if(elements[pixel.element].keyInput != undefined){ + let type = (elements[pixel.element].keyInput.startsWith("int:")) ? "int" : (elements[pixel.element].keyInput.startsWith("str:")) ? "string" : "int"; + let In = elements[pixel.element].keyInput.slice(elements[pixel.element].keyInput.indexOf(":")+1, elements[pixel.element].keyInput.length); + pixel[In] = (type == "int") ? parseFloat(this.input) : this.input; + } + }, + canPlace: false, + } + + class rangeTool { + constructor(color, func, properties = false, onSelect = false, onClicked = false){ + this.category = "machines"; + this.properties = (properties == false) ? { range: null } : properties; + this.color = color; + this.range = 0; + this.onSelect = (onSelect == false) ? ()=>{promptInput("Enter the range for this tool: ", (range)=>{this.range = parseInt(range);}, "Tool Range", this.range)} : onSelect; + this.onClicked = (onClicked == false) ? undefined : onClicked; + this.func = func; + } + tick = function(pixel){ + if(pixel.range == null){ + pixel.range = elements[pixel.element].range; + } else { + let pixelRange = mouseRange(pixel.x, pixel.y, pixel.range); + for(let coords of pixelRange){ + let p2 = getPixel(coords[0], coords[1]); + if(p2 != null){ + elements[pixel.element].func(p2); } } } } } -} + + elements.button = { + category: "machines", + color: "#c7c7c7", + hardness: 1, + onClicked: function(pixel){ + for(let coords of adjacentCoords){ + let x = pixel.x+coords[0], y = pixel.y+coords[1]; + let p = getPixel(x,y); + if(p != null && elements[p.element].conduct){ + p.charge = 1; + } + } + } + } + + elements.toggle_mixer = new rangeTool("#212420", (pixel)=>{ + let range = mouseRange(pixel.x, pixel.y, pixel.range); + let pixels = []; + for(let coords of range){ + let p2 = getPixel(coords[0], coords[1]); + if(p2 != null && pixel.toggle){ + pixels.push(p2); + } + } + for(let p of pixels){ + if(Math.random() < pixel.chance){ + let p2 = pixels[Math.round(Math.random()*pixels.length)]; + if(p != undefined && p2 != undefined && elements[p.element].movable && elements[p2.element].movable){ + swapPixels(p, p2); + if(elements[p.element].onMix != undefined){ + elements[p.element].onMix(p); + } + if(elements[p2.element].onMix != undefined){ + elements[p2.element].onMix(p2); + } + } + } + } + if(pixel.clickCd > 0){pixel.clickCd--;} + }, {range: null, toggle: false, clickCd: 0, chance: 0.35}, false, (pixel)=>{ + if(pixel.clickCd == 0 && dragStart == null){ + pixel.toggle = !pixel.toggle; + pixel.clickCd = 20; + if(pixel.toggle){ + let rgb = hexToRGB(elements.toggle_mixer.active); + let num = 5 - (Math.random()*10); + for(let key in rgb){ + rgb[key] += num; + rgb[key] = Math.round(Math.max(Math.min(rgb[key], 255), 0)); + } + pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; + } else { + let rgb = hexToRGB(elements.toggle_mixer.inactive); + let num = 5 - (Math.random()*10); + for(let key in rgb){ + rgb[key] += num; + rgb[key] = Math.round(Math.max(Math.min(rgb[key], 255), 0)); + } + pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; + } + }; + }); + elements.toggle_mixer.inactive = "#212420", elements.toggle_mixer.active = "#93a390", elements.toggle_mixer.movable = false, elements.toggle_mixer.keyInput = "chance"; + elements.toggle_mixer.hardness = 1; + + elements.toggle_smasher = new rangeTool("#2e2726", (pixel)=>{ + let range = mouseRange(pixel.x, pixel.y, pixel.range); + for(let coords of range){ + let p2 = getPixel(coords[0], coords[1]); + if(p2 != null && pixel.toggle && Math.random() < pixel.chance && elements[p2.element].breakInto != undefined){ + let elem = (Array.isArray(elements[p2.element].breakInto)) ? elements[p2.element].breakInto[Math.round(Math.random()*elements[p2.element].breakInto.length)] : elements[p2.element].breakInto; + if(elem != undefined){ + changePixel(p2, elem); + } + } + } + if(pixel.clickCd > 0){pixel.clickCd--;} + }, {range: null, toggle: false, clickCd: 0, chance: 0.35}, false, (pixel)=>{ + if(pixel.clickCd == 0 && dragStart == null){ + pixel.toggle = !pixel.toggle; + pixel.clickCd = 20; + if(pixel.toggle){ + let rgb = hexToRGB(elements.toggle_smasher.active); + let num = 5 - (Math.random()*10); + for(let key in rgb){ + rgb[key] += num; + rgb[key] = Math.round(Math.max(Math.min(rgb[key], 255), 0)); + } + pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; + } else { + let rgb = hexToRGB(elements.toggle_smasher.inactive); + let num = 5 - (Math.random()*10); + for(let key in rgb){ + rgb[key] += num; + rgb[key] = Math.round(Math.max(Math.min(rgb[key], 255), 0)); + } + pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; + } + }; + }); + elements.toggle_smasher.inactive = "#2e2726", elements.toggle_smasher.active = "#bf9e9b", elements.toggle_smasher.movable = false, elements.toggle_smasher.keyInput = "chance"; + elements.toggle_smasher.hardness = 1; + + elements.target_toggle_smasher = new rangeTool("#332422", (pixel)=>{ + let range = mouseRange(pixel.x, pixel.y, pixel.range); + for(let coords of range){ + let p2 = getPixel(coords[0], coords[1]); + if(p2 != null && pixel.toggle && Math.random() < pixel.chance && elements[p2.element].breakInto != undefined && pixel.targetElems.includes(p2.element)){ + let elem = (Array.isArray(elements[p2.element].breakInto)) ? elements[p2.element].breakInto[Math.round(Math.random()*elements[p2.element].breakInto.length)] : elements[p2.element].breakInto; + if(elem != undefined){ + changePixel(p2, elem); + } + } + } + if(pixel.clickCd > 0){pixel.clickCd--;} + }, {range: null, toggle: false, clickCd: 0, chance: 0.35, targetElems: []}, ()=>{ + promptInput("Enter the range for this tool: ", (range)=>{ + console.log(range); + elements.target_toggle_smasher.range = parseInt(range); + logMessage("Place smasher, then add elements to the target list by selecting the element and hold down shift while clicking on the pixel, then click on it to toggle on or off. Shift clicking with an element already found in the list will remove it."); + }, "Enter range", elements.target_toggle_smasher.range); + }, (pixel, elem)=>{ + if(pixel.clickCd == 0 && dragStart == null && !shiftDown){ + pixel.toggle = !pixel.toggle; + pixel.clickCd = 20; + if(pixel.toggle){ + let rgb = hexToRGB(elements.target_toggle_smasher.active); + let num = 5 - (Math.random()*10); + for(let key in rgb){ + rgb[key] += num; + rgb[key] = Math.round(Math.max(Math.min(rgb[key], 255), 0)); + } + pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; + } else { + let rgb = hexToRGB(elements.target_toggle_smasher.inactive); + let num = 5 - (Math.random()*10); + for(let key in rgb){ + rgb[key] += num; + rgb[key] = Math.round(Math.max(Math.min(rgb[key], 255), 0)); + } + pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; + } + }; + if(shiftDown && elements[elem].breakInto != undefined){ + if(pixel.targetElems.includes(elem)){ + pixel.targetElems.splice(pixel.targetElems.indexOf(elem), 1); + } else { + pixel.targetElems.push(elem); + } + } + }); + elements.target_toggle_smasher.inactive = "#332422", elements.target_toggle_smasher.active = "#b57a72", elements.target_toggle_smasher.movable = false, elements.target_toggle_smasher.keyInput = "chance"; + elements.target_toggle_smasher.hardness = 1; + + elements.target_toggle_mixer = new rangeTool("#1f291b", (pixel)=>{ + + let range = mouseRange(pixel.x, pixel.y, pixel.range); + let pixels = []; + for(let coords of range){ + let p2 = getPixel(coords[0], coords[1]); + if(p2 != null && pixel.toggle){ + pixels.push(p2); + } + } + for(let p of pixels){ + if(Math.random() < pixel.chance){ + let p2 = pixels[Math.round(Math.random()*pixels.length)]; + if(p != undefined && p2 != undefined && elements[p.element].movable && elements[p2.element].movable && pixel.targetElems.includes(p.element) && pixel.targetElems.includes(p2.element)){ + swapPixels(p, p2); + if(elements[p.element].onMix != undefined){ + elements[p.element].onMix(p); + } + if(elements[p2.element].onMix != undefined){ + elements[p2.element].onMix(p2); + } + } + } + } + if(pixel.clickCd > 0){pixel.clickCd--;} + }, {range: null, toggle: false, clickCd: 0, chance: 0.35, targetElems: []}, ()=>{ + promptInput("Enter the range for this tool: ", (range)=>{ + console.log(range); + elements.target_toggle_mixer.range = parseInt(range); + logMessage("Place mixer, then add elements to the target list by selecting the element and hold down shift while clicking on the pixel, then click on it to toggle on or off. Shift clicking with an element already found in the list will remove it."); + }, "Enter range", elements.target_toggle_mixer.range); + }, (pixel, elem)=>{ + if(pixel.clickCd == 0 && dragStart == null && !shiftDown){ + pixel.toggle = !pixel.toggle; + pixel.clickCd = 20; + if(pixel.toggle){ + let rgb = hexToRGB(elements.target_toggle_mixer.active); + let num = 5 - (Math.random()*10); + for(let key in rgb){ + rgb[key] += num; + rgb[key] = Math.round(Math.max(Math.min(rgb[key], 255), 0)); + } + pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; + } else { + let rgb = hexToRGB(elements.target_toggle_mixer.inactive); + let num = 5 - (Math.random()*10); + for(let key in rgb){ + rgb[key] += num; + rgb[key] = Math.round(Math.max(Math.min(rgb[key], 255), 0)); + } + pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; + } + }; + if(shiftDown && elements[elem].movable){ + if(pixel.targetElems.includes(elem)){ + pixel.targetElems.splice(pixel.targetElems.indexOf(elem), 1); + } else { + pixel.targetElems.push(elem); + } + } + }); + elements.target_toggle_mixer.inactive = "#1f291b", elements.target_toggle_mixer.active = "#8cbf7a", elements.target_toggle_mixer.movable = false, elements.target_toggle_mixer.keyInput = "chance"; + elements.target_toggle_mixer.hardness = 1; + elements.target_sensor = { + color: "#afb08b", + conduct: 1, + category: "machines", + properties: { + targetElems: [], + clickCd: 0, + }, + hardness: 1, + onClicked: function(pixel, element){ + if(shiftDown && element != "unknown" && pixel.clickCd == 0){ + if(pixel.targetElems.includes(element)){ + pixel.targetElems.splice(pixel.targetElems.indexOf(element), 1); + pixel.clickCd = 20; + } else { + pixel.targetElems.push(element); + pixel.clickCd = 20; + } + } + }, + tick: function(pixel){ + for(let coords of adjacentCoords){ + let x = pixel.x+coords[0], y = pixel.y+coords[1]; + let p = getPixel(x,y); + if(p != null && pixel.targetElems.includes(p.element)){ + pixel.charge = 1; + doElectricity(pixel,1); + } + } + pixel.clickCd -= (pixel.clickCd > 0) ? 1 : 0; + }, + dataInFunc: function(pixel, value){ + if(value.includes(":")){ + let valueArr = value.split(":"); + if(Array.isArray(pixel[valueArr[0]]) && !pixel[valueArr[0]].includes(valueArr[1])){ + pixel[valueArr[0]].push(valueArr[1]); + } else { + pixel[valueArr[0]] = (Number.isInteger(pixel[valueArr[0]])) ? parseInt(valueArr[1]) : valueArr[1]; + } + } + } + } + + Pixel.prototype.inRange = function(range){ + res = false; + for(let coords of range){ + if(this.x == coords[0] && this.y == coords[1]){ + res = true; + } + } + return res; + } + function acidTick(pixel){ + for(let coords of adjacentCoords){ + let x = pixel.x+coords[0], y = pixel.y+coords[1]; + let p2 = getPixel(x,y); + let ignore = false; + for(let item of elements[pixel.element].ignore){ + if(p2 != null && item.startsWith("*")&&p2.element.endsWith(item.split("*")[1])){ + ignore = true; + } else if (p2 != null && item.endsWith("*")&&p2.element.startsWith(item.split("*")[0])){ + ignore = true; + } + } + if(p2 != null && !(elements[pixel.element].ignore.includes(p2.element) || ignore || p2.element == pixel.element)){ + deletePixel(x,y); + deletePixel(pixel.x, pixel.y); + } + } + } + elements.acid.behavior = behaviors.LIQUID; + elements.acid.tick = acidTick; + elements.acid.ignore = elements.acid.ignore.concat(["nitric_acid", "aqua_regia", "nitrogen_dioxide", "nitric_acid_ice", "nitrogen_dioxide_ice", "acid", "chloroauric_acid", "*chloride", "*carbonate", "*acetate", "*sulfate", "*gallium", "*hydroxide", "salt", "*aluminum", "target_portal_in", "*magnesium", "*copper", "*iron", "*calcium", "sulfuric_acid", "*vinegar", "*gypsum", "*wall", "epsom_salt", "*platinum", "chloroplatinic_acid", "*sulfur*"]); + elements.nitric_acid = { + alias: "HNO₃", + behavior: behaviors.LIQUID, + ignore: elements.acid.ignore, + state: "liquid", + color: ["#f5e7e1", "#f7e8e1", "#f7ebe6"], + tempLow: -42, + stateLow: "nitric_acid_ice", + reactions: { + acid: {elem1: null, elem2: "aqua_regia"}, + }, + density: 1510, + category: "liquids", + tick: function(pixel){ + acidTick(pixel); + for(let coords of squareCoords){ + let x = pixel.x+coords[0], y = pixel.y+coords[1]; + let p2 = getPixel(x,y); + if(p2 != null && ["light", "liquid_light", "laser"].includes(p2.element) || Math.random()<(pixel.temp-68)/53){ + let elems = ["nitrogen_dioxide","water", "oxygen"]; + let elem = elems[Math.round(Math.random()*elems.length)]; + while (elem == undefined){ + elem = elems[Math.round(Math.random()*elems.length)]; + } + changePixel(pixel, elem); + } + } + } + } + elements.nitrogen_dioxide = { + alias: "NO₂", + color: ["#6e361f", "#7d3d22", "#873f20", "#9c4935"], + behavior: behaviors.GAS, + state: "gas", + reactions: { + water: {elem1: null, elem2: "nitric_acid"}, + }, + category: "gases", + stateHigh: ["nitrogen", "oxygen"], + tempHigh: 150, + stateLow: "nitrogen_dioxide_ice", + tempLow: -11, + }; + + elements.nitrogen_dioxide_ice = { + temp: -20, + color: ["#4f1607", "#4d1709", "#541606", "#471407"], + behavior: behaviors.WALL, + state: "solid", + category: "states", + stateHigh: "nitrogen_dioxide", + tempHigh: -10, + }; + + elements.nitric_acid_ice = { + temp: -45, + behavior: behaviors.WALL, + color: ["#f5e7e4", "#f5efed", "#fcfafa"], + state: "solid", + category: "states", + stateHigh: "nitric_acid", + tempHigh: -41 + }; + + elements.aqua_regia = { + alias: "3HCl•HNO₃", + color:["#ffc766", "#f5c36e", "#f7c163", "#ffcd75"], + behavior: behaviors.LIQUID, + ignore: elements.acid.ignore, + category: "liquids", + state: "liquid", + density: 1210, + reactions: { + gold: {elem1: "chloroauric_acid", elem2: null, chance: 0.15}, + gold_coin: {elem1: "chloroauric_acid", elem2: null, chance: 0.15}, + blue_gold: {elem1: ["chloroauric_acid", "gallium_chloride"], elem2: null, chance: 0.15}, + purple_gold: {elem1: ["chloroauric_acid", "chloroauric_acid", "chloroauric_acid", "aluminum_chloride"], elem2: null, chance: 0.15}, + }, + tick: acidTick, + }; + elements.chloroauric_acid = { + color: ["#f7bb2f", "#f5bb33", "#f5b727", "#e8ae25"], + alias: "H(AuCl₄)", + behavior: behaviors.POWDER, + category: "salts", + state: "solid", + density: 3900, + reactions: { + potassium: {elem1: "gold_coin", elem2: "potassium_salt", func: function(pixel){for(let coords of squareCoords){let x=pixel.x+coords[0],y=pixel.y+coords[1]; if(isEmpty(x,y) && !outOfBounds(x,y) && Math.random()<0.25){createPixel("hydrogen", x, y);}}}, color1: ["#574000", "#705200", "#634900", "#755600"]}, + sodium: {elem1: "gold_coin", elem2: "salt", func: function(pixel){for(let coords of squareCoords){let x=pixel.x+coords[0],y=pixel.y+coords[1]; if(isEmpty(x,y) && !outOfBounds(x,y) && Math.random()<0.25){createPixel("hydrogen", x, y);}}}, color1: ["#574000", "#705200", "#634900", "#755600"]}, + caustic_potash: {elem1: "gold_coin", elem2: "potassium_salt", func: function(pixel){for(let coords of squareCoords){let x=pixel.x+coords[0],y=pixel.y+coords[1]; if(isEmpty(x,y) && !outOfBounds(x,y) && Math.random()<0.25){createPixel("water", x, y);}}}}, + lye: {elem1: "gold_coin", elem2: "salt", func: function(pixel){for(let coords of squareCoords){let x=pixel.x+coords[0],y=pixel.y+coords[1]; if(isEmpty(x,y) && !outOfBounds(x,y) && Math.random()<0.25){createPixel("water", x, y);}}}, color1: ["#574000", "#705200", "#634900", "#755600"]}, + magnesium: {elem1: "gold_coin", elem2: "magnesium_chloride", func: function(pixel){for(let coords of squareCoords){let x=pixel.x+coords[0],y=pixel.y+coords[1]; if(isEmpty(x,y) && !outOfBounds(x,y) && Math.random()<0.25){createPixel("hydrogen", x, y);}}}, color1: ["#574000", "#705200", "#634900", "#755600"]}, + metal_scrap: {elem1: "gold_coin", elem2: "slag", func: function(pixel){for(let coords of squareCoords){let x=pixel.x+coords[0],y=pixel.y+coords[1]; if(isEmpty(x,y) && !outOfBounds(x,y) && Math.random()<0.25){createPixel("hydrogen", x, y);}}}, color1: ["#574000", "#705200", "#634900", "#755600"]}, + copper: {elem1: "copper_chloride", elem2: "gold", color2: ["#574000", "#705200", "#634900", "#755600"]} + } + }; + elements.magnesium_chloride = { + alias: "MgCl₂", + category: "salts", + behavior: behaviors.POWDER, + state: "solid", + color: ["#f2f2f2", "#f5f5f5", "#ebebeb", "#e6e6e6"], + density: 2320, + reactions: { + baking_soda: {elem1: "magnesium_carbonate", elem2: "salt"}, + lye: {elem1: "magnesium_hydroxide", elem2: "salt"}, + caustic_potash: {elem1: "magnesium_hydroxide", elem2: "potassium_salt"}, + ash: {elem1: "magnesium_carbonate", elem2: ["dust","dust",null,"potassium_salt", "charcoal"]} + }, + tempHigh: 714, + } + elements.molten_magnesium_chloride = { + alias: "MgCl₂", + density: 2150, + behavior: behaviors.MOLTEN, + state: "liquid", + color: ["#ffeb91", "#ffea8c", "#ffd480", "#ffd685", "#ffc37a"], + category: "states", + tempLow: 713, + stateLow: "magnesium_chloride", + stateHigh: ["acid_gas", "magnesium"], + tempHigh: 800, + temp: 720, + } + elements.calcium_chloride = { + flameColor: ["#fc8721", "#f58625", "#fa8d2d"], + alias: "CaCl₂", + category: "salts", + density: 2150, + behavior: behaviors.POWDER, + state: "solid", + color: ["#f2f2f2", "#f5f5f5", "#ebebeb", "#e6e6e6"], + reactions: { + baking_soda: {elem1: "limestone", elem2: "salt"}, + lye: {elem1: "slaked_lime", elem2: "salt"}, + caustic_potash: {elem1: "slaked_lime", elem2: "potassium_salt"}, + ash: {elem1: "limestone", elem2: ["dust","dust",null,"potassium_salt", "charcoal"]}, + epsom_salt: {elem1: "hardened_gypsum", elem2: "magnesium_chloride"}, + carbon_dioxide: {elem1: "limestone", elem2: "chlorine", chance: 0.001, tempMin: 60} + }, + tempHigh: 772, + stateHigh: "molten_calcium_chloride", + } + elements.molten_calcium_chloride = { + flameColor: ["#fc8721", "#f58625", "#fa8d2d"], + alias: "CaCl₂", + density: 2150, + behavior: behaviors.MOLTEN, + state: "liquid", + color: ["#ffeb91", "#ffea8c", "#ffd480", "#ffd685", "#ffc37a"], + category: "states", + tempLow: 771, + stateLow: "calcium_chloride", + reactions: { + oxygen: {elem1: "quicklime", elem2: "chlorine", chance: 0.005, tempMin: 800} + }, + temp: 780, + } + elements.sodium.reactions.carbon_dioxide = {elem1: "baking_soda", elem2: null}, elements.magnesium.reactions.carbon_dioxide = {elem1: "magnesium_carbonate", elem2:null}; + elements.acid.reactions.magnesium = {elem1: "hydrogen", elem2: "magnesium_chloride"}; + elements.magnesium_carbonate = { + alias: "MgCO₃", + category: "salts", + behavior: behaviors.POWDER, + state: "solid", + color: ["#f2f2f2", "#f5f5f5", "#ebebeb", "#e6e6e6"], + density: 2960, + reactions: { + acid: {elem1: "magnesium_chloride", elem2: ["carbon_dioxide", "foam", "seltzer", "seltzer"]}, + vinegar: {elem1: "magnesium_acetate", elem2: ["carbon_dioxide", "foam", "seltzer", "seltzer"]} + } + } + elements.magnesium_hydroxide = { + alias: "Mg(OH)₂", + category: "salts", + behavior: behaviors.POWDER, + state: "solid", + color: ["#f2f2f2", "#f5f5f5", "#ebebeb", "#e6e6e6"], + density: 2340, + reactions: { + acid: {elem1: "magnesium_chloride", elem2: "water"}, + vinegar: {elem1: "magnesium_acetate", elem2: "water"}, + }, + tempHigh: 350, + stateHigh: ["steam", "magnesium"], + } + elements.vinegar.reactions.limestone = undefined; + elements.limestone.reactions = {vinegar: {elem1: "calcium_acetate", elem2: ["carbon_dioxide", "foam", "seltzer", "seltzer"]}}; + elements.quicklime.reactions.vinegar = {elem1: "calcium_acetate", elem2: "oxygen"}; + elements.oxidized_copper.reactions.vinegar = {elem1: "copper_acetate", elem2: "water"}; + elements.slaked_lime.reactions.vinegar = {elem1: "calcium_acetate", elem2: "water"}; + elements.hardened_gypsum = { + alias: "CaSO₄•2H₂O", + color: ["#f2f2f2", "#f5f5f5", "#ebebeb", "#e6e6e6"], + category: "solids", + state: "solid", + behavior: behaviors.WALL, + density: 2320, + breakInto: "gypsum", + } + elements.gypsum = { + alias: "CaSO₄•2H₂O", + color: ["#d1d1d1", "#d6d6d6", "#cccbca", "#cfcdca", "#bfbebb"], + category: "powders", + state: "solid", + behavior: behaviors.STURDYPOWDER, + density: 2420, + tick: function(pixel){ + let chance = ((pixel.temp-18)/100*(Math.abs(pixel.temp)/40)*((pixelTicks-pixel.start)/250))*0.1; + if(Math.random(){ + elements.target_portal_in.channel = parseInt(input); + }, "Portal Channel", elements.target_portal_in.channel) + }, + tick: function(pixel){ + pixel.clickCd -= (pixel.clickCd == 0) ? 0 : 1; + if(pixel.channel == null){ + pixel.channel = elements.target_portal_in.channel; + } + if(pixel.out == null){ + for(p2 of currentPixels){ + if(p2.element == "portal_out" && p2.channel == pixel.channel){ + let adjacent = this.checkAdjacent(p2); + if(adjacent != false){ + pixel.out = p2; + break; + } + } + } + } + for(let coords of adjacentCoords){ + let x = pixel.x+coords[0], y = pixel.y+coords[1]; + if(!isEmpty(x,y) && !outOfBounds(x,y) && elements[pixelMap[x][y].element].movable && pixel.out != undefined){ + let pixel2 = getPixel(x,y); + let spots = this.checkAdjacent(pixel.out); + if(spots != false && Array.isArray(spots)){ + let num = Math.round(Math.random()*spots.length); + while(spots[num] == undefined){ + num = Math.round(Math.random()*spots.length); + } + if(pixel.targetElems.includes(pixel2.element)){ + movePixel(pixel2, spots[num][0], spots[num][1]); + } + } + } + } + }, + dataInFunc: function(pixel, value){ + if(value.includes(":")){ + let valueArr = value.split(":"); + if(Array.isArray(pixel[valueArr[0]]) && !pixel[valueArr[0]].includes(valueArr[1])){ + pixel[valueArr[0]].push(valueArr[1]); + } else { + pixel[valueArr[0]] = (Number.isInteger(pixel[valueArr[0]])) ? parseInt(valueArr[1]) : valueArr[1]; + } + } + } + } + + elements.aluminum_acetate = { + density: 1002, + color: ["#e8e8e8", "#ededed", "#e8e8e8", "#dedede"], + behavior: behaviors.POWDER, + state: "solid", + category: "salts", + alias: "Al(CH₃COO)₃", + reactions: { + acid: {elem1: "aluminum_chloride", elem2: "vinegar"}, + }, + tempHigh: 120, + stateHigh: ["vinegar", "aluminum"], + } + elements.magnesium_acetate = { + density: 1450, + color: ["#e8e8e8", "#ededed", "#e8e8e8", "#dedede"], + behavior: behaviors.POWDER, + state: "solid", + category: "salts", + alias: "Mg(CH₃COO)₂", + reactions: { + acid: {elem1: "magnesium_chloride", elem2: "vinegar"}, + baking_soda: {elem1: "magnesium_carbonate", elem2: "sodium_acetate"}, + ash: {elem1: "magnesium_carbonate", elem2: ["dust", "dust", null, "potassium_acetate"]}, + }, + tempHigh: 300, + stateHigh: ["vinegar", "magnesium_carbonate"], + } + elements.calcium_acetate = { + flameColor: ["#fc8721", "#f58625", "#fa8d2d"], + density: 1509, + color: ["#e8e8e8", "#ededed", "#e8e8e8", "#dedede"], + behavior: behaviors.POWDER, + state: "solid", + category: "salts", + alias: "Ca(CH₃COO)₂", + reactions: { + acid: {elem1: "calcium_chloride", elem2: "vinegar"}, + baking_soda: {elem1: "limestone", elem2: "sodium_acetate"}, + ash: {elem1: "limestone", elem2: ["dust", "dust", null, "potassium_acetate"]}, + epsom_salt: {elem1: "hardened_gypsum", elem2: "magnesium_acetate"}, + copper_sulfate: {elem1: "hardened_gypsum", elem2: "copper_acetate"}, + }, + tempHigh: 650, + stateHigh: ["vinegar", "limestone"] + } + elements.potassium_acetate = { + density: 1570, + fireColor: ["#e3a6ff", "#d798f5", "#d88efa"], + color: ["#e8e8e8", "#ededed", "#e8e8e8", "#dedede"], + behavior: behaviors.POWDER, + state: "solid", + category: "salts", + alias: "CH₃COOK", + reactions: { + acid: {elem1: "potassium_salt", elem2: "vinegar"}, + baking_soda: {elem1: "caustic_potash", elem2: "sodium_acetate"}, + + }, + tempHigh: 292, + } + elements.copper_acetate = { + density: 1880, + fireColor:["#4dff58", "#4ee658", "#59f054", "#54f05c"], + color: ["#00594d", "#036357", "#045661", "#044052"], + behavior: behaviors.POWDER, + state: "solid", + category: "salts", + alias: "Cu(CH₃COO)₂", + reactions: { + sodium: {elem1: "copper", elem2: "sodium_acetate"}, + potassium: {elem1: "copper", elem2: "potassium_acetate"}, + magnesium: {elem1: "copper", elem2: "magnesium_acetate"}, + calcium: {elem1: "copper", elem2: "calcium_acetate"}, + aluminum: {elem1: "copper", elem2: "aluminum_acetate"}, + wood: {stain2: "#043023"}, + }, + tempHigh: 240, + stateHigh: ["vinegar", "oxidized_copper"], + } + elements.copper_chloride = { + density: 3390, + tempHigh: 620, + stateHigh: ["copper", "chlorine"], + color: ["#59f0c2", "#57f2b2", "#53edce", "#61eddf"], + behavior: behaviors.POWDER, + state: "solid", + category: "salts", + alias: "CuCl₂", + reactions: { + sodium: {elem1: "copper", elem2: "sodium_acetate"}, + potassium: {elem1: "copper", elem2: "potassium_acetate"}, + magnesium: {elem1: "copper", elem2: "magnesium_acetate"}, + calcium: {elem1: "copper", elem2: "calcium_acetate"}, + aluminum: {elem1: "copper", elem2: "aluminum_acetate"}, + wood: {stain2: "#043023"}, + }, + properties: { + anhydrous: false + }, + fireColor: "#19abff", + tick: function(pixel){ + if(pixelTicks-pixel.start == 2 && xDown){ + pixel.anhydrous = true; + let rgb = {r: 74, g: 42, b: 10}; + let num = 6 - (Math.round(Math.random()*12)); + for(let key in rgb){ + rgb[key] += num; + } + pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; + } + let multi = (pixel.temp-70)/100; + multi = (multi < 0) ? 0 : ((multi > 1) ? 1 : multi); + if(Math.random() < 0.05*multi){ + pixel.anhydrous = true; + let rgb = {r: 74, g: 42, b: 10}; + let num = 6 - (Math.round(Math.random()*12)); + for(let key in rgb){ + rgb[key] += num; + } + pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; + } + if(pixel.anhydrous){ + let neighbors = []; + for(let coords of squareCoords){ + let x = pixel.x+coords[0], y = pixel.y+coords[1]; + neighbors[neighbors.length] = (isEmpty(x,y) && !outOfBounds(x,y)) ? "air" : (!outOfBounds(x,y)) ? pixelMap[x][y].element : undefined; + } + if(neighbors.includes("air") && pixel.temp < 50 && Math.random() < 0.00035){ + pixel.anhydrous = false; + let rgb = (Math.random() > 0.5) ? {r: 116, g: 237, b: 203} : {r: 116, g: 237, b: 231}; + let num = 6 - (Math.round(Math.random()*12)); + for(let key in rgb){ + rgb[key] += num; + } + pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; + + } else if (neighbors.includes("steam") || neighbors.includes("water") || neighbors.includes("salt_water") || neighbors.includes("sugar_water") || neighbors.includes("dirty_water") || neighbors.includes("seltzer") || neighbors.includes("pool_water") || neighbors.includes("slush")){ + pixel.anhydrous = false; + let rgb = (Math.random() > 0.5) ? {r: 116, g: 237, b: 203} : {r: 116, g: 237, b: 231}; + let num = 6 - (Math.round(Math.random()*12)); + for(let key in rgb){ + rgb[key] += num; + } + pixel.color = `rgb(${rgb.r},${rgb.g},${rgb.b})`; + } + } + } + } + elements.magnesium.reactions.water = {elem1: "magnesium_hydroxide", elem2: "hydrogen"}; + elements.sulfuric_acid = { + alias: "H₂SO₄", + category: "liquids", + ignore: elements.acid.ignore, + tick: acidTick, + color: ["#f5f5f5", "#fcfcfc", "#fffce8", "#fffce6"], + behavior: behaviors.LIQUID, + state: "liquid", + density: 1830, + reactions: { + magnesium_carbonate: {elem1: ["carbon_dioxide", "foam","foam"], elem2: "epsom_salt"}, + limestone: {elem1: ["carbon_dioxide", "foam","foam"], elem2: "hardened_gypsum"}, + quicklime: {elem1: "water", elem2: "hardened_gypsum"}, + slaked_lime: {elem1: "water", elem2: "hardened_gypsum"}, + copper_acetate: {elem1: "vinegar", elem2: "copper_sulfate"}, + copper_oxide: {elem1: "water", elem2: "copper_sulfate"}, + copper_chloride: {elem1: "acid_gas", elem2: "copper_sulfate"}, + magnesium: {elem1: "hydrogen", elem2: "epsom_salt"}, + calcium: {elem1: "hydrogen", elem2: "hardened_gypsum"}, + magnesium_chloride: {elem1: "acid_gas", elem2: "epsom_salt"}, + calcium_chloride: {elem1: "acid_gas", elem2: "hardened_gypsum"}, + calcium_acetate: {elem1: "vinegar", elem2: "hardened_gypsum"}, + }, + } + elements.platinum = { + alias: "Pt", + color: ["#cccccc", "#cfcfcf", "#d9d9d9", "#dedede"], + category: "solids", + state: "solid", + density: 21450, + behavior: behaviors.WALL, + reactions: { + aqua_regia: {elem1: "chloroplatinic_acid", elem2: "hydrogen"}, + }, + tempHigh: 1768, + stateHigh: "molten_platinum", + } + elements.molten_platinum = { + color: ["#ffd429", "#f7b228", "#ffb13d", "#ffd83d"], + behavior: behaviors.MOLTEN, + category: "states", + state: "liquid", + density: 21450, + tempLow: 1767, + stateLow: "platinum", + temp: 1770 + } + elements.chloroplatinic_acid = { + color: ["#e6842e", "#f5923b", "#f5853b", "#f57a33"], + behavior: behaviors.POWDER, + category: "salts", + state: "solid", + density: 2431, + alias: "H₂PtCl₆", + tempHigh: 500, + stateHigh: ["acid_gas", "chlorine", "platinum", "platinum"], + reactions: { + sodium: {elem1: "salt", elem2: "platinum", color2: ["#404040", "#525252", "#454545", "#2e2e2e", "#262626"]}, + potassium: {elem1: "potassium_salt", elem2: "platinum", color2: ["#404040", "#525252", "#454545", "#2e2e2e", "#262626"]}, + magnesium: {elem1: "magnesium_chloride", elem2: "platinum", color2: ["#404040", "#525252", "#454545", "#2e2e2e", "#262626"]}, + calcium: {elem1: "calcium_chloride", elem2: "platinum", color2: ["#404040", "#525252", "#454545", "#2e2e2e", "#262626"]}, + aluminum: {elem1: "aluminum_chloride", elem2: "platinum", color2: ["#404040", "#525252", "#454545", "#2e2e2e", "#262626"]}, + baking_soda: {elem1: ["salt", "foam"], elem2: "platinum", color2: ["#404040", "#525252", "#454545", "#2e2e2e", "#262626"]}, + limestone: {elem1: ["calcium_chloride", "foam"], elem2: "platinum", color2: ["#404040", "#525252", "#454545", "#2e2e2e", "#262626"]}, + caustic_potash: {elem1: "potassium_salt", elem2: "platinum", color2: ["#404040", "#525252", "#454545", "#2e2e2e", "#262626"]}, + lye: {elem1: "salt", elem2: "platinum", color2: ["#404040", "#525252", "#454545", "#2e2e2e", "#262626"]}, + ash: {elem1: ["potassium_salt", "foam", "charcoal", null, null], elem2: "platinum", color2: ["#404040", "#525252", "#454545", "#2e2e2e", "#262626"]}, + copper: {elem1: "copper_chloride", elem2: "platinum", color2: ["#404040", "#525252", "#454545", "#2e2e2e", "#262626"]} + + } + } + elements.magnet = { + keyInput: "range", + category: "machines", + range: 0, + attract: ["#1e43fc", "#1137f2", "#1c42ff", "#143bff"], + repel: ["#ff1814", "#ff1612", "#ff201c", "#ff0e0a"], + off: ["#303030", "#454545", "#3b3b3b", "#3d3d3d"], + color: ["#303030", "#454545", "#3b3b3b", "#3d3d3d"], + properties: { + range: null, + dragPixels: [], + clickCd: 0, + targetElems: [], + mode: 0, + }, + onSelect: function(){ + promptInput("Enter the range of this machine:", (input)=>{elements.magnet.range = parseInt(input);}, "Magnet Range", elements.magnet.range); + }, + onClicked: function(pixel, elem){ + if(pixel.targetElems.includes(elem) && elem != "unknown" && pixel.clickCd <= 0){ + pixel.targetElems.splice(pixel.targetElems.indexOf(elem), 1); + pixel.clickCd = 20; + } else if (elem != "unknown" && pixel.clickCd <= 0) { + pixel.targetElems.push(elem); + pixel.clickCd = 20; + } + if(elem == "unknown" && pixel.clickCd <= 0){ + switch(pixel.mode){ + case 0: + pixel.mode = 1; //attract + pixel.color = elements.magnet.attract[Math.round(Math.random()*elements.magnet.attract.length)]; + while(pixel.color == undefined){ + pixel.color = elements.magnet.attract[Math.round(Math.random()*elements.magnet.attract.length)]; + } + break; + case 1: + pixel.mode = 2; //repel + pixel.color = elements.magnet.repel[Math.round(Math.random()*elements.magnet.repel.length)]; + while(pixel.color == undefined){ + pixel.color = elements.magnet.repel[Math.round(Math.random()*elements.magnet.repel.length)]; + } + break; + case 2: + pixel.mode = 0; //off + pixel.color = elements.magnet.off[Math.round(Math.random()*elements.magnet.off.length)]; + while(pixel.color == undefined){ + pixel.color = elements.magnet.off[Math.round(Math.random()*elements.magnet.off.length)]; + } + break; + default: + pixel.mode = 0; + pixel.color = elements.magnet.off[Math.round(Math.random()*elements.magnet.off.length)]; + while(pixel.color == undefined){ + pixel.color = elements.magnet.off[Math.round(Math.random()*elements.magnet.off.length)]; + } + break; + }; + pixel.clickCd = 20; + } + }, + tick: function(pixel){ + pixel.clickCd -= (pixel.clickCd == 0) ? 0 : 1; + if(pixel.range == null){ + pixel.range = elements.magnet.range; + }; + let range = mouseRange(pixel.x, pixel.y, pixel.range); + for(let p of pixel.dragPixels){ + if(!p.inRange(range) || pixel.mode == 0 || !currentPixels.includes(p) || !pixel.targetElems.includes(p.element)){ + p.drag = false; + pixel.dragPixels.splice(pixel.dragPixels.indexOf(p), 1); + } else { + switch(pixel.mode){ + case 1: + let dX = pixel.x-p.x, dY = pixel.y-p.y; + tryMove(p, p.x+Math.sign(dX), p.y+Math.sign(dY), null, true); + break; + case 2: + let dx = p.x-pixel.x, dy = p.y-pixel.y; + tryMove(p, p.x+Math.sign(dx), p.y+Math.sign(dy), null, true); + break; + } + } + }; + for(let coords of range){ + let p2 = getPixel(coords[0], coords[1]); + if(p2 != null && pixel.targetElems.includes(p2.element) && pixel.mode != 0 && !pixel.dragPixels.includes(p2)){ + p2.drag = true; + pixel.dragPixels.push(p2); + } + } + }, + dataInFunc: function(pixel, value){ + if(value.includes(":")){ + let valueArr = value.split(":"); + if(Array.isArray(elements[pixel.element].properties[valueArr[0]]) && !pixel[valueArr[0]].includes(valueArr[1])){ + pixel[valueArr[0]].push(valueArr[1]); + } else if(!Array.isArray(elements[pixel.element].properties[valueArr[0]])){ + pixel[valueArr[0]] = (Number.isInteger(pixel[valueArr[0]])) ? parseInt(valueArr[1]) : valueArr[1]; + } + } + } + } + elements.liquid_sulfur_trioxide = { + density: 1920, + color: ["#fffdc7", "#fffdcc", "#f7f6da", "#f5f3bc"], + behavior: behaviors.LIQUID, + state: "liquid", + category: "states", + reactions: { + plant: {elem1: null, elem2: "dead_plant"}, + fruit_leaves: {elem1: null, elem2: "dead_plant"}, + fruit_branch: {elem1: null, elem2: "wood"}, + tree_branch: {elem1: null, elem2: "wood"}, + fruit_vine: {elem1: null, elem2: "dead_plant"}, + low_fruit_vine: {elem1: null, elem2: "dead_plant"}, + water: {elem1: null, elem2:"sulfuric_acid"}, + quicklime: {elem1: null, elem2: "hardened_gypsum"}, + }, + tick: function(pixel){ + for(let coords of adjacentCoords){ + let x = pixel.x+coords[0], y = pixel.y+coords[1]; + let p2 = getPixel(x,y); + if(p2 != null && eLists.ANIMAL.includes(p2.element)){ + if(p2.element == "rat"){ + deletePixel(pixel.x,pixel.y); + changePixel(p2, "rotten_meat"); + } else { + deletePixel(pixel.x,pixel.y); + changePixel(p2, "dead_bug"); + } + } else if (p2 != null && eLists.CLEANANIMAL.includes(p2.element)){ + if(["frog", "tadpole"].includes(p2.element)){ + deletePixel(pixel.x,pixel.y); + changePixel(p2, "rotten_meat"); + } else { + deletePixel(pixel.x,pixel.y); + changePixel(p2, "dead_bug"); + } + } else if (p2 != null && eLists.SEEDS.includes(p2.element)){ + deletePixel(pixel.x,pixel.y); + changePixel(p2, "dead_plant"); + } + } + }, + tempLow: 16, + stateLow: "sulfur_trioxide", + } + elements.sulfur_trioxide = { + temp: 16, + density: 1920, + color: ["#fffdc7", "#fffdcc", "#f7f6da", "#f5f3bc"], + behavior: behaviors.POWDER, + state: "solid", + category: "salts", + reactions: { + plant: {elem1: null, elem2: "dead_plant"}, + fruit_leaves: {elem1: null, elem2: "dead_plant"}, + fruit_branch: {elem1: null, elem2: "wood"}, + tree_branch: {elem1: null, elem2: "wood"}, + fruit_vine: {elem1: null, elem2: "dead_plant"}, + low_fruit_vine: {elem1: null, elem2: "dead_plant"}, + water: {elem1: null, elem2:"sulfuric_acid"}, + quicklime: {elem1: null, elem2: "hardened_gypsum"}, + grass: {elem1: null, elem2: "dead_plant"}, + vine: {elem1: null, elem2: "dead_plant"}, + evergreen: {elem1: null, elem2: "dead_plant"}, + }, + tick: function(pixel){ + for(let coords of adjacentCoords){ + let x = pixel.x+coords[0], y = pixel.y+coords[1]; + let p2 = getPixel(x,y); + if(p2 != null && eLists.ANIMAL.includes(p2.element)){ + if(p2.element == "rat"){ + deletePixel(pixel.x,pixel.y); + changePixel(p2, "rotten_meat"); + } else { + deletePixel(pixel.x,pixel.y); + changePixel(p2, "dead_bug"); + } + } else if (p2 != null && eLists.CLEANANIMAL.includes(p2.element)){ + if(["frog", "tadpole"].includes(p2.element)){ + deletePixel(pixel.x,pixel.y); + changePixel(p2, "rotten_meat"); + } else { + deletePixel(pixel.x,pixel.y); + changePixel(p2, "dead_bug"); + } + } else if (p2 != null && eLists.SEEDS.includes(p2.element)){ + deletePixel(pixel.x,pixel.y); + changePixel(p2, "dead_plant"); + } + } + }, + tempHigh: 17, + stateHigh: "liquid_sulfur_trioxide", + } + elements.sulfur.burnInto = "liquid_sulfur_trioxide", elements.molten_sulfur.burnInto = "liquid_sulfur_trioxide", elements.sulfur_gas.burnInto = "liquid_sulfur_trioxide"; + + /*Inspired by the bismuth element from nousersthings.js*/ + elements.bismuth = { + color: ["#d4d4d4", "#d6d6d6", "#dedede", "#d9d9d9", "#dbdbd5"], + tempHigh: 271, + stateHigh: "molten_bismuth", + category: "solids", + state: "solid", + density: 9807, + } + + elements.molten_bismuth = { + color: ["#d4d4d4", "#d6d6d6", "#dedede", "#d9d9d9", "#dbdbd5"], + category: "states", + state: "liquid", + behavior: behaviors.MOLTEN, + tick: function(pixel){ + if(pixel.temp > 250 && pixel.temp < 270){ + chance = 0.000075-(Math.min((pixel.temp-250)/20, 0)*0.00005); + if(Math.random() 0){ + let lowestIndex = positions.indexOf(Math.min(...positions)); + let newPos = positions[lowestIndex]+1; + let coords = coordsArr[lowestIndex], colors = pixelMap[coords[0]][coords[1]].colorArr || [ + {r:255, g:127, b:0}, + {r: 255, g:200, b:0}, + {r: 255, g:255, b:0}, + {r:0, g:255, b:0}, + {r:0, g:255, b:255}, + {r:0, g:0, b:255}, + {r:255, g:0, b:255}, + {r:255, g:0, b:70}, + {r:255, g:105, b:0}, + ]; + let current = ((newPos%11)/10)*colors.length; + let currentIndex = Math.floor(current); + let d = current-currentIndex; + let c1 = colors[currentIndex%colors.length], c2 = colors[(currentIndex+1)%colors.length]; + changePixel(pixel, "bismuth"); + pixel.crystallized = true; + pixel.position = newPos; + let num = 207 + (Math.round(Math.random()*12)-6); + let rgb = getRGB(interpolateRgb(c1, c2, d)); + rgb.r = Math.round(rgb.r*(num/255)), rgb.g = Math.round(rgb.g*(num/255)), rgb.b = Math.round(rgb.b*(num/255)); + pixel.color = normalize(rgb); + } + } + + } + }, + tempLow: 250, + stateLow: "bismuth", + temp: 270, + }; +}; diff --git a/mods/orchidslibrary.js b/mods/orchidslibrary.js new file mode 100644 index 00000000..678803ed --- /dev/null +++ b/mods/orchidslibrary.js @@ -0,0 +1,70 @@ +/* +Version 1.0.0 +*/ +function noiseify(color, range){ + if(color.startsWith("#")){ + color = hexToRGB(color); + } else { + color = getRGB(color); + } + let num = Math.round(Math.random()*(range*2))-range; + for(let value in color){ + color[value] += num; + } + return `rgb(${color.r},${color.g},${color.b})`; +} + +let is2d = (arr)=>{ + return arr.some(item => Array.isArray(item)); +} + +function colorMix(p1, p2, bias = 0.5){ + c1 = p1.color; + p1.color = interpolateRgb(getRGB(p1.color), getRGB(p2.color), bias); + p2.color = interpolateRgb(getRGB(c1), getRGB(p2.color), bias); +} + +function interpolateRgb(rgb1, rgb2, ratio = 0.5) { + const interpolatedRgb = { + r: Math.round(rgb1.r + (rgb2.r - rgb1.r) * ratio), + g: Math.round(rgb1.g + (rgb2.g - rgb1.g) * ratio), + b: Math.round(rgb1.b + (rgb2.b - rgb1.b) * ratio), + }; + return normalize(interpolatedRgb); +} + +function getRGB(rgb){ + if(rgb.startsWith("rgb(")){ + let rgb2 = rgb.replace(")", "").replace("rgb(", "").replace(/,/g, "r").split("r") + return { r: parseInt(rgb2[0]), g: parseInt(rgb2[1]), b: parseInt(rgb2[2]) }; + } else { + return hexToRGB(rgb2); + } +} +function pixelToggle(pixel, multi = {r:1,g:1,b:1}){ + if(pixel.toggle != undefined){ + pixel.toggle = !pixel.toggle; + let rgb; + if(Array.isArray(elements[pixel.element].color)){ + let elemColor = elements[pixel.element].color[Math.round(Math.random()*elements[pixel.element].color.length)]; + rgb = hexToRGB(elemColor) || getRGB(elemColor); + } else { + let elemColor = elements[pixel.element].color; + rgb = hexToRGB(elemColor) || getRGB(elemColor); + } + let num = 5 - Math.round(Math.random()*10); + if(pixel.toggle){ + for(let key in rgb){ + rgb[key] += (100*multi[key]); + rgb[key] = Math.round(Math.max(Math.min(rgb[key], 255), 0)); + } + pixel.color = `rgb(${rgb.r+num},${rgb.g+num},${rgb.b+num})`; + } + else { + pixel.color = `rgb(${rgb.r+num},${rgb.g+num},${rgb.b+num})`; + } + } +} +function normalize(obj){ + return `rgb(${obj.r},${obj.g},${obj.b})`; +} diff --git a/mods/plants.js b/mods/plants.js index 807c3f46..aca2cb25 100644 --- a/mods/plants.js +++ b/mods/plants.js @@ -1,44 +1,28 @@ /* -Version 2.2.0 +Version 2.2.1 */ -function noiseify(color, range){ - if(color.startsWith("#")){ - color = hexToRGB(color); - } else { - color = getRGB(color); +let plants; +if(!enabledMods.includes("/mods/orchidslibrary.js")){ + let continueWithout = confirm("Missing dependency for plants.js: \"orchidslibrary.js\". Continue without? (cancel will add mod and refresh the page)"); + if(!continueWithout){ + addMod("/mods/orchidslibrary.js", true); + window.location.reload(); } - let num = Math.round(Math.random()*(range*2))-range; - for(let value in color){ - color[value] += num; +} else { + let is2d = (arr)=>{ + return arr.some(item => Array.isArray(item)); } - return `rgb(${color.r},${color.g},${color.b})`; -} -let is2d = (arr)=>{ - return arr.some(item => Array.isArray(item)); -} -class growInterval { - constructor(seedPixel, pattern, basePos, c = 0.025, dieAfter = undefined, fruit = undefined, elems = undefined){ - let currentLength = 0; - let chance = c; - let pos = basePos; - let interval = setInterval(()=>{ - if(currentLength == pattern.length || seedPixel == undefined){ - clearInterval(interval); - } else { - let x = pos[0]+pattern[currentLength][0], y = pos[1]+pattern[currentLength][1]; - if(Math.random(){ + if(currentLength == pattern.length || seedPixel == undefined){ + clearInterval(interval); + } else { + let x = pos[0]+pattern[currentLength][0], y = pos[1]+pattern[currentLength][1]; + if(Math.random() exclude[0] && angle < exclude[1]){ - angle = min+(Math.random()*(max-min)); + }, 1000/tps); + this.interval = interval; } } - let res = []; - let num = (angle < 270) ? -0.5 : 0.5; - for(let i = 0; i < length; i++){ - let tempAngle = (angle+(num*i))*(Math.PI/180); - let dX = Math.cos(tempAngle)*i, dY = Math.sin(tempAngle)*i; - res.push([Math.floor(dX), Math.floor(dY)]); + let flowerExclude = ["pineapple"]; + let vineGrow = ["wood", "rock_wall", "straw", "wall", "ewall", "bush_cane", "bush_base", "fruit_branch"]; + plants = { + tree: [], + vine: ["grape", "tomato"], + bush: [], + other: ["pineapple", "watermelon", "banana", "onion"], + includes: function(target){ + for(item in this){ + if(this[item] && Array.isArray(this[item]) && this[item].includes(target)){return true;} + } + return false; + } } - return res; - }, - palm: function(length, min, max, exclude = null){ + let growthPatterns = { + pineapple1: [[-1,-1],[-2,-2],[1,-1],[2,-2],[0,-1],[0,-2],[0,-3],[0,-4],[0,-5],[0,-6],[-1,-6],[1,-6],[-1,-5],[1,-5],[-1,-4],[1,-4],[-1,-3],[1,-3],[0,-7],[-1,-8],[1,-8]], + pineapple2: [[[-1,-1],[1,-1]],[[-2,-2],[2,-2]], [0,-1],[0,-2],[0,-3],[0,-4],[0,-5],[0,-6],[[-1,-6],[1,-6]],[[-1,-5],[1,-5]],[[-1,-4],[1,-4]],[[-1,-3],[1,-3]],[[-1,-2],[1,-2]],[0,-7],[-1,-8],[1,-8]], + pineapple3: [[-1,0],[-2,-1],[-3,-2],[1,0],[2,-1],[-4,-3],[3,-2],[4,-3],[-5,-4],[5,-4],[0,-1],[0,-2],[0,-3],[0,-4],[0,-5],[0,-6],[0,-7],[0,-8],[0,-9],[0,-10],[-1,-10],[1,-10],[-1,-9],[1,-9],[-1,-8],[1,-8],[-1,-7],[1,-7],[-1,-6],[1,-6],[-1,-5],[1,-5],[-1,-4],[1,-4],[-2,-9],[2,-9],[-2,-8],[2,-8],[2,-7],[-2,-7],[-2,-6],[2,-6],[2,-5],[-2,-5],[0,-11],[-1,-12],[1,-12],[2,-13],[-2,-13]], + melon_2x2: [[0,-1],[1,-2],[1,-1],[[1,0],[2,-1]],[2,0]], + melon_3x3: [[0,-1],[0,-2],[1,-3],[2,-3],[2,-2],[[1,-2],[1,-1]],[2,-1],[2,0],[1,0],[3,0],[3,-1],[3,-2]], + melon_4x4: [[0,-1],[0,-2],[0,-3],[1,-4],[2,-4],[3,-4],[3,-3],[2,-3],[2,-2],[3,-2],[1,-2],[1,-3],[1,-1],[2,-1],[3,-1],[1,0],[2,0],[3,0],[4,0],[4,-1],[4,-2],[4,-3]], + melon_5x5: [[0,-1],[0,-2],[0,-3],[0,-4],[1,-5],[2,-5],[3,-5],[3,-4],[2,-4],[3,-3],[4,-4],[4,-3],[2,-3],[1,-4],[5,-4],[3,-2],[2,-2],[4,-2],[5,-2],[1,-2],[1,-3],[5,-3],[1,-1],[2,-1],[3,-1],[4,-1],[5,-1],[5,0],[4,0],[3,0],[2,0],[1,0]], + palm_1: [[1,-1],[2,-2],[3,-2],[4,-2],[5,-1]], + palm_2: [[1,-1],[2,-2],[3,-2],[4,-3],[5,-3],[6,-3],[7,-2]], + palm_3: [[1,-1],[2,-2],[3,-3],[4,-3],[5,-4],[6,-4],[7,-4],[8,-3],[9,-2]] , + palm_4: [[1,-1],[2,-1],[3,-2],[4,-2],[5,-3],[6,-3],[7,-3],[8,-3],[9,-2]], + "palm_5-1":[[0,-1],[0,-2],[1,-2],[0,-3],[-1,-3],[-2,-3],[2,-2],[3,-2],[4,-2],[5,-2],[-3,-3],[-4,-3],[-5,-3],[6,-2],[-6,-2],[-7,-2],[7,-1],[8,-1],[-8,-2],[-9,-1],[9,0],[0,-4],[1,-4],[1,-3],[2,-3],[-2,-4],[-3,-5],[-4,-5],[3,-4],[4,-4],[5,-5],[6,-5],[7,-5],[-5,-6],[-6,-6],[-7,-6],[-8,-5],[8,-4],[1,-5],[1,-6],[-1,-5],[-1,-6],[-2,-7],[-2,-8],[1,-7],[2,-8],[2,-9],[-3,-9],[-4,-10],[3,-10],[-1,-1],[-2,-1],[-2,0],[-1,0],[-1,1],[-2,1],[1,1],[1,0],[1,-1],[2,-1],[2,0],[2,1]], + "palm_5-2": [[-1,-1],[1,-1],[-2,-1],[2,-1],[-3,-2],[3,-2],[-4,-2],[4,-2],[5,-3],[-5,-3],[-6,-3],[6,-3],[7,-3],[-7,-3],[8,-4],[9,-4],[10,-4],[-8,-2],[11,-3],[0,-1],[1,-2],[-1,-2],[-2,-3],[2,-3],[3,-4],[4,-4],[-3,-4],[-4,-5],[-5,-5],[5,-5],[6,-5],[-6,-6],[-7,-6],[-8,-6],[7,-6],[8,-6],[9,-6],[10,-6],[-9,-5],[0,-3],[0,-2],[1,-4],[1,-5],[-1,-4],[-1,-5],[-2,-6],[-2,-7],[2,-6],[3,-7],[4,-8],[-3,-8],[-4,-9],[5,-9],[6,-9],[-5,-10],[-6,-10],[-7,-9],[7,-8],[1,0],[2,0],[3,0],[0,0],[-1,0],[-2,0],[-2,1],[-3,1],[-3,0],[-1,1],[1,1],[2,1],[3,1],[3,2],[2,2],[1,2],[-1,2],[-2,2],[-3,2],[-3,3],[-2,3],[-1,3],[1,3],[2,3],[3,3]], + "coconut_5-1":[[0,-1],[-1,-1],[-2,-1],[-3,-1],[1,-1],[2,-1],[3,-2],[4,-2],[-4,-2],[-5,-2],[-6,-2],[-7,-2],[5,-2],[6,-2],[7,-1],[-8,-1],[0,-2],[0,-3],[-1,-3],[-2,-4],[1,-2],[2,-3],[3,-4],[4,-4],[5,-4],[6,-4],[7,-4],[-3,-5],[-4,-5],[-5,-5],[-6,-5],[-7,-4],[8,-3],[0,-4],[0,-5],[1,-6],[1,-7],[2,-8],[3,-9],[4,-10],[5,-10],[-1,0],[-2,0],[-1,1],[-2,1],[-1,2],[-3,0],[-4,-1],[1,0],[1,1],[1,2],[2,0],[2,1],[3,-1],[3,0],[0,0]], + "coconut_5-2":[[0,-1],[-1,-1],[-2,-1],[-3,-2],[-4,-2],[-5,-2],[-6,-2],[-7,-1],[1,-1],[2,-2],[3,-2],[4,-3],[5,-3],[6,-3],[7,-2],[8,-2],[9,-1],[0,-2],[0,-3],[1,-3],[2,-4],[3,-5],[4,-5],[5,-6],[6,-6],[7,-6],[8,-5],[-1,-3],[-2,-4],[-3,-5],[-4,-5],[-5,-6],[-6,-6],[-7,-6],[-8,-5],[-9,-4],[0,-4],[0,-5],[1,-6],[1,-7],[2,-8],[2,-9],[3,-10],[4,-11],[-1,0],[1,0],[2,0],[2,-1],[-2,0],[-1,1],[-2,1],[-3,1],[1,1],[2,1],[3,0],[4,0],[-3,-1],[-3,0],[-4,0],[-4,1],[3,1],[4,1],[3,-1],[-1,2],[-2,2],[-3,2],[1,2],[2,2],[3,2]], + blade: function(length, min, max, exclude = null){ let angle = min+(Math.random()*(max-min)); if(exclude != null){ while(angle > exclude[0] && angle < exclude[1]){ @@ -109,423 +89,555 @@ let growthPatterns = { } } let res = []; - let num = (angle < 270) ? -3 : 3; + let num = (angle < 270) ? -0.5 : 0.5; for(let i = 0; i < length; i++){ let tempAngle = (angle+(num*i))*(Math.PI/180); let dX = Math.cos(tempAngle)*i, dY = Math.sin(tempAngle)*i; res.push([Math.floor(dX), Math.floor(dY)]); } return res; - }, - palm_bloom: function(){ - let res = []; - - let width = 3+Math.round(Math.random()*2); - let length = 5+(width-3); - for(let i = 1; i < length; i++){ - for(let ii = 1; ii < width; ii++){ - res.push([-ii,i]); - res.push([ii,i]); - } - } - return res; - }, - stalk: function(height){ - let res = []; - for(let i = 1; i <= height; i++){ - res.push([0, -i]); - } - return res; - }, -}; -let growthElems = { - pineapple1: ["fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","fruit_leaves","fruit_leaves","fruit_leaves"], - pineapple2: ["fruit_leaves","fruit_leaves","fruit_leaves","flower","flower","flower","flower","flower","flower","flower","flower","flower","fruit_leaves","fruit_leaves","fruit_leaves"], - pineapple3: ["fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves"], - melon_2x2: ["fruit_leaves","fruit_leaves","flower","flower","flower","flower"], - melon_3x3: ["fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","flower","flower","flower","flower","flower","flower","flower","flower","flower"], - melon_4x4: ["fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower"], - melon_5x5: ["fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower"], - palm_1: ["fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves"], - palm_2: ["fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves"], - palm_3: ["fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves"], - palm_4: ["fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves"], - "palm_5-1": ["fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower"], - "palm_5-2":["fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","flower","flower","flower","fruit_leaves","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower"], - "coconut_5-1": ["fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","fruit_leaves"], - "coconut_5-2": ["fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower"], -} -let ethyleneChance = { - tomato: 0.000055, - orange: 0.000005, - strawberry: 0.000005, - grape: 0.000005, - blueberry: 0.000005, - apple: 0.00005, - avocado: 0.00005, - plum: 0.00005, - peach: 0.00005, - apricot: 0.00005, - pear: 0.00005, - mango: 0.000005, - kiwi: 0.000005, - lemon: 0.000005, - raspberry: 0.000005, - blackberry: 0.000005, - get: function(name){ - return this[name] || 0.00000035; - } -} -elements.tomato.properties = { - type: "fruit", - fruit: "tomato", -}; -elements.grape.properties = { - type: "fruit", - fruit: "grape", -}; -class vineSeed { - category = "life"; - behavior = behaviors.POWDER; - tick = function(pixel){ - if(pixel.age > 40){ - changePixel(pixel, (elements[pixel.element].low) ? "low_fruit_vine" : "fruit_vine"); - } - pixel.age += 1; - }; - properties = { - age: 0, - }; - constructor(fruit, color, low = false){ - this.properties.fruit = fruit; - this.color = color; - this.low = low; - }; -} - -class treeSeed { - properties = { - age: 0, - fruit: "", - }; - tick = function(pixel) { - if (isEmpty(pixel.x,pixel.y+1)) { - movePixel(pixel,pixel.x,pixel.y+1); - } - else { - if (Math.random() < 0.02 && pixel.age > 50 && pixel.temp < 100) { - if (!outOfBounds(pixel.x,pixel.y+1)) { - var dirtPixel = pixelMap[pixel.x][pixel.y+1]; - if (["dirt", "mud", "sand", "wet_sand", "clay_soil", "mycelium"].includes(dirtPixel.element)) { - changePixel(dirtPixel,"root"); - } - } - if (isEmpty(pixel.x,pixel.y-1)) { - movePixel(pixel,pixel.x,pixel.y-1); - createPixel(Math.random() > 0.5 ? "wood" : "fruit_branch",pixel.x,pixel.y+1); - if (pixelMap[pixel.x][pixel.y+1].element == "fruit_branch" || pixelMap[pixel.x][pixel.y+1].element == "fruit_leaves" || pixelMap[pixel.x][pixel.y+1].element == "wood"){ - pixelMap[pixel.x][pixel.y+1].fruit = pixel.fruit; - pixelMap[pixel.x][pixel.y+1].age = pixel.age; - } + }, + palm: function(length, min, max, exclude = null){ + let angle = min+(Math.random()*(max-min)); + if(exclude != null){ + while(angle > exclude[0] && angle < exclude[1]){ + angle = min+(Math.random()*(max-min)); } } - else if (pixel.age > 1000) { - changePixel(pixel,"wood"); + let res = []; + let num = (angle < 270) ? -3 : 3; + for(let i = 0; i < length; i++){ + let tempAngle = (angle+(num*i))*(Math.PI/180); + let dX = Math.cos(tempAngle)*i, dY = Math.sin(tempAngle)*i; + res.push([Math.floor(dX), Math.floor(dY)]); } - pixel.age++; - } - doDefaults(pixel); + return res; + }, + palm_bloom: function(){ + let res = []; + + let width = 3+Math.round(Math.random()*2); + let length = 5+(width-3); + for(let i = 1; i < length; i++){ + for(let ii = 1; ii < width; ii++){ + res.push([-ii,i]); + res.push([ii,i]); + } + } + return res; + }, + stalk: function(height){ + let res = []; + for(let i = 1; i <= height; i++){ + res.push([0, -i]); + } + return res; + }, }; - breakInto = ["sawdust", "sap"]; - burnInto = ["charcoal", "sap", "ember"]; - tempHigh = 100; - stateHigh = "dead_plant"; - tempLow = -40; - stateLow = "frozen_plant"; - burn = 40; - burnTime = 50; - category = "life"; - seed = true; - constructor(fruit, colours){ - this.properties.fruit = fruit; - this.color = colours; + let growthElems = { + pineapple1: ["fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","fruit_leaves","fruit_leaves","fruit_leaves"], + pineapple2: ["fruit_leaves","fruit_leaves","fruit_leaves","flower","flower","flower","flower","flower","flower","flower","flower","flower","fruit_leaves","fruit_leaves","fruit_leaves"], + pineapple3: ["fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves"], + melon_2x2: ["fruit_leaves","fruit_leaves","flower","flower","flower","flower"], + melon_3x3: ["fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","flower","flower","flower","flower","flower","flower","flower","flower","flower"], + melon_4x4: ["fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower"], + melon_5x5: ["fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower"], + palm_1: ["fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves"], + palm_2: ["fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves"], + palm_3: ["fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves"], + palm_4: ["fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves"], + "palm_5-1": ["fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower"], + "palm_5-2":["fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","flower","flower","flower","fruit_leaves","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower"], + "coconut_5-1": ["fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","fruit_leaves"], + "coconut_5-2": ["fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","fruit_leaves","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower","flower"], } -} - -class fruit { - category = "food"; - behavior = [["XX", "ST:fruit_leaves AND ST:fruit_branch AND ST:wood", "XX"],["ST:fruit_leaves AND ST:fruit_branch AND ST:wood", "XX", "ST:fruit_leaves AND ST:fruit_branch AND ST:wood"],["M2", "ST:fruit_leaves AND ST:fruit_branch AND ST:wood AND M1", "M2"]]; - breakInto = "juice"; - properties = { + let ethyleneChance = { + tomato: 0.000055, + orange: 0.000005, + strawberry: 0.000005, + grape: 0.000005, + blueberry: 0.000005, + apple: 0.00005, + avocado: 0.00005, + plum: 0.00005, + peach: 0.00005, + apricot: 0.00005, + pear: 0.00005, + mango: 0.000005, + kiwi: 0.000005, + lemon: 0.000005, + raspberry: 0.000005, + blackberry: 0.000005, + get: function(name){ + return this[name] || 0.00000035; + } + } + elements.tomato.properties = { type: "fruit", + fruit: "tomato", }; - isFood = true; - constructor(name, colour, jColour, type = "tree", sColour = false, extract = false, low = false){ - this.properties.fruit = name; - this.color = colour; - this.breakIntoColor = jColour; - this.extract = (extract == false) ? undefined : extract; - if(type == "bush"){ - this.behavior = [["XX", "ST:bush_cane", "XX"],["ST:bush_cane", "XX", "ST:bush_cane"],["M2", "ST:bush_cane AND M1", "M2"]]; - } else if (type == "vine"){ - this.behavior = behaviors.VINEFRUIT; - } - plants[type].push(name); - if(sColour != false){ - if(type == "bush"){ - elements[`${name}_seed`] = new bushSeed(name, sColour); - } else if (type == "vine"){ - elements[`${name}_seed`] = new vineSeed(name, sColour, low); - } else { - elements[`${name}_seed`] = new treeSeed(name, sColour); - } - } + elements.grape.properties = { + type: "fruit", + fruit: "grape", }; - tick = function(pixel){ - let chance = ethyleneChance.get(pixel.fruit); - for(let i = 0; i < squareCoords.length; i++){ - let x = pixel.x+squareCoords[i][0], y = pixel.y+squareCoords[i][1]; - if(isEmpty(x,y) && !outOfBounds(x,y) && Math.random() < chance){ - createPixel("ethylene", x, y); - } - } - } -} -elements.tomato.tick = function(pixel){ - let chance = ethyleneChance.get(pixel.fruit); - for(let i = 0; i < squareCoords.length; i++){ - let x = pixel.x+squareCoords[i][0], y = pixel.y+squareCoords[i][1]; - if(isEmpty(x,y) && !outOfBounds(x,y) && Math.random() < chance){ - createPixel("ethylene", x, y); - } - } -} -elements.grape.tick = function(pixel){ - let chance = ethyleneChance.get(pixel.fruit); - for(let i = 0; i < squareCoords.length; i++){ - let x = pixel.x+squareCoords[i][0], y = pixel.y+squareCoords[i][1]; - if(isEmpty(x,y) && !outOfBounds(x,y) && Math.random() < chance){ - createPixel("ethylene", x, y); - } - } -} -elements.wood.properties = {age: 0, fruit: ""}; - -elements.fruit_branch = { - color: elements.tree_branch.color, - behavior: [ - "XX|XX|XX", - "XX|XX|XX", - "XX|XX|XX", - ], - tempHigh: 100, - stateHigh: "wood", - tempLow: -30, - stateLow: "wood", - category: "life", - burn: 40, - burnTime: 50, - burnInto: ["sap","ember","charcoal"], - hidden: true, - state: "solid", - density: 1500, - hardness: 0.15, - breakInto: ["sap","sawdust"], - seed: "apple_seed", - properties: { - age: 0, - fruit: "", - }, - tick: function(pixel){ - let pos = [[-1, -1], [0, -1], [1, -1]]; - for(let i = 0; i < pos.length; i++){ - let x = pixel.x+pos[i][0], y = pixel.y+pos[i][1]; - if(isEmpty(x,y) && !outOfBounds(x,y)){ - if(Math.random() < 0.035){ - let elemArr = (pos[i][0] == 0) ? ["fruit_leaves","fruit_leaves","fruit_leaves","fruit_branch","fruit_branch"] : ["fruit_branch", "fruit_branch", "fruit_leaves", "fruit_leaves", "wood"]; - createPixel(elemArr[Math.round(Math.random()*elemArr.length)], x, y); + class vineSeed { + category = "life"; + behavior = behaviors.POWDER; + tick = function(pixel){ + if(pixel.age > 40){ + changePixel(pixel, (elements[pixel.element].low) ? "low_fruit_vine" : "fruit_vine"); + } + pixel.age += 1; + }; + properties = { + age: 0, + }; + constructor(fruit, color, low = false){ + this.properties.fruit = fruit; + this.color = color; + this.low = low; + }; + } + + class treeSeed { + properties = { + age: 0, + fruit: "", + }; + tick = function(pixel) { + if (isEmpty(pixel.x,pixel.y+1)) { + movePixel(pixel,pixel.x,pixel.y+1); + } + else { + if (Math.random() < 0.02 && pixel.age > 50 && pixel.temp < 100) { + if (!outOfBounds(pixel.x,pixel.y+1)) { + var dirtPixel = pixelMap[pixel.x][pixel.y+1]; + if (["dirt", "mud", "sand", "wet_sand", "clay_soil", "mycelium"].includes(dirtPixel.element)) { + changePixel(dirtPixel,"root"); + } + } + if (isEmpty(pixel.x,pixel.y-1)) { + movePixel(pixel,pixel.x,pixel.y-1); + createPixel(Math.random() > 0.5 ? "wood" : "fruit_branch",pixel.x,pixel.y+1); + if (pixelMap[pixel.x][pixel.y+1].element == "fruit_branch" || pixelMap[pixel.x][pixel.y+1].element == "fruit_leaves" || pixelMap[pixel.x][pixel.y+1].element == "wood"){ + pixelMap[pixel.x][pixel.y+1].fruit = pixel.fruit; + pixelMap[pixel.x][pixel.y+1].age = pixel.age; + } + } + } + else if (pixel.age > 1000) { + changePixel(pixel,"wood"); + } + pixel.age++; + } + doDefaults(pixel); + }; + breakInto = ["sawdust", "sap"]; + burnInto = ["charcoal", "sap", "ember"]; + tempHigh = 100; + stateHigh = "dead_plant"; + tempLow = -40; + stateLow = "frozen_plant"; + burn = 40; + burnTime = 50; + category = "life"; + seed = true; + constructor(fruit, colours){ + this.properties.fruit = fruit; + this.color = colours; } } - } - for(var i = 0; i < adjacentCoords.length; i++){ - let x = pixel.x+adjacentCoords[i][0]; - let y = pixel.y+adjacentCoords[i][1]; - if(isEmpty(x, y) || outOfBounds(x, y)) { continue; } - let pixel2 = pixelMap[x][y]; - if(pixel2.element == "fruit_branch" || pixel2.element == "fruit_leaves" || pixel2.element == "wood"){ - if(pixel.fruit != "" && pixel2.fruit == ""){ - pixel2.fruit = pixel.fruit; - } else if (pixel.fruit == "" && pixel2.fruit != ""){ - pixel.fruit = pixel2.fruit; + + class fruit { + category = "food"; + behavior = [["XX", "ST:fruit_leaves AND ST:fruit_branch AND ST:wood", "XX"],["ST:fruit_leaves AND ST:fruit_branch AND ST:wood", "XX", "ST:fruit_leaves AND ST:fruit_branch AND ST:wood"],["M2", "ST:fruit_leaves AND ST:fruit_branch AND ST:wood AND M1", "M2"]]; + breakInto = "juice"; + properties = { + type: "fruit", + }; + isFood = true; + constructor(name, colour, jColour, type = "tree", sColour = false, extract = false, low = false){ + this.properties.fruit = name; + this.color = colour; + this.breakIntoColor = jColour; + this.extract = (extract == false) ? undefined : extract; + if(type == "bush"){ + this.behavior = [["XX", "ST:bush_cane", "XX"],["ST:bush_cane", "XX", "ST:bush_cane"],["M2", "ST:bush_cane AND M1", "M2"]]; + } else if (type == "vine"){ + this.behavior = behaviors.VINEFRUIT; + } + plants[type].push(name); + if(sColour != false){ + if(type == "bush"){ + elements[`${name}_seed`] = new bushSeed(name, sColour); + } else if (type == "vine"){ + elements[`${name}_seed`] = new vineSeed(name, sColour, low); + } else { + elements[`${name}_seed`] = new treeSeed(name, sColour); + } + } + }; + tick = function(pixel){ + let chance = ethyleneChance.get(pixel.fruit); + for(let i = 0; i < squareCoords.length; i++){ + let x = pixel.x+squareCoords[i][0], y = pixel.y+squareCoords[i][1]; + if(isEmpty(x,y) && !outOfBounds(x,y) && Math.random() < chance){ + createPixel("ethylene", x, y); + } + } + } + } + elements.tomato.tick = function(pixel){ + let chance = ethyleneChance.get(pixel.fruit); + for(let i = 0; i < squareCoords.length; i++){ + let x = pixel.x+squareCoords[i][0], y = pixel.y+squareCoords[i][1]; + if(isEmpty(x,y) && !outOfBounds(x,y) && Math.random() < chance){ + createPixel("ethylene", x, y); + } + } + } + elements.grape.tick = function(pixel){ + let chance = ethyleneChance.get(pixel.fruit); + for(let i = 0; i < squareCoords.length; i++){ + let x = pixel.x+squareCoords[i][0], y = pixel.y+squareCoords[i][1]; + if(isEmpty(x,y) && !outOfBounds(x,y) && Math.random() < chance){ + createPixel("ethylene", x, y); + } + } + } + elements.wood.properties = {age: 0, fruit: ""}; + + elements.nutrient_agar = { + category: "life", + behavior: behaviors.STURDYPOWDER, + properties: { + value: null, + }, + state: "solid", + color: ["#edeae4", "#f2f0eb", "#e8e7e3", "#f5f1e9"], + tick: function(pixel) { + for(let coords of adjacentCoords){ + let x = pixel.x+coords[0], y = pixel.y+coords[1]; + let p2 = getPixel(x,y); + if(p2 != null){ + if(["wine", "yeast", "grape", "apple", "plum"].includes(p2.element) && pixel.value == null){ + pixel.value = "yeast"; + } else if(p2.element == "mold" && pixel.value == null){ + pixel.value = "mold"; + }else if(p2.element == "mushroom_spore" && pixel.value == null){ + pixel.value = "mushroom_spore"; + }else if (p2.element == pixel.element && p2.value != null && pixel.value == null && Math.random()<0.0035){ + pixel.value = p2.value; + } + } + } + if(Math.random() < 0.00075){ + if(pixel.value == null && Math.random() < 0.025){ + let elems = ["mold", "mold", "mushroom_spore"]; + let elem = elems[Math.round(Math.random()*elems.length)]; + while(elem == undefined){ + elem = elems[Math.round(Math.random()*elems.length)]; + } + changePixel(pixel, elem); + } else { + changePixel(pixel, pixel.value); + } + } + } + }; + + elements.mold = { + category: "life", + behavior: behaviors.POWDER, + color: ["#33402a", "#303d25", "#2b4f39", "#254231"], + reactions: { + cheese: {elem2: ["rotten_cheese", "rotten_cheese", "mold"], chance: 0.075}, + meat: {elem2: ["rotten_meat", "rotten_meat", "mold"], chance: 0.075}, + }, + state: "solid", + tick: function(pixel){ + for(let coords of adjacentCoords){ + let x = pixel.x+coords[0], y = pixel.y+coords[1], p2 = getPixel(x,y); + if(p2 != null){ + if(plants.includes(p2.element) && Math.random() < 0.025){ + let elems = ["mold", "rotten_fruit", "rotten_fruit"]; + let elem = elems[Math.round(Math.random()*elems.length)]; + while(elem == undefined){ + elem = elems[Math.round(Math.random()*elems.length)]; + } + changePixel(p2, elem); + } + } + } + } + }; + + elements.rotten_fruit = { + color: ["#5e3d00", "#5c3c01", "#4a3205", "#634102"], + category: "life", + behavior: behaviors.POWDER, + reactions: { + cheese: {elem2: ["rotten_cheese", "rotten_cheese", "mold"], chance: 0.075}, + meat: {elem2: ["rotten_meat", "rotten_meat", "mold"], chance: 0.075}, + }, + state: "solid", + }; + + elements.yeast = { + color: ["#e3d3a6", "#f2dea7", "#e3cf98", "#f2dfaa"], + category: "life", + density: 1033, + behavior: behaviors.POWDER, + reactions: { + sugar_water: {elem2: "wine", color2: ["#6e85b5", "#6d81ab"], chance: 0.00025}, + water: {elem2: "seltzer", chance: 0.00005}, + }, + tick: function(pixel){ + for(let coords of adjacentCoords){ + let x = pixel.x+coords[0], y = pixel.y+coords[1], p2 = getPixel(x,y); + if(p2 != null){ + if(p2.element == "juice" && Math.random() < 0.00025){ + let rgb = getRGB(p2.color); + for(key in rgb){ + rgb[key] = Math.max(rgb[key] - 10, 0); + } + changePixel(p2, "wine"); + p2.color = normalize(rgb); + } + } + } + } + } + + elements.fruit_branch = { + color: elements.tree_branch.color, + behavior: [ + "XX|XX|XX", + "XX|XX|XX", + "XX|XX|XX", + ], + tempHigh: 100, + stateHigh: "wood", + tempLow: -30, + stateLow: "wood", + category: "life", + burn: 40, + burnTime: 50, + burnInto: ["sap","ember","charcoal"], + hidden: true, + state: "solid", + density: 1500, + hardness: 0.15, + breakInto: ["sap","sawdust"], + seed: "apple_seed", + properties: { + age: 0, + fruit: "", + }, + tick: function(pixel){ + let pos = [[-1, -1], [0, -1], [1, -1]]; + for(let i = 0; i < pos.length; i++){ + let x = pixel.x+pos[i][0], y = pixel.y+pos[i][1]; + if(isEmpty(x,y) && !outOfBounds(x,y)){ + if(Math.random() < 0.035){ + let elemArr = (pos[i][0] == 0) ? ["fruit_leaves","fruit_leaves","fruit_leaves","fruit_branch","fruit_branch"] : ["fruit_branch", "fruit_branch", "fruit_leaves", "fruit_leaves", "wood"]; + createPixel(elemArr[Math.round(Math.random()*elemArr.length)], x, y); + } + } + } + for(var i = 0; i < adjacentCoords.length; i++){ + let x = pixel.x+adjacentCoords[i][0]; + let y = pixel.y+adjacentCoords[i][1]; + if(isEmpty(x, y) || outOfBounds(x, y)) { continue; } + let pixel2 = pixelMap[x][y]; + if(pixel2.element == "fruit_branch" || pixel2.element == "fruit_leaves" || pixel2.element == "wood"){ + if(pixel.fruit != "" && pixel2.fruit == ""){ + pixel2.fruit = pixel.fruit; + } else if (pixel.fruit == "" && pixel2.fruit != ""){ + pixel.fruit = pixel2.fruit; + } + } } } } - } -} -elements.fruit_leaves = { - color: elements.plant.color, - behavior: [ - "XX|XX|XX", - "XX|XX|XX", - "XX|XX|XX", - ], - reactions: { - "vinegar": { elem1:"dead_plant", elem2:null, chance:0.035 }, - "baking_soda": { elem1:"dead_plant", elem2:null, chance:0.01 }, - "bleach": { elem1:"dead_plant", elem2:null, chance:0.05 }, - "alcohol": { elem1:"dead_plant", elem2:null, chance:0.035 } - }, - category:"life", - tempHigh: 100, - stateHigh: "dead_plant", - tempLow: -1.66, - stateLow: "frozen_plant", - burn:65, - burnTime:60, - burnInto: "dead_plant", - breakInto: "dead_plant", - state: "solid", - density: 1050, - hidden: true, - properties: { - age: 0, - fruit: "", - growthStage: 0, - dir: [1,1], - bloomColor: "#FFE2E2", - }, - tick: function(pixel){ - if(pixel.dieAfter != undefined){ - let chance = (pixel.age-pixel.dieAfter)/150; - chance = Math.max(0, Math.min(1, chance)); - if(Math.random() < chance){ - changePixel(pixel, "dead_plant"); - let neighbors = [], boolArr = []; - - for(let coords of squareCoords){ - let x = pixel.x+coords[0], y = pixel.y+coords[1]; - let p2 = getPixel(x,y); - if(p2 != null){ - neighbors[neighbors.length] = p2; - boolArr[boolArr.length] = (p2.dieAfter != undefined); + elements.fruit_leaves = { + color: elements.plant.color, + behavior: [ + "XX|XX|XX", + "XX|XX|XX", + "XX|XX|XX", + ], + reactions: { + "vinegar": { elem1:"dead_plant", elem2:null, chance:0.035 }, + "baking_soda": { elem1:"dead_plant", elem2:null, chance:0.01 }, + "bleach": { elem1:"dead_plant", elem2:null, chance:0.05 }, + "alcohol": { elem1:"dead_plant", elem2:null, chance:0.035 } + }, + category:"life", + tempHigh: 100, + stateHigh: "dead_plant", + tempLow: -1.66, + stateLow: "frozen_plant", + burn:65, + burnTime:60, + burnInto: "dead_plant", + breakInto: "dead_plant", + state: "solid", + density: 1050, + hidden: true, + properties: { + age: 0, + fruit: "", + growthStage: 0, + dir: [1,1], + bloomColor: "#FFE2E2", + }, + tick: function(pixel){ + if(pixel.dieAfter != undefined){ + let chance = (pixel.age-pixel.dieAfter)/150; + chance = Math.max(0, Math.min(1, chance)); + if(Math.random() < chance){ + changePixel(pixel, "dead_plant"); + let neighbors = [], boolArr = []; + + for(let coords of squareCoords){ + let x = pixel.x+coords[0], y = pixel.y+coords[1]; + let p2 = getPixel(x,y); + if(p2 != null){ + neighbors[neighbors.length] = p2; + boolArr[boolArr.length] = (p2.dieAfter != undefined); + } + } + if(boolArr.includes(true)){ + for(let coords of squareCoords){ + let x = pixel.x+coords[0], y = pixel.y+coords[1]; + let p2 = getPixel(x,y); + if(p2 != null){ + if(p2.dieAfter != undefined){ + p2.age = p2.dieAfter+150; + } + } + } } } - if(boolArr.includes(true)){ - for(let coords of squareCoords){ - let x = pixel.x+coords[0], y = pixel.y+coords[1]; - let p2 = getPixel(x,y); - if(p2 != null){ - if(p2.dieAfter != undefined){ - p2.age = p2.dieAfter+150; + + } + if(pixelTicks == pixel.start + 1 && pixel.blooming == undefined && !pixel.growthPattern && !pixel.noBloom){ + if(Math.floor(Math.random() * 3) == 2){ + pixel.blooming = true; + pixel.color ="#FFE2E2"; + } else { + pixel.blooming = false; + } + } + if(pixel.blooming && elements[pixel.fruit] != undefined && elements[pixel.fruit].bloomColor != undefined && !elements[pixel.fruit].bloomColor.includes(pixel.bloomColor)){ + pixel.bloomColor = elements[pixel.fruit].bloomColor; + } + if(pixel.blooming && !pixel.bloomColor.includes(pixel.c)){ + let color = ""; + if(Array.isArray(pixel.bloomColor)){ + color = pixel.bloomColor[Math.round(Math.random()*pixel.bloomColor.length)]; + while(color == undefined){ + color = pixel.bloomColor[Math.round(Math.random()*pixel.bloomColor.length)]; + } + } else { + color = pixel.bloomColor; + } + pixel.c = color; + let range = (elements[pixel.fruit] && elements[pixel.fruit].bloomRange) ? elements[pixel.fruit].bloomRange : 5; + let rgb = (color.startsWith("#")) ? hexToRGB(color) : getRGB(color); + let num = (Math.round(Math.random()*(range*2)))-range; + color = RGBToHex({r: Math.max(0, Math.min(255, rgb.r+num)), g: Math.max(0, Math.min(255, rgb.g+num)), b: Math.max(0, Math.min(255, rgb.b+num))}); + + pixel.color = color; + } + for(var i = 0; i < adjacentCoords.length; i++){ + let x = pixel.x+adjacentCoords[i][0]; + let y = pixel.y+adjacentCoords[i][1]; + if(isEmpty(x, y) || outOfBounds(x, y)) { continue; } + let pixel2 = pixelMap[x][y]; + if((["fruit_vine", "fruit_branch", "fruit_leaves", "low_fruit_vine", "wood"].includes(pixel2.element) || (pixel2.type && pixel2.type == "fruit")) && pixel2.fruit != "pineapple"){ + if(pixel.fruit && !pixel2.fruit){ + pixel2.fruit = pixel.fruit; + } else if (!pixel.fruit && pixel2.fruit){ + pixel.fruit = pixel2.fruit; + } + if(pixel.age && !pixel2.age){ + pixel2.age = pixel.age; + } else if (!pixel.age && pixel2.age){ + pixel.age = pixel2.age; + } + } else if(pixel2.element == "bee" && pixel.blooming){ + for(let value of pixel2.fruitPollen){ + if(value.fruit == pixel.fruit){ + let rgb1 = (value.color.startsWith("#")) ? hexToRGB(value.color) : getRGB(value.color); + let rgb2 = (pixel.color.startsWith("#")) ? hexToRGB(pixel.color) : getRGB(pixel.color); + let combinedRGB = {r: (rgb1.r+rgb2.r)/2, g: (rgb1.g+rgb2.g)/2, b: (rgb1.b+rgb2.b)/2}; + pixel.offspringColor = combinedRGB; + } + } + } + } + if(pixel.blooming && pixel.fruit == "pineapple" && Math.random() < 0.0035){ + let x = pixel.x, y = pixel.y; + changePixel(pixel, "unripe_fruit"); + pixelMap[x][y].fruit = "pineapple"; + } + if(pixel.blooming && !flowerExclude.includes(pixel.fruit)){ + let chance = 0.0025; + for(let i = 0; i < squareCoords.length; i++){ + let x = pixel.x+squareCoords[i][0], y = pixel.y+squareCoords[i][1]; + if(!isEmpty(x,y) && !outOfBounds(x,y)){ + let p2 = pixelMap[x][y]; + if(["ethylene","propylene"].includes(p2.element)){ + chance = [0.01, 0.0035][["ethylene","propylene"].indexOf(p2.element)] || chance; + } } } - } - } - - } - if(pixelTicks == pixel.start + 1 && pixel.blooming == undefined && !pixel.growthPattern && !pixel.noBloom){ - if(Math.floor(Math.random() * 3) == 2){ - pixel.blooming = true; - pixel.color ="#FFE2E2"; - } else { - pixel.blooming = false; - } - } - if(pixel.blooming && elements[pixel.fruit] != undefined && elements[pixel.fruit].bloomColor != undefined && !elements[pixel.fruit].bloomColor.includes(pixel.bloomColor)){ - pixel.bloomColor = elements[pixel.fruit].bloomColor; - } - if(pixel.blooming && !pixel.bloomColor.includes(pixel.c)){ - let color = ""; - if(Array.isArray(pixel.bloomColor)){ - color = pixel.bloomColor[Math.round(Math.random()*pixel.bloomColor.length)]; - while(color == undefined){ - color = pixel.bloomColor[Math.round(Math.random()*pixel.bloomColor.length)]; - } - } else { - color = pixel.bloomColor; - } - pixel.c = color; - let range = (elements[pixel.fruit] && elements[pixel.fruit].bloomRange) ? elements[pixel.fruit].bloomRange : 5; - let rgb = (color.startsWith("#")) ? hexToRGB(color) : getRGB(color); - let num = (Math.round(Math.random()*(range*2)))-range; - color = RGBToHex({r: Math.max(0, Math.min(255, rgb.r+num)), g: Math.max(0, Math.min(255, rgb.g+num)), b: Math.max(0, Math.min(255, rgb.b+num))}); - - pixel.color = color; - } - for(var i = 0; i < adjacentCoords.length; i++){ - let x = pixel.x+adjacentCoords[i][0]; - let y = pixel.y+adjacentCoords[i][1]; - if(isEmpty(x, y) || outOfBounds(x, y)) { continue; } - let pixel2 = pixelMap[x][y]; - if((["fruit_vine", "fruit_branch", "fruit_leaves", "low_fruit_vine", "wood"].includes(pixel2.element) || (pixel2.type && pixel2.type == "fruit")) && pixel2.fruit != "pineapple"){ - if(pixel.fruit && !pixel2.fruit){ - pixel2.fruit = pixel.fruit; - } else if (!pixel.fruit && pixel2.fruit){ - pixel.fruit = pixel2.fruit; - } - if(pixel.age && !pixel2.age){ - pixel2.age = pixel.age; - } else if (!pixel.age && pixel2.age){ - pixel.age = pixel2.age; - } - } else if(pixel2.element == "bee" && pixel.blooming){ - for(let value of pixel2.fruitPollen){ - if(value.fruit == pixel.fruit){ - let rgb1 = (value.color.startsWith("#")) ? hexToRGB(value.color) : getRGB(value.color); - let rgb2 = (pixel.color.startsWith("#")) ? hexToRGB(pixel.color) : getRGB(pixel.color); - let combinedRGB = {r: (rgb1.r+rgb2.r)/2, g: (rgb1.g+rgb2.g)/2, b: (rgb1.b+rgb2.b)/2}; - pixel.offspringColor = combinedRGB; - } - } - } - } - if(pixel.blooming && pixel.fruit == "pineapple" && Math.random() < 0.0035){ - let x = pixel.x, y = pixel.y; - changePixel(pixel, "unripe_fruit"); - pixelMap[x][y].fruit = "pineapple"; - } - if(pixel.blooming && !flowerExclude.includes(pixel.fruit)){ - let chance = 0.0025; - for(let i = 0; i < squareCoords.length; i++){ - let x = pixel.x+squareCoords[i][0], y = pixel.y+squareCoords[i][1]; - if(!isEmpty(x,y) && !outOfBounds(x,y)){ - let p2 = pixelMap[x][y]; - if(["ethylene","propylene"].includes(p2.element)){ - chance = [0.01, 0.0035][["ethylene","propylene"].indexOf(p2.element)] || chance; - + if(pixelTicks > pixel.start + 150){ + if(Math.random() < chance){ + if(pixel.fruit){ + if(pixel.fruit == "random"){ + changePixel(pixel, fruits[Math.floor(Math.random() * fruits.length)]); + } else { + let c = (pixel.offspringColor) ? pixel.offspringColor : undefined; + changePixel(pixel, pixel.fruit); + if(c != undefined){ + pixel.bloomColor = c; + } } - } - } - if(pixelTicks > pixel.start + 150){ - if(Math.random() < chance){ - if(pixel.fruit){ - if(pixel.fruit == "random"){ - changePixel(pixel, fruits[Math.floor(Math.random() * fruits.length)]); - } else { - let c = (pixel.offspringColor) ? pixel.offspringColor : undefined; - changePixel(pixel, pixel.fruit); - if(c != undefined){ - pixel.bloomColor = c; } } } } - } - } - if(pixel.growthPattern == true){ - let chance = (pixel.age-150)/2500; - chance = Math.max(Math.min(chance, 1), 0); - if(Math.random() < chance){ - let value = growthPatterns[pixel.pattern][pixel.growthStage]; - if(pixel.growthStage < growthPatterns[pixel.pattern].length && is2d(value)){ - for(let coords of value){ - let x = pixel.x+(coords[0]*pixel.dir[0]), y = pixel.y+(coords[1]*pixel.dir[1]); + if(pixel.growthPattern == true){ + let chance = (pixel.age-150)/2500; + chance = Math.max(Math.min(chance, 1), 0); + if(Math.random() < chance){ + let value = growthPatterns[pixel.pattern][pixel.growthStage]; + if(pixel.growthStage < growthPatterns[pixel.pattern].length && is2d(value)){ + for(let coords of value){ + let x = pixel.x+(coords[0]*pixel.dir[0]), y = pixel.y+(coords[1]*pixel.dir[1]); + if(isEmpty(x,y) && !outOfBounds(x,y)){ + if(growthElems[pixel.pattern][pixel.growthStage] == "flower"){ + createPixel("fruit_leaves", x, y); + pixelMap[x][y].blooming = true; + pixelMap[x][y].fruit = pixel.fruit; + } else { + createPixel((growthElems[pixel.pattern][pixel.growthStage] == undefined) ? growthElems[pixel.pattern][0] : growthElems[pixel.pattern][pixel.growthStage], x, y); + pixelMap[x][y].noBloom = true; + pixelMap[x][y].dieAfter = pixel.dieAfter; + } + } + } + } else if(pixel.growthStage < growthPatterns[pixel.pattern].length) { + let x = pixel.x+(value[0]*pixel.dir[0]), y = pixel.y+(value[1]*pixel.dir[1]); if(isEmpty(x,y) && !outOfBounds(x,y)){ if(growthElems[pixel.pattern][pixel.growthStage] == "flower"){ createPixel("fruit_leaves", x, y); pixelMap[x][y].blooming = true; - pixelMap[x][y].fruit = pixel.fruit; + pixelMap[x][y].fruit = pixel.fruit.split("_")[0]; } else { createPixel((growthElems[pixel.pattern][pixel.growthStage] == undefined) ? growthElems[pixel.pattern][0] : growthElems[pixel.pattern][pixel.growthStage], x, y); pixelMap[x][y].noBloom = true; @@ -533,972 +645,981 @@ elements.fruit_leaves = { } } } - } else if(pixel.growthStage < growthPatterns[pixel.pattern].length) { - let x = pixel.x+(value[0]*pixel.dir[0]), y = pixel.y+(value[1]*pixel.dir[1]); - if(isEmpty(x,y) && !outOfBounds(x,y)){ - if(growthElems[pixel.pattern][pixel.growthStage] == "flower"){ - createPixel("fruit_leaves", x, y); - pixelMap[x][y].blooming = true; - pixelMap[x][y].fruit = pixel.fruit.split("_")[0]; - } else { - createPixel((growthElems[pixel.pattern][pixel.growthStage] == undefined) ? growthElems[pixel.pattern][0] : growthElems[pixel.pattern][pixel.growthStage], x, y); - pixelMap[x][y].noBloom = true; - pixelMap[x][y].dieAfter = pixel.dieAfter; - } - } + pixel.growthStage += 1; } - pixel.growthStage += 1; + } + pixel.age++; + } + } + + + + class bushSeed{ + behavior = behaviors.STURDYPOWDER; + category = "life"; + properties = { + age: 0, + }; + tick = function(pixel){ + if(pixel.age > 40){ + let x1 = pixel.x - 1; + let y = pixel.y; + let x2 = pixel.x + 1; + if(isEmpty(x1,y) && !outOfBounds(x1,y)){ + createPixel("bush_base", x1, y); + pixelMap[x1][y].fruit = pixel.fruit; + } + if(isEmpty(x2,y) && !outOfBounds(x2,y)){ + createPixel("bush_base", x2, y); + pixelMap[x2][y].fruit = pixel.fruit; + } + if(!isEmpty(x1, y) && !isEmpty(x2, y)){ + deletePixel(pixel.x, pixel.y); + } + } + pixel.age += 1; + }; + constructor(fruit, colour){ + this.properties.fruit = fruit; + this.color = colour; } } - pixel.age++; - } -} - - - -class bushSeed{ - behavior = behaviors.STURDYPOWDER; - category = "life"; - properties = { - age: 0, - }; - tick = function(pixel){ - if(pixel.age > 40){ - let x1 = pixel.x - 1; - let y = pixel.y; - let x2 = pixel.x + 1; - if(isEmpty(x1,y) && !outOfBounds(x1,y)){ - createPixel("bush_base", x1, y); - pixelMap[x1][y].fruit = pixel.fruit; - } - if(isEmpty(x2,y) && !outOfBounds(x2,y)){ - createPixel("bush_base", x2, y); - pixelMap[x2][y].fruit = pixel.fruit; - } - if(!isEmpty(x1, y) && !isEmpty(x2, y)){ - deletePixel(pixel.x, pixel.y); - } - } - pixel.age += 1; - }; - constructor(fruit, colour){ - this.properties.fruit = fruit; - this.color = colour; - } -} -elements.bush_base = { - color: elements.wood.color, - behavior: [ - ["CR:bush_cane%25", "XX", "CR:bush_cane%25"], - ["XX", "XX", "XX"], - ["XX", "XX", "XX"] - ], - tempHigh: 100, - stateHigh: "dead_plant", - tempLow: -40, - stateLow: "frozen_plant", - burn: 65, - burnTime: 15, - category: "life", - state: "solid", - tick: function(pixel){ - let caneCoords = [[-1,-1],[1,-1]]; - for(var i = 0; i < caneCoords.length; i++){ - let x = pixel.x + caneCoords[i][0]; - let y = pixel.y + caneCoords[i][1]; - if(!isEmpty(x,y) && !outOfBounds(x,y)){ - let pixel2 = pixelMap[x][y]; - if(pixel2.element == "bush_cane" && !pixel2.fruit){ - pixel2.fruit = pixel.fruit; + elements.bush_base = { + color: elements.wood.color, + behavior: [ + ["CR:bush_cane%25", "XX", "CR:bush_cane%25"], + ["XX", "XX", "XX"], + ["XX", "XX", "XX"] + ], + tempHigh: 100, + stateHigh: "dead_plant", + tempLow: -40, + stateLow: "frozen_plant", + burn: 65, + burnTime: 15, + category: "life", + state: "solid", + tick: function(pixel){ + let caneCoords = [[-1,-1],[1,-1]]; + for(var i = 0; i < caneCoords.length; i++){ + let x = pixel.x + caneCoords[i][0]; + let y = pixel.y + caneCoords[i][1]; + if(!isEmpty(x,y) && !outOfBounds(x,y)){ + let pixel2 = pixelMap[x][y]; + if(pixel2.element == "bush_cane" && !pixel2.fruit){ + pixel2.fruit = pixel.fruit; + } + } } - } + } + }; + elements.bush_cane = { + color: elements.wood.color, + tick: function(pixel){ + if(pixel.age < 200 && Math.floor(Math.random() * 40) == 1){ + if(!outOfBounds(pixel.x,pixel.y-1)){ + if(isEmpty(pixel.x,pixel.y-1)){ + createPixel("bush_cane",pixel.x,pixel.y-1); + if(pixel.fruit){ + let pixel2 = pixelMap[pixel.x][pixel.y-1]; + pixel2.fruit = pixel.fruit; + pixel2.age = pixel.age; + } + } + } + } + if(pixel.fruit && Math.floor(Math.random() * 400) == 1 && pixel.age > 200){ + for(var i = 0; i < adjacentCoords.length; i++){ + let x = pixel.x + adjacentCoords[i][0]; + let y = pixel.y + adjacentCoords[i][1]; + if(isEmpty(x,y) && !outOfBounds(x,y)){ + createPixel("fruit_leaves", x, y); + pixelMap[x][y].fruit = pixel.fruit; + pixel.blooming = [true, false][Math.floor(Math.random() * 2)]; + } + } + } + pixel.age += 1; + }, + properties: { + age: 0, + }, + category: "life", + tempLow: -2, + stateLow: "frozen_plant", } - } -}; -elements.bush_cane = { - color: elements.wood.color, - tick: function(pixel){ - if(pixel.age < 200 && Math.floor(Math.random() * 40) == 1){ - if(!outOfBounds(pixel.x,pixel.y-1)){ - if(isEmpty(pixel.x,pixel.y-1)){ - createPixel("bush_cane",pixel.x,pixel.y-1); - if(pixel.fruit){ - let pixel2 = pixelMap[pixel.x][pixel.y-1]; - pixel2.fruit = pixel.fruit; - pixel2.age = pixel.age; + + + elements.low_fruit_vine = { + color: elements.plant.color, + behavior: behaviors.WALL, + category: "life", + properties: { + age: 0, + }, + tick: function(pixel){ + if(isEmpty(pixel.x, pixel.y - 1) && !outOfBounds(pixel.x, pixel.y - 1) && Math.random() < ((pixel.age/50000 > 0.005) ? 0.005 : (pixel.age/50000)) && pixel.fruit && ![undefined, "watermelon", "pumpkin"].includes(pixel.fruit)){ + createPixel("fruit_leaves", pixel.x, pixel.y - 1); + pixelMap[pixel.x][pixel.y - 1].blooming = true; + pixelMap[pixel.x][pixel.y - 1].color = "#FFE2E2"; + pixelMap[pixel.x][pixel.y - 1].fruit = pixel.fruit; + } + if(Math.floor(Math.random() * 100) == 1 && !["watermelon", "pumpkin", undefined].includes(pixel.fruit)){ + let num = (Math.random() > 0.5) ? -1 : 1; + if(isEmpty(pixel.x + num, pixel.y)){ + createPixel("low_fruit_vine", pixel.x + num, pixel.y); + pixelMap[pixel.x + num][pixel.y].fruit = pixel.fruit; + } + } + pixel.age++; + } + } + let str = ""; + for(let i = 0; i < vineGrow.length; i++){ + str += (i == vineGrow.length-1) ? `ST:${vineGrow[i]}` : `ST:${vineGrow[i]} AND `; + } + elements.fruit_vine = { + category: "life", + color: elements.plant.color, + behavior: [["XX", str, "XX"], [str, "XX", str], ["XX", str + " AND M1", "XX"]], + properties: { + age: 0, + }, + tick: function(pixel){ + if(Math.floor(Math.random() * 100) == 1 && pixel.age > 25 && pixel.age < 500){ + for(var i = 0; i < squareCoords.length; i++){ + let x1 = pixel.x + squareCoords[i][0]; + let y1 = pixel.y + squareCoords[i][1]; + if(!isEmpty(x1,y1) && !outOfBounds(x1,y1) && vineGrow.includes(pixelMap[x1][y1].element)){ + //pixel.drag = true; + let randomNum = Math.floor(Math.random() * 4); + let x2 = x1 + squareCoords[randomNum][0]; + let y2 = y1 + squareCoords[randomNum][1]; + if(isEmpty(x2,y2) && !outOfBounds(x2,y2)){ + createPixel("fruit_vine", x2, y2); + pixelMap[x2][y2].fruit = pixel.fruit; + pixelMap[x2][y2].bloomColor = pixel.bloomColor; + } + } //else {pixel.drag = false;} + } + } + pixel.age += 1; + if(pixel.fruit){ + for(var i = 0; i < adjacentCoords.length; i++){ + let x = pixel.x + adjacentCoords[i][0]; + let y = pixel.y + adjacentCoords[i][1]; + if(isEmpty(x,y) && !outOfBounds(x,y) && Math.floor(Math.random() * 5000) == 5 && pixel.age > 650){ + createPixel("fruit_leaves", x, y); + pixelMap[x][y].blooming = true; + pixelMap[x][y].bloomColor = pixel.bloomColor; + } + } + } + if(!pixel.fruit){ + for(var i = 0; i < squareCoords.length; i++){ + let x = pixel.x + squareCoords[i][0]; + let y = pixel.y + squareCoords[i][1]; + if(isEmpty(x,y) || outOfBounds(x,y)){ continue; } + let pixel2 = pixelMap[x][y]; + if(pixel2.fruit){ + pixel.fruit = pixel2.fruit; + } else { continue; } } } } } - if(pixel.fruit && Math.floor(Math.random() * 400) == 1 && pixel.age > 200){ - for(var i = 0; i < adjacentCoords.length; i++){ - let x = pixel.x + adjacentCoords[i][0]; - let y = pixel.y + adjacentCoords[i][1]; - if(isEmpty(x,y) && !outOfBounds(x,y)){ - createPixel("fruit_leaves", x, y); - pixelMap[x][y].fruit = pixel.fruit; - pixel.blooming = [true, false][Math.floor(Math.random() * 2)]; + + behaviors.VINEFRUIT = ["XX|ST:fruit_vine AND ST:low_fruit_vine|XX", + "ST:fruit_vine AND ST:low_fruit_vine|XX|ST:fruit_vine AND ST:low_fruit_vine", + "M2|M1|M2"]; + elements.grape.behavior = behaviors.VINEFRUIT; + elements.tomato.behavior = behaviors.VINEFRUIT; + elements.grape_seed = new vineSeed("grape",["#281B01", "#2D1F06", "#2D1F06"]); + elements.tomato_seed = new vineSeed("tomato", ["#F8F5D1","#E7E5CF","#E3E1C5"]); + elements.apple = new fruit("apple", ["#FF0507", "#EC0A0D", "#F22426", "#DC2C2E"], ["#F9C497", "#EED3BB", "#EEDEBB"]); + elements.apple.bloomColor = ["#fff0f7", "#fcebf3", "#fff0f7", "#ffe6f2", "#fff7fb"]; + elements.apple_seed = new treeSeed("apple", ["#3B1C01", "#3E2107", "#3A1C02"]); + + elements.juice.tick = function(pixel){ + for(let i = 0; i < squareCoords.length; i++){ + let x = pixel.x+squareCoords[i][0], y = pixel.y+squareCoords[i][1]; + if(!isEmpty(x,y) && !outOfBounds(x,y) && pixelMap[x][y].element == pixel.element && Math.random() < 0.005){ + colorMix(pixel, pixelMap[x][y]); + } } - } } - pixel.age += 1; - }, - properties: { - age: 0, - }, - category: "life", - tempLow: -2, - stateLow: "frozen_plant", -} - - -elements.low_fruit_vine = { - color: elements.plant.color, - behavior: behaviors.WALL, - category: "life", - properties: { - age: 0, - }, - tick: function(pixel){ - if(isEmpty(pixel.x, pixel.y - 1) && !outOfBounds(pixel.x, pixel.y - 1) && Math.random() < ((pixel.age/50000 > 0.005) ? 0.005 : (pixel.age/50000)) && pixel.fruit && ![undefined, "watermelon", "pumpkin"].includes(pixel.fruit)){ - createPixel("fruit_leaves", pixel.x, pixel.y - 1); - pixelMap[pixel.x][pixel.y - 1].blooming = true; - pixelMap[pixel.x][pixel.y - 1].color = "#FFE2E2"; - pixelMap[pixel.x][pixel.y - 1].fruit = pixel.fruit; - } - if(Math.floor(Math.random() * 100) == 1 && !["watermelon", "pumpkin", undefined].includes(pixel.fruit)){ - let num = (Math.random() > 0.5) ? -1 : 1; - if(isEmpty(pixel.x + num, pixel.y)){ - createPixel("low_fruit_vine", pixel.x + num, pixel.y); - pixelMap[pixel.x + num][pixel.y].fruit = pixel.fruit; - } - } - pixel.age++; - } -} -let str = ""; -for(let i = 0; i < vineGrow.length; i++){ - str += (i == vineGrow.length-1) ? `ST:${vineGrow[i]}` : `ST:${vineGrow[i]} AND `; -} -elements.fruit_vine = { - category: "life", - color: elements.plant.color, - behavior: [["XX", str, "XX"], [str, "XX", str], ["XX", str + " AND M1", "XX"]], - properties: { - age: 0, - }, - tick: function(pixel){ - if(Math.floor(Math.random() * 100) == 1 && pixel.age > 25 && pixel.age < 500){ - for(var i = 0; i < squareCoords.length; i++){ - let x1 = pixel.x + squareCoords[i][0]; - let y1 = pixel.y + squareCoords[i][1]; - if(!isEmpty(x1,y1) && !outOfBounds(x1,y1) && vineGrow.includes(pixelMap[x1][y1].element)){ - //pixel.drag = true; - let randomNum = Math.floor(Math.random() * 4); - let x2 = x1 + squareCoords[randomNum][0]; - let y2 = y1 + squareCoords[randomNum][1]; - if(isEmpty(x2,y2) && !outOfBounds(x2,y2)){ - createPixel("fruit_vine", x2, y2); - pixelMap[x2][y2].fruit = pixel.fruit; - pixelMap[x2][y2].bloomColor = pixel.bloomColor; - } - } //else {pixel.drag = false;} - } - } - pixel.age += 1; - if(pixel.fruit){ - for(var i = 0; i < adjacentCoords.length; i++){ - let x = pixel.x + adjacentCoords[i][0]; - let y = pixel.y + adjacentCoords[i][1]; - if(isEmpty(x,y) && !outOfBounds(x,y) && Math.floor(Math.random() * 5000) == 5 && pixel.age > 650){ - createPixel("fruit_leaves", x, y); - pixelMap[x][y].blooming = true; - pixelMap[x][y].bloomColor = pixel.bloomColor; + elements.juice.onMix = function(pixel){ + for(let i = 0; i < squareCoords.length; i++){ + let x = pixel.x+squareCoords[i][0], y = pixel.y+squareCoords[i][1]; + if(!isEmpty(x,y) && !outOfBounds(x,y) && pixelMap[x][y].element == pixel.element && Math.random() < 0.5){ + colorMix(pixel, pixelMap[x][y]); + } } - } } - if(!pixel.fruit){ - for(var i = 0; i < squareCoords.length; i++){ - let x = pixel.x + squareCoords[i][0]; - let y = pixel.y + squareCoords[i][1]; - if(isEmpty(x,y) || outOfBounds(x,y)){ continue; } - let pixel2 = pixelMap[x][y]; - if(pixel2.fruit){ - pixel.fruit = pixel2.fruit; - } else { continue; } - } + elements.fruit_milk.tick = function(pixel){ + for(let i = 0; i < squareCoords.length; i++){ + let x = pixel.x+squareCoords[i][0], y = pixel.y+squareCoords[i][1]; + if(!isEmpty(x,y) && !outOfBounds(x,y) && pixelMap[x][y].element == pixel.element && Math.random() < 0.005){ + colorMix(pixel, pixelMap[x][y]); + } + } } - } -} - -behaviors.VINEFRUIT = ["XX|ST:fruit_vine AND ST:low_fruit_vine|XX", -"ST:fruit_vine AND ST:low_fruit_vine|XX|ST:fruit_vine AND ST:low_fruit_vine", -"M2|M1|M2"]; -elements.grape.behavior = behaviors.VINEFRUIT; -elements.tomato.behavior = behaviors.VINEFRUIT; -elements.grape_seed = new vineSeed("grape",["#281B01", "#2D1F06", "#2D1F06"]); -elements.tomato_seed = new vineSeed("tomato", ["#F8F5D1","#E7E5CF","#E3E1C5"]); -elements.apple = new fruit("apple", ["#FF0507", "#EC0A0D", "#F22426", "#DC2C2E"], ["#F9C497", "#EED3BB", "#EEDEBB"]); -elements.apple.bloomColor = ["#fff0f7", "#fcebf3", "#fff0f7", "#ffe6f2", "#fff7fb"]; -elements.apple_seed = new treeSeed("apple", ["#3B1C01", "#3E2107", "#3A1C02"]); -function colorMix(p1, p2, bias = 0.5){ - p1.color = interpolateRgb(getRGB(p1.color), getRGB(p2.color), bias); - p2.color = interpolateRgb(getRGB(p1.color), getRGB(p2.color), bias); -} -function interpolateRgb(rgb1, rgb2, ratio = 0.5) { - const interpolatedRgb = { - r: Math.round(rgb1.r + (rgb2.r - rgb1.r) * ratio), - g: Math.round(rgb1.g + (rgb2.g - rgb1.g) * ratio), - b: Math.round(rgb1.b + (rgb2.b - rgb1.b) * ratio), - }; - return normalize(interpolatedRgb); -} -function getRGB(rgb){ - let rgb2 = rgb.replace(")", "").replace("rgb(", "").replace(/,/g, "r").split("r") - return { r: parseInt(rgb2[0]), g: parseInt(rgb2[1]), b: parseInt(rgb2[2]) }; -} - -elements.juice.tick = function(pixel){ - for(let i = 0; i < squareCoords.length; i++){ - let x = pixel.x+squareCoords[i][0], y = pixel.y+squareCoords[i][1]; - if(!isEmpty(x,y) && !outOfBounds(x,y) && pixelMap[x][y].element == pixel.element && Math.random() < 0.005){ - colorMix(pixel, pixelMap[x][y]); - } - } -} -elements.juice.onMix = function(pixel){ - for(let i = 0; i < squareCoords.length; i++){ - let x = pixel.x+squareCoords[i][0], y = pixel.y+squareCoords[i][1]; - if(!isEmpty(x,y) && !outOfBounds(x,y) && pixelMap[x][y].element == pixel.element && Math.random() < 0.5){ - colorMix(pixel, pixelMap[x][y]); - } - } -} -elements.fruit_milk.tick = function(pixel){ - for(let i = 0; i < squareCoords.length; i++){ - let x = pixel.x+squareCoords[i][0], y = pixel.y+squareCoords[i][1]; - if(!isEmpty(x,y) && !outOfBounds(x,y) && pixelMap[x][y].element == pixel.element && Math.random() < 0.005){ - colorMix(pixel, pixelMap[x][y]); - } - } -} -elements.fruit_milk.onMix = function(pixel){ - for(let i = 0; i < squareCoords.length; i++){ - let x = pixel.x+squareCoords[i][0], y = pixel.y+squareCoords[i][1]; - if(!isEmpty(x,y) && !outOfBounds(x,y) && pixelMap[x][y].element == pixel.element && Math.random() < 0.5){ - colorMix(pixel, pixelMap[x][y]); - } - } -} -function normalize(obj){ - return `rgb(${obj.r},${obj.g},${obj.b})`; -} - -elements.milk.reactions.juice = {func: function(p1, p2){ - let rgb = interpolateRgb(getRGB(p1.color), getRGB(p2.color), 0.25); - changePixel(p1, "fruit_milk"); - changePixel(p2, "fruit_milk"); - p1.color = rgb; - p2.color = rgb; - } -}; -elements.juice.reactions.carbon_dioxide = { func: function(p1,p2){ - let rgb = interpolateRgb(getRGB(p1.color), getRGB(elements.water.color), 0.2); - changePixel(p1, "soda"); - changePixel(p2, "foam"); - p1.color = rgb; - p2.color = rgb; - } -} -elements.juice.reactions.seltzer = { func: function(p1,p2){ - let rgb = interpolateRgb(getRGB(p1.color), getRGB(p2.color), 0.5); - changePixel(p1, "soda"); - changePixel(p2, "foam"); - p1.color = rgb; - p2.color = rgb; - } -} - -elements.milk.reactions.soda = { - func: function(p1,p2){ - let rgb = interpolateRgb(getRGB(p1.color), getRGB(p2.color), 0.5); - changePixel(p1, "pilk"); - changePixel(p2, "pilk"); - p1.color = rgb; - p2.color = rgb; - } -} - -elements.seed_maker = { - behavior: behaviors.WALL, - category: "machines", - tick: function(pixel){ - for(let i = 0; i < squareCoords.length; i++){ - let x = pixel.x+squareCoords[i][0], y = pixel.y+squareCoords[i][1]; - if((!isEmpty(x,y) && !outOfBounds(x,y)) && plants.includes(pixelMap[x][y].element)){ - let c = (pixelMap[x][y].bloomColor) ? pixelMap[x][y].bloomColor : undefined; - changePixel(pixelMap[x][y], `${pixelMap[x][y].element}_seed`); - if(c != undefined){ - pixelMap[x][y].bloomColor = c; - } - } else if ((!isEmpty(x,y) && !outOfBounds(x,y)) && pixelMap[x][y].alive == false){ - pixelMap[x][y].alive = true; + elements.fruit_milk.onMix = function(pixel){ + for(let i = 0; i < squareCoords.length; i++){ + let x = pixel.x+squareCoords[i][0], y = pixel.y+squareCoords[i][1]; + if(!isEmpty(x,y) && !outOfBounds(x,y) && pixelMap[x][y].element == pixel.element && Math.random() < 0.5){ + colorMix(pixel, pixelMap[x][y]); } - } - } -} - -elements.ethylene = { - behavior: behaviors.GAS, - category: "gases", - reactionCatalysts: { - gold: {e1: "water", product: "alcohol", chance: 0.025}, - copper: {e1: "oxygen", product: "vinegar", chance: 0.025} - }, - reactions: { - oxidized_copper: { elem1: "vinegar", elem2: "copper", chance: 0.025}, - }, - color: ["#fffffc", "#f7f7f2", "#eaebe6", "#ededed", "#f7f7f2", "#f2f2f2"], - buttonColor: ["#fffffc", "#f7f7f2"], - state: "gas", - burnInto: ["carbon_dioxide", "steam"], - burn: 100, - burnTime: 15, - stateHigh: "fire", - tempHigh: 425, - tick: function(pixel){ - catalyse(pixel); - if(settings.cleargases){ - let rgb; - if(settings.bg != undefined){ - rgb = interpolateRgb(hexToRGB("#E5EAEA"), hexToRGB(settings.bg), 0.85); - } else { - rgb = interpolateRgb(hexToRGB("#E5EAEA"), {r:0,g:0,b:0}, 0.85); - } - pixel.color = rgb; - }else if (!["#fffffc", "#f7f7f2", "#eaebe6", "#ededed", "#f7f7f2", "#f2f2f2"].includes(pixel.color)){ - pixel.color = ["#fffffc", "#f7f7f2", "#eaebe6", "#ededed", "#f7f7f2", "#f2f2f2"][Math.floor(Math.random()*6)]; - }; - }, -} -elements.propylene = { - behavior: behaviors.GAS, - category: "gases", - reactionCatalysts: { - nickel: {e1: "hydrogen", product: "propane", chance: 0.025}, - }, - color: ["#fffffc", "#f7f7f2", "#eaebe6", "#ededed", "#f7f7f2", "#f2f2f2"], - buttonColor: ["#fffffc", "#f7f7f2"], - state: "gas", - burnInto: ["carbon_dioxide", "steam"], - burn: 100, - burnTime: 15, - stateHigh: "fire", - tempHigh: 425, - tick: function(pixel){ - catalyse(pixel); - let rgb; - if(settings.cleargases){ - if(settings.bg != undefined){ - rgb = interpolateRgb(hexToRGB("#E5EAEA"), hexToRGB(settings.bg), 0.85); - } else { - rgb = interpolateRgb(hexToRGB("#E5EAEA"), {r:0,g:0,b:0}, 0.85); - } - pixel.color = rgb; - } else if (!["#fffffc", "#f7f7f2", "#eaebe6", "#ededed", "#f7f7f2", "#f2f2f2"].includes(pixel.color)){ - pixel.color = ["#fffffc", "#f7f7f2", "#eaebe6", "#ededed", "#f7f7f2", "#f2f2f2"][Math.floor(Math.random()*6)]; - }; - }, -} -elements.propane.reactionCatalysts = { - aluminum: {e2: "hydrogen", product: "propylene", chance: 0.035}, - gallium: {e2: "hydrogen", product: "propylene", chance: 0.025}, -}; -elements.propane.tick = function(pixel){ - catalyse(pixel); -} -runAfterAutogen(()=>{ - let r; - if(settings.cleargases){ - if(settings.bg != undefined){ - r = interpolateRgb(hexToRGB("#E5EAEA"), hexToRGB(settings.bg), 0.85); - } else { - r = interpolateRgb(hexToRGB("#E5EAEA"), {r:0,g:0,b:0}, 0.85); + } + } + + elements.milk.reactions.juice = {func: function(p1, p2){ + let rgb = interpolateRgb(getRGB(p1.color), getRGB(p2.color), 0.25); + changePixel(p1, "fruit_milk"); + changePixel(p2, "fruit_milk"); + p1.color = rgb; + p2.color = rgb; } }; - elements.ethylene.color = r; - elements.propylene.color = r; -}) -function catalyse(pixel){ - let rC = elements[pixel.element].reactionCatalysts; - let neighbors = []; - let p = []; - for(let i = 0; i < squareCoords.length; i++){ - let x = pixel.x+squareCoords[i][0], y = pixel.y+squareCoords[i][1]; - if(!isEmpty(x,y) && !outOfBounds(x,y)){ - neighbors.push(pixelMap[x][y].element); - p.push(pixelMap[x][y]); - } - } - for(item in rC){ - if(neighbors.includes(item) && neighbors.includes(rC[item].e1) && Math.random() < rC[item].chance){ - changePixel(pixel, rC[item].product); - if(rC[item].e2 != undefined){ - changePixel(p[neighbors.indexOf(rC[item].e1)], rC[item].e2); - } else { - let P = p[neighbors.indexOf(rC[item].e1)]; - deletePixel(P.x, P.y); + elements.juice.reactions.carbon_dioxide = { func: function(p1,p2){ + let rgb = interpolateRgb(getRGB(p1.color), getRGB(elements.water.color), 0.2); + changePixel(p1, "soda"); + changePixel(p2, "foam"); + p1.color = rgb; + p2.color = rgb; + } + } + elements.juice.reactions.seltzer = { func: function(p1,p2){ + let rgb = interpolateRgb(getRGB(p1.color), getRGB(p2.color), 0.5); + changePixel(p1, "soda"); + changePixel(p2, "foam"); + p1.color = rgb; + p2.color = rgb; + } + } + + elements.milk.reactions.soda = { + func: function(p1,p2){ + let rgb = interpolateRgb(getRGB(p1.color), getRGB(p2.color), 0.5); + changePixel(p1, "pilk"); + changePixel(p2, "pilk"); + p1.color = rgb; + p2.color = rgb; + } + } + + elements.seed_maker = { + behavior: behaviors.WALL, + category: "machines", + tick: function(pixel){ + for(let i = 0; i < squareCoords.length; i++){ + let x = pixel.x+squareCoords[i][0], y = pixel.y+squareCoords[i][1]; + if((!isEmpty(x,y) && !outOfBounds(x,y)) && plants.includes(pixelMap[x][y].element)){ + let c = (pixelMap[x][y].bloomColor) ? pixelMap[x][y].bloomColor : undefined; + changePixel(pixelMap[x][y], `${pixelMap[x][y].element}_seed`); + if(c != undefined){ + pixelMap[x][y].bloomColor = c; + } + } else if ((!isEmpty(x,y) && !outOfBounds(x,y)) && pixelMap[x][y].alive == false){ + pixelMap[x][y].alive = true; + } } - } else if (rC[item].e1 == undefined){ - if(neighbors.includes(item) && rC[item].e2 != undefined && Math.random() < rC[item].chance){ - for(let i = 0; i < squareCoords.length; i++){ - let x = pixel.x+squareCoords[i][0], y = pixel.y+squareCoords[i][1]; - if(isEmpty(x,y) && !outOfBounds(x,y)){ - createPixel(rC[item].e2, x, y); - changePixel(pixel, rC[item].product); + } + } + + elements.ethylene = { + behavior: behaviors.GAS, + category: "gases", + reactionCatalysts: { + gold: {e1: "water", product: "alcohol", chance: 0.025}, + copper: {e1: "oxygen", product: "vinegar", chance: 0.025} + }, + reactions: { + oxidized_copper: { elem1: "vinegar", elem2: "copper", chance: 0.025}, + }, + color: ["#fffffc", "#f7f7f2", "#eaebe6", "#ededed", "#f7f7f2", "#f2f2f2"], + buttonColor: ["#fffffc", "#f7f7f2"], + state: "gas", + burnInto: ["carbon_dioxide", "steam"], + burn: 100, + burnTime: 15, + stateHigh: "fire", + tempHigh: 425, + tick: function(pixel){ + catalyse(pixel); + if(settings.cleargases){ + let rgb; + if(settings.bg != undefined){ + rgb = interpolateRgb(hexToRGB("#E5EAEA"), hexToRGB(settings.bg), 0.85); + } else { + rgb = interpolateRgb(hexToRGB("#E5EAEA"), {r:0,g:0,b:0}, 0.85); + } + pixel.color = rgb; + }else if (!["#fffffc", "#f7f7f2", "#eaebe6", "#ededed", "#f7f7f2", "#f2f2f2"].includes(pixel.color)){ + pixel.color = ["#fffffc", "#f7f7f2", "#eaebe6", "#ededed", "#f7f7f2", "#f2f2f2"][Math.floor(Math.random()*6)]; + }; + }, + } + elements.propylene = { + behavior: behaviors.GAS, + category: "gases", + reactionCatalysts: { + nickel: {e1: "hydrogen", product: "propane", chance: 0.025}, + }, + color: ["#fffffc", "#f7f7f2", "#eaebe6", "#ededed", "#f7f7f2", "#f2f2f2"], + buttonColor: ["#fffffc", "#f7f7f2"], + state: "gas", + burnInto: ["carbon_dioxide", "steam"], + burn: 100, + burnTime: 15, + stateHigh: "fire", + tempHigh: 425, + tick: function(pixel){ + catalyse(pixel); + let rgb; + if(settings.cleargases){ + if(settings.bg != undefined){ + rgb = interpolateRgb(hexToRGB("#E5EAEA"), hexToRGB(settings.bg), 0.85); + } else { + rgb = interpolateRgb(hexToRGB("#E5EAEA"), {r:0,g:0,b:0}, 0.85); + } + pixel.color = rgb; + } else if (!["#fffffc", "#f7f7f2", "#eaebe6", "#ededed", "#f7f7f2", "#f2f2f2"].includes(pixel.color)){ + pixel.color = ["#fffffc", "#f7f7f2", "#eaebe6", "#ededed", "#f7f7f2", "#f2f2f2"][Math.floor(Math.random()*6)]; + }; + }, + } + elements.propane.reactionCatalysts = { + aluminum: {e2: "hydrogen", product: "propylene", chance: 0.035}, + gallium: {e2: "hydrogen", product: "propylene", chance: 0.025}, + }; + elements.propane.tick = function(pixel){ + catalyse(pixel); + } + runAfterAutogen(()=>{ + let r; + if(settings.cleargases){ + if(settings.bg != undefined){ + r = interpolateRgb(hexToRGB("#E5EAEA"), hexToRGB(settings.bg), 0.85); + } else { + r = interpolateRgb(hexToRGB("#E5EAEA"), {r:0,g:0,b:0}, 0.85); + } + }; + elements.ethylene.color = r; + elements.propylene.color = r; + }) + function catalyse(pixel){ + let rC = elements[pixel.element].reactionCatalysts; + let neighbors = []; + let p = []; + for(let i = 0; i < squareCoords.length; i++){ + let x = pixel.x+squareCoords[i][0], y = pixel.y+squareCoords[i][1]; + if(!isEmpty(x,y) && !outOfBounds(x,y)){ + neighbors.push(pixelMap[x][y].element); + p.push(pixelMap[x][y]); + } + } + for(item in rC){ + if(neighbors.includes(item) && neighbors.includes(rC[item].e1) && Math.random() < rC[item].chance){ + changePixel(pixel, rC[item].product); + if(rC[item].e2 != undefined){ + changePixel(p[neighbors.indexOf(rC[item].e1)], rC[item].e2); + } else { + let P = p[neighbors.indexOf(rC[item].e1)]; + deletePixel(P.x, P.y); + } + } else if (rC[item].e1 == undefined){ + if(neighbors.includes(item) && rC[item].e2 != undefined && Math.random() < rC[item].chance){ + for(let i = 0; i < squareCoords.length; i++){ + let x = pixel.x+squareCoords[i][0], y = pixel.y+squareCoords[i][1]; + if(isEmpty(x,y) && !outOfBounds(x,y)){ + createPixel(rC[item].e2, x, y); + changePixel(pixel, rC[item].product); + } } } } } - } -} -elements.orange = new fruit("orange", ['#FA9A14', '#E88D0F', '#F0963D', '#F4810E'], ['#FFDA0B', '#FFEA09', '#FFD609', '#FCC921'], "tree"); -elements.orange_seed = new treeSeed("orange", ['#EEE9C7', '#F4F1D0', '#E8E4C4', '#DBD5AF']); -elements.kiwi = new fruit("kiwi", ['#886002', '#7D5B0D', '#876412', '#97620F'], ['#7DB410', '#86BC1B', '#95CE22', '#91CF12'], "vine"); -elements.kiwi_seed = new vineSeed("kiwi", ['#3E2A01', '#392804', '#473307', '#1E1500']); -elements.raspberry = new fruit("raspberry", ['#FF201C', '#EF3D3A', '#FA5350', '#DF3E3B'], ['#FF4450', '#F43643', '#DF2C38', '#E92344'], "bush"); -elements.raspberry_seed = new bushSeed("raspberry", ['#572600', '#4C2506', '#592E0D', '#5E3211']); -elements.blueberry = new fruit("blueberry", ['#322954', '#3F3366', '#2B1B5E', '#4C3C81'], ['#51042C', '#550E33', '#420D28', '#520F32'], "bush", ['#78573A', '#72492D', '#7D5438', '#704F3A']); -elements.blackberry = new fruit("blackberry", ['#1A013A', '#1E073A', '#3D0A49', '#33043F'], ['#DC5F5F', '#D76D6D', '#BF6363', '#B05D5D'], "bush", ['#DA7878', '#C87B7B', '#AD6161', '#915656']); -elements.blackberry.bloomColor = ["#f5f5f5", "#ede8ec", "#ebdfe8", "#f7f2f6", "#ffffff"]; -elements.strawberry = new fruit("strawberry", ['#FE3030', '#E93030', '#DE1F1F', '#CE0B0B'], ['#EA5C46', '#E24B34', '#CE5A48', '#E7604B'], "vine", ['#B27F65', '#AA7358', '#A27553', '#AF8B62'], false, true); -elements.pear = new fruit("pear", ["#F1F8A7", "#DCE398", "#E3EE7E", "#D6E07F"], ["#F6F9D5", "#F6F9D5", "#E8ECC6", "#E8ECC0"], "tree", ["#3B1C01", "#3E2107", "#3A1C02"]); -elements.mango = new fruit("mango", ["#F74E3E", "#E95D51", "#EE853B", "#D77026", "#F8BF46", "#F8B524", "#95C408", "#A5CD2D"], ["#FFC905", "#FFD605", "#FFE205", "#FFF305", "#FCE118"], "tree", ["#E8EABB", "#E3E5BA", "#EAEDC0", "#E8EAB1", "#D8DBA5"]); -elements.lemon = new fruit("lemon", ["#FCF924", "#FCF924", "#EEEA1A", "#F6F212", "#FBF70B"], ["#F6F373", "#EEEC77", "#E3E267", "#F3F18B"], "tree", ["#F8F7B2", "#E9E9B1", "#E9E8A7", "#F1EFA4"]); -elements.plum = new fruit("plum", ["#67486E", "#705476", "#634A69", "#785281"], ["#D58D77", "#DC9984", "#CA8D7A", "#CF816A"], "tree", ["#A08C5D", "#907D50", "#9B8551", "#AA9563"]); -elements.plum.bloomColor = ["#ffb3df", "#ffa6da", "#ffbde3", "#ffd1ec"]; -elements.peach = new fruit("peach", ["#F76856", "#EA5D4A", "#EA6D4A", "#E5785A", "#FE824A", "#EE7A45", "#FAA543", "#F59D39", "#FF744D"], ["#F86F1F", "#EC742F", "#EC832F", "#EC9A2F", "#ECA62F"], "tree", ["#735940", "#7B5C3D", "#7D5935"]); -elements.peach.bloomColor = ["#ffb3df", "#ffa6da", "#ffbde3", "#ffd1ec"]; -elements.apricot = new fruit("apricot", ["#F5A61F", "#F5A61F", "#EA9B12", "#F8A109"], ["#F2B016", "#F2AD0C", "#FBB81E", "#FFB301"], "tree", ["#735940", "#7B5C3D", "#7D5935"]); -elements.apricot.bloomColor = ["#fff0fb", "#ffffff", "#fadef3", "#fcd9f4"]; -elements.avocado = new fruit("avocado", ["#3c9419", "#348514", "#367a1b", "#2f7d10"], ["#cff74a", "#caf244", "#c1e649", "#b3d640"], "tree", ["#4d290a", "#4d2b0d", "#63360f", "#572d09"]); -elements.avocado.bloomColor = ["#e3ff9c", "#e1ff96", "#e6ffa6", "#e1faa2"]; -elements.avocado.breakInto = "guacamole"; -elements.guacamole = { - color: ["#cff74a", "#caf244", "#c1e649", "#b3d640"], - behavior: behaviors.LIQUID, - viscosity: 1350, - category: "food", - state: "liquid", - isFood: true, - onMix: function(pixel){ - for(let coords of squareCoords){ - let x = pixel.x+coords[0], y = pixel.y+coords[1]; - if(!isEmpty(x,y) && !outOfBounds(x,y) && elements[pixelMap[x][y].element].isFood && pixelMap[x][y].element != "quacamole"){ - let chance = (shiftDown) ? 1 : 0.5; - if(Math.random() < chance){ - let rgb = interpolateRgb(getRGB(pixel.color), getRGB(pixelMap[x][y].color), 0.8); - changePixel(pixelMap[x][y], "guacamole"); - pixel.color = rgb; - pixelMap[x][y].color = rgb; + } + elements.orange = new fruit("orange", ['#FA9A14', '#E88D0F', '#F0963D', '#F4810E'], ['#FFDA0B', '#FFEA09', '#FFD609', '#FCC921'], "tree"); + elements.orange_seed = new treeSeed("orange", ['#EEE9C7', '#F4F1D0', '#E8E4C4', '#DBD5AF']); + elements.kiwi = new fruit("kiwi", ['#886002', '#7D5B0D', '#876412', '#97620F'], ['#7DB410', '#86BC1B', '#95CE22', '#91CF12'], "vine"); + elements.kiwi_seed = new vineSeed("kiwi", ['#3E2A01', '#392804', '#473307', '#1E1500']); + elements.raspberry = new fruit("raspberry", ['#FF201C', '#EF3D3A', '#FA5350', '#DF3E3B'], ['#FF4450', '#F43643', '#DF2C38', '#E92344'], "bush"); + elements.raspberry_seed = new bushSeed("raspberry", ['#572600', '#4C2506', '#592E0D', '#5E3211']); + elements.blueberry = new fruit("blueberry", ['#322954', '#3F3366', '#2B1B5E', '#4C3C81'], ['#51042C', '#550E33', '#420D28', '#520F32'], "bush", ['#78573A', '#72492D', '#7D5438', '#704F3A']); + elements.blackberry = new fruit("blackberry", ['#1A013A', '#1E073A', '#3D0A49', '#33043F'], ['#DC5F5F', '#D76D6D', '#BF6363', '#B05D5D'], "bush", ['#DA7878', '#C87B7B', '#AD6161', '#915656']); + elements.blackberry.bloomColor = ["#f5f5f5", "#ede8ec", "#ebdfe8", "#f7f2f6", "#ffffff"]; + elements.strawberry = new fruit("strawberry", ['#FE3030', '#E93030', '#DE1F1F', '#CE0B0B'], ['#EA5C46', '#E24B34', '#CE5A48', '#E7604B'], "vine", ['#B27F65', '#AA7358', '#A27553', '#AF8B62'], false, true); + elements.pear = new fruit("pear", ["#F1F8A7", "#DCE398", "#E3EE7E", "#D6E07F"], ["#F6F9D5", "#F6F9D5", "#E8ECC6", "#E8ECC0"], "tree", ["#3B1C01", "#3E2107", "#3A1C02"]); + elements.mango = new fruit("mango", ["#F74E3E", "#E95D51", "#EE853B", "#D77026", "#F8BF46", "#F8B524", "#95C408", "#A5CD2D"], ["#FFC905", "#FFD605", "#FFE205", "#FFF305", "#FCE118"], "tree", ["#E8EABB", "#E3E5BA", "#EAEDC0", "#E8EAB1", "#D8DBA5"]); + elements.lemon = new fruit("lemon", ["#FCF924", "#FCF924", "#EEEA1A", "#F6F212", "#FBF70B"], ["#F6F373", "#EEEC77", "#E3E267", "#F3F18B"], "tree", ["#F8F7B2", "#E9E9B1", "#E9E8A7", "#F1EFA4"]); + elements.plum = new fruit("plum", ["#67486E", "#705476", "#634A69", "#785281"], ["#D58D77", "#DC9984", "#CA8D7A", "#CF816A"], "tree", ["#A08C5D", "#907D50", "#9B8551", "#AA9563"]); + elements.plum.bloomColor = ["#ffb3df", "#ffa6da", "#ffbde3", "#ffd1ec"]; + elements.peach = new fruit("peach", ["#F76856", "#EA5D4A", "#EA6D4A", "#E5785A", "#FE824A", "#EE7A45", "#FAA543", "#F59D39", "#FF744D"], ["#F86F1F", "#EC742F", "#EC832F", "#EC9A2F", "#ECA62F"], "tree", ["#735940", "#7B5C3D", "#7D5935"]); + elements.peach.bloomColor = ["#ffb3df", "#ffa6da", "#ffbde3", "#ffd1ec"]; + elements.apricot = new fruit("apricot", ["#F5A61F", "#F5A61F", "#EA9B12", "#F8A109"], ["#F2B016", "#F2AD0C", "#FBB81E", "#FFB301"], "tree", ["#735940", "#7B5C3D", "#7D5935"]); + elements.apricot.bloomColor = ["#fff0fb", "#ffffff", "#fadef3", "#fcd9f4"]; + elements.avocado = new fruit("avocado", ["#3c9419", "#348514", "#367a1b", "#2f7d10"], ["#cff74a", "#caf244", "#c1e649", "#b3d640"], "tree", ["#4d290a", "#4d2b0d", "#63360f", "#572d09"]); + elements.avocado.bloomColor = ["#e3ff9c", "#e1ff96", "#e6ffa6", "#e1faa2"]; + elements.avocado.breakInto = "guacamole"; + elements.guacamole = { + color: ["#cff74a", "#caf244", "#c1e649", "#b3d640"], + behavior: behaviors.LIQUID, + viscosity: 1350, + category: "food", + state: "liquid", + isFood: true, + onMix: function(pixel){ + for(let coords of squareCoords){ + let x = pixel.x+coords[0], y = pixel.y+coords[1]; + if(!isEmpty(x,y) && !outOfBounds(x,y) && elements[pixelMap[x][y].element].isFood && pixelMap[x][y].element != "quacamole"){ + let chance = (shiftDown) ? 1 : 0.5; + if(Math.random() < chance){ + let rgb = interpolateRgb(getRGB(pixel.color), getRGB(pixelMap[x][y].color), 0.8); + changePixel(pixelMap[x][y], "guacamole"); + pixel.color = rgb; + pixelMap[x][y].color = rgb; + } } } } } -} -runAfterAutogen(()=>{settingsMenu.innerHTML += ` - - -`;}); -elements.cocoa = new fruit("cocoa", ["#b09533", "#ad9439", "#b39736", "#99732c", "#ab8338", "#ad8231"], ["#826a3e", "#634f28", "#634b1f", "#5c461c"], "tree", ["#826a3e", "#634f28", "#634b1f", "#5c461c"]); -elements.cocoa.breakInto = "cocoa_seed"; -elements.cocoa_seed.name = "CocoaBean"; -elements.cocoa_seed.breakInto = undefined; -elements.cocoa_seed.tempHigh = 125; -elements.cocoa_seed.stateHigh = "roasted_cocoa_bean"; -elements.roasted_cocoa_bean = { - category: "food", - behavior: behaviors.POWDER, - extract: "melted_cocoa_butter", - color: ["#2b1b01", "#291a02", "#211503", "#211503"], - breakInto: "cocoa_powder", -} -elements.cocoa_powder = { - category: "food", - behavior: behaviors.POWDER, - color: ["#3b2604", "#332104", "#402802", "#301e01"], -} -elements.cocoa_butter = { - behavior: behaviors.STURDYPOWDER, - tempHigh: 36, - color: ["#feffe8", "#f4f5dc", "#fcfce1", "#feffed", "#feffd6"], - category: "food", - isFood: true, - stateHigh: "melted_cocoa_butter", -} -elements.melted_cocoa_butter = { - behavior: behaviors.LIQUID, - color: ["#fff082", "#e3d676", "#f2e57e", "#fff07d"], - tempLow: 35, - stateLow: "cocoa_butter", - reactions: { - cocoa_powder: {elem1: "chocolate", elem2: "chocolate"} - }, - category: "states", - isFood: true, - viscosity: 750, - temp: 36, -}; -elements.extractor = { - category: "machines", - behavior: behaviors.WALL, - tick: function(pixel){ - for(let coords of squareCoords){ - let x = pixel.x+coords[0], y = pixel.y+coords[1]; - if(!isEmpty(x,y) && !outOfBounds(x,y) && elements[pixelMap[x][y].element].extract != undefined){ - changePixel(pixelMap[x][y], elements[pixelMap[x][y].element].extract); + runAfterAutogen(()=>{settingsMenu.innerHTML += ` + + + `;}); + elements.cocoa = new fruit("cocoa", ["#b09533", "#ad9439", "#b39736", "#99732c", "#ab8338", "#ad8231"], ["#826a3e", "#634f28", "#634b1f", "#5c461c"], "tree", ["#826a3e", "#634f28", "#634b1f", "#5c461c"]); + elements.cocoa.breakInto = "cocoa_seed"; + elements.cocoa_seed.name = "CocoaBean"; + elements.cocoa_seed.breakInto = undefined; + elements.cocoa_seed.tempHigh = 125; + elements.cocoa_seed.stateHigh = "roasted_cocoa_bean"; + elements.roasted_cocoa_bean = { + category: "food", + behavior: behaviors.POWDER, + extract: "melted_cocoa_butter", + color: ["#2b1b01", "#291a02", "#211503", "#211503"], + breakInto: "cocoa_powder", + } + elements.cocoa_powder = { + category: "food", + behavior: behaviors.POWDER, + color: ["#3b2604", "#332104", "#402802", "#301e01"], + } + elements.cocoa_butter = { + behavior: behaviors.STURDYPOWDER, + tempHigh: 36, + color: ["#feffe8", "#f4f5dc", "#fcfce1", "#feffed", "#feffd6"], + category: "food", + isFood: true, + stateHigh: "melted_cocoa_butter", + } + elements.melted_cocoa_butter = { + behavior: behaviors.LIQUID, + color: ["#fff082", "#e3d676", "#f2e57e", "#fff07d"], + tempLow: 35, + stateLow: "cocoa_butter", + reactions: { + cocoa_powder: {elem1: "chocolate", elem2: "chocolate"} + }, + category: "states", + isFood: true, + viscosity: 750, + temp: 36, + }; + elements.extractor = { + category: "machines", + behavior: behaviors.WALL, + tick: function(pixel){ + for(let coords of squareCoords){ + let x = pixel.x+coords[0], y = pixel.y+coords[1]; + if(!isEmpty(x,y) && !outOfBounds(x,y) && elements[pixelMap[x][y].element].extract != undefined){ + changePixel(pixelMap[x][y], elements[pixelMap[x][y].element].extract); + } } - } - }, - movable: false, -} -elements.pineapple_seed = { - behavior: behaviors.POWDER, - color: ["#242000", "#1f1c00", "#1a1701", "#1f1c01"], - category: "life", - properties: { - age: 0, - fruit: "pineapple", - growthPattern: true, - }, - tick: function(pixel){ - let num = Math.round((Math.random()*0.75)*3)+1; - chance = (pixel.age -140)/100; - chance = Math.max(Math.min(chance, 1), 0); - if(Math.random() 55){ - pixel.alive = false; - } - if(Math.random()<(pixel.age-95)/7500 && pixel.height < pixel.maxHeight && pixel.alive){ - let y = pixel.y; - tryMove(pixel, pixel.x, pixel.y-1); - pixel.height++; - createPixel("wood", pixel.x, y); - if(Math.random()<0.333){ - let i = new growInterval(pixel, growthPatterns.palm(Math.round((pixel.height/pixel.maxHeight)*14), 174, 366, [235,305]), [pixel.x, y], 0.25, 200); + elements.dead_plant.behavior = [["XX","XX","XX"],["XX","CH:dirt%0.015","XX"],["M2","M1","M2"]]; + elements.banana = { + category: "food", + breakInto: "juice", + bloomColor: ["#6e2942", "#63293e", "#703249", "#82314f"], + color: ["#e8de20", "#f2e824", "#f0e626", "#ebe01c", "#f0e51a"], + breakIntoColor: ["#f2f0cb", "#f0eec5", "#f2f0c4"], + isFood: true, + }; + elements.coconut = { + behavior: [['XX', 'XX', 'XX'],['XX', 'XX', 'XX'],['M2', 'M1 AND ST:wood', 'M2']], + color: ["#291706", "#382007", "#2e1905", "#361d05", "#361e06"], + category: "food", + properties: { + age: 0, + fruit: "coconut", + height: 0, + maxHeight: null, + alive: null, + leafLength: null, + intervals: [], + }, + breakInto: "coconut_water", + extract: "coconut_oil", + onDelete: function(pixel){ + for(let value of pixel.intervals){ + clearInterval(value); + } + }, + tick: function(pixel){ + if(pixel.alive == null){ + pixel.alive = shiftDown; + } + if(pixel.maxHeight == null){ + pixel.maxHeight = 15+Math.round(Math.random()*6); + } + if(pixel.leafLength == null){ + pixel.leafLength = Math.round((pixel.maxHeight/21)*Math.random()*4)+12; + } + if(pixel.alive && pixel.temp > 55){ + pixel.alive = false; + } + if(Math.random()<(pixel.age-95)/7500 && pixel.height < pixel.maxHeight && pixel.alive){ + let y = pixel.y; + tryMove(pixel, pixel.x, pixel.y-1); + pixel.height++; + createPixel("wood", pixel.x, y); + if(Math.random()<0.333){ + let i = new growInterval(pixel, growthPatterns.palm(Math.round((pixel.height/pixel.maxHeight)*14), 174, 366, [235,305]), [pixel.x, y], 0.25, 200); + pixel.intervals.push(i.interval); + } + } + if(pixel.height == pixel.maxHeight && Math.random()<0.055){ + let amnt = 6+Math.round(Math.random()*4); + for(let i = 0; i < amnt; i++){ + let i = new growInterval(pixel, growthPatterns.palm(16, 174, 366, [255,285]), [pixel.x, pixel.y], 0.15); + pixel.intervals.push(i.interval); + } + let i = new growInterval(pixel, growthPatterns.palm_bloom(), [pixel.x,pixel.y], 0.025, undefined, pixel.fruit, ["flower"]); pixel.intervals.push(i.interval); + pixel.height++; } + pixel.age++; } - if(pixel.height == pixel.maxHeight && Math.random()<0.055){ - let amnt = 6+Math.round(Math.random()*4); - for(let i = 0; i < amnt; i++){ - let i = new growInterval(pixel, growthPatterns.palm(16, 174, 366, [255,285]), [pixel.x, pixel.y], 0.15); - pixel.intervals.push(i.interval); - } - let i = new growInterval(pixel, growthPatterns.palm_bloom(), [pixel.x,pixel.y], 0.025, undefined, pixel.fruit, ["flower"]); - pixel.intervals.push(i.interval); - pixel.height++; - } - pixel.age++; } -} -elements.coconut_oil = { - behavior: behaviors.SOLID, - color: ["#f0efed", "#edeceb", "#e6e4e3", "#ebe9e8"], - category: "food", - isFood: true, - reactions: { - caustic_potash: {elem1: "soap", elem2: "soap"}, - lye: {elem1: "soap", elem2: "soap"}, - }, - tempHigh: 24, - stateHigh: "melted_coconut_oil", - state: "solid", -} -elements.melted_coconut_oil = { - behavior: behaviors.LIQUID, - color: ["#f0f0eb", "#e6e5d5", "#f5f4e6", "#f7f7e6", "#ededdd"], - viscosity: 750, - category: "states", - state: "liquid", - isFood: true, - reactions: { - caustic_potash: {elem1: "soap", elem2: "soap"}, - lye: {elem1: "soap", elem2: "soap"}, - }, - tempLow: 23, - stateLow: "coconut_oil" -} -elements.coconut_water = { - color: ["#8dd6d9", "#8cd9db", "#82d6d9"], - behavior: behaviors.LIQUID, - isFood: true, - category: "food", - state: "liquid", - tempHigh: 100, - stateHigh: ["sugar", "steam", "steam", "steam", "potassium_salt", "salt", "epsom_salt", "steam", "steam", "steam"] -} -elements.morning_glory_seed = { - behavior: behaviors.VINEFRUIT, - bloomColors: [["#f783f0", "#fa8cf3", "#fa96f3", "#f590ee"], ["#8d40f7", "#9a52ff", "#8041d9", "#7e3ade"], ["#ed5365", "#f0485b", "#f55b6d", "#eb3d51"], ["#f53d49", "#fa4652", "#f54e59", "#f23a46"], ["#f53d49", "#fa8cf3", "#f55b6d", "#f23a46"]], - color: ["#5c5036", "#473e29", "#4f4631", "#fcf2b8"], - properties: { - bloomColor: null, - fruit: "morning_glory_seed", - age: 0, - }, - category: "life", - tick: function(pixel){ - if(pixel.bloomColor == null){ - let arr = elements.morning_glory_seed.bloomColors[Math.round(Math.random()*elements.morning_glory_seed.bloomColors.length)]; - while(!Array.isArray(arr)){ - arr = elements.morning_glory_seed.bloomColors[Math.round(Math.random()*elements.morning_glory_seed.bloomColors.length)]; - } - let num = 100*(10**Math.random()/10); - let newArr = false; - for(let item of arr){ - let o = item; - let rgb = hexToRGB(item); - let newRGB = {r: Math.min(255, rgb.r+num), g: Math.min(255, rgb.g+num), b: Math.min(255, rgb.b+num)}; - newArr = []; - newArr[arr.indexOf(item)] = RGBToHex(newRGB); - - } - pixel.bloomColor = (newArr) ? newArr : arr; - } else if(Math.random() < (pixel.age/2000)) { - let fruit = pixel.fruit, bloomColor = pixel.bloomColor; - changePixel(pixel, "fruit_vine"); - pixel.fruit = fruit, pixel.bloomColor = bloomColor; - } - pixel.age++; + elements.coconut_oil = { + behavior: behaviors.SOLID, + color: ["#f0efed", "#edeceb", "#e6e4e3", "#ebe9e8"], + category: "food", + isFood: true, + reactions: { + caustic_potash: {elem1: "soap", elem2: "soap"}, + lye: {elem1: "soap", elem2: "soap"}, + }, + tempHigh: 24, + stateHigh: "melted_coconut_oil", + state: "solid", } -} -elements.apricot_seed.tempHigh = 175; -elements.apricot_seed.stateHigh = "almond"; -elements.almond = { - color: ["#ab9450", "#b3994d", "#a18943", "#a18c43", "#a18d47"], - behavior: behaviors.POWDER, - state: "solid", - category: "food", - isFood: true, - density: 1100, - stateHigh: ["charcoal", "fire", "smoke"], - tempHigh: 550, - tick: function(pixel){ - for(let coords of squareCoords){ - let x = pixel.x+coords[0], y = pixel.y+coords[1]; - let p2 = getPixel(x,y); - let chance = (pixel.temp > 0) ? ((pixel.temp**0.1)-1)*0.0025 : 0; - if(p2 != null && p2.element == "alcohol" && Math.random() < chance){ - changePixel(p2, "almond_extract"); + elements.melted_coconut_oil = { + behavior: behaviors.LIQUID, + color: ["#f0f0eb", "#e6e5d5", "#f5f4e6", "#f7f7e6", "#ededdd"], + viscosity: 750, + category: "states", + state: "liquid", + isFood: true, + reactions: { + caustic_potash: {elem1: "soap", elem2: "soap"}, + lye: {elem1: "soap", elem2: "soap"}, + }, + tempLow: 23, + stateLow: "coconut_oil" + } + elements.coconut_water = { + color: ["#8dd6d9", "#8cd9db", "#82d6d9"], + behavior: behaviors.LIQUID, + isFood: true, + category: "food", + state: "liquid", + tempHigh: 100, + stateHigh: ["sugar", "steam", "steam", "steam", "potassium_salt", "salt", "epsom_salt", "steam", "steam", "steam"] + } + elements.morning_glory_seed = { + behavior: behaviors.VINEFRUIT, + bloomColors: [["#f783f0", "#fa8cf3", "#fa96f3", "#f590ee"], ["#8d40f7", "#9a52ff", "#8041d9", "#7e3ade"], ["#ed5365", "#f0485b", "#f55b6d", "#eb3d51"], ["#f53d49", "#fa4652", "#f54e59", "#f23a46"], ["#f53d49", "#fa8cf3", "#f55b6d", "#f23a46"]], + color: ["#5c5036", "#473e29", "#4f4631", "#fcf2b8"], + properties: { + bloomColor: null, + fruit: "morning_glory_seed", + age: 0, + }, + category: "life", + tick: function(pixel){ + if(pixel.bloomColor == null){ + let arr = elements.morning_glory_seed.bloomColors[Math.round(Math.random()*elements.morning_glory_seed.bloomColors.length)]; + while(!Array.isArray(arr)){ + arr = elements.morning_glory_seed.bloomColors[Math.round(Math.random()*elements.morning_glory_seed.bloomColors.length)]; + } + let num = 100*(10**Math.random()/10); + let newArr = false; + for(let item of arr){ + let o = item; + let rgb = hexToRGB(item); + let newRGB = {r: Math.min(255, rgb.r+num), g: Math.min(255, rgb.g+num), b: Math.min(255, rgb.b+num)}; + newArr = []; + newArr[arr.indexOf(item)] = RGBToHex(newRGB); + + } + pixel.bloomColor = (newArr) ? newArr : arr; + } else if(Math.random() < (pixel.age/2000)) { + let fruit = pixel.fruit, bloomColor = pixel.bloomColor; + changePixel(pixel, "fruit_vine"); + pixel.fruit = fruit, pixel.bloomColor = bloomColor; + } + pixel.age++; + } + } + elements.apricot_seed.tempHigh = 175; + elements.apricot_seed.stateHigh = "almond"; + elements.almond = { + color: ["#ab9450", "#b3994d", "#a18943", "#a18c43", "#a18d47"], + behavior: behaviors.POWDER, + state: "solid", + category: "food", + isFood: true, + density: 1100, + stateHigh: ["charcoal", "fire", "smoke"], + tempHigh: 550, + tick: function(pixel){ + for(let coords of squareCoords){ + let x = pixel.x+coords[0], y = pixel.y+coords[1]; + let p2 = getPixel(x,y); + let chance = (pixel.temp > 0) ? ((pixel.temp**0.1)-1)*0.0025 : 0; + if(p2 != null && p2.element == "alcohol" && Math.random() < chance){ + changePixel(p2, "almond_extract"); + } } } } -} -elements.almond_extract = { - color: ["#cfccbe", "#d6d4c7", "#c9c7bb", "#ccc9b8"], - behavior: behaviors.LIQUID, - isFood: true, - category: "food", - state: "liquid", - density: 815, - tempHigh: 78, - stateHigh: ["alcohol_gas", "fragrance"], - tempLow: -118, - stateLow: "frozen_almond_extract", - burn: 100, - burnTime: 15, - fireColor: ['#80acf0', '#96cdfe', '#bee6d4'], - burnInto: ["fragrance", "smoke", "smoke"], -} -elements.frozen_almond_extract = { - color: ["#cfccbe", "#d6d4c7", "#c9c7bb", "#ccc9b8"], - behavior: behaviors.SOLID, - isFood: true, - category: "states", - state: "solid", - density: 865, - tempHigh: -117, - stateHigh: "almond_extract", -} - -elements.onion = { - category: "food", - color: ["#dbaa5a", "#cc9b4b", "#bd9048", "#faebb4", "#fcf5d9", "#f2e9c7", "#7d2d50", "#ad3d6e", "#c25182"], - state: "solid", - properties: { - age: 0, - sprouted: null, - intervals: [], - height: null, - }, - isFood: true, - behavior: behaviors.POWDER, - onDelete: function(pixel){ - for(let value of pixel.intervals){ - clearInterval(value); - } - }, - tick: function(pixel){ - let inDirt = (getPixel(pixel.x,pixel.y+1) != null && eLists.SOIL.includes(pixelMap[pixel.x][pixel.y+1].element)) ? true : false; - for(let coords of adjacentCoords){ - let x = pixel.x+coords[0], y = pixel.y+coords[1]; - let p2 = getPixel(x,y); - if(p2 != null){ - inDirt = (eLists.SOIL.includes(p2.element)) ? true : inDirt; + elements.almond_extract = { + color: ["#cfccbe", "#d6d4c7", "#c9c7bb", "#ccc9b8"], + behavior: behaviors.LIQUID, + isFood: true, + category: "food", + state: "liquid", + density: 815, + tempHigh: 78, + stateHigh: ["alcohol_gas", "fragrance"], + tempLow: -118, + stateLow: "frozen_almond_extract", + burn: 100, + burnTime: 15, + fireColor: ['#80acf0', '#96cdfe', '#bee6d4'], + burnInto: ["fragrance", "smoke", "smoke"], + } + elements.frozen_almond_extract = { + color: ["#cfccbe", "#d6d4c7", "#c9c7bb", "#ccc9b8"], + behavior: behaviors.SOLID, + isFood: true, + category: "states", + state: "solid", + density: 865, + tempHigh: -117, + stateHigh: "almond_extract", + } + + elements.onion = { + category: "food", + color: ["#dbaa5a", "#cc9b4b", "#bd9048", "#faebb4", "#fcf5d9", "#f2e9c7", "#7d2d50", "#ad3d6e", "#c25182"], + state: "solid", + properties: { + age: 0, + sprouted: null, + intervals: [], + height: null, + }, + isFood: true, + behavior: behaviors.POWDER, + onDelete: function(pixel){ + for(let value of pixel.intervals){ + clearInterval(value); } - if((pixel.sprouted == null && pixel.sprouted != "disabled") && pixel.age > 60 && inDirt){ - let height = 7+Math.round(Math.random()*4); - pixel.height = height; - let i = new growInterval(pixel, growthPatterns.stalk(height), [pixel.x,pixel.y], 0.15); - pixel.intervals.push(i.interval); - pixel.sprouted = true; - } else if ((pixel.sprouted == true && pixel.sprouted != "disabled") && Math.random() < 0.0015){ - let i = new growInterval(pixel, growthPatterns.blade(7, 235, 315, [255,295]), [pixel.x,pixel.y], 0.15); - pixel.intervals.push(i.interval); - } - } - if(inDirt){ + }, + tick: function(pixel){ + let inDirt = (getPixel(pixel.x,pixel.y+1) != null && eLists.SOIL.includes(pixelMap[pixel.x][pixel.y+1].element)) ? true : false; for(let coords of adjacentCoords){ let x = pixel.x+coords[0], y = pixel.y+coords[1]; let p2 = getPixel(x,y); - if(p2!=null && eLists.SOIL.includes(p2.element) && Math.random()<0.0005){ - changePixel(p2, "onion"); - p2.color = noiseify(pixel.color, 6); - p2.sprouted = "disabled"; + if(p2 != null){ + inDirt = (eLists.SOIL.includes(p2.element)) ? true : inDirt; + } + if((pixel.sprouted == null && pixel.sprouted != "disabled") && pixel.age > 60 && inDirt){ + let height = 7+Math.round(Math.random()*4); + pixel.height = height; + let i = new growInterval(pixel, growthPatterns.stalk(height), [pixel.x,pixel.y], 0.15); + pixel.intervals.push(i.interval); + pixel.sprouted = true; + } else if ((pixel.sprouted == true && pixel.sprouted != "disabled") && Math.random() < 0.0015){ + let i = new growInterval(pixel, growthPatterns.blade(7, 235, 315, [255,295]), [pixel.x,pixel.y], 0.15); + pixel.intervals.push(i.interval); } } - } - if(pixel.sprouted === true && pixel.age > 600 && Math.random()<0.001){ - let length = Math.round(Math.random()*2); - for(let i = 0; i < 5; i++){ - let ii = new growInterval(pixel, growthPatterns.blade(length,0,360), [pixel.x, pixel.y-pixel.height-length+1], 0.25, undefined, "onion_seed",['flower']); - pixel.intervals.push(ii.interval); + if(inDirt){ + for(let coords of adjacentCoords){ + let x = pixel.x+coords[0], y = pixel.y+coords[1]; + let p2 = getPixel(x,y); + if(p2!=null && eLists.SOIL.includes(p2.element) && Math.random()<0.0005){ + changePixel(p2, "onion"); + p2.color = noiseify(pixel.color, 6); + p2.sprouted = "disabled"; + } + } } - } - pixel.age++; - }, -} -elements.onion_seed = { - behavior: behaviors.POWDER, - color: ["#0f0f0f", "#0f0f0f", "#0a0a0a", "#0a0a0a"], - category: "life", - state: "solid", - tick: function(pixel){ - let inDirt = (getPixel(pixel.x,pixel.y+1) != null && eLists.SOIL.includes(pixelMap[pixel.x][pixel.y+1].element)) ? true : false; - for(let coords of adjacentCoords){ - let x = pixel.x+coords[0], y = pixel.y+coords[1]; - let p2 = getPixel(x,y); - if(p2 != null){ - inDirt = (eLists.SOIL.includes(p2.element)) ? true : inDirt; + if(pixel.sprouted === true && pixel.age > 600 && Math.random()<0.001){ + let length = Math.round(Math.random()*2); + for(let i = 0; i < 5; i++){ + let ii = new growInterval(pixel, growthPatterns.blade(length,0,360), [pixel.x, pixel.y-pixel.height-length+1], 0.25, undefined, "onion_seed",['flower']); + pixel.intervals.push(ii.interval); + } + } + pixel.age++; + }, + } + elements.onion_seed = { + behavior: behaviors.POWDER, + color: ["#0f0f0f", "#0f0f0f", "#0a0a0a", "#0a0a0a"], + category: "life", + state: "solid", + tick: function(pixel){ + let inDirt = (getPixel(pixel.x,pixel.y+1) != null && eLists.SOIL.includes(pixelMap[pixel.x][pixel.y+1].element)) ? true : false; + for(let coords of adjacentCoords){ + let x = pixel.x+coords[0], y = pixel.y+coords[1]; + let p2 = getPixel(x,y); + if(p2 != null){ + inDirt = (eLists.SOIL.includes(p2.element)) ? true : inDirt; + } + } + if(inDirt && Math.random() < 0.025){ + changePixel(pixel, "onion"); } - } - if(inDirt && Math.random() < 0.025){ - changePixel(pixel, "onion"); } } + elements.grape.reactions.sugar_water = {elem2: "wine", chance: 0.0006}; + elements.grape.reactions.water = {elem2: "wine", chance: 0.00006}; + elements.wine = { + density: 992, + color: ["#381b30", "#402137", "#261321", "#38192f"], + behavior: behaviors.LIQUID, + category: "liquids", + state: "liquid", + properties: { + alcChance: 0.13, + }, + tick: function(pixel){ + if(Math.random() < 0.00025){ + pixel.alcChance += 0.01; + } + if(pixel.temp >70){ + let chanceMulti = (pixel.temp-70)/20; + let chance = (pixel.alcChance/100)*chanceMulti; + for(let coords of squareCoords){ + let x = pixel.x+coords[0], y = pixel.y+coords[1]; + if(isEmpty(x,y) && !outOfBounds(x,y) && Math.random() < chance){ + createPixel("alcohol_gas", x,y); + if(Math.random() < 0.5){ + let rgb = getRGB(pixel.color); + for(let key in rgb){ + rgb[key] += 10; + rgb[key] = Math.max(rgb[key], 0); + } + changePixel(pixel, "juice"); + + pixel.color = noiseify(RGBToHex(rgb), 6); + } + } + } + } + }, + tempHigh: 100, + stateHigh: ["sugar", "carbon_dioxide", "steam", "alcohol_gas"], + }; + + }