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 ;
2024-02-11 13:05:26 -05:00
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 ; }
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 ) {
Version 1.13.2 - January 11, 2026
+ Edit Mode
~ Moved Special tools to the edit tab
~ Expect more tools in the future
+ Relations - Multiple pixels as a single entity
+ Group and Ungroup tool in edit tab
+ Grouped pixels fall and move as one structure
+ Grouped pixels are ungrouped when broken or changing states
+ Grouped pixels can displace fluids (Experimental)
+ More Shift-Select functionality:
+ Battery can set a frequency to create timers
+ Image tool can set element
~ Fire begins more yellow and gets redder quicker
+ Icing (Hidden) made with Butter and Sugar
~ Liquids and Gases appear less grainy
~ Settings changes
+ Speed option in Settings to replace TPS button
+ Keybind: T to change TPS
~ Renamed E button to Elem button
~ Improved simulation speeds
- Removed World Gen
~ We recommend the PRNGworldgenlib.js mod, a much better world generator
- Removed Cheerful Mode
[Changes]
+ Escape can be pressed to cancel while drawing a line
+ Fillers can be painted and will fight other colors
+ Portals show destination lines when hovered over or selected
+ Portal In can be selected with the Elem button by typing 'Portal'
+ Lightning placed near certain elements will change color
+ Worms can break down Flour, Dough, Adobe, Paper, Confetti, Cellulose, Cheese, and Potato
+ Worms can move through Mulch
+ Radiation will radiate Batter
+ Rad Steam causes Cheese to rot
~ Filters and Gates are Acid-resistant
~ Portals no longer teleport Fuse
~ Ruler measures diagonal lines as a pixel count instead of hypotenuse
~ Unique flame colors for Nickel, Iron, and Mercury
~ Rearranged Special category
~ Opening the Info, Mods, or Settings menus will pause the game
~ Steam: All canvas sizes now stretch to the full screen width
+ Assigned densities to many solids
+ Keybind: Quote (") to toggle Edit Mode
[Bug Fixes]
~ Fixed: Dragging pixels through Filters creates ghost pixels
~ Fixed: Filters can break when transporting to Gates or Pipes
~ Fixed: Pixels are rendered in incorrect position when mixing with Pipe, Filter, or Gate
~ Fixed: Broken modded saves are loaded every bootup
~ Fixed: Precision Dot is misaligned with 2- and 4-wide brushes
~ Fixed: Portals can't transmit electricity if surrounded by pixels
~ Fixed: E-cloner can't be set to Fuse by clicking on it
~ Fixed: Some saves throw TypeError "Cannot set properties of undefined"
~ Fixed: Prop tool always unpauses after dialog
~ Fixed: Z and Backspace keys select Heat by default instead of Sand
~ Fixed: Random can't place Fire, Plasma, Ink, Bless, Rock Wall, Cold Fire, Sun, Pointer, or Art
~ Fixed: Elem dialog doesn't close if button is pressed again
~ Fixed: Wrong font when language set to Italian
~ Fixed: Magnesium melts at a much lower temperature than expected
~ Fixed: Shift-selecting Random and inputting 'random' causes errors
[Technical]
~ Note: Optimizations mean a lot of code was rewritten, please report any issues and be patient
~ Note: Don't pass an 'rgba' color to drawSquare, use the 'alpha' argument instead
+ Pixel relations system
+ Used to group pixels together
+ '_r' pixel property to identify its relation (should be an integer)
+ 'trackPaint' element property (boolean)
+ 'painted' pixel property (color code) given to these elements when painted
+ "Failed to load" message instead of hanging forever
~ 'con' contents only render if element has existing 'canContain' property
~ 'onMouseDown' element event only triggers with left clicks
~ Acid Gas 'ignore' property is now identical to Acid
~ Elements with a set density but no state are set to solid
~ Fuse no longer shows hidden element
~ Save version is now sb7
2026-01-11 13:52:44 -05:00
if ( elements [ pixel . element ] . seed === true && pixel . element !== "cactus" ) { 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 ( ) ;
} ) ;