sandboxels/mods/survival.js

505 lines
19 KiB
JavaScript
Raw Normal View History

2024-02-10 22:31:14 -05:00
if (!settings.survival) {
settings.survival = {
"wall": 999,
"dirt": 999,
"sapling": 1,
"seeds": 5,
2024-02-11 13:05:26 -05:00
"ice": 25,
2024-02-10 22:31:14 -05:00
"cloner": 1,
}
}
settings.survival.cloner = 1;
2024-02-10 22:43:34 -05:00
settings.unhide = 0;
2024-02-10 22:31:14 -05:00
// settings.survivalClone=null; settings.survival = null; saveSettings();
survivalTimeout = null;
function survivalSave() {
if (survivalTimeout) { clearTimeout(survivalTimeout); }
survivalTimeout = setTimeout(function(){
saveSettings();
},1000);
}
function survivalAdd(element,amount,skipSave) {
2024-02-10 23:15:05 -05:00
if (elements[element].category === "tools") { return }
2024-02-10 22:31:14 -05:00
if (settings.survival[element]) {
settings.survival[element] += amount;
}
else {
settings.survival[element] = amount;
}
survivalUpdate(element);
if (!skipSave) {survivalSave()}
}
function survivalRemove(element,amount,skipSave) {
2024-02-10 23:15:05 -05:00
if (elements[element].category === "tools") { return }
2024-02-10 22:31:14 -05:00
if (settings.survival[element]) {
settings.survival[element] -= amount;
survivalUpdate(element);
}
if (settings.survival[element] <= 0) {
delete settings.survival[element];
var btn = document.getElementById("elementButton-"+element);
if (btn) { btn.remove(); }
2024-02-11 13:05:26 -05:00
selectElement("unknown");
2024-02-10 22:31:14 -05:00
}
if (!skipSave) {survivalSave()}
}
function survivalCount(element) {
return settings.survival[element] || 0;
}
function survivalUpdate(element) {
2024-02-11 13:05:26 -05:00
if (element === "gold_coin") {
// if it is not an integer, round it to 0.1
if (settings.survival.gold_coin % 1 !== 0) {
settings.survival.gold_coin = Math.round(settings.survival.gold_coin*10)/10;
}
document.getElementById("coinCount").innerHTML = settings.survival.gold_coin||0;
}
2024-02-10 22:31:14 -05:00
var btn = document.getElementById("elementButton-"+element);
2024-02-10 23:06:10 -05:00
if (elements[element] && elements[element].category === "tools") { return }
2024-02-10 22:31:14 -05:00
if (btn) {
btn.innerHTML = btn.innerHTML.split("(")[0]+"("+settings.survival[element]+")";
}
else if (elements[element]) {
createElementButton(element);
document.getElementById("elementButton-"+element).innerHTML += "("+settings.survival[element]+")";
}
}
runAfterAutogen(function(){
elements.erase.name = "pick_up";
delete elements.paint.category;
2024-02-10 23:06:10 -05:00
delete elements.lookup.category;
2024-02-10 22:31:14 -05:00
delete elements.pick;
2024-02-11 14:08:15 -05:00
delete elements.prop;
2024-02-10 23:06:10 -05:00
elements.radiation.category = "tools";
2024-02-10 22:31:14 -05:00
for (var element in elements) {
if (elements[element].category !== "tools") {
elements[element].hidden = true;
2026-01-25 11:53:09 -05:00
if (!settings.survival || Object.keys(settings.survival).length < 25) {
elements[element].category = "inventory";
}
2024-02-10 22:31:14 -05:00
}
Version 1.13 - December 17, 2025 - Gizmos & Gadgets + Filter + Only allows the first element it touches to pass + Gate + Only allows pixels to pass if electrified + Only conducts electricity into itself and Wire + Canvas background images + Some presets and custom image URLs + Outline View (Press 5) + 2-wide and 4-wide brushes + Ruler tool in Special to measure lengths and angles + Manual element control + Shift-clicking certain element buttons prompt the user for more information + Erase tool allows only deleting certain elements + Cloners allow multiple comma-separated elements + Filters allow states (solid, liquid, or gas) or multiple elements + Sensors allow sensing specific elements + Portals allow the setting of channels + Void allows only deleting certain elements + Random tool allows pre-selected element choices + Explosion allows custom radius + Antibombs allow pre-selected explosion elements ~ Replaced LED Red, Green, and Blue with a single customizable LED ~ LEDs in old saves are automatically converted to the new element - Merged Superheaters and Freezers with Heaters and Coolers + Heaters can be heated to heat the same as a Superheater + Coolers can be cooled to cool the same as a Freezer - Removed Tesla Coil and Shocker ~ These elements in old saves are automatically converted to E-cloners ~ Drag tool is faster and smoother ~ Pixelated and colorful button borders + Translations for Swedish + Parital translations for Japanese, Thai, Arabic, Hebrew, and Viossa [Changes] + Pipes can transport pixels directly with Filter and Gate ~ Pipes no longer conduct heat ~ Brightened blue stage in Pipes ~ Incomplete pipes darken after being initialized + Oxygen can be used to dispose Molten Lead in reactors + Electrolysis of raw Salt + Smashing hot Cooked Meat releases Grease + Worms can compost Lettuce, Tomato, Corn, Pickle, and Bread + Rats can eat Spiders + Caramel and Herb make peppermint-colored sugar + Baking Soda can be made with Lye and Carbon Dioxide + Melting Ash with Dirt creates Tuff ~ Poison Gas no longer makes Slag from molten elements ~ Perfume can exist at room temperature ~ Acid doesn't dissolve Mercury or Diamond ~ Sulfur ignites when hot ~ All Cloud types can be smashed like Rain Cloud ~ Thermite burns into less Iron ~ Rock Wall deletes Light when placed over it for better eclipses - Removed Gallium-Sodium reaction ~ Copper Sulfate reacts with more carbs ~ Rainbow recipe uses Pointer instead of Flash ~ Bless deletes Strange Matter instead of turning it into Neutron + Static recipe + Malware can mix with some metals to create machine parts + Tea stains Paper + Unique fire color for Tin ~ Element buttons are consistently spaced on all sides ~ Recolored Pyrite ~ Acid has a smoother texture ~ Purple Gold is slightly more purple ~ Hyphae and Lichen are grainier ~ Recolored Random button ~ Recolored Balloon button ~ Recolored Confetti button ~ Recolored Hair button ~ Recolored Pistil button ~ Reordered colors in many buttons for consistent "lighting" look ~ Rice, Candy, Nut Oil, Dye, Rainbow, and Spray Paint buttons display with dark text + Firefly alias 'Lightning Bug' ~ Shortened hiding setting labels ~ Language should automatically be set from browser preferences (Untested) ~ Re-saving after saving automatically fills in name, author, and description ~ Save browser thumbnails are crisper ~ Steam Deck compliance [Technical] + 'onShiftSelect' element property, called when selecting element while holding Shift + 'onlyConduct' element property, list of the only elements to conduct electricity into + 'renderTool' element property, renderer function called once per frame while selected + 'updateOrder' element property, prioritizes (positive) or deprioritizes (negative) tick order (integer; default 0) + autoResizeRatio(height,width) function (e.g. (16,9)) ~ 'shiftDown' variable is set even when in a menu [Bug Fixes] ~ Fixed: Placing Humans with Replace Mode causes a gory mess ~ Fixed: Using Human on Cloners cause a gory mess ~ Fixed: Bottom pixels can be cut off on certain window sizes ~ Fixed: Line-drawing preview is opaque when using a theme ~ Fixed: Text in Debug popup can't be selected ~ Fixed: onClicked passes "unknown" when no element is selected, now passes null ~ Fixed: onMouseDown doesn't get called on mobile ~ Fixed: onMouseDown is called when clicking out of a menu ~ Fixed: Using Heat Ray on Stained Glass can make Rainbows ~ Fixed: Saves with pipes containing invalid elements fail to load ~ Fixed: Some Fireflies stay illuminated after hitting another ~ Fixed: Liquid/gaseous pixels with 'skip' property can be displaced by denser pixels ~ Fixed: Salt isn't considered a food and can't be eaten by Humans ~ Fixed: Corn can't be dragged or put into Pipes
2025-12-17 12:08:39 -05:00
if (elements[element].onShiftSelect) delete elements[element].onShiftSelect;
2024-02-10 22:31:14 -05:00
}
for (var element in settings.survival) {
if (!elements[element]) { continue; }
2024-02-10 23:26:27 -05:00
if (elements[element].category === "tools") { continue; }
2026-01-28 15:27:08 -05:00
if (!elements[element].colorObject) {
elements[element].color = "#ffffff";
elements[element].colorObject = {"r": 255,"g": 255,"b": 255};
}
2024-02-10 22:31:14 -05:00
createElementButton(element);
document.getElementById("elementButton-"+element).innerHTML += "("+settings.survival[element]+")";
}
});
delete elements.cloner.behavior;
elements.cloner.tick = function(pixel) {
if (settings.survivalClone) {
if (Math.random() < 0.025) {
// 1 or -1
var x = pixel.x + (Math.random() < 0.5 ? 1 : -1);
var y = pixel.y + (Math.random() < 0.5 ? 1 : -1);
if (isEmpty(x,y)) {
createPixel(settings.survivalClone,x,y);
}
}
}
else {
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 (!isEmpty(x,y,true)) {
if (pixelMap[x][y].clone) { pixel.clone = pixelMap[x][y].clone; break }
var element = pixelMap[x][y].element;
if (element === pixel.element || elements[pixel.element].ignore.indexOf(element) !== -1) { continue }
settings.survivalClone = element;
survivalSave();
break;
}
}
}
};
2024-02-11 14:22:07 -05:00
elements.cloner.ignore = elements.cloner.ignore.concat(["gold","gold_coin","molten_gold","sun","supernova","diamond"]);
2024-02-11 13:05:26 -05:00
elements.cloner.desc = "You can only clone one element at a time!"
2024-02-10 23:06:10 -05:00
elements.smash.tool = function(pixel) {
2026-01-28 15:27:08 -05:00
if (elements[pixel.element].seed === true) { return }
2024-02-10 23:06:10 -05:00
if (elements[pixel.element].breakInto !== undefined || (elements[pixel.element].seed !== undefined && elements[pixel.element].seed !== true)) {
// times 0.25 if not shiftDown else 1
if (Math.random() < (elements[pixel.element].hardness || 1) * (shiftDown ? 1 : 0.25)) {
var breakInto = elements[pixel.element].breakInto;
2024-02-11 14:08:15 -05:00
if (elements[pixel.element].seed && (!breakInto || Math.random() < 0.5)) {
2024-02-10 23:15:05 -05:00
if (Math.random() < 0.2) {
2024-02-10 23:06:10 -05:00
breakInto = elements[pixel.element].seed;
}
else {
breakInto = null;
}
}
// if breakInto is an array, pick one
if (Array.isArray(breakInto)) {
breakInto = breakInto[Math.floor(Math.random() * breakInto.length)];
}
if (breakInto === null) {
2024-02-10 23:15:05 -05:00
deletePixel(pixel.x,pixel.y);
return;
2024-02-10 23:06:10 -05:00
}
var oldelement = pixel.element;
changePixel(pixel,breakInto);
pixelTempCheck(pixel);
if (elements[oldelement].breakIntoColor) {
pixel.color = pixelColorPick(pixel, elements[oldelement].breakIntoColor);
}
}
}
};
2024-02-10 22:31:14 -05:00
elementWorth = {
"gold_coin": 1,
2024-02-11 14:22:07 -05:00
"diamond": 100,
2024-02-11 13:05:26 -05:00
"ketchup": 15,
"jelly": 10,
"soda": 10,
"toast": 10,
2024-02-11 18:03:08 -05:00
"oil": 10,
2024-02-11 13:05:26 -05:00
"bread": 3,
"glass": 5,
"rad_glass": 6,
"glass_shard": 2,
"rad_shard": 3,
"paper": 5,
"broth": 5,
2024-02-11 14:50:36 -05:00
"honey": 5,
2024-02-11 13:05:26 -05:00
"caramel": 5,
2024-02-11 14:50:36 -05:00
"sap": 4,
2024-02-11 13:05:26 -05:00
"candy": 5,
"popcorn": 2,
"flour": 2,
"lettuce": 2,
"sauce": 2,
"wood": 0.2,
"tree_branch": 0.1,
"plant": 0.1,
"mushroom_cap": 0.1,
"mushroom_gill": 0.3,
"vine": 0.1,
2024-02-11 15:25:25 -05:00
"cactus": 0.1,
2024-02-10 22:31:14 -05:00
"cloner": 0,
"wall": 0,
2024-02-10 23:06:10 -05:00
"fire": 0,
"smoke": 0,
"plasma": 0,
2024-02-11 14:08:15 -05:00
"light": 0,
2024-02-11 14:22:07 -05:00
"laser": 0,
"liquid_light": 0.1,
"flash": 0,
2024-02-11 15:17:37 -05:00
"radiation": 0,
2024-02-10 23:15:05 -05:00
"petal": -1,
2024-02-11 13:05:26 -05:00
"cell": -1,
"cancer": -1,
2024-02-11 14:50:36 -05:00
"foam": -1,
2024-02-10 22:31:14 -05:00
}
elements.sell = {
color: ["#fff0b5","#ffe680","#c48821","#986a1a","#eca832","#f0bb62"],
tool: function(pixel) {
if (elementWorth[pixel.element] === 0) { return; }
deletePixel(pixel.x,pixel.y);
2024-02-10 23:06:10 -05:00
if (elementWorth[pixel.element] === -1) { return; }
2024-02-10 22:31:14 -05:00
survivalAdd("gold_coin",elementWorth[pixel.element]||1);
},
Version 1.10.2 - December 15, 2024 - Birthday III [Version 1.10.2 - December 15, 2024 - Birthday III] + Cheese Powder, from breaking Cheese + Chocolate Powder, from breaking Chocolate [Changes] ~ Drawing lines shows a preview of pixel placement ~ Updated Brick texture for better shading ~ LEDs, Light Bulbs, and Fireflies can be painted + Humans panic when seeing dangerous things, like Fire + Humans change direction after hitting walls ~ Humans eat more consistently ~ Humans have a panic limit ~ Humans no longer eat Human meat ~ Smash tool moves pixels if they can't be broken + Steam decomposes at extreme temperatures + Ruins has a Brick texture ~ Brick Rubble no longer breaks into Dust ~ Recolored Brick Rubble + Glass has a light border ~ Fancy textures have grain, besides Glass + Rock Wall can be made by gluing Rocks + Brick can be made by gluing Brick Rubble + Mudstone can be made by gluing Dirt + Packed Sand can be made by Sand + Sponges can dry Mud and Wet Sand + Clay can be made by dissolving Wet Sand in Acid + Cement can be made with Clay and Quicklime ~ Quicklime no longer turns into Limestone on its own + Plastic breaks into Beads + Charcoal slowly stains solids + Animals can spawn Eggs or offspring in Water + Seeds planted under soil will rise + Birds eat Spiders and their Webs + Rocks destroy Webs + Frogs release Steam when cooked + Worms break down Fiber ~ Worms compost some Sawdust into Dirt + Soap kills Snails and Slugs + Soap removes Slime + Alcohol kills Flower Pistils + Mercury kills Algae ~ Sap boils into some Steam ~ Bread is less flammable + Ammonia affects Wheat + Poison dirties Salt Water, Sugar Water, and Seltzer + Water on burning Oil will explode + Bleach reacts with Nut Oil and Grease + Baking Soda reacts with Soap + Copper Sulfate kills Spiders + Copper Sulfate stains Zinc + Bless removes Heat Ray + Plague makes Heads green + Plague destroys Skin + Hair absorbs some Water ~ Breaking Balloons makes some Pop ~ Cheese flows slower ~ Coffee Grounds in Milk brew into Coffee instead ~ Mushroom Spores no longer break ~ Acid Clouds don't precipitate when too hot or cold ~ Border can be painted ~ Tweaked Charcoal heat color ~ Moved Light Bulb to after LEDs + Midas Touch turns Paper green ~ Midas Touch turns Humans into solid Gold instead of Coins + Wall alias 'Solid' + Mayo alias 'Mayonnaise' + Alcohol alias 'Ethanol' + Unbreakable elements are clarified in element info ~ Screenshots download with name of current save ~ Pixel count turns red when all canvas sizes are full ~ Log messages have a black shadow to read on bright backgrounds ~ TPS dialog displays minimum and maximum [Bug Fixes] ~ Fixed: Replace Mode causes pixels to float while placing ~ Fixed: Detached Heads and dead Humans can eat food ~ Fixed: Pixel alpha isn't set from element properties on creation ~ Fixed: Molten Thermite continues to heat when not burning ~ Fixed: Prop tool can't set value when existing value is null ~ Fixed: Unbreakable pixels can burn away when using Prop tool (Perma-burning!!!) ~ Fixed: Pixels with burnt states never burn when using Prop tool ~ Fixed: Prop tool doesn't retain "0" value on next dialog ~ Fixed: Prop tool doesn't handle changing "x" and "y" properties ~ Fixed: Placing Fire on insulative pixels heats them ~ Fixed: Burning heats insulative pixels ~ Fixed: Rays, Bless, Radiation, and some Bombs change insulative pixel temperature ~ Fixed: Stink Bugs aren't properly killed by Frogs, Sap, Copper Sulfate, and Borax ~ Fixed: Erasing with Lookup selected will only erase 1x1 ~ Fixed: Erasing fast with Pick or Lookup selected will leave gaps ~ Fixed: Hail doesn't conduct heat ~ Fixed: Hail cannot break solids without a defined state ~ Fixed: Breaking Humans eventually creates Sand and Cement ~ Fixed: Element buttons arranged in weird columns after certain issues ~ Fixed: Ball doesn't have density and floats on gases [Technical] + BORDER render preset + 'grain' element property + 'toolHoverStat' element property, function that takes the hovered pixel while selected + 'buttonColor' element property ~ Humans now eat any element with true 'isFood' property ~ Pixels with 0% alpha won't appear in Basic View ~ LEDs with 0% alpha will only appear when powered + releaseElement function has option to replace liquids ~ Fixed: lineCoords function returns duplicate values + empty.js mod for browser JavaScript overriding
2024-12-15 11:45:52 -05:00
toolHoverStat: function(pixel) {
return "$"+(elementWorth[pixel.element]||1);
},
2024-02-10 22:31:14 -05:00
category: "tools",
2024-02-11 13:05:26 -05:00
desc: "Exchanges pixels for their market value in Gold Coins"
}
elements.seeds.name = "seed";
/*
~Cloner
~Sell
Shop
Cloner Reset
~Ammonia
~Dirt
~Water
~Seeds
~Sapling
~Pinecone
~Primordial Soup
~Worm
~Bee
~Human
~TNT
Seller (Runs Sell tool on pixels that touch it)
Buyer (Cloner but uses store price every time, prompt to select item on select)
Prices tab
*/
survivalShop = {
"dirt*25": 25,
"water*25": 250,
"ammonia*25": 500,
"seeds*1": 500,
"sapling*1": 500,
"pinecone*1": 500,
"tnt*25": 1000,
"worm*1": 1000,
"bee*1": 5000,
"primordial_soup*5": 10000,
"human*1": 50000,
2024-02-11 14:09:08 -05:00
"sun*1": 500000,
2024-02-11 13:05:26 -05:00
}
function survivalBuy(element) {
var price = survivalShop[element];
if (!price) { alert("The shop isn't selling "+element+"!"); return }
2024-02-11 13:14:59 -05:00
if (!settings.survival.gold_coin || settings.survival.gold_coin < price) { alert("You can't afford that!"); return }
2024-02-11 13:05:26 -05:00
survivalRemove("gold_coin",price);
var amount = 1;
if (element.indexOf("*") !== -1) { amount = parseInt(element.split("*")[1]); element = element.split("*")[0]; }
survivalAdd(element,amount);
selectElement(element);
}
function survivalResetCloner() {
2024-02-11 13:14:59 -05:00
if (!settings.survival.gold_coin || settings.survival.gold_coin < 1000) { alert("You can't afford that!"); return }
2024-02-11 13:05:26 -05:00
survivalRemove("gold_coin",1000);
settings.survivalClone = null;
survivalSave();
2024-02-10 22:31:14 -05:00
}
2024-02-12 17:05:26 -05:00
worldgentypes = {}
2024-02-10 22:31:14 -05:00
window.addEventListener("load",function(){
// move to start of tools
var erase = document.getElementById("elementButton-erase");
var sell = document.getElementById("elementButton-sell");
var parent = erase.parentElement;
parent.removeChild(sell);
parent.insertBefore(sell,parent.firstChild);
parent.removeChild(erase);
parent.insertBefore(erase,parent.firstChild);
document.getElementById("replaceButton").remove();
document.getElementById("savesButton").remove();
document.getElementById("elemSelectButton").remove();
doRandomEvents = function() {}
worldGen = function() {}
2024-02-12 17:05:26 -05:00
worldgentypes = {}
2024-02-10 22:31:14 -05:00
loadSave = function() {}
showSaves = function() {}
placeImage = function() {}
chooseElementPrompt = function() {}
2024-02-10 22:43:34 -05:00
document.getElementById("toolControls").insertAdjacentHTML("beforeend",`<button class="controlButton" title="Erases all survival.js data" onclick="if (confirm('THIS WILL ERASE ALL survival.js DATA!!! ARE YOU SURE?')) {settings.survivalClone=null; settings.survival = null; saveSettings(); location.reload()}">StartOver</button>`);
2024-02-11 13:05:26 -05:00
createCategoryDiv("shop");
var shopDiv = document.getElementById("category-shop");
shopDiv.style.display = "none";
shopDiv.insertAdjacentHTML("beforeend",`<p>You have $<span id="coinCount">${settings.survival.gold_coin||0}</span></p>`);
for (var element in survivalShop) {
var price = survivalShop[element];
var button = document.createElement("button");
var name = element;
var amount = 1;
if (element.indexOf("*") !== -1) { amount = parseInt(element.split("*")[1]); name = element.split("*")[0]; }
var elemname = name;
name = (elements[elemname].name||name).replace(/_/g, " ").replace("."," ").replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();}).replace(" ",".").replace(/ /g, "");
button.classList.add("elementButton");
button.setAttribute("element",element);
button.setAttribute("category","shop");
button.setAttribute("title",amount+" "+name+" for $"+price);
button.innerHTML = name+"<span style='font-family:Arial;font-size:1.15em'> ("+amount+" for $"+price+")</span>";
if (elements[elemname]) {
if (elements[elemname].color instanceof Array) {
button.style.backgroundImage = "linear-gradient(to bottom right, "+elements[elemname].color.join(", ")+")";
// choose the middlemost item in array
var colorObject = elements[elemname].colorObject[Math.floor(elements[elemname].colorObject.length/2)];
if (elements[elemname].darkText !== false && (elements[elemname].darkText || (colorObject.r+colorObject.g+colorObject.b)/3 > 200)) {
button.className += " bright"
}
}
else {
button.style.background = elements[elemname].color;
var colorObject = elements[elemname].colorObject;
if (elements[elemname].darkText !== false && (elements[elemname].darkText || (colorObject.r+colorObject.g+colorObject.b)/3 > 200)) {
button.className += " bright"
}
}
}
button.addEventListener("click",function(){
survivalBuy(this.getAttribute("element"));
});
shopDiv.appendChild(button);
}
shopDiv.insertAdjacentHTML("beforeend",`<p><button style="background-color:#dddd00" class="elementButton bright" title="Resets the cloner" onclick="survivalResetCloner()">ResetCloner<span style='font-family:Arial;font-size:1.15em'> ($1000)</span></button></p>`);
2024-02-11 13:11:32 -05:00
createCategoryDiv("prices");
var pricesDiv = document.getElementById("category-prices");
pricesDiv.style.display = "none";
for (var element in elementWorth) {
2024-02-11 13:16:54 -05:00
if (elementWorth[element] <= 0) { continue }
2024-02-11 13:11:32 -05:00
var name = (elements[element].name||element).replace(/_/g, " ").replace("."," ").replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();}).replace(" ",".");
// create text with the name of the element and its worth, separated by •
var text = name+"="+elementWorth[element] + " • ";
pricesDiv.insertAdjacentHTML("beforeend",`${text}`);
}
pricesDiv.innerHTML = pricesDiv.innerHTML.slice(0,-2);
pricesDiv.innerHTML = "<p style='font-family:Arial'>"+pricesDiv.innerHTML+"</p>";
2024-02-10 22:31:14 -05:00
});
runAfterLoad(function(){
checkUnlock = function(element) {
return;
}
oldClearAll = clearAll;
clearAll = function() {
if (currentPixels && currentPixels.length > 0) {
for (var i = 0; i < currentPixels.length; i++) {
var pixel = currentPixels[i];
if (pixel && pixel.element) {
survivalAdd(pixel.element,1);
}
}
}
oldClearAll();
}
mouseAction = function(e,mouseX,mouseY,startPos) {
if (mouseType == "left") {
mouse1Action(e,mouseX,mouseY,startPos);
}
else if (mouseType == "right") { mouse2Action(e,mouseX,mouseY,startPos); }
else if (mouseType == "middle") { mouseMiddleAction(e,mouseX,mouseY); }
}
mouse1Action = function(e,mouseX=undefined,mouseY=undefined,startPos) {
if (currentElement === "erase") { mouse2Action(e,mouseX,mouseY); return; }
else if (currentElement === "pick") { mouseMiddleAction(e,mouseX,mouseY); return; }
// If x and y are undefined, get the mouse position
if (mouseX == undefined && mouseY == undefined) {
// var canvas = document.getElementById("game");
// var ctx = canvas.getContext("2d");
lastPos = mousePos;
mousePos = getMousePos(canvas, e);
var mouseX = mousePos.x;
var mouseY = mousePos.y;
}
var cooldowned = false;
if ((mouseSize===1 || elements[currentElement].maxSize===1) && elements[currentElement].cooldown) {
if (pixelTicks-lastPlace < elements[currentElement].cooldown) {
return;
}
cooldowned = true;
}
lastPlace = pixelTicks;
startPos = startPos || lastPos
if (!(isMobile || (cooldowned && startPos.x===lastPos.x && startPos.y===lastPos.y) || elements[currentElement].tool || elements[currentElement].category==="tools")) {
var coords = lineCoords(startPos.x,startPos.y,mouseX,mouseY);
}
else { var coords = mouseRange(mouseX,mouseY); }
var element = elements[currentElement];
var mixList = [];
// For each x,y in coords
for (var i = 0; i < coords.length; i++) {
var x = coords[i][0];
var y = coords[i][1];
if (currentElement === "mix") {
if (!isEmpty(x,y,true)) {
var pixel = pixelMap[x][y];
if (!(elements[pixel.element].movable !== true || elements[pixel.element].noMix === true) || shiftDown) {
mixList.push(pixel);
}
}
}
else if (elements[currentElement].tool && !(elements[currentElement].canPlace && isEmpty(x,y))) {
// run the tool function on the pixel
if (!isEmpty(x,y,true)) {
var pixel = pixelMap[x][y];
// if the current element has an ignore property and the pixel's element is in the ignore property, don't do anything
if (elements[currentElement].ignore && elements[currentElement].ignore.indexOf(pixel.element) != -1) {
continue;
}
elements[currentElement].tool(pixel);
}
}
else if (isEmpty(x, y)) {
2024-02-10 23:06:10 -05:00
if (survivalCount(currentElement) < 1 && elements[currentElement].category !== "tools") {
2024-02-10 22:31:14 -05:00
return;
}
2024-11-26 17:08:08 -05:00
createPixel(currentElement,x,y);
Version 1.11 - February 21, 2025 - Everyone's Update [Version 1.11 - February 21, 2025 - Everyone's Update] + Portals! + Portal In and Portal Out elements + Portals teleport pixels and electricity + Coral + Grows in Water + Bleaches in high temperatures + Adobe, made from Mud and Straw + Element translations for Turkish and Hungarian [Electricity Rework] ~ Electricity is now more consistent in highly conductive material ~ Sensors give out a single charge instead of 4 ~ Pixels now store when they were charged ~ Note: Effects on existing builds should be limited but please report any issues [Changes] + Liquid pixels of the same element move around + Tiny canvas size + Molten elements oscillate color (Experimental) ~ Pixels can now exist along the border of the canvas ~ Disabling Staining will clear all existing pixel stains + Dye, Paint, etc. retain their selected color independently + Radioactive Tornado variant + Humans panic when shocked ~ Humans are less heat-resistant ~ Pipes are no longer unbreakable + Smoke rises in normal air density ~ Tweaked Fire and Cold Fire behavior + Sabatier process for producing Methane + Bergius process for producing Oil + Acid reacts with Potassium ~ Increased Methane autoignition point + Uranium radiates Glass on contact + Burning Lamp Oil explodes in Water + Liquid Ozone explodes when broken or shocked + Molten Gallium can react with Gold Coins + Slaked Lime reacts with Carbon Dioxide + Molten Plastic evaporates + Glue turns Color Sand into Stained Glass + Butter and Caustic Potash make Soap + Neutrons radiate Glass, Clouds, and Water ~ Light absorbed by LEDs is deleted ~ Foam made from Oxygen + Water releases the Oxygen ~ Tweaked Bleach and Acid reaction ~ Increased Molten Sulfur freezing point ~ Tweaked Smash tool + Cyanide dirties Water variants + Infection dirties Water + Tea and Coffee bubble when hot + CO2 carbonates Salt Water instead of dirtying + Soda and Seltzer release Foam when mixed + Pilk creates Foam + Cells can ferment Milk variants ~ Cells ferment Milk slower ~ Cheese keeps color when breaking into powder (Pilk Powder?) ~ Caramel is more heat-resistant ~ Acid turns Humans into Bone ~ Birds are less flammable + Fish turn to white meat when cooked + Worms can compost Petal, Pistil, and Vine + Rats can eat Hard Yolk + Alcohol calms Humans + Humans panic from bad smells + Smog breaks into Dirty Water ~ Fireworks create less Carbon Dioxide + Bless can fix Brick Rubble + Midas Touch converts some metals to Gold variants + Malware can affect Snake ~ Pointer retains same speed at any TPS ~ Optimized Cell and Cancer ~ Recolored Pipe Wall ~ Improved Slug, Brick, and Ruins buttons ~ Hid Liquid Oxygen ~ Unhid Liquid Hydrogen ~ Moved Liquid Hydrogen to Liquids ~ Moved Poison Gas to Gases + Liquid Nitrogen alias 'LN2' + Electric alias 'Electron' + Light alias 'Photon' + Nut Oil alias 'Cooking Oil' + Epsom Salt alias 'Magnesium Sulfate' + Pyrite alias 'Iron Sulfide' + Limestone alias 'Calcium Carbonate' + Quicklime alias 'Calcium Oxide' + Slaked Lime alias 'Calcium Hydroxide' ~ Petal displays with dark text ~ Slightly moved Porcelain + Built-in dialog boxes ~ Canvas touches the top of the page ~ Wide canvas size takes up more screen space ~ White border no longer shown on wide canvas size ~ Buttons, menus, and the canvas have thicker borders ~ "Elem" in stats bar is no longer uppercase ~ Unknown has no grain - Loading a save no longer changes your selected element + Ctrl+S to bring up save prompt + Ctrl+Shift+S to instantly save canvas + Retroactive changelogs for versions v0.1-v0.4 + Bluesky social link + Partial translations for Ukrainian, Toki Pona, and Halacae + Finished translations for Spanish and Russian [Bug Fixes] ~ Fixed: Oxygen from hydrolysis immediately turns to Foam ~ Fixed: Menu heights vary dramatically with long categories ~ Fixed: Mod Manager and Info Screen text boxes don't stick to bottom ~ Fixed: Lattice Wars appear without borders ~ Fixed: Smash tool breaks harder elements faster ~ Fixed: Error in console on page load ~ Fixed: Artifacts above stats bar text on Chrome ~ Fixed: Console logging when Hail breaks a pixel ~ Fixed: Milk variants still heat into Yogurt ~ Fixed: Controls still show Smooth View keybind ~ Fixed: "Save to File" button cut off on some small screens ~ Fixed: Many aliases can't be used in Element Select ~ Fixed: Prop tool doesn't change pixel state when changing temperature ~ Fixed: Grenades stop moving while charged ~ Fixed: Lightning doesn't reach bottom on large canvases ~ Fixed: Ghost pixels when placing Foam with low air temperature set ~ Fixed: 'CR' behavior cell errors with low air temperature set [Technical] + Portal 'channel' property can be set with the Prop tool (Integer) + runAfterReset function + isBreakable function + 'breakIntoColorMultiplier' element property + 'onMoveInto' element property, called when another pixel moves into it (function(pixel1,pixel2)) + 'chargeStart' pixel property ~ 'breakIntoColor' element property can be used without 'breakInto' + 'sense' sensor property to detect a certain element ~ Optimized electricity ~ Fire is affected by air density + View setting dropdown includes views added by mods ~ currentSaveData is now always defined, and holds metadata about the current canvas, even non-saves + currentSaveData always contains a UUID for seeded randomness ~ Default max pixel count slightly increased ~ Save version is now sb3 ~ Canvas border width is now stored (Default 1 for old saves) ~ Pixel properties with value "undefined" are skipped + Error message in console for broken translation files + GUI translation support + More GUI elements have IDs + Future standalone mode
2025-02-21 13:47:50 -05:00
if (pixelMap[x][y] && currentElement === pixelMap[x][y].element && (elements[currentElement].customColor || elements[currentElement].singleColor)) {
pixelMap[x][y].color = pixelColorPick(pixelMap[x][y],currentColorMap[currentElement]);
2024-02-10 22:31:14 -05:00
}
2024-02-11 13:05:26 -05:00
if (elements[currentElement].category !== "tools") { survivalRemove(currentElement,1); }
2024-02-10 22:31:14 -05:00
}
}
if (currentElement == "mix") {
for (var i = 0; i < mixList.length; i++) {
var pixel1 = mixList[Math.floor(Math.random()*mixList.length)];
var pixel2 = mixList[Math.floor(Math.random()*mixList.length)];
swapPixels(pixel1,pixel2);
mixList.splice(mixList.indexOf(pixel1),1);
mixList.splice(mixList.indexOf(pixel2),1);
if (elements[pixel1.element].onMix) {
elements[pixel1.element].onMix(pixel1,pixel2);
}
if (elements[pixel2.element].onMix) {
elements[pixel2.element].onMix(pixel2,pixel1);
}
}
}
}
mouse2Action = function(e,mouseX=undefined,mouseY=undefined,startPos) {
// Erase pixel at mouse position
if (mouseX == undefined && mouseY == undefined) {
// var canvas = document.getElementById("game");
// var ctx = canvas.getContext("2d");
lastPos = mousePos;
mousePos = getMousePos(canvas, e);
var mouseX = mousePos.x;
var mouseY = mousePos.y;
}
if (dragStart) {
dragStart = 0;
for (var i = 0; i < draggingPixels.length; i++) {
var pixel = draggingPixels[i];
delete pixel.drag;
}
draggingPixels = null;
}
// If the current element is "pick" or "lookup", coords = [mouseX,mouseY]
if (currentElement == "pick" || currentElement == "lookup") {
var coords = [[mouseX,mouseY]];
}
else if (!isMobile) {
startPos = startPos || lastPos
var coords = lineCoords(startPos.x,startPos.y,mouseX,mouseY);
}
else {
var coords = mouseRange(mouseX,mouseY);
}
// For each x,y in coords
for (var i = 0; i < coords.length; i++) {
var x = coords[i][0];
var y = coords[i][1];
if (!isEmpty(x, y)) {
if (outOfBounds(x,y)) {
continue
}
var pixel = pixelMap[x][y];
survivalAdd(pixel.element,1);
delete pixelMap[x][y];
// Remove pixel from currentPixels
for (var j = 0; j < currentPixels.length; j++) {
if (currentPixels[j].x == x && currentPixels[j].y == y) {
currentPixels.splice(j, 1);
break;
}
}
}
}
}
})
window.addEventListener("beforeunload",function(){
clearAll();
saveSettings();
});