This commit is contained in:
JustAGenericUsername 2025-09-06 09:48:55 -04:00
commit 891a8275dd
22 changed files with 8453 additions and 529 deletions

View File

@ -7,4 +7,4 @@ Rules for publishing mods:
Failure to follow these rules may result in your pull request being ignored!
Learn more about [submitting your mod](https://sandboxels.wiki.gg/wiki/Modding_tutorial#Putting_it_online).
Learn more about [submitting your mod](https://sandboxels.wiki.gg/wiki/Modding/Putting_it_online).

View File

@ -6,7 +6,12 @@ Play for free at [Sandboxels.R74n.com](https://sandboxels.r74n.com/).
Join the [Discord server](https://discord.com/invite/ejUc6YPQuS).
![Landscape made in Sandboxels](https://raw.githubusercontent.com/R74nCom/sandboxels/main/icons/cover-3840x1240px-text.png)
# Modding
New to modding? Read the Sandboxels Wiki articles on [getting started with modding](https://sandboxels.wiki.gg/wiki/Modding/Getting_started) or [publishing your mod](https://sandboxels.wiki.gg/wiki/Modding/Putting_it_online).
Please read the [Contribution Guidelines](https://github.com/R74nCom/sandboxels/tree/main/.github/CONTRIBUTING.md) before submitting your mod.
# Controls
* Left Click = Draw pixels
* Right Click = Erase pixels

View File

@ -71,6 +71,9 @@
.R74nLink {
color: #00ffff;
}
ol li {
margin-bottom: 10px;
}
</style>
</head>
@ -81,7 +84,9 @@
<p>Sandboxels has a huge selection of mods that add new content to the simulator. They are created by community members and aren't endorsed by the developer of Sandboxels.</p>
<h2>How to enable a mod</h2>
<p>Jump to: <a href="#Create">Create your own mod</a>, <a href="#Issues">Issues with mods</a></p>
<h2 id="Enable">How to enable a mod</h2>
<ol>
<li>Go to the official <a href="https://sandboxels.R74n.com/">Sandboxels website</a>.</li>
<li>Press the <strong>Mods</strong> button in the toolbar to open the Mod Manager.</li>
@ -89,7 +94,7 @@
<li>Press enter, then refresh the page.</li>
</ol>
<h2>Sandboxels Mod List</h2>
<h2 id="List">Sandboxels Mod List</h2>
<p>Mods submitted to our <a href="https://github.com/R74nCom/sandboxels/tree/main/mods" target="_blank">GitHub repo</a> are listed here.</p>
<table>
<thead>
@ -189,6 +194,7 @@
<tr><td>text.js</td><td>Tools to write text</td><td>RedBirdly</td></tr>
<tr><td>texturepack.js</td><td>Tools that let you create and share custom texture packs</td><td>nousernamefound</td></tr>
<tr><td>the_ground.js</td><td>Several rock types, worldgen settings, and gemstones</td><td>Alice</td></tr>
<tr><td>worldEdit.js</td><td>Selection and editing tools</td><td>RedBirdly</td></tr>
<tr><td>worldgenlibrary.js</td><td>World generation library</td><td>Adora</td></tr>
<!----><tr><td class="modCat" colspan="3">Science & Chemistry</td></tr><!---->
@ -263,6 +269,7 @@
<tr><td>pullers.js</td><td>Pixels that pull pixels towards them</td><td>voidapex11</td></tr>
<tr><td>pushers.js</td><td>Pixels that push elements away from them</td><td>Alice</td></tr>
<tr><td>sandboxels.js</td><td>Digital screen to play a mini version of Sandboxels</td><td>Nekonico</td></tr>
<tr><td>schematics.js</td><td>Schematics for logic gates</td><td>SquareScreamYT</td></tr>
<tr><td>spouts.js</td><td>Spouts for all liquids</td><td>kaeud</td></tr>
<tr><td>state_voids.js</td><td>Several elements that delete specific states of matter</td><td>Alice</td></tr>
<tr><td>switches.js</td><td>Electrical switches that can be toggled</td><td>Alice</td></tr>
@ -394,6 +401,7 @@
<!----><tr><td class="modCat" colspan="3">Visual Effects</td></tr><!---->
<tr><td>acid_and_shapes.js</td><td>Weird visual effects enabled in settings</td><td>Alice</td></tr>
<tr><td>asciiboxels.js</td><td>Renders pixels as ASCII characters</td><td>Nekonico</td></tr>
<tr><td>clouds.js</td><td>Moving clouds, sky.js recommended</td><td>RedBirdly</td></tr>
<tr><td>customBackground.js</td><td>Set your background to an image link</td><td>Jayd</td></tr>
<tr><td>fast_lightmap.js</td><td>Light sources glow, but faster</td><td>RedBirdly</td></tr>
@ -473,11 +481,12 @@
</tbody>
</table>
<h2>How to create your own mod</h2>
<p>To create a Sandboxels mod yourself, you may need knowledge of JavaScript programming and GitHub.</p>
<p>There is a <a href="https://sandboxels.wiki.gg/wiki/Modding_tutorial" target="_blank">modding tutorial</a> on the Sandboxels Wiki, and an <a href="https://sandboxels.r74n.com/mods/example_mod.js">Example Mod</a> to base yours off of.</p>
<h2 id="Create">How to create your own mod</h2>
<h2>Issues with mods</h2>
<p>To learn to create your own Sandboxels mod, read the <a href="https://sandboxels.wiki.gg/wiki/Modding/Getting_started" target="_blank">Modding Tutorial</a> on the Sandboxels Wiki, and an <a href="https://sandboxels.r74n.com/mods/example_mod.js">Example Mod</a> to base yours off of.</p>
<p>Mods are submitted to the <a href="https://github.com/R74nCom/sandboxels" target="_blank">GitHub repo</a>.</p>
<h2 id="Issues">Issues with mods</h2>
<p>We don't provide support for unofficial mods. You may ask for help in our <a href="https://discord.gg/ejUc6YPQuS">Discord server</a>, or press Clear Mods in <a href="help">Settings</a>.</p>
<p>Some mods may not work every time you load the game, or even at all!</p>

View File

@ -1,5 +1,6 @@
// created by SquareScreamYT
// https://github.com/SquareScreamYT/aChefsDream.js
// created by SquareScreamYT/sq
// https://github.com/SquareScreamYT/
// https://youtube.com/@sqec
runAfterLoad(function() {
console.log("Thanks for using aChefsDream.js! -sqec")
@ -2335,7 +2336,7 @@ elements.lemon_juice = {
hidden: true,
tempLow: 0,
reactions: {
"sugar": {elem1:"lemonade", elem2: "null", chance:0.35}
"sugar": {elem1:"lemonade", elem2: null, chance:0.35}
}
};
eLists.JUICEMIXABLE.push("lemon_juice");
@ -7447,8 +7448,8 @@ elements.raw_beef = {
stateHigh: "steak",
reactions: {
"smoke": {elem1: "smoked_beef"},
"charcoal": {elem1: "barbecued_beef", tempMin: 70},
"fire": {elem1: "barbecued_beef"}
"charcoal": {elem1: "brisket", tempMin: 70},
"fire": {elem1: "brisket"}
}
};

View File

@ -1,393 +1,598 @@
// created by SquareScreamYT
// the sequel to aChefsDream!
// created by SquareScreamYT/sq
// https://github.com/SquareScreamYT/
// https://youtube.com/@sqec
version = "v2.1.0"
runAfterLoad(function() {
console.log("Thanks for using aChefsDream2.js! -sqec")
console.log("Current aChefsDream version: "+version)
})
var mods_to_include = ["mods/aChefsDream.js"]
dependOn("aChefsDream.js", function(){
var mods_included = mods_to_include.map(mod => enabledMods.includes(mod));
var all_mods_included = mods_included.reduce(function(a,b) { return a && b });
if(!all_mods_included) {
var mods_needed = mods_to_include.filter(function(modPath) { return !(enabledMods.includes(modPath)) });
mods_needed.forEach(function(modPath) {
enabledMods.splice(enabledMods.indexOf("mods/aChefsDream2"),0,modPath);
});
localStorage.setItem("enabledMods", JSON.stringify(enabledMods));
}
console.log("we recommend using nousersthings.js, elementEraser.js and delete_all_of_element.js for a better cooking experience!")
// Pork and Pigs
elements.pig = {
color: ["#9c6732", "#dbb997", "#fcaeae"],
behavior: [
"M2%1|XX|M2%1",
"M2%10|XX|M2%10",
"XX|M1|XX",
],
category:"life",
color: ["#9c6732", "#dbb997", "#fcaeae"],
behavior: [
"M2%1|XX|M2%1",
"M2%10|XX|M2%10",
"XX|M1|XX",
],
category:"life",
state: "solid",
reactions: {
"petal": { elem2:null, chance:0.2, func:behaviors.FEEDPIXEL },
"corn": { elem2:null, chance:0.3, func:behaviors.FEEDPIXEL },
"lettuce": { elem2:null, chance:0.3, func:behaviors.FEEDPIXEL },
"wheat": { elem2:null, chance:0.3, func:behaviors.FEEDPIXEL },
"grass": { elem2:null, chance:0.1, func:behaviors.FEEDPIXEL },
"grape": { elem2:null, chance:0.3, func:behaviors.FEEDPIXEL },
"pumpkin_seed": { elem2:null, chance:0.3, func:behaviors.FEEDPIXEL },
"pumpkin": { elem2:null, chance:0.1, func:behaviors.FEEDPIXEL },
"nut": { elem2:null, chance:0.2, func:behaviors.FEEDPIXEL },
"lichen": { elem2:null, chance:0.2, func:behaviors.FEEDPIXEL },
"oxygen": { elem2:"carbon_dioxide", chance:0.3 },
"mercury": { elem1:"rotten_meat", chance:0.1 },
"bleach": { elem1:"rotten_meat", chance:0.1 },
"infection": { elem1:"rotten_meat", chance:0.025 },
"uranium": { elem1:"rotten_meat", chance:0.1 },
"cyanide": { elem1:"rotten_meat", chance:0.1 },
"chlorine": { elem1:"meat", chance:0.1 },
"dirty_water": { elem1:"rotten_meat", chance:0.0001 },
},
egg: "piglet",
foodNeed: 10,
temp: 40,
tempHigh: 75,
stateHigh: "cooked_pork",
tempLow: -18,
stateLow: "frozen_meat",
breakInto: "raw_pork",
burn:85,
burnTime:450,
state: "solid",
density: 1117,
conduct: 0.3,
extractInto: "raw_pork",
reactions: {
"petal": { elem2:null, chance:0.2, func:behaviors.FEEDPIXEL },
"corn": { elem2:null, chance:0.3, func:behaviors.FEEDPIXEL },
"lettuce": { elem2:null, chance:0.3, func:behaviors.FEEDPIXEL },
"wheat": { elem2:null, chance:0.3, func:behaviors.FEEDPIXEL },
"grass": { elem2:null, chance:0.1, func:behaviors.FEEDPIXEL },
"grape": { elem2:null, chance:0.3, func:behaviors.FEEDPIXEL },
"pumpkin_seed": { elem2:null, chance:0.3, func:behaviors.FEEDPIXEL },
"pumpkin": { elem2:null, chance:0.1, func:behaviors.FEEDPIXEL },
"nut": { elem2:null, chance:0.2, func:behaviors.FEEDPIXEL },
"lichen": { elem2:null, chance:0.2, func:behaviors.FEEDPIXEL },
"oxygen": { elem2:"carbon_dioxide", chance:0.3 },
"mercury": { elem1:"rotten_meat", chance:0.1 },
"bleach": { elem1:"rotten_meat", chance:0.1 },
"infection": { elem1:"rotten_meat", chance:0.025 },
"uranium": { elem1:"rotten_meat", chance:0.1 },
"cyanide": { elem1:"rotten_meat", chance:0.1 },
"chlorine": { elem1:"meat", chance:0.1 },
"dirty_water": { elem1:"rotten_meat", chance:0.0001 },
},
egg: "piglet",
foodNeed: 10,
temp: 40,
tempHigh: 75,
stateHigh: "cooked_pork",
tempLow: -18,
stateLow: "frozen_meat",
breakInto: "raw_pork",
burn:85,
burnTime:450,
state: "solid",
density: 1117,
conduct: 0.3,
extractInto: "raw_pork",
};
elements.piglet = {
color: ["#f7bebe", "#d1a88e"],
behavior: [
"M2%1|XX|M2%1",
"M2%10|FX%5 AND CH:pig%0.1|M2%10",
"XX|M1|XX",
],
category: "life",
state: "solid",
foodNeed: 20,
temp: 40,
tempHigh: 75,
stateHigh: "cooked_pork",
tempLow: -18,
stateLow: "frozen_meat",
breakInto: "blood",
burn:85,
burnTime:450,
state: "solid",
density: 900,
conduct: 0.1,
reactions: {
"petal": { elem2:null, chance:0.2, func:behaviors.FEEDPIXEL },
"corn": { elem2:null, chance:0.3, func:behaviors.FEEDPIXEL },
"lettuce": { elem2:null, chance:0.3, func:behaviors.FEEDPIXEL },
"wheat": { elem2:null, chance:0.3, func:behaviors.FEEDPIXEL },
"grass": { elem2:null, chance:0.1, func:behaviors.FEEDPIXEL },
"grape": { elem2:null, chance:0.3, func:behaviors.FEEDPIXEL },
"pumpkin_seed": { elem2:null, chance:0.3, func:behaviors.FEEDPIXEL },
"pumpkin": { elem2:null, chance:0.1, func:behaviors.FEEDPIXEL },
"nut": { elem2:null, chance:0.2, func:behaviors.FEEDPIXEL },
"lichen": { elem2:null, chance:0.2, func:behaviors.FEEDPIXEL },
"oxygen": { elem2:"carbon_dioxide", chance:0.3 },
"mercury": { elem1:"rotten_meat", chance:0.1 },
"bleach": { elem1:"rotten_meat", chance:0.1 },
"infection": { elem1:"rotten_meat", chance:0.025 },
"uranium": { elem1:"rotten_meat", chance:0.1 },
"cyanide": { elem1:"rotten_meat", chance:0.1 },
"chlorine": { elem1:"meat", chance:0.1 },
"dirty_water": { elem1:"rotten_meat", chance:0.0001 },
},
color: ["#f7bebe", "#d1a88e"],
behavior: [
"M2%1|XX|M2%1",
"M2%10|FX%5 AND CH:pig%0.1|M2%10",
"XX|M1|XX",
],
category: "life",
state: "solid",
foodNeed: 20,
temp: 40,
tempHigh: 75,
stateHigh: "cooked_pork",
tempLow: -18,
stateLow: "frozen_meat",
breakInto: "blood",
burn:85,
burnTime:450,
state: "solid",
density: 900,
conduct: 0.1,
reactions: {
"petal": { elem2:null, chance:0.2, func:behaviors.FEEDPIXEL },
"corn": { elem2:null, chance:0.3, func:behaviors.FEEDPIXEL },
"lettuce": { elem2:null, chance:0.3, func:behaviors.FEEDPIXEL },
"wheat": { elem2:null, chance:0.3, func:behaviors.FEEDPIXEL },
"grass": { elem2:null, chance:0.1, func:behaviors.FEEDPIXEL },
"grape": { elem2:null, chance:0.3, func:behaviors.FEEDPIXEL },
"pumpkin_seed": { elem2:null, chance:0.3, func:behaviors.FEEDPIXEL },
"pumpkin": { elem2:null, chance:0.1, func:behaviors.FEEDPIXEL },
"nut": { elem2:null, chance:0.2, func:behaviors.FEEDPIXEL },
"lichen": { elem2:null, chance:0.2, func:behaviors.FEEDPIXEL },
"oxygen": { elem2:"carbon_dioxide", chance:0.3 },
"mercury": { elem1:"rotten_meat", chance:0.1 },
"bleach": { elem1:"rotten_meat", chance:0.1 },
"infection": { elem1:"rotten_meat", chance:0.025 },
"uranium": { elem1:"rotten_meat", chance:0.1 },
"cyanide": { elem1:"rotten_meat", chance:0.1 },
"chlorine": { elem1:"meat", chance:0.1 },
"dirty_water": { elem1:"rotten_meat", chance:0.0001 },
},
};
elements.barbecued_pork = {
color:["#a1391f","#ab5e32"],
behavior: behaviors.STURDYPOWDER,
category: "food",
state: "solid",
temp:55,
tempHigh: 600,
stateHigh: ["ash","smoke"],
isFood: true,
hidden: true,
color:["#a1391f","#ab5e32"],
behavior: behaviors.STURDYPOWDER,
category: "food",
state: "solid",
temp:55,
tempHigh: 600,
stateHigh: ["ash","smoke"],
isFood: true,
hidden: true,
}
elements.cooked_pork = {
color: ["#e6bf8a", "#e3be96"],
behavior: behaviors.STURDYPOWDER,
category: "food",
state: "solid",
temp: 40,
tempHigh: 600,
stateHigh: ["ash", "smoke"],
hidden: true,
alias: "cooked_pork"
color: ["#e6bf8a", "#e3be96"],
behavior: behaviors.STURDYPOWDER,
category: "food",
state: "solid",
temp: 40,
tempHigh: 600,
stateHigh: ["ash", "smoke"],
hidden: true,
alias: "cooked_pork"
};
elements.raw_pork = {
color: ["#ed5d47", "#e0423d"],
behavior: behaviors.STURDYPOWDER,
category: "food",
state: "solid",
burnInto: "cooked_pork",
temp:25,
tempHigh: 200,
stateHigh: "cooked_pork",
reactions: {
"charcoal": {elem1: "barbecued_pork", tempMin: 70},
"fire": {elem1: "barbecued_pork"}
}
color: ["#ed5d47", "#e0423d"],
behavior: behaviors.STURDYPOWDER,
category: "food",
state: "solid",
burnInto: "cooked_pork",
temp:25,
tempHigh: 200,
stateHigh: "cooked_pork",
reactions: {
"charcoal": {elem1: "barbecued_pork", tempMin: 70},
"fire": {elem1: "barbecued_pork"}
}
};
// Extraction tool
elements.extract = {
color: "#82452c",
// other needed properties
tool: (pixel) => {
//store extractInto as a variable for legibility
var extractInto = elements[pixel.element].extractInto;
//if theres no extractInto, it should equal undefined, which is falsey and !undefined = true
if (!extractInto) { return };
//if extractInto is an array, randomly pick one of its elements
if(extractInto instanceof Array) { extractInto = extractInto[Math.floor(Math.random() * extractInto.length)] };
//change pixel into the (chosen) element
if (shiftDown) {
if (Math.random() < 0.5) {
var thiselement = pixel.element;
changePixel(pixel, extractInto)
pixelTempCheck(pixel);
if (elements[thiselement].extractIntoColor) {
pixel.color = pixelColorPick(pixel, elements[thiselement].extractIntoColor);
}
}
color: "#82452c",
// other needed properties
tool: (pixel) => {
//store extractInto as a variable for legibility
var extractInto = elements[pixel.element].extractInto;
//if theres no extractInto, it should equal undefined, which is falsey and !undefined = true
if (!extractInto) { return };
//if extractInto is an array, randomly pick one of its elements
if(extractInto instanceof Array) { extractInto = extractInto[Math.floor(Math.random() * extractInto.length)] };
//change pixel into the (chosen) element
if (shiftDown) {
if (Math.random() < 0.5) {
var thiselement = pixel.element;
changePixel(pixel, extractInto)
pixelTempCheck(pixel);
if (elements[thiselement].extractIntoColor) {
pixel.color = pixelColorPick(pixel, elements[thiselement].extractIntoColor);
}
else if (!shiftDown) {
if (Math.random() < 0.1) {
var thiselement = pixel.element;
changePixel(pixel, extractInto)
pixelTempCheck(pixel);
if (elements[thiselement].extractIntoColor) {
pixel.color = pixelColorPick(pixel, elements[thiselement].extractIntoColor);
}
}
}
}
else if (!shiftDown) {
if (Math.random() < 0.1) {
var thiselement = pixel.element;
changePixel(pixel, extractInto)
pixelTempCheck(pixel);
if (elements[thiselement].extractIntoColor) {
pixel.color = pixelColorPick(pixel, elements[thiselement].extractIntoColor);
}
},
category: "tools",
canPlace: false,
desc: "Use on pixels to extract the essence from them, if possible. [BETA]"
}
}
},
category: "tools",
canPlace: false,
desc: "Use on pixels to extract the essence from them, if possible. [BETA]"
}
// spices
elements.allspice = {
color: ["#7B5B3A", "#A75B3D", "#B67B57", "#C19A6B"],
behavior: behaviors.POWDER,
category: "food",
state: "solid",
isFood: true,
temp: 20,
hidden: true,
tempHigh: 250,
stateHigh: ["ash", "smoke"],
color: ["#7B5B3A", "#A75B3D", "#B67B57", "#C19A6B"],
behavior: behaviors.POWDER,
category: "food",
state: "solid",
isFood: true,
temp: 20,
hidden: true,
tempHigh: 250,
stateHigh: ["ash", "smoke"],
}
elements.cumin = {
color: "#A58459",
behavior: behaviors.POWDER,
category: "food",
state: "solid",
isFood: true,
temp: 20,
hidden: true,
tempHigh: 250,
stateHigh: ["ash", "smoke"],
color: "#A58459",
behavior: behaviors.POWDER,
category: "food",
state: "solid",
isFood: true,
temp: 20,
hidden: true,
tempHigh: 250,
stateHigh: ["ash", "smoke"],
}
elements.paprika = {
color: ["#C72C29","#b22b02"],
behavior: behaviors.POWDER,
category: "food",
state: "solid",
isFood: true,
temp: 20,
hidden: true,
tempHigh: 250,
stateHigh: ["ash", "smoke"],
color: ["#C72C29","#b22b02"],
behavior: behaviors.POWDER,
category: "food",
state: "solid",
isFood: true,
temp: 20,
hidden: true,
tempHigh: 250,
stateHigh: ["ash", "smoke"],
}
elements.turmeric = {
color: ["#E5B635","#D9A322"],
behavior: behaviors.POWDER,
category: "food",
state: "solid",
isFood: true,
temp: 20,
hidden: true,
tempHigh: 250,
stateHigh: ["ash", "smoke"],
color: ["#E5B635","#D9A322"],
behavior: behaviors.POWDER,
category: "food",
state: "solid",
isFood: true,
temp: 20,
hidden: true,
tempHigh: 250,
stateHigh: ["ash", "smoke"],
}
elements.saffron = {
color: ["#b83b3b","#a82525"],
behavior: behaviors.POWDER,
category: "food",
state: "solid",
isFood: true,
temp: 20,
hidden: true,
tempHigh: 250,
stateHigh: ["ash", "smoke"],
color: ["#b83b3b","#a82525"],
behavior: behaviors.POWDER,
category: "food",
state: "solid",
isFood: true,
temp: 20,
hidden: true,
tempHigh: 250,
stateHigh: ["ash", "smoke"],
}
// sugarcane
elements.sugarcane_plant = {
color: ["#fbc852","#dfad54"],
behavior: [
"XX|M2%2|XX",
"XX|L2:sugarcane AND C2:sugarcane%10|XX",
"XX|M1|XX",
],
tick: behaviors.SEEDRISE,
tempHigh: 100,
stateHigh: "dead_plant",
tempLow: -2,
stateLow: "sugarcane",
burn: 30,
burnTime: 100,
category: "life",
state: "solid",
density: 686,
breakInto: "cane_sugar",
cooldown: defaultCooldown,
seed: true
color: ["#fbc852","#dfad54"],
behavior: [
"XX|M2%2|XX",
"XX|L2:sugarcane AND C2:sugarcane%10|XX",
"XX|M1|XX",
],
tick: behaviors.SEEDRISE,
tempHigh: 100,
stateHigh: "dead_plant",
tempLow: -2,
stateLow: "sugarcane",
burn: 30,
burnTime: 100,
category: "life",
state: "solid",
density: 686,
breakInto: "cane_sugar",
cooldown: defaultCooldown,
seed: true
}
elements.sugarcane = {
color: ["#7cc05c","#77a052"],
behavior: behaviors.STURDYPOWDER,
tempHigh: 380,
stateHigh: ["ember","fire","fire","fire"],
burn: 10,
burnTime: 200,
burnInto: ["ember","fire","fire","fire"],
category: "food",
state: "solid",
density: 686,
breakInto: "cane_sugar",
seed: "sugarcane_plant"
color: ["#7cc05c","#77a052"],
behavior: behaviors.STURDYPOWDER,
tempHigh: 380,
stateHigh: ["ember","fire","fire","fire"],
burn: 10,
burnTime: 200,
burnInto: ["ember","fire","fire","fire"],
category: "food",
state: "solid",
density: 686,
breakInto: "cane_sugar",
seed: "sugarcane_plant"
}
elements.cane_sugar = {
color: "#ffeedb",
behavior: behaviors.POWDER,
reactions: {
"grape": { elem1:null, elem2:"jelly", chance:0.005, tempMin:100 },
"water": { elem1:null, elem2:"sugar_water"},
},
category: "food",
tempHigh: 186,
stateHigh: "caramel",
state: "solid",
density: 1590,
isFood: true
color: "#ffeedb",
behavior: behaviors.POWDER,
reactions: {
"grape": { elem1:null, elem2:"jelly", chance:0.005, tempMin:100 },
"water": { elem1:null, elem2:"sugar_water"},
},
category: "food",
tempHigh: 186,
stateHigh: "caramel",
state: "solid",
density: 1590,
isFood: true
}
elements.tea_leaves = {
color: ["#3e6e26","#507e28","#759e2e"],
reactions: {
"water": { elem2:"tea", tempMin:80 },
"salt_water": { elem2:"tea", tempMin:80 },
"sugar_water": { elem2:"tea", tempMin:80 },
"seltzer": { elem2:"tea", tempMin:80 },
"stench": { elem2:null, chance:0.25 },
"steam": { elem2:"fragrance", chance:0.1 },
"flea": { elem2:null, chance:0.01 },
"termite": { elem2:null, chance:0.01 },
"fly": { elem2:null, chance:0.01 },
"ant": { elem2:null, chance:0.01 },
"stink_bug": { elem2:null, chance:0.01 },
},
behavior: behaviors.POWDER,
tempHigh: 300,
stateHigh: ["fire","smoke","smoke","smoke","ash"],
tempLow: -2,
stateLow: "frozen_plant",
burn:10,
burnTime:300,
burnInto: ["fire","smoke","smoke","smoke","smoke","smoke","smoke","fragrance"],
category:"food",
state: "solid",
density: 1400,
isFood: true,
color: ["#3e6e26","#507e28","#759e2e"],
reactions: {
"water": { elem2:"tea", tempMin:80 },
"salt_water": { elem2:"tea", tempMin:80 },
"sugar_water": { elem2:"tea", tempMin:80 },
"seltzer": { elem2:"tea", tempMin:80 },
"stench": { elem2:null, chance:0.25 },
"steam": { elem2:"fragrance", chance:0.1 },
"flea": { elem2:null, chance:0.01 },
"termite": { elem2:null, chance:0.01 },
"fly": { elem2:null, chance:0.01 },
"ant": { elem2:null, chance:0.01 },
"stink_bug": { elem2:null, chance:0.01 },
},
behavior: behaviors.POWDER,
tempHigh: 300,
stateHigh: ["fire","smoke","smoke","smoke","ash"],
tempLow: -2,
stateLow: "frozen_plant",
burn:10,
burnTime:300,
burnInto: ["fire","smoke","smoke","smoke","smoke","smoke","smoke","fragrance"],
category:"food",
state: "solid",
density: 1400,
isFood: true,
}
elements.cinnamon = {
color: "#986544",
reactions: {
"stench": { elem2:null, chance:0.25 },
"steam": { elem2:"fragrance", chance:0.1 },
"flea": { elem2:null, chance:0.01 },
"termite": { elem2:null, chance:0.01 },
"fly": { elem2:null, chance:0.01 },
"ant": { elem2:null, chance:0.01 },
"stink_bug": { elem2:null, chance:0.01 },
},
behavior: behaviors.STURDYPOWDER,
tempHigh: 300,
stateHigh: ["fire","smoke","smoke","smoke","ash"],
burn:10,
burnTime:300,
burnInto: ["fire","smoke","smoke","smoke","fragrance"],
category:"food",
state: "solid",
density: 1400,
isFood: true,
breakInto: "cinnamon_powder"
color: "#986544",
reactions: {
"stench": { elem2:null, chance:0.25 },
"steam": { elem2:"fragrance", chance:0.1 },
"flea": { elem2:null, chance:0.01 },
"termite": { elem2:null, chance:0.01 },
"fly": { elem2:null, chance:0.01 },
"ant": { elem2:null, chance:0.01 },
"stink_bug": { elem2:null, chance:0.01 },
},
behavior: behaviors.STURDYPOWDER,
tempHigh: 300,
stateHigh: ["fire","smoke","smoke","smoke","ash"],
burn:10,
burnTime:300,
burnInto: ["fire","smoke","smoke","smoke","fragrance"],
category:"food",
state: "solid",
density: 1400,
isFood: true,
breakInto: "cinnamon_powder"
}
elements.cinnamon_powder = {
color: "#D2691E",
reactions: {
"stench": { elem2:null, chance:0.25 },
"steam": { elem2:"fragrance", chance:0.1 },
"flea": { elem2:null, chance:0.01 },
"termite": { elem2:null, chance:0.01 },
"fly": { elem2:null, chance:0.01 },
"ant": { elem2:null, chance:0.01 },
"stink_bug": { elem2:null, chance:0.01 },
},
behavior: behaviors.POWDER,
tempHigh: 300,
stateHigh: ["fire","smoke","smoke","smoke","ash"],
burn:10,
burnTime:300,
burnInto: ["fire","smoke","smoke","smoke","smoke","smoke","smoke","fragrance"],
category:"food",
state: "solid",
density: 1400,
isFood: true,
color: "#D2691E",
reactions: {
"stench": { elem2:null, chance:0.25 },
"steam": { elem2:"fragrance", chance:0.1 },
"flea": { elem2:null, chance:0.01 },
"termite": { elem2:null, chance:0.01 },
"fly": { elem2:null, chance:0.01 },
"ant": { elem2:null, chance:0.01 },
"stink_bug": { elem2:null, chance:0.01 },
},
behavior: behaviors.POWDER,
tempHigh: 300,
stateHigh: ["fire","smoke","smoke","smoke","ash"],
burn:10,
burnTime:300,
burnInto: ["fire","smoke","smoke","smoke","smoke","smoke","smoke","fragrance"],
category:"food",
state: "solid",
density: 1400,
isFood: true,
}
elements.cola_syrup = {
color: "#4f0e0e",
behavior: behaviors.LIQUID,
tempHigh: 170,
stateHigh: ["sugar","smoke","smoke"],
tempLow: -15,
category:"liquids",
state: "liquid",
viscosity: 15,
hidden: true,
density: 1400,
reactions: {
"seltzer": { elem1: ["cola_syrup", "cola_syrup", "foam"], elem2:"soda"},
"soda": { elem1: "foam", chance:0.001},
},
color: "#4f0e0e",
behavior: behaviors.LIQUID,
tempHigh: 170,
stateHigh: ["sugar","smoke","smoke"],
tempLow: -15,
category:"liquids",
state: "liquid",
viscosity: 15,
hidden: true,
density: 1400,
reactions: {
"seltzer": { elem1: ["cola_syrup", "cola_syrup", "foam"], elem2:"soda"},
"soda": { elem1: "foam", chance:0.001},
},
}
if (!elements.sugar_water.reactions) elements.sugar_water.reactions = {};
elements.sugar_water.reactions.lemon_juice = { elem1: "sugar_water", elem2: null, color1: "#fff7ba" }
if (!elements.sugar_water.reactions) elements.sugar_water.reactions = {};
elements.sugar_water.reactions.cinnamon_powder = { elem1: "cola_syrup", elem2: null }
elements.sugar_water.reactions.cinnamon_powder = { elem1: "cola_syrup", elem2: null }
elements.brisket = {
color:["#704534", "#6b3d2b", "#733526"],
behavior: behaviors.SUPPORT,
category: "food",
state: "solid",
temp:55,
tempHigh: 600,
stateHigh: ["ash","smoke"],
isFood: true,
hidden: true,
}
if (!elements.cured_meat.reactions) elements.cured_meat.reactions = {};
elements.cured_meat.reactions.smoke = { elem1: "brisket", elem2: null }
elements.cured_meat.tempHigh = 111
// spices
elements.star_anise = {
color: ["#8B4513", "#A0522D", "#D2691E"],
behavior: behaviors.POWDER,
category: "food",
state: "solid",
isFood: true,
temp: 20,
hidden: true,
tempHigh: 250,
stateHigh: ["ash", "smoke"],
}
elements.curry_leaves = {
color: ["#228B22", "#32CD32", "#6B8E23"],
behavior: behaviors.POWDER,
category: "food",
state: "solid",
isFood: true,
temp: 20,
hidden: true,
tempHigh: 250,
stateHigh: ["ash", "smoke"],
}
elements.laksa_leaves = {
color: ["#6a8e3d", "#7d9a57", "#8ea54b"],
behavior: behaviors.POWDER,
category: "food",
state: "solid",
isFood: true,
temp: 20,
hidden: true,
tempHigh: 250,
stateHigh: ["ash", "smoke"],
}
elements.bay_leaves = {
color: ["#556B2F", "#808000", "#9ACD32"],
behavior: behaviors.POWDER,
category: "food",
state: "solid",
isFood: true,
temp: 20,
hidden: true,
tempHigh: 250,
stateHigh: ["ash", "smoke"],
}
elements.rosemary = {
color: ["#483C32", "#708238", "#8FBC8F"],
behavior: behaviors.POWDER,
category: "food",
state: "solid",
isFood: true,
temp: 20,
hidden: true,
tempHigh: 250,
stateHigh: ["ash", "smoke"],
}
elements.coriander_leaves = {
color: ["#4b5f44", "#6b7b55", "#3f5c32"],
behavior: behaviors.POWDER,
category: "food",
state: "solid",
isFood: true,
temp: 20,
hidden: true,
tempHigh: 250,
stateHigh: ["ash", "smoke"],
}
elements.coriander_seeds = {
color: ["#F4A460", "#D2691E"],
behavior: behaviors.POWDER,
category: "food",
state: "solid",
isFood: true,
temp: 20,
hidden: true,
tempHigh: 250,
stateHigh: ["ash", "smoke"],
}
elements.parsley = {
color: ["#228B22", "#32CD32", "#3CB371"],
behavior: behaviors.POWDER,
category: "food",
state: "solid",
isFood: true,
temp: 20,
hidden: true,
tempHigh: 250,
stateHigh: ["ash", "smoke"],
}
elements.cloves = {
color: ["#654321", "#8B4513", "#A0522D"],
behavior: behaviors.POWDER,
category: "food",
state: "solid",
isFood: true,
temp: 20,
hidden: true,
tempHigh: 250,
stateHigh: ["ash", "smoke"],
}
var spices = [
// 2
"allspice",
"cumin",
"paprika",
"turmeric",
"saffron",
"cinnamon_powder",
"star_anise",
"curry_leaves",
"laksa_leaves",
"bay_leaves",
"rosemary",
"coriander_leaves",
"coriander_seeds",
"parsley",
"cloves",
"cinnamon",
// 1
"pepper",
"chilli_powder",
"onion_powder",
"herb",
"cut_ginger",
"fried_onion",
"chopped_spring_onion",
"salt"
];
/*elements.spice_mix = {
color: ["#8B7D6B", "#A0935C", "#B8A77A"],
behavior: behaviors.POWDER,
category: "food",
state: "solid",
isFood: true,
temp: 20,
tempHigh: 250,
stateHigh: ["ash", "smoke"],
tick: function(pixel) {
var randomSpice = spices[Math.floor(Math.random() * spices.length)];
changePixel(pixel, randomSpice);
}
}*/
elements.pistachio = {
color: ["#E8D5B7", "#F2E3C1", "#DDD0A8"],
behavior: behaviors.POWDER,
category: "food",
state: "solid",
isFood: true,
temp: 20,
tempHigh: 250,
stateHigh: ["ash", "smoke"],
breakInto: "pistachio_powder",
cutInto: "pistachio_meat"
}
elements.pistachio_meat = {
color: ["#98C93A", "#A3D645", "#8BB832"],
behavior: behaviors.POWDER,
category: "food",
state: "solid",
isFood: true,
temp: 20,
tempHigh: 250,
stateHigh: ["ash", "smoke"],
breakInto: "pistachio_powder",
hidden: true
}
elements.pistachio_powder = {
color: ["#7A9B2F", "#85A635", "#6F8728"],
behavior: behaviors.POWDER,
category: "food",
state: "solid",
isFood: true,
temp: 20,
tempHigh: 250,
stateHigh: ["ash", "smoke"],
hidden: true
}
},true)

View File

@ -1,7 +1,7 @@
// created by SquareScreamYT
// please visit the repo to see the code
fetch('https://raw.githubusercontent.com/SquareScreamYT/aChefsDream.js/main/aChefsDream.js')
fetch('https://raw.githubusercontent.com/SquareScreamYT/sandboxels/main/mods/aChefsDream2.js')
.then(response => response.text())
.then(code => {
eval(code);

231
mods/asciiboxels.js Normal file
View File

@ -0,0 +1,231 @@
/*window.addEventListener('load', function() { // original plan for mod
for (var element in elements) {
elements[element].renderer = function(pixel, ctx) {}
}
}); */
if (!enabledMods.includes("mods/betterSettings.js")) { enabledMods.unshift("mods/betterSettings.js"); localStorage.setItem("enabledMods", JSON.stringify(enabledMods)); window.location.reload() };
var ascii_settingsTab = new SettingsTab("Ascii");
var asciicustomcolor_setting = new Setting("Custom Colors", "customcolors", settingType.BOOLEAN, false, defaultValue=false);
var bw_setting = new Setting("Ascii B&W", "bw", settingType.BOOLEAN, false, defaultValue=true);
var asciicolor_setting = new Setting("Ascii Color", "asciicolor", settingType.COLOR, false, defaultValue="#ff0000");
var darklight_setting = new Setting("Flip Darkness", "asciidarklight", settingType.BOOLEAN, false, defaultValue=true, description="Whether the shading of ascii pixels flip depending on background or not.");
ascii_settingsTab.registerSettings("Color", asciicustomcolor_setting);
ascii_settingsTab.registerSettings("Color", bw_setting);
ascii_settingsTab.registerSettings("Color", asciicolor_setting);
ascii_settingsTab.registerSettings("Color", darklight_setting);
settingsManager.registerTab(ascii_settingsTab);
asciiListD = "`.-':~,^=;><+!rc*/z?sLTv)J7(|Fi{C}fI31tlu[neoZ5Yxjya]2ESwqkP6h9d4VpOGbUAKXHm8RD#$Bg0MNWQ%&@"
asciiListL = "@&%QWNM0gB$#DR8mHXKAUbGOpV4d9h6PkqwSE2]ayjxY5Zoen[ult13If}C{iF|(7J)vTLs?z/*cr!+<>;=^,~:'-.`"
asciiNum = [-1, 0.0829, 0.0848, 0.1227, 0.1403, 0.1559, 0.185, 0.2183, 0.2417, 0.2571, 0.2852, 0.2902, 0.2919, 0.3099, 0.3192, 0.3232, 0.3294, 0.3384, 0.3609, 0.3619, 0.3667, 0.3737, 0.3747, 0.3838, 0.3921, 0.396, 0.3984, 0.3993, 0.4075, 0.4091, 0.4101, 0.42, 0.423, 0.4247, 0.4274, 0.4293, 0.4328, 0.4382, 0.4385, 0.442, 0.4473, 0.4477, 0.4503, 0.4562, 0.458, 0.461, 0.4638, 0.4667, 0.4686, 0.4693, 0.4703, 0.4833, 0.4881, 0.4944, 0.4953, 0.4992, 0.5509, 0.5567, 0.5569, 0.5591, 0.5602, 0.5602, 0.565, 0.5776, 0.5777, 0.5818, 0.587, 0.5972, 0.5999, 0.6043, 0.6049, 0.6093, 0.6099, 0.6465, 0.6561, 0.6595, 0.6631, 0.6714, 0.6759, 0.6809, 0.6816, 0.6925, 0.7039, 0.7086, 0.7235, 0.7302, 0.7332, 0.7602, 0.7834, 0.8037, 0.9999]
hex_is_light = function(color) {
hex = color.replace('#', '');
c_r = parseInt(hex.substring(0, 0 + 2), 16);
c_g = parseInt(hex.substring(2, 2 + 2), 16);
c_b = parseInt(hex.substring(4, 4 + 2), 16);
brightness = ((c_r * 334) + (c_g * 334) + (c_b * 332)) / 1000;
if (brightness > 127.5) {
return true
}
else {
return false
}
}
invertColor = function(color) {
let hex = color.replace(/^#/, '');
if (hex.length === 3) hex = hex.replace(/./g, '$&$&'); // Expand
if (hex.length !== 6) throw new Error(`Invalid HEX color: ${color}`);
return `#${(0xFFFFFF ^ parseInt(hex, 16)).toString(16).padStart(6, '0')}`;
}
/* // original plan for mod
renderPostPixel(function(ctx){
for (pixel of currentPixels){
if (pixel.color){
ctx.font = `${pixelSize}pt Arial`
if (asciicustomcolor_setting.value == false) {
ctx.fillStyle = pixel.color;
}
else if (bw_setting.value !== true && asciicolor_setting.value) {
ctx.fillStyle = asciicolor_setting.value;
}
else {
ctx.fillStyle = invertColor(settings.bg)
}
var rgb1 = pixel.color.match(/\d+/g);
// average the colors
let sum = 0;
for (const number of rgb1) {
sum += Number(number);
}
var rgb = ((sum / rgb1.length)/225)
if (hex_is_light(settings.bg) == false || darklight_setting.value == false) {
for (i = 0; i < asciiNum.length; i++) {
if (rgb > asciiNum[i]) {
var asciiType = asciiListD[i]
}
}
}
else if (hex_is_light(settings.bg) == true) {
for (i = 0; i < asciiNum.length; i++) {
if (rgb > asciiNum[i]) {
var asciiType = asciiListL[i]
}
}
}
if (asciiType) {
ctx.fillText(asciiType, canvasCoord(pixel.x), canvasCoord(pixel.y+1), pixelSize)
}
}
}
}) */
drawSquare = function(ctx,color,x,y,scale=1,opacity=1) {
if (color) {
if (scale) {
ctx.font = `${pixelSize*scale}pt Arial`
}
else {
ctx.font = `${pixelSize}pt Arial`
}
if (ctx.globalAlpha !== opacity) { ctx.globalAlpha = opacity; }
if (asciicustomcolor_setting.value == false) {
ctx.fillStyle = color;
}
else if (bw_setting.value !== true && asciicolor_setting.value) {
ctx.fillStyle = asciicolor_setting.value;
}
else {
ctx.fillStyle = invertColor(settings.bg)
}
var rgb1 = color.match(/\d+/g);
// average the colors
let sum = 0;
for (const number of rgb1) {
sum += Number(number);
}
var rgb = ((sum / rgb1.length)/255)
if (hex_is_light(settings.bg) == false || darklight_setting.value == false) {
for (i = 0; i < asciiNum.length; i++) {
if (rgb > asciiNum[i]) {
var asciiType = asciiListD[i]
}
}
}
else if (hex_is_light(settings.bg) == true) {
for (i = 0; i < asciiNum.length; i++) {
if (rgb > asciiNum[i]) {
var asciiType = asciiListL[i]
}
}
}
//ctx.fillRect(canvasCoord(x), canvasCoord(y), pixelSize*scale, pixelSize*scale);
ctx.fillText(asciiType, canvasCoord(x), canvasCoord(y+scale), pixelSize*scale)
}
}
drawPlus = function(ctx,color,x,y,scale=1,opacity=1) {
if (color) {
opacity = 0.5*opacity;
if (ctx.globalAlpha!==opacity) { ctx.globalAlpha = opacity; }
ctx.font = `${pixelSize}pt Arial`
if (asciicustomcolor_setting.value == false) {
ctx.fillStyle = color;
}
else if (bw_setting.value !== true && asciicolor_setting.value) {
ctx.fillStyle = asciicolor_setting.value;
}
else {
ctx.fillStyle = invertColor(settings.bg)
}
var rgb1 = color.match(/\d+/g);
// average the colors
let sum = 0;
for (const number of rgb1) {
sum += Number(number);
}
var rgb = ((sum / rgb1.length)/255)
if (hex_is_light(settings.bg) == false || darklight_setting.value == false) {
for (i = 0; i < asciiNum.length; i++) {
if (rgb > asciiNum[i]) {
var asciiType = asciiListD[i]
}
}
}
else if (hex_is_light(settings.bg) == true) {
for (i = 0; i < asciiNum.length; i++) {
if (rgb > asciiNum[i]) {
var asciiType = asciiListL[i]
}
}
}
ctx.fillText(asciiType, canvasCoord(x-1), canvasCoord(y+scale), pixelSize)
ctx.fillText(asciiType, canvasCoord(x+1), canvasCoord(y+scale), pixelSize)
ctx.fillText(asciiType, canvasCoord(x), canvasCoord((y+scale)+1), pixelSize)
ctx.fillText(asciiType, canvasCoord(x), canvasCoord((y+scale)-1), pixelSize)
ctx.fillText(asciiType, canvasCoord(x), canvasCoord(y+scale), pixelSize)
}
}
function drawCursor() {
var layerCtx = canvasLayers.gui.getContext('2d');
var mouseOffset = Math.trunc(mouseSize/2);
var topLeft = [mousePos.x-mouseOffset,mousePos.y-mouseOffset];
var bottomRight = [mousePos.x+mouseOffset,mousePos.y+mouseOffset];
// Draw a square around the mouse
layerCtx.globalAlpha = mouseAlpha;
layerCtx.lineWidth = 2;
layerCtx.font = `${pixelSize}pt Arial`
if (asciicustomcolor_setting.value == false) {
layerCtx.fillStyle = mouseColor;
}
else if (bw_setting.value !== true && asciicolor_setting.value) {
layerCtx.fillStyle = asciicolor_setting.value;
}
else {
layerCtx.fillStyle = invertColor(settings.bg)
}
if (mouseSize > 1) {
for (i = mousePos.x-mouseOffset; i <= mousePos.x+mouseOffset; i++) { // top
layerCtx.fillText("_", (i)*pixelSize, (mousePos.y-mouseOffset)*pixelSize, pixelSize)
}
for (i = mousePos.y-mouseOffset; i <= mousePos.y+mouseOffset; i++) { // left
layerCtx.fillText("|", (mousePos.x-mouseOffset)*pixelSize, ((i)*pixelSize)+pixelSize, pixelSize)
}
for (i = mousePos.x+mouseOffset; i >= mousePos.x-mouseOffset; i--) { // bottom
layerCtx.fillText("_", (i)*pixelSize, ((mousePos.y+mouseOffset)*pixelSize)+pixelSize, pixelSize)
}
for (i = mousePos.y+mouseOffset; i >= mousePos.y-mouseOffset; i--) { // right
layerCtx.fillText("|", ((mousePos.x+mouseOffset)*pixelSize)+pixelSize, ((i)*pixelSize)+pixelSize, pixelSize)
}
}
else {
layerCtx.font = `${pixelSize*1.5}pt Arial`
layerCtx.fillText("▢", ((mousePos.x+mouseOffset)*pixelSize)-(pixelSize*0.25), ((mousePos.y+mouseOffset)*pixelSize)+(pixelSize*1.25), pixelSize*1.5)
}
// draw one transparent pixel in the center
if (settings.precision) {
layerCtx.fillText("o", mousePos.x*pixelSize, (mousePos.y*pixelSize)+pixelSize, pixelSize)
}
if (shaping) {
if (shaping === 1) { // Draw a white line from shapeStart.x to shapeStart.y
let coords = lineCoords(shapeStart.x,shapeStart.y,mousePos.x,mousePos.y);
coords.forEach((coord) => {
if (outOfBounds(coord[0],coord[1])) return;
drawSquare(layerCtx,mouseColor,coord[0],coord[1],undefined,mouseAlpha)
})
}
}
}

View File

@ -75,22 +75,22 @@ renderPresets.FLESHBURN = function(pixel,ctx) {
var ratio = ((pixel.char/max*100)|0)/100;
if (ratio < 0.5) { return }
if (ratio > 1) { ratio = 1 }
drawSquare(ctx,"#000000",pixel.x,pixel.y,undefined,Math.min(0.8,(ratio-0.5)*0.8));
drawSquare(ctx,"rgb(0,0,0)",pixel.x,pixel.y,undefined,Math.min(0.8,(ratio-0.5)*0.8));
},
renderPresets.NERVE = function(pixel,ctx) {
drawDefault(ctx,pixel)
if (pixel.darkcharge === true) {
drawSquare(ctx,"#000000",pixel.x,pixel.y,undefined,Math.min(0.8,0.55));
drawSquare(ctx,"rgb(0,0,0)",pixel.x,pixel.y,undefined,Math.min(0.8,0.55));
}
if (pixel.darkchargeCD === true) {
drawSquare(ctx,"#000000",pixel.x,pixel.y,undefined,Math.min(0.8,0.5));
drawSquare(ctx,"rgb(0,0,0)",pixel.x,pixel.y,undefined,Math.min(0.8,0.5));
}
if (pixel.lightcharge === true) {
drawSquare(ctx,"#ffffff",pixel.x,pixel.y,undefined,Math.min(0.8,0.55));
drawSquare(ctx,"rgb(255,255,255)",pixel.x,pixel.y,undefined,Math.min(0.8,0.55));
}
if (pixel.lightchargeCD === true) {
drawSquare(ctx,"#ffffff",pixel.x,pixel.y,undefined,Math.min(0.8,0.5));
drawSquare(ctx,"rgb(255,255,255)",pixel.x,pixel.y,undefined,Math.min(0.8,0.5));
}
},

76
mods/boompaste.js Normal file
View File

@ -0,0 +1,76 @@
activated_meltpasteBlacklist = ["activated_meltpaste"]
let v = -1.797693134862315E+308;
let w = v * 1.001;
let x = 1.797693134862315E+308;
let y = x * 1.001;
elements.boompaste = {
temp: y,
color: "#008009",
behavior: behaviors.MOLTEN,
burn:300,
category: "Boom",
state: "solid",
burnTime: 10000,
reactions:{
"boompaste": { elem1:"boompaste" , elem2: "boompaste"},
"fire": { elem1: "boompaste" , elem2:"boompaste" },
"plasma": { elem1: "boompaste" , elem2:"boompaste" },
"flash":{ elem1: "boompaste" , elem2:"flash" },
"water":{ elem1: "flash" , elem2:"flash" },
},
}
//i stole this from the alkest mod (duh) please steal from me -g
elements.meltpaste = {
density:y,
temp: y,
color: "#755858",
behavior: behaviors.POWDER,
burn:300,
category: "Boom",
state: "solid",
burnTime: 10000,
lowtemp:-1,
lowstate:"plasma",
tick: function(pixel) {
for(i = 0; i < adjacentCoords.length; i++) {
if(Math.random() < 0.1) {
var pX = pixel.x
var pY = pixel.y
var oX = adjacentCoords[i][0];
var oY = adjacentCoords[i][1];
var checkPosX = pX+oX;
var checkPosY = pY+oY;
if(!isEmpty(checkPosX,checkPosY,true)) {
var newPixel = pixelMap[checkPosX][checkPosY];
var newElement = newPixel.element;
if(!activated_meltpasteBlacklist.includes(newElement)) { //unless someone's willing to implement dragon parts
if(typeof(pixel[newElement]) === "undefined") {
pixel[newElement] = 0;
};
pixel[newElement]++;
deletePixel(checkPosX,checkPosY);
};
};
};
};
},
}
elements.gasoline = {
color: "#008000",
behavior: behaviors.LIQUID,
category: "Boom",
state: "liquid",
burn:300,
burnTime:999 ,
}
elements.afterburn = {
color: "#c8d600",
behavior: behaviors.LIQUID,
category: "Boom",
state: "liquid",
burn:y,
burnTime:30,
burnInto:["gasoline","afterburn"],
}

View File

@ -1,3 +1,7 @@
// TypeScript integration for Sandboxels modding
// Enables function autocomplete & element definition hints
/// <reference path="./sandboxels-types.d.ts" />
// Get the file here: https://github.com/Cube14yt/sandboxels-types
// Changelog
// Starts at version 3
@ -21,8 +25,15 @@ Machines: Robot, Adjustable heater/cooler
Bug Fixes
Fixed compatibility issue with nousersthings.js
*/
V4
Machines: Paper filter, Indestructable filter, and Note block
Life: Cacao Plants (seed, stem, fruit)
Tools: Polish
Extras: 2 ways to make an element with no name
Special: Black hole
Building Materials: Roman concrete/cement
*/
elements.button = {
@ -567,10 +578,17 @@ keybinds["KeyT"] = function () {
tpsPrompt()
}
function addRow() {
function addRowWhenReady() {
const table = document.getElementById("controlsTable");
const rowCount = table.rows.length;
if (!table) {
// Table not ready yet, try again in 100ms
setTimeout(addRowWhenReady, 100);
return;
}
// Table exists, add the row
const rowCount = table.rows.length;
const newRow = table.insertRow(rowCount - 1);
const cell1 = newRow.insertCell(0);
@ -578,9 +596,13 @@ function addRow() {
cell1.textContent = "Change TPS";
cell2.innerHTML = "<kbd>T</kbd>";
console.log("Row added successfully!");
}
addRow()
// Start the process
addRowWhenReady();
elements.randomizer = {
buttonColor: ["#ff0000", "#ff8800", "#ffff00", "#00ff00", "#00ffff", "#0000ff", "#ff00ff"],
@ -1534,6 +1556,7 @@ function tryJump(headPixel) {
elements.robot_head = {
color: "#d9d9d9",
category: "machines",
state: "solid",
tick(pixel) {
const body = getPixel(pixel.x, pixel.y + 1);
@ -1572,6 +1595,7 @@ elements.robot_head = {
elements.robot_body = {
color: "#b1b1b1",
category: "machines",
state: "solid",
tick(pixel) {
const head = getPixel(pixel.x, pixel.y - 1);
@ -1597,6 +1621,7 @@ elements.robot_body = {
elements.robot = {
color: "#b1b1b1",
category: "machines",
state: "solid",
onSelect() {
promptChoose(
"Choose robot mode",
@ -1652,6 +1677,7 @@ elements.broken_adjustable_heater = {
category: "extras",
insulate: true,
behavior: behaviors.WALL,
onSelect() {
promptInput(
"Select the temperature you want to adjust to",
@ -1719,24 +1745,7 @@ elements.adjustable_heater = {
} else if (current_pixel.temp > adjusted_temp) {
current_pixel.temp = Math.max(current_pixel.temp - heatAmount, adjusted_temp);
}
// Phase change check (forces melting/boiling/etc.)
let elemDef = elements[current_pixel.element];
if (elemDef) {
// Too hot for current state → change to high state
if (typeof elemDef.tempHigh === "number" &&
current_pixel.temp >= elemDef.tempHigh &&
elemDef.stateHigh) {
changePixel(current_pixel, elemDef.stateHigh);
}
// Too cold for current state → change to low state
if (typeof elemDef.tempLow === "number" &&
current_pixel.temp <= elemDef.tempLow &&
elemDef.stateLow) {
changePixel(current_pixel, elemDef.stateLow);
}
}
pixelTempCheck(current_pixel)
}
}
}
@ -1820,26 +1829,633 @@ elements.adjustable_cooler = {
current_pixel.temp = Math.min(current_pixel.temp + coolAmount, adjusted_cool_temp);
}
// Phase change check (forces melting/freezing/etc.)
let elemDef = elements[current_pixel.element];
if (elemDef) {
// Too hot → change to high state
if (typeof elemDef.tempHigh === "number" &&
current_pixel.temp >= elemDef.tempHigh &&
elemDef.stateHigh) {
changePixel(current_pixel, elemDef.stateHigh);
}
// Too cold → change to low state
if (typeof elemDef.tempLow === "number" &&
current_pixel.temp <= elemDef.tempLow &&
elemDef.stateLow) {
changePixel(current_pixel, elemDef.stateLow);
}
}
pixelTempCheck(current_pixel)
}
}
}
};
let polishedList = new Set()
elements.polish = {
category: "tools",
color: ["#a0dff0", "#c0e8f8", "#e0f5ff"],
tool(pixel) {
let element = pixel.element
if ((elements[pixel.element].colorPattern && !polishedList.has(`${pixel.x}, ${pixel.y}`)) || shiftDown) {
deletePixel(pixel.x, pixel.y)
createPixel(element, pixel.x, pixel.y)
polishedList.add(`${pixel.x}, ${pixel.y}`)
}
},
onUnselect() {
polishedList.clear()
}
}
elements[" "] = {
category: "extras",
onSelect() {
logMessage("This Element has weird properties since its a space ' '")
},
alias: "space"
}
elements.paper_filter = {
desc: "Filters solids from liquids",
color: "#ececec",
behavior: behaviors.WALL,
reactions: {
"light": { stain1: "#ebdfa7" },
"oxygen": { stain1: "#ebdfa7" }
},
tempHigh: 248,
stateHigh: ["fire", "fire", "fire", "fire", "fire", "ash"],
burn: 70,
burnTime: 300,
burnInto: ["fire", "fire", "fire", "fire", "fire", "ash"],
category: "machines",
density: 1201,
breakInto: "confetti",
breakIntoColor: ["#ffffff", "#e6e6e6", "#dbdbdb"],
tick(pixel) {
let upPixel = getPixel(pixel.x, pixel.y - 1)
if (upPixel && elements[upPixel.element].state == "liquid" && !pixel.con) {
deletePixel(pixel.x, pixel.y - 1)
pixel.con = upPixel
}
if (upPixel && (upPixel.element === "paper_filter" || upPixel.element === "indestructable_filter") && upPixel.con && !pixel.con) {
let liquid = upPixel.con
let viscMove = true
if (elements[liquid.element].viscosity) {
viscMove = (Math.random() * 100) < (100 / Math.pow(elements[liquid.element].viscosity, 0.5))
}
if (viscMove) {
pixel.con = liquid
delete upPixel.con
}
}
if (isEmpty(pixel.x, pixel.y + 1) && !outOfBounds(pixel.x, pixel.y + 1) && pixel.con) {
let liquid = pixel.con
let viscExit = true
if (elements[liquid.element].viscosity) {
viscExit = (Math.random() * 100) < (100 / Math.pow(elements[liquid.element].viscosity, 0.5))
}
if (viscExit) {
createPixel(liquid.element, pixel.x, pixel.y + 1)
delete pixel.con
}
}
}
}
elements.indestructable_filter = {
desc: "Filters solids from liquids",
color: "#aaaaaa",
behavior: behaviors.WALL,
category: "machines",
state: "solid",
movable: false,
tick(pixel) {
let upPixel = getPixel(pixel.x, pixel.y - 1)
let belowPixel = getPixel(pixel.x, pixel.y + 1)
if (upPixel && elements[upPixel.element].state == "liquid" && !pixel.con) {
deletePixel(pixel.x, pixel.y - 1)
pixel.con = upPixel
}
if (upPixel && (upPixel.element === "indestructable_filter" || upPixel.element === "paper_filter") && upPixel.con && !pixel.con) {
let liquid = upPixel.con
let viscMove = true
if (elements[liquid.element].viscosity) {
viscMove = (Math.random() * 100) < (100 / Math.pow(elements[liquid.element].viscosity, 0.5))
}
if (viscMove) {
pixel.con = liquid
delete upPixel.con
}
}
if (isEmpty(pixel.x, pixel.y + 1) && !outOfBounds(pixel.x, pixel.y + 1) && pixel.con) {
let liquid = pixel.con
let viscExit = true
if (elements[liquid.element].viscosity) {
viscExit = (Math.random() * 100) < (100 / Math.pow(elements[liquid.element].viscosity, 0.5))
}
if (viscExit) {
createPixel(liquid.element, pixel.x, pixel.y + 1)
delete pixel.con
}
}
}
}
let black_hole_expand = false
elements.black_hole = {
color: "#111111",
hardness: 1,
category: "special",
properties: {
absorbed: 0
},
renderer: function (pixel, ctx) {
if (!viewInfo[view].colorEffects) { drawDefault(ctx, pixel); return }
renderPresets.HEATGLOW(pixel, ctx);
if (pixel.alpha === 0) return;
let edge = false;
pixel.edge = false;
pixel.color = "#111111";
for (var i = 0; i < adjacentCoords.length; i++) {
var coords = adjacentCoords[i];
var x = pixel.x + coords[0];
var y = pixel.y + coords[1];
if (!outOfBounds(x, y)) {
let neighbor = getPixel(x, y);
if (!neighbor || elements[neighbor.element].movable !== elements[pixel.element].movable) {
edge = true;
break;
}
}
}
if (edge) { pixel.color = "#ffae00"; pixel.edge = true }
},
tick(pixel) {
// Glow effect
if (pixel.edge) {
pixel.glow = true;
if (enabledMods.includes("mods/glow.js")) {
pixel.emit = 10;
}
}
else {
pixel.glow = false;
if (enabledMods.includes("mods/glow.js")) {
pixel.emit = 0;
}
}
// Suction physics
let radius = 20; // how far the suction reaches
for (let dx = -radius; dx <= radius; dx++) {
for (let dy = -radius; dy <= radius; dy++) {
if (dx === 0 && dy === 0) continue;
let x = pixel.x + dx;
let y = pixel.y + dy;
if (!outOfBounds(x, y)) {
let other = getPixel(x, y);
if (other && other !== pixel) {
let elemDef = elements[other.element];
// Skip if indestructible
if (elemDef.hardness === 1) continue;
// Distance to black hole
let dist = Math.sqrt(dx * dx + dy * dy);
if (dist <= radius) {
// Suction chance: closer = stronger pull
let chance = 1 / dist;
if (Math.random() < chance) {
let stepX = Math.sign(pixel.x - x);
let stepY = Math.sign(pixel.y - y);
let newX = x + stepX;
let newY = y + stepY;
if (isEmpty(newX, newY) && !outOfBounds(newX, newY)) {
movePixel(other, newX, newY);
}
else if (dist <= 1.5) {
deletePixel(x, y); // absorb it
pixel.absorbed++
}
}
}
}
}
}
if (black_hole_expand) {
for (var i = 0; i < adjacentCoords.length; i++) {
var x = pixel.x + adjacentCoords[i][0];
var y = pixel.y + adjacentCoords[i][1];
if (pixel.absorbed >= 30 && isEmpty(x, y)) {
createPixel("black_hole", x, y)
pixel.absorbed = 0
}
}
}
}
},
forceSaveColor: true,
onSelect() {
promptChoose(
"Do you want the black hole to grow?",
["Yes", "No"],
(choice) => {
if (!choice) {
choice = false
}
if (choice == "Yes") {
black_hole_expand = true
}
else {
black_hole_expand = false
}
}
)
}
};
elements.cacao_fruit = {
color: "#854700",
behavior: [
"XX|ST:cacao_stem|XX",
"ST:cacao_stem|XX|ST:cacao_stem",
"XX|ST:cacao_stem AND M1|XX"
],
isFood: true,
burn: 10,
burnTime: 100,
burnInto: "ash",
breakInto: "cacao_bean",
category: "food",
state: "solid",
density: 1000
}
elements.cacao_bean = {
color: "#ffe7ba",
isFood: true,
behavior: [
"XX|XX|XX",
"XX|XX|XX",
"M2%10|M1|M2%10"
],
tempHigh: 100,
stateHigh: "dried_cacao_bean",
onStateHigh(pixel) { releaseElement(pixel, "steam") },
state: "solid",
category: "food",
density: 1000
}
elements.dried_cacao_bean = {
color: "#61321e",
behavior: behaviors.POWDER,
reactions: {
"sugar_water": { elem2: "melted_chocolate", tempMin: 65 },
"water": { elem2: "melted_chocolate", tempMin: 65 }
},
tempHigh: 400,
stateHigh: "ash",
isFood: true,
category: "food",
state: "solid",
density: 1000
}
elements.coffee_bean.reactions.sugar_water = { elem2: "coffee", tempMin: 80 }
elements.coffee.reactions.sugar_water = { elem2: "coffee", tempMin: 70, chance: 0.2 }
elements.coffee_ground.reactions.sugar_water = elements.coffee_ground.reactions.water
elements._ = {
category: "extras",
onSelect() {
logMessage("Another way to make an element with no name \"_\"")
},
alias: ["underscore"]
}
elements.cacao_seed = {
color: "#8b3f00",
behavior: behaviors.STURDYPOWDER,
cooldown: defaultCooldown,
category: "life",
tempHigh: 400,
stateHigh: "fire",
tempLow: -2,
stateLow: "frozen_plant",
burn: 50,
burnTime: 20,
state: "solid",
tick(pixel) {
let belowPixel = getPixel(pixel.x, pixel.y + 1)
if ((!isEmpty(pixel.x, pixel.y + 1) && belowPixel) || outOfBounds(pixel.x, pixel.y + 1) && Math.random() <= 0.005) {
changePixel(pixel, "cacao_stem")
pixel.stage = 1
}
}
}
elements.cacao_stem = {
color: "#916a00",
renderer: renderPresets.WOODCHAR,
movable: false,
tempHigh: 100,
stateHigh: "wood",
tempLow: -30,
stateLow: "wood",
category: "life",
burn: 2,
burnTime: 300,
burnInto: ["sap", "ember", "charcoal", "smoke"],
state: "solid",
density: 1500,
hardness: 0.15,
breakInto: ["sap", "sawdust"],
seed: "cacao_seed",
forceSaveColor: true,
stateHighColorMultiplier: 0.95,
onPlace(pixel) {
pixel.stage = 1
},
hoverStat(pixel) {
if (pixel.stage) return pixel.stage;
else return 0;
},
tick(pixel) {
// 1 = trunk
// 2 = spread
// 3 = stop
if (pixel.stage === 1 && isEmpty(pixel.x, pixel.y - 1) && Math.random() <= 0.05) {
tryMove(pixel, pixel.x, pixel.y - 1, "cacao_stem")
let oldPixel = getPixel(pixel.x, pixel.y + 1)
delete oldPixel.stage
if (Math.random() <= 0.3) {
pixel.stage = 2
}
}
if (pixel.stage === 2) {
let rand = Math.random()
let nx;
if (rand < 0.4) {
nx = 1
}
else if (rand < 0.8) {
nx = -1
}
else nx = 0;
if (isEmpty(pixel.x + nx, pixel.y - 1) && Math.random() <= 0.05) {
createPixel(["cacao_stem", "plant"], pixel.x + nx, pixel.y - 1)
newPixel = getPixel(pixel.x + nx, pixel.y - 1)
if (Math.random() <= 0.2) {
newPixel.stage = 3
}
else newPixel.stage = 2;
}
if (!isEmpty(pixel.x + 1, pixel.y - 1) && !isEmpty(pixel.x, pixel.y - 1) && !isEmpty(pixel.x - 1, pixel.y - 1) && Math.random() <= 0.005) {
shuffleArray(adjacentCoordsShuffle)
for (var i = 0; i < adjacentCoordsShuffle.length; i++) {
var x = pixel.x + adjacentCoordsShuffle[i][0];
var y = pixel.y + adjacentCoordsShuffle[i][1];
if (isEmpty(x, y) && !pixel.fruitMade) {
createPixel("cacao_fruit", x, y)
pixel.fruitMade = true
pixel.fruitCoordsx = x
pixel.fruitCoordsy = y
break
}
}
}
}
if (pixel.fruitCoordsx && pixel.fruitCoordsy) {
if (getPixel(pixel.fruitCoordsx, pixel.fruitCoordsy) && getPixel(pixel.fruitCoordsx, pixel.fruitCoordsy).element === "cacao_fruit") return;
pixel.fruitMade = false
delete pixel.fruitCoordsx
delete pixel.fruitCoordsy
}
}
}
// --- audio setup ---
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
function playNote(frequency, duration = 1, type = "sine", volume = 0.1) {
if (!Number.isFinite(frequency)) {
console.error("Invalid frequency:", frequency);
return;
}
const osc = audioCtx.createOscillator();
const gain = audioCtx.createGain();
osc.type = type;
osc.frequency.value = frequency;
gain.gain.setValueAtTime(volume, audioCtx.currentTime);
osc.connect(gain);
gain.connect(audioCtx.destination);
gain.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime + duration);
osc.start();
osc.stop(audioCtx.currentTime + duration);
}
const pianoFrequencies = {
"A0": 27.500, "A#0": 29.135, "BB0": 29.135, "B0": 30.868,
"C1": 32.703, "C#1": 34.648, "DB1": 34.648, "D1": 36.708,
"D#1": 38.891, "EB1": 38.891, "E1": 41.203, "F1": 43.654,
"F#1": 46.249, "GB1": 46.249, "G1": 48.999, "G#1": 51.913,
"AB1": 51.913, "A1": 55.000, "A#1": 58.270, "BB1": 58.270,
"B1": 61.735,
"C2": 65.406, "C#2": 69.296, "DB2": 69.296, "D2": 73.416,
"D#2": 77.782, "EB2": 77.782, "E2": 82.407, "F2": 87.307,
"F#2": 92.499, "GB2": 92.499, "G2": 97.999, "G#2": 103.826,
"AB2": 103.826, "A2": 110.000, "A#2": 116.541, "BB2": 116.541,
"B2": 123.471,
"C3": 130.813, "C#3": 138.591, "DB3": 138.591, "D3": 146.832,
"D#3": 155.563, "EB3": 155.563, "E3": 164.814, "F3": 174.614,
"F#3": 184.997, "GB3": 184.997, "G3": 195.998, "G#3": 207.652,
"AB3": 207.652, "A3": 220.000, "A#3": 233.082, "BB3": 233.082,
"B3": 246.942,
"C4": 261.626, "C#4": 277.183, "DB4": 277.183, "D4": 293.665,
"D#4": 311.127, "EB4": 311.127, "E4": 329.628, "F4": 349.228,
"F#4": 369.994, "GB4": 369.994, "G4": 391.995, "G#4": 415.305,
"AB4": 415.305, "A4": 440.000, "A#4": 466.164, "BB4": 466.164,
"B4": 493.883,
"C5": 523.251, "C#5": 554.365, "DB5": 554.365, "D5": 587.330,
"D#5": 622.254, "EB5": 622.254, "E5": 659.255, "F5": 698.456,
"F#5": 739.989, "GB5": 739.989, "G5": 783.991, "G#5": 830.609,
"AB5": 830.609, "A5": 880.000, "A#5": 932.328, "BB5": 932.328,
"B5": 987.767,
"C6": 1046.502, "C#6": 1108.731, "DB6": 1108.731, "D6": 1174.659,
"D#6": 1244.508, "EB6": 1244.508, "E6": 1318.510, "F6": 1396.913,
"F#6": 1479.978, "GB6": 1479.978, "G6": 1567.982, "G#6": 1661.219,
"AB6": 1661.219, "A6": 1760.000, "A#6": 1864.655, "BB6": 1864.655,
"B6": 1975.533,
"C7": 2093.005, "C#7": 2217.461, "DB7": 2217.461, "D7": 2349.318,
"D#7": 2489.016, "EB7": 2489.016, "E7": 2637.020, "F7": 2793.826,
"F#7": 2959.955, "GB7": 2959.955, "G7": 3135.963, "G#7": 3322.438,
"AB7": 3322.438, "A7": 3520.000, "A#7": 3729.310, "BB7": 3729.310,
"B7": 3951.066,
"C8": 4186.009
};
let note = 261.626; // default C4
let notesToPlay = [];
function flushNotes() {
if (notesToPlay.length === 0) return;
let baseVolume = 0.2;
let volume = baseVolume / Math.sqrt(notesToPlay.length);
for (let f of notesToPlay) {
playNote(f, 1, "sine", volume);
}
notesToPlay = [];
}
elements.note_block = {
color: "#965500",
behavior: behaviors.WALL,
onSelect() {
promptInput(
"Select the note this note block should be",
function (choice) {
if (!choice) {
if (!note) { note = 261.626; }
return;
}
let key = choice.toUpperCase();
if (key in pianoFrequencies) {
note = pianoFrequencies[key];
} else {
note = 261.626; // fallback = C4
}
},
"Note prompt"
);
},
onPlace(pixel) {
pixel.note = note;
},
tick(pixel) {
if (pixel.charge) {
notesToPlay.push(Number(pixel.note));
}
},
conduct: 1,
category: "machines"
};
runEveryTick(function () { flushNotes() });
/*
elements.uncook = {
color: ["#4dcdff", "#70ddff", "#bcddff", "#ffffff"],
category: "tools",
tool(pixel) {
if (!pixel || !pixel.element) return;
// 1) If the current element itself defines stateLow, use it (common case)
const cur = elements[pixel.element];
if (cur && cur.stateLow !== undefined) {
const low = cur.stateLow;
pixel.element = Array.isArray(low) ? low[Math.floor(Math.random() * low.length)] : low;
if (typeof pixel.temp === "number") pixel.temp = Math.max(0, pixel.temp - 1);
return; // done
}
// 2) Otherwise search for an element whose stateHigh === the current element
for (const key in elements) {
const el = elements[key];
if (!el) continue;
if (el.stateHigh === pixel.element) {
// 'key' is the low-state element name
changePixel(pixel, key)
if (typeof pixel.temp === "number") pixel.temp = Math.max(0, pixel.temp - 1);
return; // done
}
// If el.stateHigh can be an array of high-state names:
if (Array.isArray(el.stateHigh) && el.stateHigh.includes(pixel.element)) {
changePixel(pixel, key)
if (typeof pixel.temp === "number") pixel.temp = Math.max(0, pixel.temp - 1);
return;
}
}
}
};
*/
elements.roman_cement = {
color: "#b8b8b8",
behavior: behaviors.LIQUID,
category: "liquids",
viscosity: 1000,
density: 1400,
state: "solid",
tempLow: -10,
stateLow: "roman_concrete",
tempHigh: 1550,
stateHigh: "magma",
tick(pixel) {
if (pixelTicks - pixel.start > 100 && Math.random() <= 0.1) {
changePixel(pixel, "roman_concrete")
}
}
}
elements.roman_concrete = {
color: "#ababab",
behavior: behaviors.SUPPORT,
tempHigh: 1500,
stateHigh: "magma",
category: "powders",
state: "solid",
density: 2400,
hardness: 0.5,
breakInto: "dust",
darkText: true
}
/**
*
* @param {string} element
* @param {object} reaction
* @returns {void}
*/
function doWaterReactions(element, reaction) {
if (!elements[element].reactions) {
elements[element].reactions = {}
}
elements[element].reactions.water = reaction
elements[element].reactions.salt_water = reaction
elements[element].reactions.pool_water = reaction
elements[element].reactions.sugar_water = reaction
elements[element].reactions.dirty_water = reaction
elements[element].reactions.selter = reaction
elements[element].reactions.primordial_soup = reaction
elements[element].reactions.nut_milk = reaction
}
doWaterReactions("slaked_lime", {elem1:"roman_cement", elem2: null, chance: 0.25})

View File

@ -4,9 +4,11 @@ let finalEraseElement = null;
elements.element_eraser = {
color: "#eeeeee",
onSelect: function() {
var answer = prompt("Please input the element you wish to delete. It will not work if you enter multiple element types while paused.",(finalEraseElement||undefined));
if (!answer) { return }
finalEraseElement = mostSimilarElement(answer);
promptInput("Please input the element you wish to delete. It will not work if you enter multiple element types while paused.", (answer) => {
// var answer = prompt("Please input the element you wish to delete. It will not work if you enter multiple element types while paused.",(finalEraseElement||undefined));
if (!answer) { return }
finalEraseElement = mostSimilarElement(answer);
}, "Delete Element")
},
tool: function(pixel) {
if (pixel.element === finalEraseElement) {
@ -21,9 +23,11 @@ let finalEraseElement2 = null;
elements.exclusive_element_eraser = {
color: "#eeeeee",
onSelect: function() {
var answer = prompt("Please input the element you do not wish to delete. It will not work if you enter multiple element types while paused.",(finalEraseElement2||undefined));
if (!answer2) { return }
finalEraseElement2 = mostSimilarElement(answer2);
promptInput("Please input the element you do not wish to delete. It will not work if you enter multiple element types while paused.", (answer2) => {
// var answer2 = prompt("Please input the element you do not wish to delete. It will not work if you enter multiple element types while paused.",(finalEraseElement2||undefined));
if (!answer2) { return }
finalEraseElement2 = mostSimilarElement(answer2);
}, "Don't Delete")
},
tool: function(pixel) {
if (pixel.element != finalEraseElement2) {

View File

@ -1,25 +1,24 @@
// This is how to add a new mod to the game.
// To create a mod:
// Create a new Javascript file like this one.
// Add the file to the mods folder on GitHub, or host it somewhere else.
// https://github.com/R74nCom/sandboxels/tree/main/mods
// For more help with modding, check the wiki: https://sandboxels.wiki.gg/wiki/Modding_tutorial
// To learn about modding, check the wiki: https://sandboxels.wiki.gg/wiki/Modding
// Or join our Discord: https://r74n.com/discord/
// To add it in the Mod Loader:
// To add it in the Mod Manager:
// If it is in the mods folder, you can just use the name of the file. (example_mod.js)
// If it is hosted somewhere else, you can use the full URL, including the HTTPS://.
// Adding elements:
elements.mayo = {
color: "#ffffff",
elements.mustard = {
color: "#ffff00",
behavior: behaviors.LIQUID,
category: "liquids",
viscosity: 100000,
state: "liquid",
density: 720
};
density: 1100,
viscosity: 60000,
}
// Changing existing elements:
elements.water.color = "#ff0000";
@ -29,15 +28,20 @@ elements.water.behavior = behaviors.WALL;
// Be aware, things may break
delete elements.ketchup;
// Adding behavior presets:
behaviors.SELFDELETE = [
"XX|XX|XX",
"XX|DL|XX",
"XX|XX|XX"
];
// Custom behaviors:
elements.blue_sand = {
color: "#0000ff",
behavior: [
"XX|XX|XX",
"XX|XX|XX",
"M2|M1|M2"
],
category: "land",
state: "solid"
}
// Raw JavaScript behaviors:
behaviors.mud.tick = function(pixel) {
elements.mud.tick = function(pixel) {
if (tryMove(pixel, pixel.x, pixel.y+1)) {
console.log("Moved!");
}
@ -57,28 +61,29 @@ elements.sand_exploder = {
category: "tools",
};
// Add reactions to existing elements
if (!elements.water.reactions) { // Include this block once
elements.water.reactions = {} // This creates the property if it doesn't exist
// Reactions:
elements.sugar_stick = {
color: "#ffffff",
behavior: behaviors.STURDYPOWDER,
reactions: {
"water": { elem1:null, elem2:"sugar_water", chance:0.1 },
"salt_water": { elem1:null, elem2:"sugar_water", chance:0.1 }
},
state: "solid",
density: 1580
}
elements.water.reactions.mayo = { "elem1":null, "elem2":"mayo_water" };
// Add reactions to existing elements:
// Include this block once to ensure the property exists
if (!elements.water.reactions) elements.water.reactions = {};
elements.water.reactions.mustard = { "elem1":null, "elem2":"mustard_water" };
elements.water.reactions.soap = { "elem1":null, "elem2":"soapy_water" };
// Run after all mods are loaded, for cross-mod compatibility
runAfterLoad(function() {
// Your code here
console.log("Hello World!");
});
// Run if another mod is active
dependOn("mods/test.js", function(){
console.log("Hello World!");
})
// More dependency info: See dependency_test.js
// Creating eLists:
eLists.CONDIMENT = ["ketchup","melted_cheese","mayo"];
// Adding elements to eLists:
eLists.CONDIMENT.push("honey");
// Rendering: See 1.10example.js
// Custom element renderers:
elements.ball.renderer = function(pixel,ctx) {
// Draw three horizontal squares
drawSquare(ctx,"#00ff00",pixel.x-1,pixel.y);
drawSquare(ctx,"#00ff00",pixel.x,pixel.y);
drawSquare(ctx,"#00ff00",pixel.x+1,pixel.y);
};
// See 1.10example.js for more rendering examples.

84
mods/example_mod_old.js Normal file
View File

@ -0,0 +1,84 @@
// This is how to add a new mod to the game.
// Create a new Javascript file like this one.
// Add the file to the mods folder on GitHub, or host it somewhere else.
// https://github.com/R74nCom/sandboxels/tree/main/mods
// For more help with modding, check the wiki: https://sandboxels.wiki.gg/wiki/Modding_tutorial
// Or join our Discord: https://r74n.com/discord/
// To add it in the Mod Loader:
// If it is in the mods folder, you can just use the name of the file. (example_mod.js)
// If it is hosted somewhere else, you can use the full URL, including the HTTPS://.
// Adding elements:
elements.mayo = {
color: "#ffffff",
behavior: behaviors.LIQUID,
category: "liquids",
viscosity: 100000,
state: "liquid",
density: 720
};
// Changing existing elements:
elements.water.color = "#ff0000";
elements.water.behavior = behaviors.WALL;
// Removing elements:
// Be aware, things may break
delete elements.ketchup;
// Adding behavior presets:
behaviors.SELFDELETE = [
"XX|XX|XX",
"XX|DL|XX",
"XX|XX|XX"
];
// Raw JavaScript behaviors:
elements.mud.tick = function(pixel) {
if (tryMove(pixel, pixel.x, pixel.y+1)) {
console.log("Moved!");
}
else {
console.log("Couldn't move!")
}
};
// Create a new tool:
elements.sand_exploder = {
color: "#ff0000",
tool: function(pixel) {
if (pixel.element == "sand") {
pixel.element = "explosion"
}
},
category: "tools",
};
// Add reactions to existing elements
if (!elements.water.reactions) { // Include this block once
elements.water.reactions = {} // This creates the property if it doesn't exist
}
elements.water.reactions.mayo = { "elem1":null, "elem2":"mayo_water" };
elements.water.reactions.soap = { "elem1":null, "elem2":"soapy_water" };
// Run after all mods are loaded, for cross-mod compatibility
runAfterLoad(function() {
// Your code here
console.log("Hello World!");
});
// Run if another mod is active
dependOn("mods/test.js", function(){
console.log("Hello World!");
})
// More dependency info: See dependency_test.js
// Creating eLists:
eLists.CONDIMENT = ["ketchup","melted_cheese","mayo"];
// Adding elements to eLists:
eLists.CONDIMENT.push("honey");
// Rendering: See 1.10example.js

460
mods/graphite.js Normal file
View File

@ -0,0 +1,460 @@
elements.graphite = {
color: "#4d4f4f",
behavior: behaviors.POWDER,
category: "GraphiteMod",
state: "solid",
density: 2.26,
tempHigh: 3600,
stateHigh: "carbon_gas",
flammable: false,
reactions: {
"oxygen": { elem1: "carbon_dioxide", elem2: null, tempMin: 700 },
"fire": { elem1: "carbon_monoxide", elem2: null, tempMin: 700 },
"fluorine": { elem1: "carbon_tetrafluoride", elem2: null },
"silicon_dioxide": { elem1: "silicon", elem2: "carbon_monoxide", tempMin: 1700 }
}
};
/* Carbon (solid) */
elements.carbon = {
color: "#7a7d7d",
behavior: behaviors.POWDER,
category: "GraphiteMod",
state: "solid",
density: 2.2,
tempHigh: 3600,
stateHigh: "carbon_gas",
flammable: false,
reactions: {
"oxygen": { elem1: "carbon_dioxide", elem2: null, tempMin: 700 },
"fire": { elem1: "carbon_monoxide", elem2: null, tempMin: 700 },
"fluorine": { elem1: "carbon_tetrafluoride", elem2: null },
"silicon_dioxide": { elem1: "silicon", elem2: "carbon_monoxide", tempMin: 1700 }
}
};
/* Carbon gas (vapor) */
elements.carbon_gas = {
color: "#666666",
behavior: behaviors.GAS,
category: "GraphiteMod",
state: "gas",
density: 0.0018,
reactions: {
"oxygen": { elem1: "carbon_monoxide", elem2: null },
"fluorine": { elem1: "carbon_tetrafluoride", elem2: null },
"hydrogen": { elem1: "hydrocarbon_gas", elem2: null, tempMin: 1200 },
"silicon": { elem1: "silicon_carbide", elem2: null, tempMin: 1400 }
}
};
/* Hydrocarbon gas (generic hydrocarbon product placeholder) */
elements.hydrocarbon_gas = {
color: "#ffdca3",
behavior: behaviors.GAS,
category: "GraphiteMod",
state: "gas",
density: 0.7,
reactions: {
"oxygen": { elem1: "carbon_dioxide", elem2: "water" },
"fire": { elem1: "carbon_dioxide", elem2: "water" },
"fluorine": { elem1: "carbon_tetrafluoride", elem2: "hydrogen_fluoride" },
"water": { elem1: "water", elem2: null }
}
};
/* Carbon monoxide */
elements.carbon_monoxide = {
color: "#bfbfbf",
behavior: behaviors.GAS,
category: "GraphiteMod",
state: "gas",
density: 1.145,
reactions: {
"oxygen": { elem1: "carbon_dioxide", elem2: null },
"fire": { elem1: "carbon_dioxide", elem2: null },
"iron_oxide": { elem1: "iron", elem2: "carbon_dioxide", tempMin: 800 },
"fluorine": { elem1: "carbonyl_fluoride", elem2: null }
}
};
/* Carbonyl fluoride (COF2) */
elements.carbonyl_fluoride = {
color: "#cfeef0",
behavior: behaviors.GAS,
category: "GraphiteMod",
state: "gas",
density: 2.5,
reactions: {
"water": { elem1: "carbon_dioxide", elem2: "hydrogen_fluoride" },
"fire": { elem1: "carbon_dioxide", elem2: "fluorine" },
"hydrofluoric_acid": { elem1: "hydrogen_fluoride", elem2: "carbon_dioxide" },
"oxygen": { elem1: "carbon_dioxide", elem2: "fluorine" }
}
};
/* Fluorine */
elements.fluorine = {
color: "#b5e61d",
behavior: behaviors.GAS,
category: "GraphiteMod",
state: "gas",
density: 1.696,
temp: 25,
flammable: false,
reactions: {
"graphite": { elem1: "carbon_tetrafluoride", elem2: null },
"carbon": { elem1: "carbon_tetrafluoride", elem2: null },
"hydrogen": { elem1: "hydrogen_fluoride", elem2: null },
"water": { elem1: "hydrogen_fluoride", elem2: "oxygen" },
"silicon": { elem1: "silicon_tetrafluoride", elem2: null }
}
};
/* Carbon tetrafluoride (CF4) */
elements.carbon_tetrafluoride = {
color: "#ccffff",
behavior: behaviors.GAS,
category: "GraphiteMod",
state: "gas",
density: 3.72,
flammable: false,
reactions: {
"fire": { elem1: "carbon_dioxide", elem2: "fluorine", tempMin: 2000 },
"silicon": { elem1: "silicon_tetrafluoride", elem2: "carbon", tempMin: 900 },
"molten_silicon": { elem1: "silicon_tetrafluoride", elem2: "carbon", tempMin: 900 },
"silicon_dioxide": { elem1: "silicon_tetrafluoride", elem2: "carbon_monoxide", tempMin: 1500 }
}
};
/* Hydrogen fluoride (gas) */
elements.hydrogen_fluoride = {
color: "#e0ffff",
behavior: behaviors.GAS,
category: "GraphiteMod",
state: "gas",
density: 0.98,
temp: 25,
flammable: false,
reactions: {
"water": { elem1: "hydrofluoric_acid", elem2: null },
"silicon_dioxide": { elem1: "silicon_tetrafluoride", elem2: "water" },
"calcium_carbonate": { elem1: "calcium_fluoride", elem2: "carbon_dioxide" },
"calcium_hydroxide": { elem1: "calcium_fluoride", elem2: "water" }
}
};
/* Hydrofluoric acid (aqueous HF) */
elements.hydrofluoric_acid = {
color: "#66ccff",
behavior: behaviors.LIQUID,
category: "GraphiteMod",
state: "liquid",
density: 1.15,
tempLow: -83,
stain: "#99ddff",
reactions: {
"glass": { elem1: "silicon_tetrafluoride", elem2: "water" },
"sand": { elem1: "silicon_tetrafluoride", elem2: "water" },
"silicon_dioxide": { elem1: "silicon_tetrafluoride", elem2: "water" },
"calcium_carbonate": { elem1: "calcium_fluoride", elem2: "carbon_dioxide" },
"calcium_hydroxide": { elem1: "calcium_fluoride", elem2: "water" }
}
};
/* Silicon tetrafluoride */
elements.silicon_tetrafluoride = {
color: "#e6ffff",
behavior: behaviors.GAS,
category: "GraphiteMod",
state: "gas",
density: 1.66,
flammable: false,
reactions: {
"water": { elem1: "hydrofluoric_acid", elem2: "silicon_dioxide" },
"sand": { elem1: "hydrofluoric_acid", elem2: "silicon_dioxide" },
"glass": { elem1: "hydrofluoric_acid", elem2: "silicon_dioxide" },
"calcium_hydroxide": { elem1: "calcium_fluoride", elem2: "hydrofluoric_acid" }
}
};
/* Silicon (solid) */
elements.silicon = {
color: "#9a9a9a",
behavior: behaviors.SOLID,
category: "GraphiteMod",
state: "solid",
density: 2.33,
tempHigh: 1414,
stateHigh: "molten_silicon",
flammable: false,
reactions: {
"oxygen": { elem1: "silicon_dioxide", elem2: null, tempMin: 500 },
"fluorine": { elem1: "silicon_tetrafluoride", elem2: null },
"hydrofluoric_acid": { elem1: "silicon_tetrafluoride", elem2: null },
"carbon_tetrafluoride": { elem1: "silicon_tetrafluoride", elem2: "carbon", tempMin: 900 }
}
};
elements.molten_silicon = {
color: "#ffb366",
behavior: behaviors.LIQUID,
category: "GraphiteMod",
state: "liquid",
density: 2.5,
temp: 1414,
stateLow: "silicon",
reactions: {
"oxygen": { elem1: "silicon_dioxide", elem2: null },
"fluorine": { elem1: "silicon_tetrafluoride", elem2: null },
"carbon_tetrafluoride": { elem1: "silicon_tetrafluoride", elem2: "carbon" },
"graphite": { elem1: "silicon_carbide", elem2: null, tempMin: 1500 }
}
};
/* Silicon dioxide (quartz / sand) */
elements.silicon_dioxide = {
color: "#f2f2f2",
behavior: behaviors.SOLID,
category: "GraphiteMod",
state: "solid",
density: 2.65,
tempHigh: 1710,
stateHigh: "molten_silicon_dioxide",
flammable: false,
reactions: {
"hydrofluoric_acid": { elem1: "silicon_tetrafluoride", elem2: "water" },
"hydrogen_fluoride": { elem1: "silicon_tetrafluoride", elem2: "water" },
"graphite": { elem1: "silicon", elem2: "carbon_monoxide", tempMin: 1700 },
"carbon": { elem1: "silicon", elem2: "carbon_monoxide", tempMin: 1700 }
}
};
elements.molten_silicon_dioxide = {
color: "#ffcc99",
behavior: behaviors.LIQUID,
category: "GraphiteMod",
state: "liquid",
density: 2.3,
temp: 1710,
stateLow: "silicon_dioxide",
flammable: false,
reactions: {
"hydrofluoric_acid": { elem1: "silicon_tetrafluoride", elem2: "water" },
"hydrogen_fluoride": { elem1: "silicon_tetrafluoride", elem2: "water" },
"graphite": { elem1: "silicon", elem2: "carbon_monoxide", tempMin: 1700 },
"carbon": { elem1: "silicon", elem2: "carbon_monoxide", tempMin: 1700 }
}
};
/* Calcium carbonate (limestone) */
elements.calcium_carbonate = {
color: "#fffccc",
behavior: behaviors.SOLID,
category: "GraphiteMod",
state: "solid",
density: 2.71,
flammable: false,
reactions: {
"acid": { elem1: "carbon_dioxide", elem2: "water" },
"hydrofluoric_acid": { elem1: "calcium_fluoride", elem2: "carbon_dioxide" },
"hydrogen_fluoride": { elem1: "calcium_fluoride", elem2: "carbon_dioxide" },
"fire": { elem1: "calcium_oxide", elem2: "carbon_dioxide", tempMin: 850 }
}
};
/* Calcium oxide (quicklime) */
elements.calcium_oxide = {
color: "#fafafa",
behavior: behaviors.SOLID,
category: "GraphiteMod",
state: "solid",
density: 3.34,
tempHigh: 2572,
stateHigh: "molten_calcium_oxide",
reactions: {
"water": { elem1: "calcium_hydroxide", elem2: null },
"carbon_dioxide": { elem1: "calcium_carbonate", elem2: null },
"hydrogen_fluoride": { elem1: "calcium_fluoride", elem2: "water" },
"hydrofluoric_acid": { elem1: "calcium_fluoride", elem2: "water" }
}
};
elements.molten_calcium_oxide = {
color: "#f0e6cc",
behavior: behaviors.LIQUID,
category: "GraphiteMod",
state: "liquid",
density: 3.0,
temp: 2572,
stateLow: "calcium_oxide",
reactions: {
"water": { elem1: "calcium_hydroxide", elem2: null },
"carbon_dioxide": { elem1: "calcium_carbonate", elem2: null },
"hydrogen_fluoride": { elem1: "calcium_fluoride", elem2: "water" },
"hydrofluoric_acid": { elem1: "calcium_fluoride", elem2: "water" }
}
};
/* Calcium hydroxide (slaked lime) */
elements.calcium_hydroxide = {
color: "#f9fff9",
behavior: behaviors.SOLID,
category: "GraphiteMod",
state: "solid",
density: 2.21,
flammable: false,
reactions: {
"carbon_dioxide": { elem1: "calcium_carbonate", elem2: "water" },
"hydrofluoric_acid": { elem1: "calcium_fluoride", elem2: "water" },
"hydrogen_fluoride": { elem1: "calcium_fluoride", elem2: "water" },
"silicon_tetrafluoride": { elem1: "calcium_fluoride", elem2: "hydrofluoric_acid" }
}
};
/* Calcium fluoride (fluorspar) */
elements.calcium_fluoride = {
color: "#ccccff",
behavior: behaviors.SOLID,
category: "GraphiteMod",
state: "solid",
density: 3.18,
flammable: false,
reactions: {
"acid": { elem1: "hydrofluoric_acid", elem2: "calcium_sulfate" },
"hydrofluoric_acid": { elem1: "calcium_fluoride", elem2: null },
"hydrogen_fluoride": { elem1: "calcium_fluoride", elem2: null },
"molten_silicon_dioxide": { elem1: "calcium_silicate", elem2: null }
}
};
/* Calcium silicate (simple placeholder for Ca-silicates) */
elements.calcium_silicate = {
color: "#ddd8cc",
behavior: behaviors.SOLID,
category: "GraphiteMod",
state: "solid",
density: 2.9,
flammable: false,
reactions: {
"acid": { elem1: "calcium_fluoride", elem2: "silicon_tetrafluoride" },
"water": { elem1: "calcium_hydroxide", elem2: "silicon_dioxide" },
"fire": { elem1: "molten_calcium_silicate", elem2: null, tempMin: 1400 },
"hydrofluoric_acid": { elem1: "calcium_fluoride", elem2: "silicon_tetrafluoride" }
}
};
elements.molten_calcium_silicate = {
color: "#f0e6cc",
behavior: behaviors.LIQUID,
category: "GraphiteMod",
state: "liquid",
density: 2.9,
temp: 1400,
stateLow: "calcium_silicate",
flammable: false
};
/* Calcium sulfate (gypsum/anhydrite) */
elements.calcium_sulfate = {
color: "#e6e6e6",
behavior: behaviors.SOLID,
category: "GraphiteMod",
state: "solid",
density: 2.96,
flammable: false,
reactions: {
"water": { elem1: "gypsum", elem2: null },
"carbon": { elem1: "calcium_sulfide", elem2: "carbon_dioxide", tempMin: 1200 },
"hydrofluoric_acid": { elem1: "calcium_fluoride", elem2: "acid" },
"hydrogen_fluoride": { elem1: "calcium_fluoride", elem2: "acid" }
}
};
/* Gypsum (hydrated CaSO4) */
elements.gypsum = {
color: "#f3f3f3",
behavior: behaviors.SOLID,
category: "GraphiteMod",
state: "solid",
density: 2.32,
flammable: false,
reactions: {
"fire": { elem1: "calcium_sulfate", elem2: "water", tempMin: 250 },
"acid": { elem1: "calcium_sulfate", elem2: "acid" },
"carbon": { elem1: "calcium_sulfide", elem2: "carbon_dioxide", tempMin: 1200 },
"water": { elem1: "gypsum", elem2: null }
}
};
/* Calcium sulfide (product of high-T reduction) */
elements.calcium_sulfide = {
color: "#cfa76f",
behavior: behaviors.SOLID,
category: "GraphiteMod",
state: "solid",
density: 2.8,
flammable: false,
reactions: {
"water": { elem1: "hydrogen_sulfide", elem2: null },
"acid": { elem1: "hydrogen_sulfide", elem2: "calcium_fluoride" },
"fire": { elem1: "calcium_sulfide", elem2: null },
"carbon_dioxide": { elem1: "calcium_carbonate", elem2: "sulfur_dioxide" }
}
};
elements.silicon_carbide = {
color: "#2e2e2e",
behavior: behaviors.SOLID,
category: "GraphiteMod",
state: "solid",
density: 3.21,
tempHigh: 2730,
stateHigh: "molten_silicon_carbide",
reactions: {
"oxygen": { elem1: "silicon_dioxide", elem2: "carbon_dioxide", tempMin: 1000 },
"fluorine": { elem1: "silicon_tetrafluoride", elem2: "carbon_tetrafluoride", tempMin: 500 },
"hydrofluoric_acid": { elem1: "silicon_tetrafluoride", elem2: "carbon_tetrafluoride" },
"hydrogen_fluoride": { elem1: "silicon_tetrafluoride", elem2: "carbon_tetrafluoride" }
}
};
elements.molten_silicon_carbide = {
color: "#443f3f",
behavior: behaviors.LIQUID,
category: "GraphiteMod",
state: "liquid",
density: 3.2,
temp: 2730,
stateLow: "silicon_carbide",
flammable: false
};
/* Paper with graphite (drawing) */
elements.paper_with_graphite = {
color: "#888888",
behavior: behaviors.SOLID,
category: "GraphiteMod",
state: "solid",
density: 0.8,
flammable: true,
reactions: {
"fire": { elem1: "ash", elem2: "smoke" },
"oxygen": { elem1: "ash", elem2: "smoke", tempMin: 300 },
"water": { elem1: "paper", elem2: null },
"hydrofluoric_acid": { elem1: "ash", elem2: "acid" }
}
};
elements.eraser = {
color: "#ffffff",
tool: function(pixel) {
if (pixel.element == "paper_with_graphite") {
pixel.element = "paper"
pixel.color = "#ffffff"
}
},
category: "tools",
};

View File

@ -1,19 +1,36 @@
/*
Version 2.0.0
Version 2.1.0
*/
function multiChoice(text, handler, title) {
let pause = false;
if (promptState) { pause = promptState.wasPaused }
else if (paused) { pause = true }
promptState = {
type: "confirm",
text: text,
handler: handler,
title: title || "Are you sure?",
wasPaused: pause
}
showPromptScreen();
}
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 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,
@ -57,18 +74,23 @@ elements.copper_sulfate = {
tick: function(pixel){
if(pixelTicks-pixel.start == 2 && xDown){
pixel.anhydrous = true;
}
let colour;
let num = Math.round(Math.random()*2);
if(pixel.anhydrous && !["rgb(235,247,250)","rgb(242,248,250)"].includes(pixel.color)){
pixel.color = ["rgb(235,247,250)","rgb(242,248,250)"][num];
} else if (!pixel.anhydrous && !['rgb(67,145,253)', 'rgb(0,76,254)'].includes(pixel.color)){
pixel.color = ['rgb(67,145,253)', 'rgb(0,76,254)'][num];
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 = [];
@ -78,12 +100,26 @@ elements.copper_sulfate = {
}
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})`;
}
}
}
}
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;});
@ -94,18 +130,20 @@ elements.toggle_cloner = {
color: "#333300",
name: "ToggleableCloner",
keyInput: "chance",
insulate: 1,
properties: {
clone: null,
toggle: false,
chance: 0.0166666667,
clickCd: 0,
},
ignore: ["cloner", "toggle_cloner", "floating_cloner", "clone_powder", "slow_cloner", "ecloner", "destroyable_cloner", "destroyable_clone_powder", "ewall", "wall"],
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 = (element == "unknown" || elements.toggle_cloner.ignore.includes(element)) ? pixel.clone : element;
} else if (pixel.clickCd == 0) {
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);
@ -125,14 +163,16 @@ elements.toggle_cloner = {
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;
console.log(element);
};
},
onSelect: function(){
logMessage("Click on the pixel while adjacent to a clonable pixel to set clone, then click on it to toggle on or off.");
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--;}
@ -141,6 +181,7 @@ elements.toggle_cloner = {
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;
}
}
}
@ -154,6 +195,48 @@ elements.toggle_cloner = {
}
};
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",
@ -163,6 +246,7 @@ elements.toggle = {
toggle: false,
clickCd: 0,
},
hardness: 1,
onClicked: function(pixel){
if(pixel.clickCd == 0 && dragStart == null){
pixel.toggle = !pixel.toggle;
@ -198,7 +282,37 @@ elements.toggle = {
}
}
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",
@ -207,6 +321,7 @@ elements.toggle_temper = {
category: "machines",
targetTemp: 25,
keyInput: "targetTemp",
hardness: 1,
properties: {
toggle: false,
clickCd: 0,
@ -260,12 +375,16 @@ 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, and targetTemp for toggleable temper.", (In)=>{
this.input = parseFloat(In) || 0;
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){
pixel[elements[pixel.element].keyInput] = this.input;
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,
}
@ -295,6 +414,21 @@ class rangeTool {
}
}
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 = [];
@ -343,6 +477,7 @@ elements.toggle_mixer = new rangeTool("#212420", (pixel)=>{
};
});
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);
@ -380,3 +515,446 @@ elements.toggle_smasher = new rangeTool("#2e2726", (pixel)=>{
};
});
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()<chance){
changePixel(pixel, "hardened_gypsum");
}
}
}
elements.gallium_chloride = {
category: "salts",
alas: "GaCl₃",
behavior: behaviors.POWDER,
state: "solid",
color: ["#ffffff", "#fcfcfc", "#ffffff", "#ededed"],
density: 2470,
reactions: {
water: {elem1: "gallium", elem2: "acid"},
steam: {elem1: "gallium", elem2: "acid_gas"},
salt_water: {elem1: "gallium", elem2: ["acid", "salt"]},
seltzer: {elem1: "gallium", elem2: ["acid", "acid", "acid", "carbon_dioxide"]},
dirty_water: {elem1: "gallium", elem2: ["acid", "acid", "dirt"]},
sugar_water: {elem1: "gallium", elem2: ["acid", "sugar"]},
aluminum: {elem1: "gallium", elem2: "aluminum_chloride"},
sodium: {elem1: "gallium", elem2: "salt"},
potassium: {elem1: "gallium", elem2: "potassium_salt"},
magnesium: {elem1: "gallium", elem2: "magnesium_chloride"},
},
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) && Math.random()<0.0015){
createPixel("acid",x,y);
changePixel(pixel, "gallium");
}
}
}
};
elements.aluminum_chloride = {
category: "salts",
color: ["#fcd732", "#fad42d", "#f5d133", "#fad83e"],
alias: "AlCl₃",
behavior: behaviors.POWDER,
state: "solid",
density: 2480,
}
elements.acid.reactions.aluminum = {elem1: "hydrogen", elem2: "aluminum_chloride"};
elements.acid.reactions.purple_gold = {elem1: ["aluminum_chloride", "aluminum_chloride", "hydrogen"], elem2: "gold"};
elements.acid.reactions.blue_gold = {elem1: ["gallium_chloride", "gallium_chloride", "hydrogen"], elem2: "gold"};
elements.portal_in.keyInput = "channel", elements.portal_out.keyInput = "channel";
elements.target_portal_in = {
keyInput: "channel",
category: "machines",
state: "solid",
behavior: behaviors.WALL,
channel: 0,
movable: false,
hardness: 1,
checkAdjacent: function(pixel){
let adjacent = [];
for(let coords of adjacentCoords){
let x = pixel.x+coords[0], y = pixel.y+coords[1];
if(isEmpty(x,y) && !outOfBounds(x,y)){
adjacent.push([x,y]);
}
}
return (adjacent.length == 0) ? false : adjacent;
},
color: ["#f7ab05", "#fab011", "#faaf0c", "#f5aa0a", "#ffaf03"],
properties: {clickCd: 0, targetElems: [], channel: null, out: null},
onClicked: function(pixel, elem){
if(pixel.clickCd == 0){
if(elem != null){
if(pixel.targetElems.includes(elem)){
pixel.targetElems.splice(pixel.targetElems.indexOf(elem), 1);
} else {
pixel.targetElems.push(elem);
}
}
pixel.clickCd = 20;
}
},
onSelect: function(){
promptInput("Enter channel for the portal: ", (input)=>{
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]);
}
}
}
}
}
}

4895
mods/noita.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -2,9 +2,15 @@ pixelResizeButton = document.createElement("button");
pixelResizeButton.onclick = function(pixel) {
let canvas_width = document.getElementById("game").width;
let canvas_height = document.getElementById("game").height;
let pixelSizeNeeded = prompt("How big should pixels be?");
if (!pixelSizeNeeded || isNaN(pixelSizeNeeded)) { alert('number is invalid!'); return; }
resizeCanvas(canvas_height,canvas_width, parseFloat(pixelSizeNeeded), true);
promptInput("How big should pixels be?", (pixelSizeNeeded) => {
// let pixelSizeNeeded = prompt("How big should pixels be?");
if (!pixelSizeNeeded || isNaN(pixelSizeNeeded)) {
// alert('number is invalid!');
promptText("Number is invalid!");
return;
}
resizeCanvas(canvas_height,canvas_width, parseFloat(pixelSizeNeeded), true);
},"Pixel Size")
};
pixelResizeButton.textContent = "Resize";
window.addEventListener("load",function(){

View File

@ -1,16 +1,67 @@
/*
Version 2.1.0
Version 2.2.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));
}
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()<chance && isEmpty(x,y) && !outOfBounds(x,y) && !paused){
let elem = (elems != undefined && elems[currentLength] != undefined) ? elems[currentLength] : (elems != undefined) ? elems[0] : "fruit_leaves";
createPixel((elem == "flower") ? "fruit_leaves" : elem, x, y);
pixelMap[x][y].noBloom = (elem == "flower") ? false : true;
pixelMap[x][y].blooming = (elem == "flower");
pixelMap[x][y].fruit = fruit;
if(elem == "fruit_leaves"){
pixelMap[x][y].dieAfter = dieAfter;
}
currentLength++;
} else if (!isEmpty(x,y) && !outOfBounds(x,y)){
if(eLists.SOIL.includes(pixelMap[x][y].element)){
deletePixel(x,y);
let elem = (elems != undefined && elems[currentLength] != undefined) ? elems[currentLength] : (elems != undefined) ? elems[0] : "fruit_leaves";
createPixel((elem == "flower") ? "fruit_leaves" : elem, x, y);
pixelMap[x][y].noBloom = (elem == "flower") ? false : true;
pixelMap[x][y].blooming = (elem == "flower");
pixelMap[x][y].fruit = fruit;
if(elem == "fruit_leaves"){
pixelMap[x][y].dieAfter = dieAfter;
}
}
currentLength++;
}
}
}, 1000/tps);
this.interval = interval;
}
}
let flowerExclude = ["pineapple"];
let vineGrow = ["wood", "rock_wall", "straw", "wall", "ewall", "bush_cane", "bush_base", "fruit_branch"];
let plants = {
tree: [],
vine: ["grape", "tomato"],
bush: [],
other: ["pineapple"],
other: ["pineapple", "watermelon", "banana"],
includes: function(target){
for(item in this){
if(this[item] && Array.isArray(this[item]) && this[item].includes(target)){return true;}
@ -26,6 +77,66 @@ let growthPatterns = {
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]){
angle = min+(Math.random()*(max-min));
}
}
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)]);
}
return res;
},
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));
}
}
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)]);
}
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"],
@ -35,6 +146,14 @@ let growthElems = {
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,
@ -276,6 +395,35 @@ elements.fruit_leaves = {
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(pixelTicks == pixel.start + 1 && pixel.blooming == undefined && !pixel.growthPattern && !pixel.noBloom){
if(Math.floor(Math.random() * 3) == 2){
pixel.blooming = true;
@ -287,13 +435,22 @@ elements.fruit_leaves = {
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.color)){
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++){
@ -312,6 +469,15 @@ elements.fruit_leaves = {
} 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){
@ -337,7 +503,11 @@ elements.fruit_leaves = {
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;
}
}
}
}
@ -359,6 +529,7 @@ elements.fruit_leaves = {
} 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;
}
}
}
@ -372,6 +543,7 @@ elements.fruit_leaves = {
} 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;
}
}
}
@ -528,6 +700,7 @@ elements.fruit_vine = {
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;}
}
@ -540,7 +713,7 @@ elements.fruit_vine = {
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].color = "#FFE2E2";
pixelMap[x][y].bloomColor = pixel.bloomColor;
}
}
}
@ -566,6 +739,7 @@ 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);
@ -662,19 +836,18 @@ elements.seed_maker = {
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;
}
}
}
}
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 = {
behavior: behaviors.GAS,
category: "gases",
@ -685,8 +858,8 @@ elements.ethylene = {
reactions: {
oxidized_copper: { elem1: "vinegar", elem2: "copper", chance: 0.025},
},
color: r || ["#fffffc", "#f7f7f2", "#eaebe6", "#ededed", "#f7f7f2", "#f2f2f2"],
colorObject: (r != undefined) ? r.split("(")[1].split(")")[0].split(",") : undefined,
color: ["#fffffc", "#f7f7f2", "#eaebe6", "#ededed", "#f7f7f2", "#f2f2f2"],
buttonColor: ["#fffffc", "#f7f7f2"],
state: "gas",
burnInto: ["carbon_dioxide", "steam"],
burn: 100,
@ -714,8 +887,8 @@ elements.propylene = {
reactionCatalysts: {
nickel: {e1: "hydrogen", product: "propane", chance: 0.025},
},
color: r || ["#fffffc", "#f7f7f2", "#eaebe6", "#ededed", "#f7f7f2", "#f2f2f2"],
colorObject: (r != undefined) ? r.split("(")[1].split(")")[0].split(",") : undefined,
color: ["#fffffc", "#f7f7f2", "#eaebe6", "#ededed", "#f7f7f2", "#f2f2f2"],
buttonColor: ["#fffffc", "#f7f7f2"],
state: "gas",
burnInto: ["carbon_dioxide", "steam"],
burn: 100,
@ -744,6 +917,18 @@ elements.propane.reactionCatalysts = {
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 = [];
@ -785,14 +970,19 @@ elements.raspberry = new fruit("raspberry", ['#FF201C', '#EF3D3A', '#FA5350', '#
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"],
@ -914,6 +1104,7 @@ elements.unripe_fruit = {
elements.pineapple = {
category: "food",
breakInto: "juice",
bloomColor: ["#ff6682", "#ff6e88", "#ff6198", "#de73a5"],
color: ["#ffe712", "#f0d802", "#f2db05", "#d9c409"],
breakIntoColor: ["#fafa2a", "#f2f23d", "#f7f748", "#eded26"],
isFood: true,
@ -969,6 +1160,7 @@ elements.sugarcane_seed = {
},
}
elements.watermelon = new fruit("watermelon", ["#0e6614", "#065c0c", "#03700b", "#109119", "#098f12"], ["#ff4242", "#ed2f2f", "#ff2e2e", "#ed2828"]);
elements.watermelon.bloomColor = ["#e9ed11", "#f1f50a", "#fbff19", "#fbff29"];
elements.watermelon.behavior = behaviors.WALL;
elements.watermelon_seed = {
behavior: behaviors.POWDER,
@ -1002,3 +1194,311 @@ elements.watermelon_seed = {
}
}
elements.tomato.bloomColor = ["#edd93e", "#fae334", "#e6dc22", "#f5ec3d"];
elements.banana_seed = {
behavior: [['XX', 'XX', 'XX'],['XX', 'XX', 'XX'],['M2', 'M1 AND ST:wood', 'M2']],
color: ["#121211", "#121211", "#0f0f0e", "#171716"],
category: "life",
properties: {
age: 0,
fruit: "banana",
height: 0,
maxHeight: null,
leafLength: null,
intervals: [],
},
onDelete: function(pixel){
for(let value of pixel.intervals){
clearInterval(value);
}
},
tick: function(pixel){
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(Math.random()<(pixel.age-95)/7500 && pixel.height < pixel.maxHeight){
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.min(Math.round((pixel.height/pixel.maxHeight)*10),10)+4, 174, 366, [235,285]), [pixel.x, y], 0.25, 250);
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(pixel.leafLength, 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.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++;
}
}
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.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;
}
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){
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(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");
}
}
}

View File

@ -10,26 +10,30 @@ document.addEventListener("keydown", function(e) { //replace prompt listener
});
function replaceElementPrompt() {
var fromElement = prompt("Enter the element you want to change");
// replace spaces with underscores
fromElement = fromElement.replace(/ /g, "_");
fromElementS = mostSimilarElement(fromElement);
if (fromElementS === null || fromElementS === undefined || fromElementS === "") {
alert("Element \"" + fromElement + "\" not found! Defaulting to rock.");
fromElementS = "rock";
};
var toElement = prompt("Enter what you want to replace \"" + fromElementS + "\" with");
// replace spaces with underscores
toElement = toElement.replace(/ /g, "_");
toElementS = mostSimilarElement(toElement);
if (toElementS === null || toElementS === undefined || toElementS === "") {
alert("Element \"" + toElement + "\" not found! Defaulting to sand.");
toElementS = "sand";
};
replaceFrom = fromElementS;
replaceTo = toElementS;
updateReplaceDescriptions();
promptInput("Enter the element you want to change", (fromElement) => {
// var fromElement = prompt("Enter the element you want to change");
// replace spaces with underscores
fromElement = fromElement.replace(/ /g, "_");
fromElementS = mostSimilarElement(fromElement);
if (fromElementS === null || fromElementS === undefined || fromElementS === "") {
alert("Element \"" + fromElement + "\" not found! Defaulting to rock.");
fromElementS = "rock";
};
promptInput("Enter what you want to replace \"" + fromElementS + "\" with", (toElement) => {
// var toElement = prompt("Enter what you want to replace \"" + fromElementS + "\" with");
// replace spaces with underscores
toElement = toElement.replace(/ /g, "_");
toElementS = mostSimilarElement(toElement);
if (toElementS === null || toElementS === undefined || toElementS === "") {
alert("Element \"" + toElement + "\" not found! Defaulting to sand.");
toElementS = "sand";
};
replaceFrom = fromElementS;
replaceTo = toElementS;
updateReplaceDescriptions();
},"Replace With")
},"Replace Element")
}
function updateReplaceDescriptions() {

211
mods/schematics.js Normal file
View File

@ -0,0 +1,211 @@
// for pasting schematics (mostly logic gates)
// created by SquareScreamYT/sq
// https://github.com/SquareScreamYT/
// https://youtube.com/@sqec
elems = {
e: "ecloner", // ecloner with flash at -250c
E: "ecloner", // ecloner with flash at 20c
c: "cloner", // cloner with flash at -250c
C: "cloner", // cloner with flash at 20c
l: "ecloner", // ecloner with sand
L: "ecloner", // ecloner with liquid light
A: "ecloner", // cloner with antifluid
a: "ecloner", // cloner with antipowder
p: "porcelain",
W: "water",
w: "wall",
m: "meat",
b: "battery",
f: "flash",
s: "sensor",
x: "wire",
F: "fuse",
v: "void",
R: "led_r",
G: "led_g",
B: "led_b",
}
schematics = {
not_gate_1: `
C e
b
m
x
`,
not_gate_2: `
CeC
pWp
wsw
`,
or_gate: `
E E
s
`,
and_gate: `
Ce eC
pWwWp
wsxsw
CeC
pWp
wsw
`,
nand_gate: `
Ce eC
pWwWp
wsxsw
`,
nor_gate: `
Ce eC
pWwWp
wsxsw
CeC
pWp
wsw
`,
xor_gate: `
w x x w
xxxe exxx
xC Cx
x pWwWp x
x wsxsw x
Ce ex xe eC
C
pWwWp pWwWp
wsxsx xsxsw
Ce eC
pWwWp
wsxsw
`,
xnor_gate: `
w x x w
xxxe exxx
xC Cx
x pWwWp x
x wsxsw x
Ce ex xe eC
C
pWwWp pWwWp
wsxsx xsxsw
Ce eC
pWwWp
wsxsw
CeC
pWp
wsw
`,
intersection_tl: `
wlww
A s
w vw
wsww
`,
intersection_tr: `
wwlw
s A
wv w
wwsw
`,
intersection_bl: `
wsww
w vw
L s
waww
`,
intersection_br: `
wwsw
wv w
s L
wwaw
`,
}
function pasteSchematic(pattern, startX, startY) {
const lines = pattern.trim().split('\n');
for (let y = 0; y < lines.length; y++) {
for (let x = 0; x < lines[y].length; x++) {
const char = lines[y][x];
if (char !== ' ' && elems[char]) {
const pixelX = startX + x;
const pixelY = startY + y;
if (isEmpty(pixelX, pixelY)) {
createPixel(elems[char], pixelX, pixelY);
if (char.toLowerCase() == "e" || char.toLowerCase() == "c") {
pixelMap[pixelX][pixelY].clone = "flash"
if (char.toLowerCase() == char) {
pixelMap[pixelX][pixelY].temp = -250
}
} else if (char.toLowerCase() == "l" || char.toLowerCase() == "a") {
if (char == "a") {
pixelMap[pixelX][pixelY].clone = "antipowder"
} else if (char == "A") {
pixelMap[pixelX][pixelY].clone = "antifluid"
} else if (char == "L") {
pixelMap[pixelX][pixelY].clone = "liquid_light"
pixelMap[pixelX][pixelY].temp = -273.15
} else if (char == "l") {
pixelMap[pixelX][pixelY].clone = "sand"
}
}
}
}
}
}
}
for (schematic in schematics) {
elements[schematic] = {
category: "schematics",
color: "#888888",
behavior: behaviors.WALL,
state: "solid",
maxSize: 1,
onSelect: (function(pattern) {
return function() {
const lines = pattern.trim().split('\n');
let pixelCount = 0;
const height = lines.length;
const width = Math.max(...lines.map(line => line.length));
for (let y = 0; y < lines.length; y++) {
for (let x = 0; x < lines[y].length; x++) {
const char = lines[y][x];
if (char !== ' ' && elems[char]) {
pixelCount++;
}
}
}
logMessage(pixelCount + " pixels, " + width + "x" + height);
}
})(schematics[schematic]),
tick: (function(pattern) {
return function(pixel) {
deletePixel(pixel.x, pixel.y);
pasteSchematic(pattern, pixel.x, pixel.y);
}
})(schematics[schematic]),
excludeRandom: true
}
}

View File

@ -1,6 +1,6 @@
"use strict";
// WorldEdit.js (compiled)
// Version: 1.1.0
// Version: 1.2.0
// Constants
const w_accentColor = "#7cff62";
const w_style = {
@ -9,7 +9,8 @@ const w_style = {
selectStroke: w_accentColor,
selectDash: true,
pasteFill: "#00FFFF40",
pasteStroke: "#00FFFF"
pasteStroke: "#00FFFF",
pastePixelColor: "#00FFFF44"
};
// Global variables
let worldEditElements = {};
@ -18,7 +19,7 @@ let w_state = {
firstSelectionPos: {x: 0, y: 0},
selection: null,
clipboard: null,
prevNonWorldEditElement: "unknown"
lastNonWorldEditElement: "unknown"
};
// Define settings
let w_settingsTab;
@ -81,6 +82,10 @@ class Rect {
}
// Functions
function reverseString(str) {
return [...str].reverse().join("");
}
function isPointInWorld(point) {
return point.x >= 0 && point.x <= width && point.y >= 0 && point.y <= height;
}
@ -112,10 +117,11 @@ function updatePastePreviewCanvas() {
const imageData = pastePreviewCtx.createImageData(clipboardRect.w, clipboardRect.h);
const buffer = new Uint32Array(imageData.data.buffer);
buffer.fill(0x00000000);
const pixelColorBinary = parseInt(reverseString(w_style.pastePixelColor.slice(1)), 16);
for (let y = 0; y < clipboardRect.h; y++) {
for (let x = 0; x < clipboardRect.w; x++) {
if (clipboard[y][x])
buffer[y * clipboardRect.w + x] = 0x44FFFF00;
buffer[y * clipboardRect.w + x] = pixelColorBinary;
}
}
pastePreviewCtx.putImageData(imageData, 0, 0);
@ -200,8 +206,8 @@ function modifySelectElement() {
// @ts-ignore
selectElement = (element) => {
// Keep track of last non-worldEdit element
if (!worldEditElements.hasOwnProperty(currentElement))
w_state.prevNonWorldEditElement = currentElement;
if (!worldEditElements.hasOwnProperty(element))
w_state.lastNonWorldEditElement = element;
originalSelectElement(element);
};
}
@ -221,7 +227,7 @@ function addWorldEditElements(elementsToAdd) {
element.rawOnSelect = originalOnSelect;
element.onSelect = function (...args) {
originalOnSelect(...args);
selectElement(w_state.prevNonWorldEditElement);
selectElement(w_state.lastNonWorldEditElement);
};
}
}
@ -248,17 +254,17 @@ worldEditElements.w_select = {
return;
if (!isPointInWorld(pos))
return;
if (mouseType === "middle" || mouseType === "right")
if (e.button === 1 || e.button === 2)
return;
w_state.firstSelectionPos = pos;
},
onPointerMove: function (e) {
onPointerMoveAnywhere: function (e) {
const pos = mousePosToWorldPos({x: e.clientX, y: e.clientY});
if (!mouseIsDown)
return;
if (showingMenu)
return;
if (mouseType === "middle" || mouseType === "right")
if (e.button === 1 || e.button === 2)
return;
if (currentElement !== "w_select")
return;
@ -291,12 +297,12 @@ worldEditElements.w_copy = {
}
};
worldEditElements.w_paste = {
onPointerDown: function () {
onPointerDown: function (e) {
if (showingMenu)
return;
if (!isPointInWorld(mousePos))
return;
if (mouseType === "middle" || mouseType === "right")
if (e.button === 1 || e.button === 2)
return;
const clipboard = w_state.clipboard;
if (!clipboard) {
@ -380,7 +386,7 @@ worldEditElements.w_delete = {
worldEditElements.w_fill = {
onSelect: function () {
const selection = w_state.selection;
const fillElement = w_state.prevNonWorldEditElement;
const fillElement = w_state.lastNonWorldEditElement;
if (!selection) {
logMessage("Error: Nothing is selected.");
return;
@ -388,9 +394,11 @@ worldEditElements.w_fill = {
// Fill area
for (let y = selection.y; y < selection.y2; y++) {
for (let x = selection.x; x < selection.x2; x++) {
if (pixelMap[x][y])
continue;
const placed = currentPixels.push(new Pixel(x, y, fillElement));
if (!placed)
return;
continue;
if (currentPixels.length > maxPixelCount || !fillElement) {
currentPixels[currentPixels.length - 1].del = true;
} else if (elements[fillElement] && elements[fillElement].onPlace !== undefined) {
@ -425,5 +433,9 @@ runAfterReset(() => {
if (elements[currentElement] && elements[currentElement].onPointerMove)
elements[currentElement].onPointerMove(e);
}, {passive: false});
document.addEventListener("pointermove", (e) => {
if (elements[currentElement] && elements[currentElement].onPointerMoveAnywhere)
elements[currentElement].onPointerMoveAnywhere(e);
});
addedCustomEventListeners = true;
});

View File

@ -1,12 +1,12 @@
// WorldEdit.ts
// Version: 1.1.0
// Version: 1.2.0
// Interfaces
interface WorldEditState {
firstSelectionPos: Vec2D,
clipboard: Pixel[][] | null
selection: Rect | null
prevNonWorldEditElement: string
lastNonWorldEditElement: string
}
interface WorldEditStyle {
@ -16,17 +16,21 @@ interface WorldEditStyle {
selectDash: boolean
pasteFill: string
pasteStroke: string
pastePixelColor: string
}
// Constants
const w_accentColor = "#7cff62"
const w_style: WorldEditStyle = {
strokeWidth: 1,
selectFill: "#57b64530",
selectStroke: w_accentColor,
selectDash: true,
pasteFill: "#00FFFF40",
pasteStroke: "#00FFFF"
pasteStroke: "#00FFFF",
pastePixelColor: "#00FFFF44"
}
// Global variables
@ -37,7 +41,7 @@ let w_state: WorldEditState = {
firstSelectionPos: {x: 0, y: 0},
selection: null,
clipboard: null,
prevNonWorldEditElement: "unknown"
lastNonWorldEditElement: "unknown"
}
// Define settings
@ -121,6 +125,10 @@ class Rect {
}
// Functions
function reverseString(str: string): string {
return [...str].reverse().join("")
}
function isPointInWorld(point: Vec2D): boolean {
return point.x >= 0 && point.x <= width && point.y >= 0 && point.y <= height
}
@ -159,10 +167,17 @@ function updatePastePreviewCanvas(): void {
buffer.fill(0x00000000)
const pixelColorBinary: number = parseInt(
reverseString(
w_style.pastePixelColor.slice(1)
),
16
);
for (let y = 0; y < clipboardRect.h; y++) {
for (let x = 0; x < clipboardRect.w; x++) {
if (clipboard[y][x])
buffer[y * clipboardRect.w + x] = 0x44FFFF00
buffer[y * clipboardRect.w + x] = pixelColorBinary
}
}
@ -280,8 +295,8 @@ function modifySelectElement(): void {
// @ts-ignore
selectElement = (element: string): void => {
// Keep track of last non-worldEdit element
if (!worldEditElements.hasOwnProperty(currentElement))
w_state.prevNonWorldEditElement = currentElement
if (!worldEditElements.hasOwnProperty(element))
w_state.lastNonWorldEditElement = element
originalSelectElement(element)
}
@ -304,7 +319,7 @@ function addWorldEditElements(elementsToAdd: ElementsType): void {
element.rawOnSelect = originalOnSelect
element.onSelect = function (...args: any[]) {
originalOnSelect(...args)
selectElement(w_state.prevNonWorldEditElement)
selectElement(w_state.lastNonWorldEditElement)
}
}
}
@ -334,16 +349,16 @@ worldEditElements.w_select = {
if (showingMenu) return
if (!isPointInWorld(pos)) return
if (mouseType === "middle" || mouseType === "right") return
if (e.button === 1 || e.button === 2) return
w_state.firstSelectionPos = pos
},
onPointerMove: function (e: PointerEvent): void {
onPointerMoveAnywhere: function (e: PointerEvent): void {
const pos = mousePosToWorldPos({x: e.clientX, y: e.clientY})
if (!mouseIsDown) return
if (showingMenu) return
if (mouseType === "middle" || mouseType === "right") return
if (e.button === 1 || e.button === 2) return
if (currentElement !== "w_select") return
const rect = Rect.fromCorners(
@ -388,10 +403,11 @@ worldEditElements.w_copy = {
}
worldEditElements.w_paste = {
onPointerDown: function (): void {
onPointerDown: function (e: PointerEvent): void {
if (showingMenu) return
if (!isPointInWorld(mousePos)) return
if (mouseType === "middle" || mouseType === "right") return
if (e.button === 1 || e.button === 2) return
const clipboard = w_state.clipboard
@ -430,7 +446,6 @@ worldEditElements.w_cut = {
onSelect: function (): void {
const selection = w_state.selection
if (!selection) {
logMessage("Error: Nothing is selected.")
return
@ -489,7 +504,7 @@ worldEditElements.w_delete = {
worldEditElements.w_fill = {
onSelect: function (): void {
const selection = w_state.selection
const fillElement = w_state.prevNonWorldEditElement
const fillElement = w_state.lastNonWorldEditElement
if (!selection) {
logMessage("Error: Nothing is selected.")
@ -499,8 +514,10 @@ worldEditElements.w_fill = {
// Fill area
for (let y = selection.y; y < selection.y2; y++) {
for (let x = selection.x; x < selection.x2; x++) {
if (pixelMap[x][y]) continue
const placed = currentPixels.push(new Pixel(x, y, fillElement))
if (!placed) return
if (!placed) continue
if (currentPixels.length > maxPixelCount || !fillElement) {
currentPixels[currentPixels.length - 1].del = true
@ -543,5 +560,10 @@ runAfterReset(() => {
elements[currentElement].onPointerMove(e)
}, {passive: false})
document.addEventListener("pointermove", (e: PointerEvent) => {
if (elements[currentElement] && elements[currentElement].onPointerMoveAnywhere)
elements[currentElement].onPointerMoveAnywhere(e)
})
addedCustomEventListeners = true
})