2025-09-19 06:24:54 -04:00
/ *
Use intellisense for sandboxels modding here :
to show availavle functions and show global variables
2026-02-02 01:04:25 -05:00
https : //github.com/R74nCom/sandboxels-types
2025-09-19 06:24:54 -04:00
* /
2025-08-05 08:19:49 -04:00
2025-09-19 06:24:54 -04:00
// Changelog
2025-08-05 08:19:49 -04:00
/ *
2025-09-19 06:24:54 -04:00
V1
Solids : Aerogel , Nordic Gold , Nordic Gold coin , Pyrite
Machines : Disco Ball
Extras : Fire Extinguisher Powder
V2
Machines : Button , Disco Floor , Faulty Wire , Randomizer ,
Tools : Press , Circle
Solids : Cardboard , Obsidian
Powders : Glow Stick , Obsidian Shard
Liquids : Glow Stick Liquid , Lighter fluid , Gasoline
Life : Mold , Moss ,
Gases : Lighter Fluid Gas
Food : Pie , Pie Crust
2025-08-05 08:19:49 -04:00
V3
2025-08-08 08:14:26 -04:00
Tools : RGB LED , Dice , Custom Bomb
Life : Pineapple Plants ( seed , stem , fruit )
Hazards : Lithium Battery , Lithium , Rubidium , Asbestos
Minerals : Chalk , Chalk Powder , Lapis Lazuli
Light : UV Light , Phosphor , Neon Tube
Extras : Realistic Ball
V3 . 1
Bug Fixes
Chalk powder , Wet chalk poeder , and Obsidian shard can now be glued back as intended .
Dog can now be smashed correctly .
2025-08-11 07:32:23 -04:00
Steam support with promptInput ( ) instead of prompt ( )
2025-08-18 05:45:28 -04:00
V3 . 2
Machines : Robot , Adjustable heater / cooler
Bug Fixes
Fixed compatibility issue with nousersthings . js
2025-08-31 08:11:28 -04:00
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
2025-09-19 06:24:54 -04:00
V5
Machines : Random Teleporter
Life : Carrot seed and fruit
Minerals : Quartz and Quartz powder
Special : Random Word Generator , Fill all ,
Element fill all , Pulsing Color , Element line , White hole
Changes :
Moved sandstone to land category
Technical :
New helpers for squareCoords and adjacentCoords
Rainbow color preset
2025-08-05 08:19:49 -04:00
* /
2025-09-19 06:24:54 -04:00
let globals = {
circleRad : 7 ,
circleElem : "wood" ,
red : randomIntInRange ( 0 , 255 ) ,
green : randomIntInRange ( 0 , 255 ) ,
blue : randomIntInRange ( 0 , 255 ) ,
explodeElem : "fire" ,
adjusted _heater _temp : 100
}
2025-08-05 08:19:49 -04:00
2025-09-19 06:24:54 -04:00
const rainbowColor = [ "#ff0000" , "#ff8800" , "#ffff00" , "#00ff00" , "#00ffff" , "#0000ff" , "#ff00ff" ]
2025-08-05 08:19:49 -04:00
2025-07-19 22:52:04 -04:00
elements . button = {
color : "#970000" ,
conduct : 1 ,
charge : 0 ,
category : "machines" ,
2025-07-27 04:27:24 -04:00
behavior : behaviors . WALL ,
state : "solid" ,
2025-07-19 22:52:04 -04:00
onSelect : function ( ) {
logMessage ( "Click the button with no elements equipped to charge the button." )
} ,
properties : {
clicked : false ,
clickTime : 1 ,
} ,
onClicked : function ( pixel ) {
pixel . clicked = true
pixel . clickTime = 1
} ,
tick : function ( pixel ) {
if ( pixel . clicked == true && pixel . clickTime > 0 ) {
pixel . charge = 1
pixel . clickTime --
}
else if ( pixel . clicked == true && pixel . clickTime <= 0 ) {
pixel . clicked = false
pixel . charge = 0
}
}
}
2025-07-27 04:27:24 -04:00
function isPressable ( pixel ) {
if ( elements [ pixel . element ] . pressInto !== undefined ) return true ;
}
2025-07-19 22:52:04 -04:00
elements . aerogel = {
color : "#79ffff" ,
category : "solids" ,
behavior : behaviors . WALL ,
state : "solid" ,
tempHigh : 1200 ,
stateHigh : "ash" ,
insulate : true ,
density : 0.2 ,
hardness : 0.1 ,
breakInto : "dust" ,
onPlace : function ( pixel ) {
if ( pixel . alpha === undefined ) { pixel . alpha = Math . random ( ) * ( 0.5 - 0.4 ) + 0.4 }
}
}
let oldCopperReactions = elements . copper . reactions
elements . molten _copper . reactions . molten _aluminum = { elem1 : "molten_nordic_gold" , elem2 : null , chance : 0.5 }
elements . acid . ignore . push ( "nordic_gold" )
elements . acid . ignore . push ( "nordic_gold_coin" )
elements . nordic _gold = {
color : [ "#f1db7c" , "#e5c34b" , "#d2a742" , "#b98c31" , "#a47320" ] ,
tempHigh : 1060 ,
behavior : behaviors . WALL ,
category : "solids" ,
state : "solid" ,
density : 8800 ,
conduct : 0.90 ,
breakInto : "nordic_gold_coin"
}
elements . nordic _gold _coin = {
color : [ "#f1db7c" , "#e5c34b" , "#d2a742" , "#b98c31" , "#a47320" ] ,
tempHigh : 1060 ,
stateHigh : "molten_nordic_gold" ,
behavior : behaviors . POWDER ,
category : "powders" ,
state : "solid" ,
density : 8800 ,
conduct : 0.90 ,
alias : "euro_coin" ,
reactions : {
"glue" : { elem1 : "nordic_gold" , elem2 : null }
}
}
function randomColor ( ) {
const letters = "0123456789ABCDEF" ;
let color = "#" ;
for ( let i = 0 ; i < 6 ; i ++ ) {
color += letters [ Math . floor ( Math . random ( ) * 16 ) ] ;
}
return color ;
}
elements . disco _ball = {
color : "#ebebc3" ,
2025-09-19 06:24:54 -04:00
buttonColor : rainbowColor ,
2025-07-19 22:52:04 -04:00
renderer : renderPresets . LED ,
behavior : behaviors . WALL ,
category : "machines" ,
tempHigh : 1500 ,
stateHigh : [ "molten_glass" , "molten_glass" , "molten_copper" ] ,
conduct : 1 ,
breakInto : "glass_shard" ,
forceSaveColor : true ,
tick : function ( pixel ) {
2025-09-19 06:24:54 -04:00
if ( ! pixel . charge ) {
pixel . charge = 0
}
2025-07-19 22:52:04 -04:00
for ( var i = 0 ; i < squareCoords . length ; i ++ ) {
var coord = squareCoords [ i ] ;
var x = pixel . x + coord [ 0 ] ;
var y = pixel . y + coord [ 1 ] ;
if ( pixel . charge > 0 ) {
pixel . color = randomColor ( )
if ( isEmpty ( x , y ) ) {
createPixel ( "light" , x , y )
let p = getPixel ( x , y )
if ( p !== null && p . element == "light" ) {
p . color = pixel . color
}
}
}
else { pixel . color = "#ebebc3" }
}
2025-08-05 08:19:49 -04:00
} ,
state : "solid"
2025-07-19 22:52:04 -04:00
}
elements . molten _iron . reactions . sulfur = { elem1 : "pyrite" , elem2 : null , chance : 0.25 }
elements . molten _iron . reactions . molten _sulfur = { elem1 : "pyrite" , elem2 : null , chance : 0.25 }
elements . molten _iron . reactions . sulfur _gas = { elem1 : "pyrite" , elem2 : null , chance : 0.25 }
2025-12-18 00:14:33 -05:00
elements . cubesstuff _pyrite = {
2025-07-19 22:52:04 -04:00
color : [ "#d8c25e" , "#bbaa49" , "#998f3e" ] ,
alias : [ "fools_gold" , "Iron Disulfide" ] ,
density : 5000 ,
tempHigh : 1177 ,
stateHigh : [ "iron" , "molten_sulfur" ] ,
grain : 0.4 ,
state : "solid" ,
behavior : behaviors . WALL ,
2025-12-18 00:14:33 -05:00
category : "deprecated"
2025-07-19 22:52:04 -04:00
}
elements . fire _extinguisher _powder = {
color : "#ececec" ,
behavior : [
"XX|XX|XX" ,
"XX|DL%1|XX" ,
"M2%30|M1%30|M2%30"
] ,
extinguish : true ,
tick : function ( pixel ) {
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 ( getPixel ( x , y ) ? . burning === true ) {
let elem = getPixel ( x , y )
elem . burning = false
}
}
} ,
2025-07-27 04:27:24 -04:00
tool : function ( pixel ) {
if ( pixel . burning === true ) {
2025-07-19 22:52:04 -04:00
delete pixel . burning ;
delete pixel . burnStart ;
}
} ,
canPlace : true ,
2025-08-05 08:19:49 -04:00
category : "powders" ,
state : "solid"
2025-07-27 04:27:24 -04:00
}
elements . pie _crust = {
color : "#f1f192" ,
breakInto : "crumb" ,
tempHigh : 500 ,
stateHigh : "ash" ,
burn : 5 ,
burnTime : 400 ,
burnInto : [ "smoke" , "smoke" , "smoke" , "ash" ] ,
category : "food" ,
state : "solid" ,
behavior : behaviors . STURDYPOWDER ,
isFood : true ,
hidden : true ,
density : 230 ,
reactions : {
"pumpkin" : { elem1 : "pie" , elem2 : null , tempMin : 200 } ,
"cooked_meat" : { elem1 : "pie" , elem2 : null , tempMin : 200 } ,
"meat" : { elem1 : "pie" , elem2 : null , tempMin : 200 } ,
"potato" : { elem1 : "pie" , elem2 : null , tempMin : 200 } ,
"mashed_potato" : { elem1 : "pie" , elem2 : null , tempMin : 200 } ,
"baked_potato" : { elem1 : "pie" , elem2 : null , tempMin : 200 } ,
2025-08-05 08:19:49 -04:00
"grape" : { elem1 : "pie" , elem2 : null , tempMin : 200 , func : function ( pixel ) { pixel . originColor = "#8200fc" } } ,
"pineapple" : { elem1 : "pie" , elem2 : null , tempMin : 200 , func : function ( pixel ) { pixel . originColor = "#ffd900" } }
2025-07-27 04:27:24 -04:00
}
}
elements . pie = {
color : "#fac145" ,
darkText : false ,
behavior : behaviors . STURDYPOWDER ,
category : "food" ,
isFood : true ,
density : 240 ,
burn : 5 ,
burnTime : 400 ,
burnInto : [ "smoke" , "smoke" , "smoke" , "ash" ] ,
state : "solid" ,
tempHigh : 500 ,
stateHigh : "ash" ,
breakInto : "sauce" ,
2025-08-05 08:19:49 -04:00
breakIntoColor : [ "#ff822e" , "#ff8c2e" ] ,
tick : function ( pixel ) {
if ( pixel . originColor ) {
pixel . breakIntoColor = pixel . originColor
}
}
2025-07-27 04:27:24 -04:00
}
elements . gasoline = {
color : [ "#ffff66" , "#ffff55" , "#ffff44" ] ,
behavior : behaviors . LIQUID ,
burn : 80 ,
burnTime : 100 ,
burnInto : [ "fire" , "fire" , "fire" , "explosion" ] ,
viscosity : 0.7 ,
density : 750 ,
category : "liquids" ,
state : "liquid" ,
conduct : 0.02 ,
behaviorOn : [
"XX|XX|XX" ,
"XX|EX:10|XX" ,
"XX|XX|XX"
]
}
// Make molten sulfur stinky
elements . molten _sulfur . tick = function ( pixel ) {
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 ) && Math . random ( ) <= 0.0005 ) {
createPixel ( "stench" , x , y )
2025-09-19 06:24:54 -04:00
let p = getPixel ( x , y )
2025-07-27 04:27:24 -04:00
if ( p !== null && p . element == "stench" ) {
p . temp = pixel . temp
}
}
}
}
elements . disco _floor = {
2025-09-19 06:24:54 -04:00
color : rainbowColor ,
2025-07-27 04:27:24 -04:00
breakInto : "glass_shard" ,
category : "machines" ,
forceSaveColor : true ,
conduct : 1 ,
behavior : behaviors . WALL ,
2025-08-05 08:19:49 -04:00
state : "solid" ,
2025-07-27 04:27:24 -04:00
tick : function ( pixel ) {
pixel . changeCd ? ? = 20 ;
pixel . changeCd -- ;
if ( pixel . changeCd <= 0 ) {
let colors = elements . disco _floor . color ;
pixel . color = colors [ Math . floor ( Math . random ( ) * colors . length ) ] ;
pixel . changeCd = 20 ;
}
}
} ;
elements . moss = {
color : [ "#007900" , "#006000" , "#008300" ] ,
behavior : behaviors . POWDER ,
tick : function ( pixel ) {
for ( var i = 0 ; i < squareCoords . length ; i ++ ) {
var coords = squareCoords [ i ] ;
var x = pixel . x + coords [ 0 ] ;
var y = pixel . y + coords [ 1 ] ;
if ( isEmpty ( x , y ) && Math . random ( ) <= 0.01 && getPixel ( pixel . x , pixel . y + 1 ) && getPixel ( pixel . x , pixel . y + 1 ) . element !== "moss" ) {
createPixel ( 'moss' , x , y )
}
}
} ,
tempHigh : 70 ,
stateHigh : "dead_plant" ,
extraTempHigh : {
"100" : [ "dead_plant" , "dead_plant" , "steam" ]
} ,
tempLow : - 10 ,
stateLow : "frozen_plant" ,
burn : 50 ,
burnTime : 30 ,
reactions : {
"carbon_dioxide" : { elem2 : "oxygen" , chance : 0.1 } ,
"rock" : { elem2 : "dirt" , chance : 0.0025 } ,
"rock_wall" : { elem2 : "dirt" , chance : 0.0025 } ,
"gravel" : { elem2 : "dirt" , chance : 0.0025 } ,
} ,
2025-08-05 08:19:49 -04:00
category : "life" ,
state : "solid"
2025-07-27 04:27:24 -04:00
}
elements . magma . extraTempLow = { "700" : "obsidian" }
elements . obsidian = {
color : [ "#1f1f1f" , "#1f1f1f" , "#1f1f1f" , "#1f1f1f" , "#292929" ] ,
buttonColor : [ "#1a1a1a" , "#2b2b2b" , "#3b3b3b" ] ,
colorPattern : textures . GLASS ,
colorKey : {
"g" : "#1f1f1f" ,
"s" : "#292929" ,
"S" : "#252525"
} ,
grain : 0 ,
behavior : behaviors . WALL ,
category : "solids" ,
tempHigh : 1200 ,
stateHigh : "magma" ,
state : "solid" ,
density : 2500 ,
breakInto : "obsidian_shard"
}
elements . obsidian _shard = {
color : [ "#1f1f1f" , "#1f1f1f" , "#1f1f1f" , "#1f1f1f" , "#292929" ] ,
behavior : behaviors . POWDER ,
grain : 0 ,
category : "powders" ,
tempHigh : 1200 ,
stateHigh : "magma" ,
state : "solid" ,
density : 2500 ,
2025-08-08 08:14:26 -04:00
reactions : {
2025-08-11 07:32:23 -04:00
"glue" : { elem1 : "obsidian" , elem2 : null }
2025-08-08 08:14:26 -04:00
}
2025-07-27 04:27:24 -04:00
}
elements . cardboard = {
color : [ "#9E6B34" ] ,
burn : 70 ,
burnTime : 300 ,
burnInto : [ "fire" , "fire" , "fire" , "fire" , "fire" , "ash" ] ,
behavior : behaviors . WALL ,
reactions : {
"water" : { elem1 : "cellulose" , elem2 : null } ,
"dirty_water" : { elem1 : "cellulose" , elem2 : null } ,
"salt_water" : { elem1 : "cellulose" , elem2 : null } ,
"sugar_water" : { elem1 : "cellulose" , elem2 : null } ,
"seltzer" : { elem1 : "cellulose" , elem2 : null } ,
"soda" : { elem1 : "cellulose" , elem2 : null } ,
"blood" : { elem1 : "cellulose" , elem2 : null } ,
"foam" : { elem1 : "cellulose" , elem2 : null } ,
"bubble" : { elem1 : "cellulose" , elem2 : null } ,
"oil" : { elem1 : "cellulose" , elem2 : null } ,
"alcohol" : { elem1 : "cellulose" , elem2 : null } ,
"vinegar" : { elem1 : "cellulose" , elem2 : null }
} ,
category : "solids" ,
tempHigh : 248 ,
stateHigh : [ "fire" , "fire" , "fire" , "fire" , "fire" , "ash" ] ,
state : "solid" ,
density : 1200
}
elements . paper . pressInto = "cardboard"
2025-08-05 08:19:49 -04:00
function pressPixel ( pixel ) {
if ( elements [ pixel . element ] . pressInto === undefined ) { return ; }
// if it is an array, choose a random item, else just use the value
let result ;
if ( elements [ pixel . element ] . pressInto !== undefined ) {
if ( Array . isArray ( elements [ pixel . element ] . pressInto ) ) {
result = elements [ pixel . element ] . pressInto [ Math . floor ( Math . random ( ) * elements [ pixel . element ] . pressInto . length ) ] ;
}
else {
result = elements [ pixel . element ] . pressInto ;
}
}
// change the pixel to the result
if ( result === null ) {
deletePixel ( pixel . x , pixel . y ) ;
return ;
}
else if ( result !== undefined ) {
changePixel ( pixel , result ) ;
}
}
2025-07-27 04:27:24 -04:00
elements . press = {
color : [ "#999999" , "#c0c0c0" , "#999999" ] ,
category : "tools" ,
tool : function ( pixel ) {
// edited smash code
if ( isPressable ( pixel ) ) {
2025-08-05 08:19:49 -04:00
let old = pixel . element
if ( Math . random ( ) < ( 1 - ( elements [ pixel . element ] . resistPress || 0 ) ) / ( shiftDown ? 1 : 4 ) ) {
pressPixel ( pixel )
2025-07-27 04:27:24 -04:00
}
2025-08-05 08:19:49 -04:00
else if ( old === pixel . element && elements [ pixel . element ] . movable && ! isEmpty ( pixel . x , pixel . y + 1 ) && ! paused ) {
let x = 0 ; let y = 0 ;
if ( Math . random ( ) < 0.66 ) x = Math . random ( ) < 0.5 ? 1 : - 1 ;
if ( Math . random ( ) < 0.66 ) y = Math . random ( ) < 0.5 ? 1 : - 1 ;
tryMove ( pixel , pixel . x + x , pixel . y + y )
2025-07-27 04:27:24 -04:00
}
}
2025-09-19 06:24:54 -04:00
if ( elements [ pixel . element ] . onPress !== undefined ) {
elements [ pixel . element ] . onPress ( pixel )
}
2025-07-27 04:27:24 -04:00
}
}
elements . malware . reactions . wire = { elem2 : [ null , "faulty_wire" ] , chance : 0.01 } ;
elements . faulty _wire = {
color : [ "#4d0a03" , "#4d0a03" , "#4d0a03" , "#4d0a03" , "#4d0a03" , "#4d0a03" , "#4d0a03" , "#4d0a03" , "#4d0a03" , "#a95232" , ] ,
buttonColor : "#4d0a03" ,
behavior : behaviors . WALL ,
behaviorOn : [
"XX|CR:electric,flash%1|XX" ,
"CR:electric,flash%1|XX|CR:electric,flash%1" ,
"XX|CR:electric,flash%1|XX"
] ,
category : "machines" ,
insulate : true ,
conduct : 0.7 ,
noMix : true ,
2025-08-05 08:19:49 -04:00
state : "solid"
2025-07-27 04:27:24 -04:00
}
elements . lighter _fluid = {
color : "#f1e185" ,
behavior : [
"XX|XX|XX" ,
"M2 AND SW:lighter_fluid_gas|XX|M2 AND SW:lighter_fluid_gas" ,
"M1 AND SW:lighter_fluid_gas|M1 AND SW:lighter_fluid_gas|M1 AND SW:lighter_fluid_gas"
] ,
category : "liquids" ,
state : "liquid" ,
density : 750 ,
tick : function ( pixel ) {
pixel . gasMade ? ? = 0
for ( var i = 0 ; i < squareCoordsShuffle . length ; i ++ ) {
var coord = squareCoordsShuffle [ i ] ;
var x = pixel . x + coord [ 0 ] ;
var y = pixel . y + coord [ 1 ] ;
2025-08-05 08:19:49 -04:00
if ( isEmpty ( x , y ) && Math . random ( ) >= 0.75 ) {
2025-07-27 04:27:24 -04:00
createPixel ( "lighter_fluid_gas" , x , y )
pixel . gasMade += 1
}
}
if ( pixel . gasMade > 100 && Math . random ( ) <= 0.01 ) {
deletePixel ( pixel . x , pixel . y )
}
}
}
elements . lighter _fluid _gas = {
color : "#f1e185" ,
alpha : 0.1 ,
behavior : behaviors . GAS ,
category : "gases" ,
state : "gas" ,
burn : 100 ,
isGas : true ,
hidden : true ,
density : 20 ,
tick : function ( pixel ) {
2025-08-05 08:19:49 -04:00
if ( Math . random ( ) <= 0.1 ) {
2025-07-27 04:27:24 -04:00
deletePixel ( pixel . x , pixel . y )
}
}
}
elements . mold = {
color : "#054e05" ,
category : "life" ,
behavior : behaviors . POWDER ,
state : "solid" ,
burn : 70 ,
burnTime : 100 ,
tempHigh : 200 ,
stateHigh : "fire" ,
tempLow : - 10 ,
stateLow : "frozen_plant" ,
reactions : {
"meat" : { elem1 : "rotten_meat" , elem2 : "rotten_meat" } ,
"cheese" : { elem1 : "rotten_cheese" , elem2 : "rotten_cheese" }
} ,
tick : function ( pixel ) {
let moldable = [ "meat" , "cheese" , "rotten_meat" , "rotten_cheese" ]
for ( var i = 0 ; i < squareCoords . length ; i ++ ) {
var coords = squareCoords [ i ] ;
var x = pixel . x + coords [ 0 ] ;
var y = pixel . y + coords [ 1 ] ;
if ( isEmpty ( x , y ) && Math . random ( ) <= 0.01 && getPixel ( pixel . x , pixel . y + 1 ) && moldable . includes ( getPixel ( pixel . x , pixel . y + 1 ) . element ) ) {
createPixel ( 'mold' , x , y )
}
}
}
}
elements . glow _stick = {
color : [ "#00ff00" , "#ea00ff" , "#00eeff" ] ,
glow : true ,
behavior : behaviors . POWDER ,
breakInto : "glow_stick_liquid" ,
2025-08-05 08:19:49 -04:00
category : "powders" ,
tempHigh : 300 ,
stateHigh : [ "molten_plastic" , "stench" ] ,
state : "solid"
2025-07-27 04:27:24 -04:00
}
elements . glow _stick _liquid = {
color : [ "#00ff00" , "#ea00ff" , "#00eeff" ] ,
glow : true ,
behavior : behaviors . LIQUID ,
2025-08-05 08:19:49 -04:00
category : "liquids" ,
hidden : true ,
tempHigh : 300 ,
stateHigh : "stench" ,
tempLow : - 5 ,
stateLow : "glow_stick_ice" ,
state : "solid"
2025-07-27 04:27:24 -04:00
}
2025-08-05 08:19:49 -04:00
elements . glow _stick _ice = {
color : [ "#00ff00" , "#ea00ff" , "#00eeff" ] ,
behavior : behaviors . WALL ,
category : "states" ,
hidden : true ,
temp : - 5 ,
tempHigh : - 5 ,
stateHigh : "glow_stick_liquid" ,
state : "solid"
}
2025-07-27 04:27:24 -04:00
elements . randomizer = {
2025-09-19 06:24:54 -04:00
buttonColor : rainbowColor ,
2025-07-27 04:27:24 -04:00
excludeRandom : true ,
onSelect : function ( ) {
logMessage ( "Warning: It can fill up the screen with random elements" )
} ,
tick : function ( pixel ) {
pixel . color = randomColor ( )
for ( var i = 0 ; i < adjacentCoords . length ; i ++ ) {
var coords = adjacentCoords [ i ] ;
var x = pixel . x + coords [ 0 ] ;
var y = pixel . y + coords [ 1 ] ;
let p = getPixel ( x , y )
if ( ! isEmpty ( x , y ) && ! outOfBounds ( x , y ) ) {
2025-09-19 06:24:54 -04:00
if ( p && p . element !== "randomizer" ) {
2025-07-27 04:27:24 -04:00
changePixel ( p , "random" )
}
}
}
} ,
behavior : behaviors . WALL ,
insulate : true ,
hardness : 1 ,
2025-08-05 08:19:49 -04:00
category : "special" ,
state : "solid"
2025-07-27 04:27:24 -04:00
}
elements . cloner . ignore . push ( "randomizer" )
elements . ecloner . ignore . push ( "randomizer" )
elements . floating _cloner . ignore . push ( "randomizer" )
elements . slow _cloner . ignore . push ( "randomizer" )
elements . rocket . ignore . push ( "randomizer" )
elements . antibomb . tick = function ( pixel ) {
doDefaults ( pixel )
if ( ! tryMove ( pixel , pixel . x , pixel . y + 1 ) ) {
if ( ! outOfBounds ( pixel . x , pixel . y + 1 ) ) {
var elem = pixelMap [ pixel . x ] [ pixel . y + 1 ] . element ;
if ( elements [ elem ] . isGas ) { return }
}
else {
var elem = "smoke" ;
}
if ( elem !== "antibomb" && elem !== "randomizer" ) {
explodeAt ( pixel . x , pixel . y , 8 , elem )
}
}
}
function drawCircle ( x0 , y0 , radius , element ) {
for ( let y = - radius ; y <= radius ; y ++ ) {
for ( let x = - radius ; x <= radius ; x ++ ) {
if ( x * x + y * y <= radius * radius ) {
let px = x0 + x ;
let py = y0 + y ;
if ( isEmpty ( px , py ) ) {
createPixel ( element , px , py ) ;
}
}
}
}
}
elements . circle = {
2025-08-05 08:19:49 -04:00
color : "#ffffff" ,
2025-07-27 04:27:24 -04:00
behavior : behaviors . WALL ,
category : "special" ,
2025-08-05 08:19:49 -04:00
state : "solid" ,
onSelect : function ( ) {
2025-08-11 07:32:23 -04:00
promptInput (
"Select the radius you want your circle to be:" ,
function ( input1 ) {
let ans1 = Number ( input1 )
if ( Number . isInteger ( ans1 ) && ans1 > 0 ) {
2025-09-19 06:24:54 -04:00
globals . circleRad = ans1
2025-08-11 07:32:23 -04:00
} else {
2025-09-19 06:24:54 -04:00
globals . circleRad = 7
logMessage ( "Invalid radius, using default size: " + globals . circleRad ) ;
2025-08-11 07:32:23 -04:00
}
promptInput (
"Select the element you want your circle to be:" ,
function ( ans2 ) {
let similar = mostSimilarElement ( ans2 ) ;
if ( similar && elements [ similar ] ) {
2025-09-19 06:24:54 -04:00
globals . circleElem = similar ;
2025-08-11 07:32:23 -04:00
} else {
2025-09-19 06:24:54 -04:00
globals . circleElem = "wood"
logMessage ( "Invalid element, using default element: " + globals . circleElem ) ;
2025-08-11 07:32:23 -04:00
}
} ,
"Element prompt" ,
"wood"
) ;
} ,
"Radius prompt" ,
"7"
) ;
2025-07-27 04:27:24 -04:00
} ,
2025-08-05 08:19:49 -04:00
onPlace : function ( pixel ) {
2025-09-19 06:24:54 -04:00
drawCircle ( pixel . x , pixel . y , globals . circleRad , globals . circleElem ) ;
changePixel ( pixel , globals . circleElem ) ;
pixel . temp = ( elements [ globals . circleElem ] . temp || 20 )
2025-07-27 04:27:24 -04:00
} ,
2025-08-05 08:19:49 -04:00
maxSize : 1 ,
excludeRandom : true
2025-07-27 04:27:24 -04:00
} ;
2025-08-05 08:19:49 -04:00
runAfterReset ( function ( ) {
2025-09-19 06:24:54 -04:00
if ( globals . rCircle ) {
globals . circleRad = 7 ;
globals . circleElem = "wood" ;
}
2025-07-27 04:27:24 -04:00
} )
2025-08-05 08:19:49 -04:00
2025-09-19 06:24:54 -04:00
/ * *
* gets a random int in a range
* @ param { number } min
* @ param { number } max
* @ returns { number }
* /
2025-08-05 08:19:49 -04:00
function randomIntInRange ( min , max ) {
return Math . floor ( Math . random ( ) * ( max - min + 1 ) ) + min ;
}
2025-09-19 06:24:54 -04:00
2025-08-05 08:19:49 -04:00
elements . rgb _led = {
2025-09-19 06:24:54 -04:00
buttonColor : rainbowColor ,
2025-08-05 08:19:49 -04:00
behavior : behaviors . WALL ,
2025-08-11 07:32:23 -04:00
desc : "Input the red, green, and blue value (not exceeding 255) and get the color." ,
2025-08-05 08:19:49 -04:00
renderer : renderPresets . LED ,
conduct : 1 ,
state : "solid" ,
breakInto : "glass_shard" ,
forceSaveColor : true ,
reactions : {
"light" : { charge1 : 1 , elem2 : null } ,
"liquid_light" : { charge1 : 1 , elem2 : null }
} ,
2025-12-18 00:14:33 -05:00
category : "deprecated" ,
2025-08-05 08:19:49 -04:00
tempHigh : 1500 ,
stateHigh : [ "molten_glass" , "molten_glass" , "molten_glass" , "molten_gallium" ] ,
2025-08-11 07:32:23 -04:00
onSelect : ( ) => {
2026-02-02 01:04:25 -05:00
promptInput ( "Enter red value (0-255):" , function ( old _r _inp ) {
let r _inp = parseInt ( old _r _inp ) ;
2025-08-11 07:32:23 -04:00
if ( r _inp > 255 || r _inp < 0 || isNaN ( r _inp ) ) {
2025-11-19 23:22:26 -05:00
logMessage ( "Red value is invalid, using default/last red value: " + globals . red ) ;
2025-08-11 07:32:23 -04:00
} else {
2025-09-19 06:24:54 -04:00
globals . red = r _inp ;
2025-08-11 07:32:23 -04:00
}
2025-08-05 08:19:49 -04:00
2026-02-02 01:04:25 -05:00
promptInput ( "Enter green value (0-255):" , function ( old _g _inp ) {
let g _inp = parseInt ( old _g _inp ) ;
2025-08-11 07:32:23 -04:00
if ( g _inp > 255 || g _inp < 0 || isNaN ( g _inp ) ) {
2025-11-19 23:22:26 -05:00
logMessage ( "Green value is invalid, using default/last green value: " + globals . green ) ;
2025-08-11 07:32:23 -04:00
} else {
2025-09-19 06:24:54 -04:00
globals . green = g _inp ;
2025-08-11 07:32:23 -04:00
}
2025-08-05 08:19:49 -04:00
2026-02-02 01:04:25 -05:00
promptInput ( "Enter blue value (0-255):" , function ( old _b _inp ) {
let b _inp = parseInt ( old _b _inp ) ;
2025-08-11 07:32:23 -04:00
if ( b _inp > 255 || b _inp < 0 || isNaN ( b _inp ) ) {
2025-11-19 23:22:26 -05:00
logMessage ( "Blue value is invalid, using default/last blue value: " + globals . blue ) ;
2025-08-11 07:32:23 -04:00
} else {
2025-09-19 06:24:54 -04:00
globals . blue = b _inp ;
2025-08-11 07:32:23 -04:00
}
2026-02-02 01:04:25 -05:00
} , "Blue Value" , String ( globals . blue ) ) ; // optional default input
} , "Green Value" , String ( globals . green ) ) ;
} , "Red Value" , String ( globals . red ) ) ;
2025-08-05 08:19:49 -04:00
} ,
2025-08-11 07:32:23 -04:00
2025-08-05 08:19:49 -04:00
onPlace : ( pixel ) => {
2025-11-19 23:22:26 -05:00
var ledColor = RGBToHex ( [ globals . red , globals . green , globals . blue ] ) ;
2025-08-05 08:19:49 -04:00
pixel . color = ledColor ;
}
} ;
2025-08-11 07:32:23 -04:00
2025-08-05 08:19:49 -04:00
runAfterReset ( ( ) => {
2025-09-19 06:24:54 -04:00
if ( globals . rRGBLed ) {
globals . red = 100 ;
globals . greed = 100 ;
globals . blue = 100 ;
}
2025-08-05 08:19:49 -04:00
} )
2025-09-19 06:24:54 -04:00
if ( ! elements . malware . reactions ) { elements . malware . reactions = { } }
2025-08-05 08:19:49 -04:00
elements . malware . reactions . rgb _led = { elem2 : [ "led_r" , "led_g" , "led_b" ] , chance : 0.01 }
elements . malware . reactions . led _r = { elem2 : [ "rgb_led" , "led_g" , "led_b" ] , chance : 0.01 }
elements . malware . reactions . led _g = { elem2 : [ "rgb_led" , "led_r" , "led_b" ] , chance : 0.01 }
elements . malware . reactions . led _b = { elem2 : [ "rgb_led" , "led_g" , "led_r" ] , chance : 0.01 }
elements . dice = {
color : "#d5d5d5" ,
state : "solid" ,
onClicked ( pixel ) {
pixel . clicked = true ;
} ,
tick ( pixel ) {
if ( pixel . rolled === undefined ) {
pixel . rolled = false ;
}
if ( pixel . clicked && ! pixel . rolled ) {
const roll = randomIntInRange ( 1 , 6 ) ;
clearLog ( )
logMessage ( "Dice roll: " + roll ) ;
pixel . rolled = true ;
}
if ( ! pixel . clicked ) {
pixel . rolled = false ;
}
pixel . clicked = false ;
} ,
behavior : behaviors . WALL ,
density : 500 ,
category : "special" ,
onSelect : ( ) => {
logMessage ( "Click The Dice to Roll" )
logMessage ( "It is reccomended to roll only one dice at a time as it will only show one value" )
}
}
elements . wood . pressInto = "plank" ;
elements . wood . resistPress = 0.5 ;
elements . plank = {
color : "#98633B" ,
behavior : behaviors . WALL ,
renderer : renderPresets . WOODCHAR ,
tempHigh : 400 ,
stateHigh : [ "ember" , "charcoal" , "fire" , "fire" , "fire" ] ,
category : "solids" ,
burn : 5 ,
burnTime : 300 ,
burnInto : [ "ember" , "charcoal" , "fire" ] ,
state : "solid" ,
hardness : 0.50 ,
breakInto : "sawdust" ,
forceSaveColor : true
}
elements . sand . pressInto = "packed_sand" ;
elements . sand . resistPress = 0.2
elements . snow . pressInto = "packed_snow" ;
elements . snow . resistPress = 0.2
elements . asbestos = {
color : "#f1f5f1" ,
behavior : [
"SP|XX|SP" ,
"XX|XX|XX" ,
"SA AND M2|M1|SP AND M2"
] ,
category : "powders" ,
state : "solid" ,
tempHigh : 800 ,
stateHigh : [ "dust" , "ash" , "fire" ] ,
breakInto : [ "gravel" , "sand" , "dust" ] ,
reactions : {
"body" : { elem2 : "cancer" , chance : 0.5 } ,
"head" : { elem2 : "cancer" , chance : 0.5 }
} ,
nocheer : true
}
elements . lithium _battery = {
color : "#616161" ,
behavior : [
"XX|SH|XX" ,
"SH|XX|SH" ,
"XX|SH|XX"
] ,
tempHigh : 1400 ,
stateHigh : [ "explosion" , "lithium" , "acid_gas" ] ,
hardness : 0.8 ,
breakInto : [ "lithium" , "acid" ] ,
category : "machines" ,
alias : "lithium-ion battery" ,
state : "solid"
}
elements . lithium = {
color : "#acacac" ,
behavior : behaviors . POWDER ,
reactions : {
"water" : { elem1 : [ "pop" , "pop" , "pop" , "hydrogen" ] , chance : 0.01 , temp2 : 200 } ,
"salt_water" : { elem1 : [ "pop" , "pop" , "pop" , "hydrogen" ] , chance : 0.01 , temp2 : 200 } ,
"pool_water" : { elem1 : [ "pop" , "pop" , "pop" , "hydrogen" ] , chance : 0.01 , temp2 : 200 } ,
"sugar_water" : { elem1 : [ "pop" , "pop" , "pop" , "hydrogen" ] , chance : 0.01 , temp2 : 200 } ,
"seltzer" : { elem1 : [ "pop" , "pop" , "pop" , "hydrogen" ] , chance : 0.01 , temp2 : 200 } ,
"dirty_water" : { elem1 : [ "pop" , "pop" , "pop" , "hydrogen" ] , chance : 0.01 , temp2 : 200 } ,
"primordial_soup" : { elem1 : [ "pop" , "pop" , "pop" , "hydrogen" ] , chance : 0.01 , temp2 : 200 } ,
"nut_milk" : { elem1 : [ "pop" , "pop" , "pop" , "hydrogen" ] , chance : 0.01 , temp2 : 200 }
} ,
density : 533.4 ,
tempHigh : 180.5 ,
conduct : 0.45 ,
category : "powders" ,
state : "solid"
}
elements . molten _lithium = {
tempHigh : 1344 ,
stateHigh : 'lithium_gas' ,
reactions : {
"water" : { elem1 : [ "pop" , "pop" , "pop" , "hydrogen" ] , chance : 0.01 , temp2 : 200 } ,
"salt_water" : { elem1 : [ "pop" , "pop" , "pop" , "hydrogen" ] , chance : 0.01 , temp2 : 200 } ,
"pool_water" : { elem1 : [ "pop" , "pop" , "pop" , "hydrogen" ] , chance : 0.01 , temp2 : 200 } ,
"sugar_water" : { elem1 : [ "pop" , "pop" , "pop" , "hydrogen" ] , chance : 0.01 , temp2 : 200 } ,
"seltzer" : { elem1 : [ "pop" , "pop" , "pop" , "hydrogen" ] , chance : 0.01 , temp2 : 200 } ,
"dirty_water" : { elem1 : [ "pop" , "pop" , "pop" , "hydrogen" ] , chance : 0.01 , temp2 : 200 } ,
"primordial_soup" : { elem1 : [ "pop" , "pop" , "pop" , "hydrogen" ] , chance : 0.01 , temp2 : 200 } ,
"nut_milk" : { elem1 : [ "pop" , "pop" , "pop" , "hydrogen" ] , chance : 0.01 , temp2 : 200 }
} ,
state : "liquid"
}
elements . lithium _gas = {
color : "#cccccc" ,
behavior : behaviors . GAS ,
isGas : true ,
tempLow : 1334 ,
stateLow : "molten_lithium" ,
density : 533.4 ,
conduct : 0.45 ,
temp : 1334 ,
category : "states" ,
hidden : true ,
state : "gas"
}
elements . chalk = {
color : "#fff3ac" ,
behavior : behaviors . WALL ,
stain : 0.25 ,
category : "land" ,
breakInto : "chalk_powder" ,
tempHigh : 1000 ,
density : 2700 ,
reactions : {
"water" : { elem1 : "wet_chalk" , elem2 : null , chance : 0.5 } ,
"salt_water" : { elem1 : "wet_chalk" , elem2 : null , chance : 0.5 } ,
"seltzer" : { elem1 : "wet_chalk" , elem2 : null , chance : 0.5 } ,
"dirty_water" : { elem1 : "wet_chalk" , elem2 : null , chance : 0.5 } ,
"sugar_water" : { elem1 : "wet_chalk" , elem2 : null , chance : 0.5 } ,
"pool_water" : { elem1 : "wet_chalk" , elem2 : null , chance : 0.5 } ,
"primordial_soup" : { elem1 : "wet_chalk" , elem2 : null , chance : 0.5 } ,
"nut_milk" : { elem1 : "wet_chalk" , elem2 : null , chance : 0.5 }
} ,
alias : "calcite" ,
state : "solid"
}
elements . chalk _powder = {
color : "#fff3ac" ,
behavior : behaviors . POWDER ,
stain : 0.25 ,
category : "powders" ,
tempHigh : 1000 ,
stateHigh : "molten_chalk" ,
density : 2700 ,
reactions : {
"water" : { elem1 : "wet_chalk_powder" , elem2 : null , chance : 0.5 } ,
"salt_water" : { elem1 : "wet_chalk_powder" , elem2 : null , chance : 0.5 } ,
"seltzer" : { elem1 : "wet_chalk_powder" , elem2 : null , chance : 0.5 } ,
"dirty_water" : { elem1 : "wet_chalk_powder" , elem2 : null , chance : 0.5 } ,
"sugar_water" : { elem1 : "wet_chalk_powder" , elem2 : null , chance : 0.5 } ,
"pool_water" : { elem1 : "wet_chalk_powder" , elem2 : null , chance : 0.5 } ,
"primordial_soup" : { elem1 : "wet_chalk_powder" , elem2 : null , chance : 0.5 } ,
2025-08-08 08:14:26 -04:00
"nut_milk" : { elem1 : "wet_chalk_powder" , elem2 : null , chance : 0.5 } ,
2025-08-11 07:32:23 -04:00
"glue" : { elem1 : "chalk" , elem2 : null }
2025-08-05 08:19:49 -04:00
} ,
state : "solid"
}
elements . wet _chalk = {
color : "#bbb17b" ,
behavior : behaviors . WALL ,
stain : 0.25 ,
category : "land" ,
breakInto : "wet_chalk_powder" ,
tempHigh : 100 ,
stateHigh : "chalk" ,
density : 2300 ,
onStateHigh : ( pixel ) => {
releaseElement ( pixel , "steam" )
} ,
state : "solid"
}
elements . wet _chalk _powder = {
color : "#bbb17b" ,
behavior : behaviors . POWDER ,
stain : 0.25 ,
category : "powders" ,
tempHigh : 100 ,
stateHigh : "chalk_powder" ,
density : 2000 ,
onStateHigh : ( pixel ) => {
releaseElement ( pixel , "steam" )
} ,
2025-08-08 08:14:26 -04:00
state : "solid" ,
reactions : {
2025-08-11 07:32:23 -04:00
"glue" : { elem1 : "chalk" , elem2 : null }
2025-08-08 08:14:26 -04:00
}
2025-08-05 08:19:49 -04:00
}
elements . lapis _lazuli = {
color : [ "#0000df" , "#1212cc" , "#120A8F" , "#060080" ] ,
behavior : behaviors . WALL ,
breakInto : "lapis_lazuli_powder" ,
tempHigh : 1100 ,
stateHigh : 'magma' ,
state : "solid" ,
category : "solids"
}
elements . lapis _lazuli _powder = {
color : "#120A8F" ,
behavior : behaviors . POWDER ,
tempHigh : 1100 ,
stateHigh : "magma" ,
alias : "Ultramarine" ,
category : "powders" ,
state : "solid"
}
elements . uv _light = {
color : "#440088" ,
behavior : [
"XX|XX|XX" ,
"XX|DL%1|XX" ,
"XX|XX|XX"
] ,
glow : true ,
tick : behaviors . BOUNCY ,
temp : 35 ,
tempLow : - 273 ,
stateLow : [ "liquid_light" , null ] ,
stateLowColorMultiplier : 0.8 ,
breakInto : "light" ,
breakIntoColor : "#ffcfcf" ,
category : "energy" ,
state : "gas" ,
density : 0.00001 ,
ignoreAir : true ,
reactions : {
"ozone" : { elem1 : null , chance : 0.9 } ,
}
} ;
if ( ! settings . cheerful ) {
elements . uv _light . reactions . cell = { elem2 : "cancer" , chance : 0.05 } ,
elements . uv _light . reactions . skin = { elem2 : "cancer" , chance : 0.005 }
}
else {
if ( elements . uv _light . reactions . cell ) {
delete elements . uv _light . reactions . cell
}
if ( elements . uv _light . reactions . skin ) {
delete elements . uv _light . reactions . skin
}
}
function fadeColor ( base , glow , ratio ) {
// ratio 1 = full glow, 0 = base color
let r1 = parseInt ( glow . substr ( 1 , 2 ) , 16 ) ;
let g1 = parseInt ( glow . substr ( 3 , 2 ) , 16 ) ;
let b1 = parseInt ( glow . substr ( 5 , 2 ) , 16 ) ;
let r2 = parseInt ( base . substr ( 1 , 2 ) , 16 ) ;
let g2 = parseInt ( base . substr ( 3 , 2 ) , 16 ) ;
let b2 = parseInt ( base . substr ( 5 , 2 ) , 16 ) ;
let r = Math . round ( r1 * ratio + r2 * ( 1 - ratio ) ) ;
let g = Math . round ( g1 * ratio + g2 * ( 1 - ratio ) ) ;
let b = Math . round ( b1 * ratio + b2 * ( 1 - ratio ) ) ;
return ` # ${ r . toString ( 16 ) . padStart ( 2 , "0" ) } ${ g . toString ( 16 ) . padStart ( 2 , "0" ) } ${ b . toString ( 16 ) . padStart ( 2 , "0" ) } ` ;
}
elements . phosphor = {
color : "#fffbe7" ,
behavior : behaviors . POWDER ,
tick : function ( pixel ) {
let nearUV = false ;
for ( let i = 0 ; i < adjacentCoords . length ; i ++ ) {
let x = pixel . x + adjacentCoords [ i ] [ 0 ] ;
let y = pixel . y + adjacentCoords [ i ] [ 1 ] ;
let p = getPixel ( x , y ) ;
if ( p && p . element == "uv_light" ) {
nearUV = true ;
break ;
}
}
if ( nearUV ) {
pixel . colorStay = 60 ; // longer for realism
}
if ( pixel . colorStay > 0 ) {
let ratio = pixel . colorStay / 60 ; // exponential fade would be even better
pixel . color = fadeColor ( "#fffbe7" , "#00c500" , ratio ) ;
pixel . colorStay -- ;
} else {
pixel . color = "#fffbe7"
}
if ( enabledMods . includes ( "mods/glow.js" ) ) {
if ( pixel . color !== "#fffbe7" ) {
pixel . emit = pixel . colorStay / 10
}
}
} ,
category : "powders" ,
state : "solid" ,
} ;
elements . packed _sand . pressInto = "sandstone"
elements . packed _sand . resistPress = 0.7
elements . packed _snow . pressInto = "ice"
elements . packed _snow . resistPress = 0.7
elements . sandstone = {
color : "#d3bc56" ,
behavior : behaviors . WALL ,
breakInto : "sand" ,
hardness : 0.5 ,
state : "solid" ,
stateHigh : "glass" ,
tempHigh : 1700 ,
2025-09-19 06:24:54 -04:00
category : "land"
2025-08-05 08:19:49 -04:00
}
// Glow.js integrtion
if ( enabledMods . includes ( "mods/glow.js" ) ) {
elements . uv _light . emit = true
elements . glow _stick . emit = true
delete elements . glow _stick . glow
elements . glow _stick _liquid . emit = true
delete elements . glow _stick _liquid . glow
}
let neonTubeChoice = "#00ff00" ; // default color
elements . neon _tube = {
color : "#d1d1b5" ,
renderer : renderPresets . BORDER ,
alpha : 0.25 ,
conduct : 1 ,
behavior : behaviors . WALL ,
breakInto : [ "neon" , "glass_shard" ] ,
grain : 0 ,
category : "machines" ,
state : "solid" ,
tick : ( pixel ) => {
pixel . def _color ? ? = pixel . color ;
pixel . glow _color ? ? = neonTubeChoice ;
if ( pixel . charge ) {
pixel . alpha = 1 ;
pixel . color = pixel . glow _color ;
} else {
pixel . alpha = 0.25 ;
pixel . color = pixel . def _color ;
}
if ( enabledMods . includes ( "mods/glow.js" ) ) {
if ( pixel . charge ) {
pixel . emit = true ;
pixel . emitColor = pixel . glow _color ;
} else {
delete pixel . emit ;
delete pixel . emitColor ;
}
}
} ,
// Broken since yellow stacks above color
// only green is good
/ *
onSelect ( ) {
promptChoose (
"Pick a color for your neon tube:" ,
[ "Red" , "Green" , "Blue" , "Pink" ] ,
function ( choice ) {
let colors = {
"Red" : "#ff0000" ,
"Green" : "#00ff00" ,
"Blue" : "#0000ff" ,
"Pink" : "#ff66cc"
} ;
neonTubeChoice = colors [ choice ] || "#00ff00" ;
logMessage ( "Neon tube color set to " + choice ) ;
} ,
"Neon Tube Setup"
) ;
}
* /
} ;
elements . realistic _ball = {
color : "#e35693" ,
tempHigh : 250 ,
stateHigh : "molten_plastic" ,
category : "special" ,
state : "solid" ,
density : 1052 ,
hidden : true ,
tick : function ( pixel ) {
// initialize velocity
if ( pixel . vy === undefined ) {
pixel . vy = 0 ;
}
// gravity
pixel . vy += 0.3 ;
// predict next position
let nextY = pixel . y + Math . sign ( pixel . vy ) ;
if ( isEmpty ( pixel . x , nextY ) ) {
// free space → move
tryMove ( pixel , pixel . x , pixel . y + Math . sign ( pixel . vy ) ) ;
} else {
// collision: reverse velocity (bounce)
pixel . vy *= - 0.7 ;
// stop very small bounces
if ( Math . abs ( pixel . vy ) < 0.5 ) {
pixel . vy = 0 ;
}
}
}
}
elements . custom _bomb = {
color : "#49443b" ,
category : "weapons" ,
state : "solid" ,
density : 1300 ,
excludeRandom : true ,
cooldown : defaultCooldown ,
behavior : behaviors . STURDYPOWDER ,
onSelect : function ( ) {
2025-08-11 07:32:23 -04:00
promptInput (
"Input the element you want your bomb to explode into" ,
function ( input ) {
2025-09-19 06:24:54 -04:00
let pr1 = mostSimilarElement ( input )
if ( pr1 && elements [ pr1 ] ) {
2025-08-11 07:32:23 -04:00
if ( pr1 === "custom_bomb" ) {
2025-09-19 06:24:54 -04:00
promptConfirm ( "Are you sure you want custom bomb to create itself as it will spread" , ( a ) => { if ( ! a ) { globals . explodeElem = 'fire' } else globals . explodeElem = 'custom_bomb' } , "Warning" )
2025-08-11 07:32:23 -04:00
}
2025-09-19 06:24:54 -04:00
else { globals . explodeElem = pr1 }
2025-08-11 07:32:23 -04:00
}
else {
2025-09-19 06:24:54 -04:00
globals . explodeElem = 'fire'
2025-08-11 07:32:23 -04:00
logMessage ( "Invalid element. Using default: fire" )
}
} ,
"Element prompt" ,
"fire"
)
2025-08-05 08:19:49 -04:00
} ,
tick : function ( pixel ) {
let belowPixel = getPixel ( pixel . x , pixel . y + 1 ) ;
// If pixel is at the bottom or resting on a solid
if ( outOfBounds ( pixel . x , pixel . y + 1 ) || ( belowPixel && belowPixel . element !== "custom_bomb" && ! isEmpty ( pixel . x , pixel . y + 1 ) && belowPixel . element !== "fire" && belowPixel . element !== "smoke" ) ) {
2025-11-19 23:22:26 -05:00
explodeAt ( pixel . x , pixel . y , 10 , globals . explodeElem ) ;
2025-08-05 08:19:49 -04:00
deletePixel ( pixel . x , pixel . y ) ;
}
}
}
runAfterReset ( ( ) => {
2025-09-19 06:24:54 -04:00
if ( globals . rCustomBomb ) {
globals . explodeElem = 'fire'
}
2025-08-05 08:19:49 -04:00
} )
elements . pineapple = {
color : "#ffd900" ,
isFood : true ,
behavior : behaviors . STURDYPOWDER ,
breakInto : [ "juice" , "juice" , "juice" , "juice" , "juice" , "pineapple_seed" ] ,
breakIntoColor : "#fffc00" ,
category : "food" ,
state : "solid" ,
seed : "pineapple_seed"
}
elements . pineapple _seed = {
color : "#695531" ,
behavior : behaviors . STURDYPOWDER ,
cooldown : defaultCooldown ,
category : "life" ,
tempHigh : 400 ,
stateHigh : "fire" ,
tempLow : - 2 ,
stateLow : "frozen_plant" ,
burn : 50 ,
burnTime : 20 ,
state : "solid" ,
tick : function ( pixel ) {
let belowPixel = getPixel ( pixel . x , pixel . y + 1 )
if (
! isEmpty ( pixel . x , pixel . y + 1 ) &&
belowPixel &&
Math . random ( ) <= 0.05
) {
changePixel ( pixel , "pineapple_stem" )
pixel . growthState = 1
pixel . growDiagLeft = true
pixel . growDiagRight = true
}
} ,
seed : true
}
eListAdd ( "SEEDS" , "pineapple_seed" )
elements . pineapple _stem = {
color : "#3aab11" ,
behavior : behaviors . WALL ,
movable : false ,
category : "life" ,
tempHigh : 100 ,
stateHigh : "dead_plant" ,
tempLow : - 1.66 ,
stateLow : "frozen_plant" ,
burn : 15 ,
burnTime : 60 ,
burnInto : "dead_plant" ,
breakInto : "dead_plant" ,
tick : function ( pixel ) {
let left = pixel . x - 1
let right = pixel . x + 1
let up = pixel . y - 1
let down = pixel . y + 1
let belowPixel = getPixel ( pixel . x , down )
pixel . fruitCD ? ? = 60
if ( ! outOfBounds ( pixel . x , down ) && belowPixel && eLists . SOIL . includes ( belowPixel . element ) && pixel . growthState === 1 ) {
changePixel ( belowPixel , "root" )
}
if ( pixel . growthState === 1 && Math . random ( ) <= 0.05 ) {
if ( isEmpty ( left , up ) && pixel . growDiagLeft === true ) {
createPixel ( "pineapple_stem" , left , up )
let newPixel = getPixel ( left , up )
if ( newPixel ) {
newPixel . growthState = 2
newPixel . growDiagLeft = true
delete newPixel . growDiagRight
}
}
else {
delete pixel . growDiagLeft
}
if ( isEmpty ( right , up ) && pixel . growDiagRight === true ) {
createPixel ( "pineapple_stem" , right , up )
let newPixel = getPixel ( right , up )
if ( newPixel ) {
newPixel . growthState = 2
newPixel . growDiagRight = true
delete newPixel . growDiagLeft
}
}
else {
delete pixel . growDiagRight
}
}
if ( ! pixel . growDiagLeft && ! pixel . growDiagRight && pixel . growthState === 1 ) {
if ( Math . random ( ) <= 0.05 && isEmpty ( pixel . x , up ) && ! pixel . fruitCD && ! pixel . pineappleGrown ) {
createPixel ( "pineapple" , pixel . x , up )
pixel . fruitCD = 60
pixel . pineappleGrown = true
}
if ( pixel . fruitCD && ! pixel . pineappleGrown ) {
pixel . fruitCD --
}
}
if ( isEmpty ( pixel . x , up ) ) {
pixel . pineappleGrown = false
}
if ( pixel . growthState === 2 && Math . random ( ) <= 0.05 ) {
if ( isEmpty ( left , up ) && pixel . growDiagLeft === true ) {
createPixel ( "pineapple_stem" , left , up )
}
if ( isEmpty ( right , up ) && pixel . growDiagRight === true ) {
createPixel ( "pineapple_stem" , right , up )
}
}
}
}
// making redstone conductive bc idk why its not
if ( enabledMods . includes ( "mods/minecraft.js" ) ) {
runAfterLoad ( ( ) => {
elements . redstone _dust . conduct = 1
} )
}
elements . rubidium = {
color : "#c0c0c0" ,
state : "solid" ,
behavior : behaviors . POWDER ,
tempHigh : 39.30 ,
stateHigh : "liquid_rubidium" ,
density : 1534 ,
conduct : 0.6 ,
reactions : {
"water" : { elem1 : [ "explosion" , "explosion" , "hydrogen" ] , temp2 : 200 } ,
"salt_water" : { elem1 : [ "explosion" , "explosion" , "hydrogen" ] , temp2 : 200 } ,
"sugar_water" : { elem1 : [ "explosion" , "explosion" , "hydrogen" ] , temp2 : 200 } ,
"pool_water" : { elem1 : [ "explosion" , "explosion" , "hydrogen" ] , temp2 : 200 } ,
"dirty_water" : { elem1 : [ "explosion" , "explosion" , "hydrogen" ] , temp2 : 200 } ,
"seltzer" : { elem1 : [ "explosion" , "explosion" , "hydrogen" ] , temp2 : 200 } ,
"primordial_soup" : { elem1 : [ "explosion" , "explosion" , "hydrogen" ] , temp2 : 200 } ,
"nut_milk" : { elem1 : [ "explosion" , "explosion" , "hydrogen" ] , temp2 : 200 }
} ,
category : "powders"
}
elements . liquid _rubidium = {
color : "#d0d0d0" ,
state : "liquid" ,
behavior : behaviors . LIQUID ,
tempHigh : 688 ,
density : 1460 ,
conduct : 0.6 ,
tempLow : 39.30 ,
stateLow : "rubidium" ,
temp : 40 ,
reactions : {
"water" : { elem1 : [ "explosion" , "explosion" , "hydrogen" ] , temp2 : 200 } ,
"salt_water" : { elem1 : [ "explosion" , "explosion" , "hydrogen" ] , temp2 : 200 } ,
"sugar_water" : { elem1 : [ "explosion" , "explosion" , "hydrogen" ] , temp2 : 200 } ,
"pool_water" : { elem1 : [ "explosion" , "explosion" , "hydrogen" ] , temp2 : 200 } ,
"dirty_water" : { elem1 : [ "explosion" , "explosion" , "hydrogen" ] , temp2 : 200 } ,
"seltzer" : { elem1 : [ "explosion" , "explosion" , "hydrogen" ] , temp2 : 200 } ,
"primordial_soup" : { elem1 : [ "explosion" , "explosion" , "hydrogen" ] , temp2 : 200 } ,
"nut_milk" : { elem1 : [ "explosion" , "explosion" , "hydrogen" ] , temp2 : 200 }
} ,
category : "states" ,
hidden : true
}
elements . dog = {
color : [ "#221d0c" , "#5c4300" , "#7c5b00" , "#fcfceb" ] ,
behavior : [
"XX|XX|M2%3" ,
"XX|FX%5|M2%5" ,
"XX|M1|XX"
] ,
tempHigh : 100 ,
stateHigh : "cooked_meat" ,
tempLow : - 10 ,
stateLow : "frozen_meat" ,
category : "life" ,
state : "solid" ,
burn : 30 ,
burnTime : 50 ,
burnInto : [ "cooked_meat" , "smoke" ] ,
2025-08-08 08:14:26 -04:00
breakInto : [ "meat" , "blood" ] ,
2025-08-05 08:19:49 -04:00
reactions : {
2025-08-11 07:32:23 -04:00
"meat" : { elem2 : null , chance : 0.5 , func : behaviors . FEEDPIXEL } ,
"egg" : { elem2 : null , chance : 0.5 , func : behaviors . FEEDPIXEL } ,
"yolk" : { elem2 : null , chance : 0.5 , func : behaviors . FEEDPIXEL } ,
"cheese" : { elem2 : null , chance : 0.5 , func : behaviors . FEEDPIXEL } ,
"cooked_meat" : { elem2 : null , chance : 0.5 , func : behaviors . FEEDPIXEL } ,
"chocolate" : { elem2 : null , chance : 0.2 , func : behaviors . FEEDPIXEL , elem1 : "rotten_meat" } ,
"grape" : { elem2 : null , chance : 0.2 , func : behaviors . FEEDPIXEL , elem1 : "rotten_meat" } ,
"rat" : { elem2 : null , chance : 0.3 , func : behaviors . FEEDPIXEL } ,
"nut_butter" : { elem2 : null , chance : 0.5 , func : behaviors . FEEDPIXEL } ,
2025-08-05 08:19:49 -04:00
} ,
egg : "dog" ,
}
2025-08-18 05:45:28 -04:00
// Keyboard state tracking
const robotKeys = {
left : false ,
right : false ,
jump : false
} ;
// Set up keyboard listeners
window . addEventListener ( 'keydown' , ( e ) => {
const key = e . key . toLowerCase ( ) ;
if ( key === 'a' || key === 'arrowleft' ) robotKeys . left = true ;
if ( key === 'd' || key === 'arrowright' ) robotKeys . right = true ;
if ( key === 'w' || key === 'arrowup' ) robotKeys . jump = true ;
} ) ;
window . addEventListener ( 'keyup' , ( e ) => {
const key = e . key . toLowerCase ( ) ;
if ( key === 'a' || key === 'arrowleft' ) robotKeys . left = false ;
if ( key === 'd' || key === 'arrowright' ) robotKeys . right = false ;
if ( key === 'w' || key === 'arrowup' ) robotKeys . jump = false ;
} ) ;
// Helper function for movement
function tryMoveRobot ( headPixel , direction ) {
const newX = headPixel . x + direction ;
const body = getPixel ( headPixel . x , headPixel . y + 1 ) ;
if ( body && body . element === "robot_body" &&
isEmpty ( newX , headPixel . y ) &&
isEmpty ( newX , body . y ) ) {
movePixel ( body , newX , body . y ) ;
movePixel ( headPixel , newX , headPixel . y ) ;
return true ;
}
return false ;
}
function tryJump ( headPixel ) {
const body = getPixel ( headPixel . x , headPixel . y + 1 ) ;
if ( ! body || body . element !== "robot_body" ) return false ;
// Check if grounded (on solid surface or bottom of screen)
const underBody = getPixel ( body . x , body . y + 1 ) ;
const isGrounded = ( ! isEmpty ( body . x , body . y + 1 ) || outOfBounds ( body . x , body . y + 1 ) ) ;
if ( isGrounded ) {
// Check space above
if ( isEmpty ( headPixel . x , headPixel . y - 1 ) &&
isEmpty ( headPixel . x , headPixel . y - 2 ) ) {
// Two-stage jump animation
pixelTicks = 0 ;
headPixel . jumping = true ;
// First frame - small hop
movePixel ( headPixel , headPixel . x , headPixel . y - 1 ) ;
movePixel ( body , body . x , headPixel . y + 1 ) ;
// Second frame - complete jump (after small delay)
setTimeout ( ( ) => {
if ( headPixel . jumping ) { // Only if still jumping
movePixel ( headPixel , headPixel . x , headPixel . y - 1 ) ;
movePixel ( body , body . x , headPixel . y + 1 ) ;
headPixel . jumping = false ;
}
} , 100 ) ; // 100ms delay for smoother animation
return true ;
}
}
return false ;
}
// Robot elements
elements . robot _head = {
color : "#d9d9d9" ,
category : "machines" ,
2025-08-31 08:05:10 -04:00
state : "solid" ,
2025-08-18 05:45:28 -04:00
tick ( pixel ) {
const body = getPixel ( pixel . x , pixel . y + 1 ) ;
if ( body && body . element === "robot_body" ) {
pixel . connected = true ;
body . connected = true ;
// Controlled movement
if ( pixel . mode === "Controlled" ) {
if ( robotKeys . left ) {
tryMoveRobot ( pixel , - 1 ) ;
}
else if ( robotKeys . right ) {
tryMoveRobot ( pixel , 1 ) ;
}
if ( robotKeys . jump && ! pixel . jumping ) {
tryJump ( pixel ) ;
}
}
// Aimless wandering
else if ( pixel . mode === "Aimless" && Math . random ( ) < 0.02 ) {
pixel . dir = pixel . dir || ( Math . random ( ) < 0.5 ? - 1 : 1 ) ;
if ( ! tryMoveRobot ( pixel , pixel . dir ) ) {
pixel . dir *= - 1 ;
}
}
}
else {
pixel . connected = false ;
tryMove ( pixel , pixel . x , pixel . y + 1 ) ;
}
}
} ;
elements . robot _body = {
color : "#b1b1b1" ,
category : "machines" ,
2025-08-31 08:05:10 -04:00
state : "solid" ,
2025-08-18 05:45:28 -04:00
tick ( pixel ) {
const head = getPixel ( pixel . x , pixel . y - 1 ) ;
if ( head && head . element === "robot_head" ) {
pixel . connected = true ;
head . connected = true ;
// Gravity - move down if space below
if ( isEmpty ( pixel . x , pixel . y + 1 ) ) {
let oldY = pixel . y ;
movePixel ( pixel , pixel . x , pixel . y + 1 ) ;
movePixel ( head , head . x , oldY ) ;
}
}
else {
pixel . connected = false ;
tryMove ( pixel , pixel . x , pixel . y + 1 ) ;
}
}
} ;
// Robot creator element
2025-11-19 23:22:26 -05:00
globals . mode = "Aimless"
2025-08-18 05:45:28 -04:00
elements . robot = {
color : "#b1b1b1" ,
category : "machines" ,
2025-08-31 08:05:10 -04:00
state : "solid" ,
2025-08-18 05:45:28 -04:00
onSelect ( ) {
promptChoose (
"Choose robot mode" ,
[ "Aimless" , "Controlled" ] ,
( choice ) => {
if ( choice === "Controlled" && isMobile ) {
logMessage ( "Controlled mode doesn't work on mobile" ) ;
2025-11-19 23:22:26 -05:00
globals . mode = "Aimless" ;
2025-08-18 05:45:28 -04:00
} else {
2025-11-19 23:22:26 -05:00
globals . mode = choice || "Aimless" ;
if ( globals . mode === "Controlled" ) {
2025-08-18 05:45:28 -04:00
logMessage ( "Controls: A/D to move and W to jump or (Not reccomended) ←/→ to move, and ↑ to jump" ) ;
}
}
} ,
"Robot Mode"
) ;
} ,
onPlace ( pixel ) {
// Try to create head above
if ( isEmpty ( pixel . x , pixel . y - 1 ) ) {
createPixel ( "robot_head" , pixel . x , pixel . y - 1 ) ;
const head = getPixel ( pixel . x , pixel . y - 1 ) ;
2025-11-19 23:22:26 -05:00
head . mode = globals . mode ;
2025-08-18 05:45:28 -04:00
changePixel ( pixel , "robot_body" ) ;
2025-11-19 23:22:26 -05:00
pixel . mode = globals . mode ;
2025-08-18 05:45:28 -04:00
}
// Try to create body below if above is blocked
else if ( isEmpty ( pixel . x , pixel . y + 1 ) ) {
createPixel ( "robot_body" , pixel . x , pixel . y + 1 ) ;
const body = getPixel ( pixel . x , pixel . y + 1 ) ;
2025-11-19 23:22:26 -05:00
body . mode = globals . mode ;
2025-08-18 05:45:28 -04:00
changePixel ( pixel , "robot_head" ) ;
2025-11-19 23:22:26 -05:00
pixel . mode = globals . mode ;
2025-08-18 05:45:28 -04:00
}
// Delete if no space
else {
deletePixel ( pixel . x , pixel . y ) ;
}
} ,
cooldown : defaultCooldown
} ;
elements . mercury _gas . behaviorOn = [
"M2|CR:uv_light%10 AND M1|M2" ,
"CR:uv_light%10 AND M1|XX|CR:uv_light%10 AND M1" ,
"M2|CR:uv_light%10 AND M1|M2"
]
2025-09-19 06:24:54 -04:00
2025-08-18 05:45:28 -04:00
elements . broken _adjustable _heater = {
color : "#ff0000" ,
category : "extras" ,
insulate : true ,
behavior : behaviors . WALL ,
2025-08-31 08:05:10 -04:00
2025-08-18 05:45:28 -04:00
onSelect ( ) {
promptInput (
"Select the temperature you want to adjust to" ,
function ( choice ) {
if ( choice && ! isNaN ( Number ( choice ) ) ) {
2025-09-19 06:24:54 -04:00
globals . adjusted _heater _temp = Number ( choice )
2025-08-18 05:45:28 -04:00
logMessage ( "Occasionally creates superheated pixels" )
}
} ,
2025-09-19 06:24:54 -04:00
"Temperature Prompt" , ` ${ globals . adjusted _heater _temp } `
2025-08-18 05:45:28 -04:00
)
} ,
tick ( pixel ) {
2025-09-19 06:24:54 -04:00
pixel . heat _temp ? ? = globals . adjusted _heater _temp
2025-08-18 05:45:28 -04:00
for ( let i = 0 ; i < adjacentCoords . length ; i ++ ) {
let x = pixel . x + adjacentCoords [ i ] [ 0 ] ;
let y = pixel . y + adjacentCoords [ i ] [ 1 ] ;
let current _pixel = getPixel ( x , y ) ;
if (
current _pixel &&
! elements [ current _pixel . element ] ? . insulate
&& current _pixel . temp < pixel . heat _temp
) {
current _pixel . temp = Math . min ( current _pixel . temp + 2 , pixel . heat _temp ) ;
}
}
}
} ;
2025-09-19 06:24:54 -04:00
globals . adjusted _temp = 100
globals . heatAmount = 2
2025-08-18 05:45:28 -04:00
elements . adjustable _heater = {
color : "#ff0000" ,
2026-02-02 01:04:25 -05:00
category : "machines" ,
2025-08-18 05:45:28 -04:00
insulate : true ,
behavior : behaviors . WALL ,
onSelect ( ) {
promptInput (
"Select the temperature you want to adjust to" ,
function ( choice ) {
if ( choice && ! isNaN ( Number ( choice ) ) ) {
2025-09-19 06:24:54 -04:00
globals . adjusted _temp = Number ( choice ) ;
2025-08-18 05:45:28 -04:00
}
} ,
2025-09-19 06:24:54 -04:00
"Temperature Prompt" , ` ${ globals . adjusted _temp } `
2025-08-18 05:45:28 -04:00
) ;
} ,
tick ( pixel ) {
for ( let i = 0 ; i < adjacentCoords . length ; i ++ ) {
let x = pixel . x + adjacentCoords [ i ] [ 0 ] ;
let y = pixel . y + adjacentCoords [ i ] [ 1 ] ;
let current _pixel = getPixel ( x , y ) ;
if (
current _pixel &&
! elements [ current _pixel . element ] ? . insulate
) {
// Heat or cool toward the adjusted temp
2025-09-19 06:24:54 -04:00
if ( current _pixel . temp < globals . adjusted _temp ) {
current _pixel . temp = Math . min ( current _pixel . temp + globals . heatAmount , globals . adjusted _temp ) ;
} else if ( current _pixel . temp > globals . adjusted _temp ) {
current _pixel . temp = Math . max ( current _pixel . temp - globals . heatAmount , globals . adjusted _temp ) ;
2025-08-18 05:45:28 -04:00
}
2025-08-31 08:05:10 -04:00
pixelTempCheck ( current _pixel )
2025-08-18 05:45:28 -04:00
}
}
}
} ;
2025-09-19 06:24:54 -04:00
globals . adjusted _cooler _temp = 0 ; // default cooling target
2025-08-18 05:45:28 -04:00
elements . broken _adjustable _cooler = {
color : "#0000ff" ,
category : "extras" ,
insulate : true ,
behavior : behaviors . WALL ,
onSelect ( ) {
promptInput (
"Select the temperature you want to cool to" ,
function ( choice ) {
if ( choice && ! isNaN ( Number ( choice ) ) ) {
2025-09-19 06:24:54 -04:00
globals . adjusted _cooler _temp = Number ( choice ) ;
2025-08-18 05:45:28 -04:00
logMessage ( "Occasionally creates supercooled pixels" ) ;
}
} ,
2025-09-19 06:24:54 -04:00
"Temperature Prompt" , ` ${ globals . adjusted _cooler _temp } `
2025-08-18 05:45:28 -04:00
) ;
} ,
tick ( pixel ) {
2025-09-19 06:24:54 -04:00
pixel . cool _temp ? ? = globals . adjusted _cooler _temp ;
2025-08-18 05:45:28 -04:00
for ( let i = 0 ; i < adjacentCoords . length ; i ++ ) {
let x = pixel . x + adjacentCoords [ i ] [ 0 ] ;
let y = pixel . y + adjacentCoords [ i ] [ 1 ] ;
let current _pixel = getPixel ( x , y ) ;
if (
current _pixel &&
! elements [ current _pixel . element ] ? . insulate &&
current _pixel . temp > pixel . cool _temp
) {
// Cool the pixel toward the target
current _pixel . temp = Math . max ( current _pixel . temp - 2 , pixel . cool _temp ) ;
}
}
}
} ;
2025-09-19 06:24:54 -04:00
globals . adjusted _cool _temp = 0 ; // default cooling target
globals . coolAmount = 2 ; // adjustable step
2025-08-18 05:45:28 -04:00
elements . adjustable _cooler = {
color : "#0000ff" ,
2026-02-02 01:04:25 -05:00
category : "machines" ,
2025-08-18 05:45:28 -04:00
insulate : true ,
behavior : behaviors . WALL ,
onSelect ( ) {
promptInput (
"Select the temperature you want to cool to" ,
function ( choice ) {
if ( choice && ! isNaN ( Number ( choice ) ) ) {
2025-09-19 06:24:54 -04:00
globals . adjusted _cool _temp = Number ( choice ) ;
2025-08-18 05:45:28 -04:00
}
} ,
2025-09-19 06:24:54 -04:00
"Temperature Prompt" , ` ${ globals . adjusted _cool _temp } `
2025-08-18 05:45:28 -04:00
) ;
} ,
tick ( pixel ) {
for ( let i = 0 ; i < adjacentCoords . length ; i ++ ) {
let x = pixel . x + adjacentCoords [ i ] [ 0 ] ;
let y = pixel . y + adjacentCoords [ i ] [ 1 ] ;
let current _pixel = getPixel ( x , y ) ;
if (
current _pixel &&
! elements [ current _pixel . element ] ? . insulate
) {
// Cool or heat toward target (mirrors fixed heater logic)
2025-09-19 06:24:54 -04:00
if ( current _pixel . temp > globals . adjusted _cool _temp ) {
current _pixel . temp = Math . max ( current _pixel . temp - globals . coolAmount , globals . adjusted _cool _temp ) ;
} else if ( current _pixel . temp < globals . adjusted _cool _temp ) {
current _pixel . temp = Math . min ( current _pixel . temp + globals . coolAmount , globals . adjusted _cool _temp ) ;
2025-08-18 05:45:28 -04:00
}
2025-08-31 08:05:10 -04:00
pixelTempCheck ( current _pixel )
}
}
}
} ;
2025-09-19 06:24:54 -04:00
globals . polishedList = new Set ( )
2025-08-31 08:05:10 -04:00
elements . polish = {
2025-09-19 06:24:54 -04:00
desc : "Polishes textured elements" ,
2025-08-31 08:05:10 -04:00
category : "tools" ,
color : [ "#a0dff0" , "#c0e8f8" , "#e0f5ff" ] ,
tool ( pixel ) {
let element = pixel . element
2025-09-19 06:24:54 -04:00
if ( ( elements [ pixel . element ] . colorPattern && ! globals . polishedList . has ( ` ${ pixel . x } , ${ pixel . y } ` ) ) || shiftDown ) {
2025-08-31 08:05:10 -04:00
deletePixel ( pixel . x , pixel . y )
createPixel ( element , pixel . x , pixel . y )
2025-09-19 06:24:54 -04:00
globals . polishedList . add ( ` ${ pixel . x } , ${ pixel . y } ` )
2025-08-31 08:05:10 -04:00
}
} ,
onUnselect ( ) {
2025-09-19 06:24:54 -04:00
globals . polishedList . clear ( )
2025-08-31 08:05:10 -04:00
}
}
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
2025-09-19 06:24:54 -04:00
let visc = elements [ liquid . element ] . viscosity
if ( visc ) {
viscMove = ( Math . random ( ) * 100 ) < ( 100 / Math . pow ( visc , 0.5 ) )
2025-08-31 08:05:10 -04:00
}
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
2025-09-19 06:24:54 -04:00
let visc = elements [ liquid . element ] . viscosity
if ( visc ) {
viscExit = ( Math . random ( ) * 100 ) < ( 100 / Math . pow ( visc , 0.5 ) )
2025-08-31 08:05:10 -04:00
}
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
2025-09-19 06:24:54 -04:00
let visc = elements [ liquid . element ] . viscosity
if ( visc ) {
viscMove = ( Math . random ( ) * 100 ) < ( 100 / Math . pow ( visc , 0.5 ) )
2025-08-31 08:05:10 -04:00
}
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
2025-09-19 06:24:54 -04:00
let visc = elements [ liquid . element ] . viscosity
if ( visc ) {
viscExit = ( Math . random ( ) * 100 ) < ( 100 / Math . pow ( visc , 0.5 ) )
2025-08-31 08:05:10 -04:00
}
if ( viscExit ) {
createPixel ( liquid . element , pixel . x , pixel . y + 1 )
delete pixel . con
}
}
}
}
2025-11-19 23:22:26 -05:00
globals . blackHoleExpand = false
2025-08-31 08:05:10 -04:00
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 ++
}
}
}
}
}
}
2025-11-19 23:22:26 -05:00
if ( globals . blackHoleExpand ) {
2025-08-31 08:05:10 -04:00
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
2025-08-18 05:45:28 -04:00
}
2025-08-31 08:05:10 -04:00
}
}
}
} ,
forceSaveColor : true ,
onSelect ( ) {
promptChoose (
"Do you want the black hole to grow?" ,
[ "Yes" , "No" ] ,
( choice ) => {
if ( ! choice ) {
2025-09-19 06:24:54 -04:00
choice = "No"
2025-08-31 08:05:10 -04:00
}
if ( choice == "Yes" ) {
2025-11-19 23:22:26 -05:00
globals . blackHoleExpand = true
2025-08-31 08:05:10 -04:00
}
else {
2025-11-19 23:22:26 -05:00
globals . blackHoleExpand = false
2025-08-31 08:05:10 -04:00
}
}
)
}
} ;
2025-09-19 06:24:54 -04:00
elements . white _hole = {
color : "#ffffff" ,
renderer : function ( pixel , ctx ) {
if ( ! viewInfo [ view ] . colorEffects ) { drawDefault ( ctx , pixel ) ; return }
renderPresets . HEATGLOW ( pixel , ctx ) ;
if ( pixel . alpha === 0 ) return ;
let edge = false ;
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 ) || ( ! outOfBounds ( x , y ) && elements [ pixelMap [ x ] [ y ] . element ] . movable !== elements [ pixel . element ] . movable ) ) {
edge = true ;
break ;
}
}
if ( edge ) { drawSquare ( ctx , "rgba(0,0,0," + ( pixel . alpha || 1 ) / 4 + ")" , pixel . x , pixel . y ) }
} ,
tick ( pixel ) {
for ( var i = 0 ; i < squareCoords . length ; i ++ ) {
var coord = squareCoords [ i ] ;
var x = pixel . x + coord [ 0 ] ;
var y = pixel . y + coord [ 1 ] ;
if ( isEmpty ( x , y ) && ! outOfBounds ( x , y ) && Math . random ( ) <= 0.0005 ) {
createPixel (
[ "proton" , "neutron" , "electric" ,
"proton" , "neutron" , "electric" ,
"proton" , "neutron" , "electric" ,
"proton" , "neutron" , "electric" ,
"random" ] , x , y )
}
}
let radius = 20 ;
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 ] ;
2025-09-28 03:46:04 -04:00
if ( elemDef . hardness === 1 ) continue ;
2025-09-19 06:24:54 -04:00
let dist = Math . sqrt ( dx * dx + dy * dy ) ;
if ( dist <= radius ) {
let chance = 1 / ( dist * 0.75 ) ;
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 ) ;
}
}
}
}
}
}
}
} ,
hardness : 1 ,
behavior : behaviors . WALL ,
category : "special"
}
2025-08-31 08:05:10 -04:00
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
}
2025-08-18 05:45:28 -04:00
2025-08-31 08:05:10 -04:00
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 )
2025-09-19 06:24:54 -04:00
if ( oldPixel ) {
delete oldPixel . stage
}
2025-08-31 08:05:10 -04:00
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 )
2025-09-19 06:24:54 -04:00
let newPixel = getPixel ( pixel . x + nx , pixel . y - 1 )
if ( Math . random ( ) <= 0.2 && newPixel ) {
2025-08-31 08:05:10 -04:00
newPixel . stage = 3
}
2025-09-19 06:24:54 -04:00
else if ( newPixel ) newPixel . stage = 2 ;
2025-08-31 08:05:10 -04:00
}
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
2025-08-18 05:45:28 -04:00
}
}
}
}
2025-08-31 08:05:10 -04:00
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 ---
2026-02-02 01:04:25 -05:00
// @ts-ignore
2025-08-31 08:05:10 -04:00
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
} ;
2025-09-19 06:24:54 -04:00
globals . note = 261.626 ; // default C4
globals . notesToPlay = [ ] ;
2025-08-31 08:05:10 -04:00
function flushNotes ( ) {
2025-09-19 06:24:54 -04:00
if ( globals . notesToPlay . length === 0 ) return ;
2025-08-31 08:05:10 -04:00
let baseVolume = 0.2 ;
2025-09-19 06:24:54 -04:00
let volume = baseVolume / Math . sqrt ( globals . notesToPlay . length ) ;
2025-08-31 08:05:10 -04:00
2025-09-19 06:24:54 -04:00
for ( let f of globals . notesToPlay ) {
2025-08-31 08:05:10 -04:00
playNote ( f , 1 , "sine" , volume ) ;
}
2025-09-19 06:24:54 -04:00
globals . notesToPlay = [ ] ;
2025-08-31 08:05:10 -04:00
}
elements . note _block = {
color : "#965500" ,
behavior : behaviors . WALL ,
onSelect ( ) {
promptInput (
"Select the note this note block should be" ,
function ( choice ) {
if ( ! choice ) {
2025-09-19 06:24:54 -04:00
if ( ! globals . note ) { globals . note = 261.626 ; }
2025-08-31 08:05:10 -04:00
return ;
}
let key = choice . toUpperCase ( ) ;
if ( key in pianoFrequencies ) {
2025-09-19 06:24:54 -04:00
globals . note = pianoFrequencies [ key ] ;
2025-08-31 08:05:10 -04:00
} else {
2025-09-19 06:24:54 -04:00
globals . note = 261.626 ; // fallback = C4
2025-08-31 08:05:10 -04:00
}
} ,
"Note prompt"
) ;
} ,
onPlace ( pixel ) {
2025-09-19 06:24:54 -04:00
pixel . note = globals . note ;
2025-08-31 08:05:10 -04:00
} ,
tick ( pixel ) {
if ( pixel . charge ) {
2025-09-19 06:24:54 -04:00
globals . notesToPlay . push ( Number ( pixel . note ) ) ;
2025-08-31 08:05:10 -04:00
}
} ,
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 ;
}
}
2025-08-18 05:45:28 -04:00
}
} ;
2025-08-31 08:05:10 -04:00
* /
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" )
}
}
}
2025-08-18 05:45:28 -04:00
2025-08-31 08:05:10 -04:00
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
}
2025-08-18 10:31:32 -04:00
2025-08-31 08:05:10 -04:00
/ * *
*
* @ 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
}
2025-08-24 07:59:51 -04:00
2025-09-19 06:24:54 -04:00
doWaterReactions ( "slaked_lime" , { elem1 : "roman_cement" , elem2 : null , chance : 0.25 } )
globals . cachedWords = [ ] ;
globals . otherCachedWords = [ ] ;
globals . filteredCachedWords = [ ] ;
globals . loadingLogged = false ;
async function getWordList ( ) {
if ( globals . cachedWords ) return globals . cachedWords ;
try {
const response = await fetch ( "https://raw.githubusercontent.com/first20hours/google-10000-english/refs/heads/master/google-10000-english-no-swears.txt" ) ;
if ( ! response . ok ) throw new Error ( 'Network error' ) ;
const text = await response . text ( ) ;
globals . cachedWords = text . split ( "\n" ) ;
return globals . cachedWords ;
} catch ( err ) {
console . error ( err ) ;
return [ ] ;
}
}
async function getCleanWordList ( ) {
if ( globals . otherCachedWords ) return globals . otherCachedWords ;
try {
const response = await fetch ( "https://raw.githubusercontent.com/dwyl/english-words/refs/heads/master/words.txt" ) ;
if ( ! response . ok ) throw new Error ( 'Network error' ) ;
const text = await response . text ( ) ;
globals . otherCachedWords = text . split ( "\n" ) ;
return globals . otherCachedWords ;
} catch ( err ) {
console . error ( err ) ;
return [ ] ;
}
}
async function filterWordList ( ) {
if ( ! globals . cachedWords ) await getWordList ( ) ;
if ( ! globals . otherCachedWords ) await getCleanWordList ( ) ;
if ( globals . filteredCachedWords ) return globals . filteredCachedWords ;
const cleanSet = new Set ( globals . otherCachedWords ) ;
globals . filteredCachedWords = [ ] ;
const chunkSize = 1000 ;
for ( let i = 0 ; i < globals . cachedWords . length ; i += chunkSize ) {
const chunk = globals . cachedWords . slice ( i , i + chunkSize ) ;
globals . filteredCachedWords . push ( ... chunk . filter ( word => cleanSet . has ( word ) ) ) ;
await new Promise ( requestAnimationFrame ) ;
}
console . log ( "Finished filtering" )
return globals . filteredCachedWords ;
}
filterWordList ( )
// getting myself familiar with async functions
elements . random _word _generator = {
color : "#ffffff" ,
behavior : behaviors . WALL ,
desc : "When shocked logs a random word" ,
conduct : 1 ,
category : "special" ,
tick : function ( pixel ) {
pixel . cd ? ? = 0 ;
if ( pixel . charge === 1 && pixel . cd <= 0 ) {
if ( ! globals . filteredCachedWords && ! globals . loadingLogged ) {
logMessage ( "Loading..." ) ;
globals . loadingLogged = true ;
}
const words = globals . filteredCachedWords ? ? [ ]
if ( words . length > 0 ) {
const word = words [ Math . floor ( Math . random ( ) * words . length ) ] ;
logMessage ( "Your word is: " + word ) ;
pixel . cd = 10 ;
} else {
logMessage ( "Failed to load words." ) ;
}
} else if ( pixel . cd > 0 ) {
pixel . cd -- ;
}
}
} ;
globals . paint _color = "#ff0000" ;
elements . paint _using _hex = {
color : elements . paint . color ,
onSelect ( ) {
promptInput (
"Select the color you want in hex. If you pass an array, make sure each hex value is wrapped with quotes." ,
( choice ) => {
if ( ! choice ) return ;
const regex = /^#([a-fA-F0-9]{6})$/ ;
if ( regex . test ( choice ) ) {
globals . paint _color = choice ;
return ;
}
try {
const converted = choice . replace ( /'/g , '"' )
const parsed = JSON . parse ( converted ) ;
if ( Array . isArray ( parsed ) ) {
let valid = true ;
for ( let value of parsed ) {
if ( ! regex . test ( value ) ) {
valid = false ;
break ;
}
}
if ( valid ) {
globals . paint _color = parsed ;
return ;
}
}
} catch ( e ) {
logMessage ( "Parse failed" )
console . log ( e )
}
logMessage ( "Invalid color or array of colors" ) ;
console . log ( ` ${ choice } ` )
}
) ;
} ,
tool ( pixel ) {
if ( ! shiftDown ) {
pixel . color = pixelColorPick ( pixel , globals . paint _color ) ;
}
else if ( Array . isArray ( globals . paint _color ) ) {
pixel . color = choose ( globals . paint _color )
}
else {
pixel . color = globals . paint _color
}
} ,
category : "tools"
} ;
globals . rCircle = false
globals . rRGBLed = false
globals . rCustomBomb = false
dependOn ( "betterSettings.js" , ( ) => {
2026-02-02 01:04:25 -05:00
// @ts-ignore
2025-09-19 06:24:54 -04:00
var Reset = new SettingsTab ( "Reset" ) ;
2026-02-02 01:04:25 -05:00
// @ts-ignore
2025-09-19 06:24:54 -04:00
var resetCircle = new Setting ( "Reset circle value and radius on reset" , "Reset circle" , settingType . BOOLEAN , false , defaultValue = false ) ;
2026-02-02 01:04:25 -05:00
// @ts-ignore
2025-09-19 06:24:54 -04:00
var resetRGBLed = new Setting ( "Reset RGB Led value on reset" , "Reset RGB Led" , settingType . BOOLEAN , false , defaultValue = false ) ;
2026-02-02 01:04:25 -05:00
// @ts-ignore
2025-09-19 06:24:54 -04:00
var resetCustomBomb = new Setting ( "Reset Custom Bomb value on reset" , "Reset Custom Bomb" , settingType . BOOLEAN , false , defaultValue = false ) ;
Reset . registerSettings ( "Reset" , resetRGBLed )
Reset . registerSettings ( "Reset" , resetCircle )
Reset . registerSettings ( "Reset" , resetCustomBomb )
2026-02-02 01:04:25 -05:00
// @ts-ignore
2025-09-19 06:24:54 -04:00
settingsManager . registerTab ( Reset ) ;
runEveryTick ( ( ) => {
if ( resetCircle . value == true ) {
globals . rCircle = true
} else globals . rCircle = false
if ( resetCustomBomb . value == true ) {
globals . rCustomBomb = true
} else globals . rCustomBomb = false
if ( resetRGBLed . value == true ) {
globals . rRGBLed = true
} else globals . rRGBLed = false
} )
} , true )
elements . quartz = {
color : [ "#f0f0f0" , "#ebebeb" , "#f8f8f8" ] ,
grain : 0 ,
conduct : 0.3 ,
behavior : behaviors . WALL ,
onBreak ( pixel ) {
if ( Math . random ( ) <= 0.2 ) {
pixel . charge = 1
}
} ,
onPress ( pixel ) {
if ( Math . random ( ) <= 0.2 ) {
pixel . charge = 1
}
} ,
density : 2650 ,
hardness : 0.7 ,
breakInto : "quartz_powder" ,
category : "solids"
}
elements . quartz _powder = {
color : [ "#dddddd" , "#e0e0e0" , "#f0f0f0" ] ,
grain : 0 ,
conduct : 0.3 ,
behavior : behaviors . POWDER ,
onBreak ( pixel ) {
if ( Math . random ( ) <= 0.2 ) {
pixel . charge = 1
}
} ,
density : 2650 ,
hardness : 0.7 ,
category : "powders"
}
elements . carrot _seed = {
color : '#925420' ,
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 ( belowPixel && eLists . SOIL . includes ( belowPixel . element ) && Math . random ( ) <= 0.05 ) {
changePixel ( belowPixel , "carrot" )
belowPixel . stage = 1
belowPixel . connected = true
changePixel ( pixel , "plant" )
}
}
}
elements . carrot = {
color : [ "#ec9a00" , "#d67200" ] ,
behavior : behaviors . STURDYPOWDER ,
category : "food" ,
density : 700 ,
isFood : true ,
breakInto : "juice" ,
breakIntoColor : "#ffa600" ,
hoverStat ( pixel ) {
if ( pixel . stage ) return pixel . stage
else return 0 ;
} ,
tick ( pixel ) {
let belowPixel = getPixel ( pixel . x , pixel . y + 1 )
if ( getPixel ( pixel . x , pixel . y - 1 ) && getPixel ( pixel . x , pixel . y - 1 ) . element != "carrot" && getPixel ( pixel . x , pixel . y - 1 ) . element != "plant" ) {
pixel . connected = false ;
}
if ( ! getPixel ( pixel . x , pixel . y - 1 ) ) {
pixel . connected = false
}
if ( pixel . stage == 1 && Math . random ( ) <= 0.05 && belowPixel && eLists . SOIL . includes ( belowPixel . element ) && pixel . connected ) {
changePixel ( belowPixel , "carrot" ) ;
let newStage ;
if ( Math . random ( ) <= 0.3 ) newStage = 1 ; else newStage = 2 ;
belowPixel . stage = newStage
belowPixel . connected = true
}
else if ( pixel . stage == 2 ) {
if ( Math . random ( ) <= 0.1 && belowPixel && eLists . SOIL . includes ( belowPixel . element ) && pixel . connected ) {
changePixel ( belowPixel , "root" )
}
}
}
}
function factorial ( n ) {
if ( n < 0 ) throw new Error ( "Factorial not defined for negative numbers" ) ;
let result = 1 ;
for ( let i = 2 ; i <= Number ( n ) ; i ++ ) {
result *= i ;
}
return result ;
}
function parseEquation ( eq ) {
eq = eq . replace ( /\s+/g , "" ) ;
let tokens = [ ] ;
let current _num = "" ;
for ( let i = 0 ; i < eq . length ; i ++ ) {
// Multi-character constants
if ( eq . startsWith ( "pi" , i ) ) {
if ( current _num !== "" ) { tokens . push ( parseFloat ( current _num ) ) ; current _num = "" ; }
tokens . push ( Math . PI ) ;
i ++ ;
continue ;
}
if ( eq . startsWith ( "phi" , i ) ) {
if ( current _num !== "" ) { tokens . push ( parseFloat ( current _num ) ) ; current _num = "" ; }
tokens . push ( 1.6180339887 ) ;
i += 2 ;
continue ;
}
// Multi-character functions
if ( eq . startsWith ( "sqrt" , i ) ) {
if ( current _num !== "" ) { tokens . push ( parseFloat ( current _num ) ) ; current _num = "" ; }
tokens . push ( "sqrt" ) ;
i += 3 ; // skip 'qrt'
continue ;
}
let char = eq [ i ] ;
if ( /[0-9.]/ . test ( char ) ) {
current _num += char ;
} else {
if ( current _num !== "" ) { tokens . push ( parseFloat ( current _num ) ) ; current _num = "" ; }
if ( char === "-" && ( i === 0 || /[+\-*/(]/ . test ( eq [ i - 1 ] ) ) ) {
current _num = "-" ;
}
else if ( char === "e" ) { tokens . push ( Math . E ) ; }
else if ( char === "π" ) { tokens . push ( Math . PI ) ; }
else if ( char === "φ" ) { tokens . push ( 1.6180339887 ) ; }
else if ( char === "× " ) { tokens . push ( "*" ) ; }
else if ( char === "÷" ) { tokens . push ( "/" ) ; }
else { tokens . push ( char ) ; }
}
}
if ( current _num !== "" ) { tokens . push ( parseFloat ( current _num ) ) ; }
// Implicit multiplication
let fixed = [ ] ;
for ( let i = 0 ; i < tokens . length ; i ++ ) {
fixed . push ( tokens [ i ] ) ;
let curr = tokens [ i ] ;
let next = tokens [ i + 1 ] ;
if (
( typeof curr === "number" && next === "(" ) ||
( curr === ")" && typeof next === "number" ) ||
( curr === ")" && next === "(" ) ||
( typeof curr === "number" && next === "sqrt" ) // implicit multiplication with functions
) {
fixed . push ( "*" ) ;
}
}
return fixed ;
}
function evaluate ( tokens ) {
function helper ( start = 0 ) {
let stack = [ ] ;
let i = start ;
while ( i < tokens . length ) {
let token = tokens [ i ] ;
if ( typeof token === "number" ) {
stack . push ( token ) ;
// Check for factorial
if ( tokens [ i + 1 ] === "!" ) {
stack [ stack . length - 1 ] = factorial ( stack [ stack . length - 1 ] ) ;
i ++ ; // skip the '!' token
}
}
else if ( token === "sqrt" ) {
let [ val , nextIndex ] = helper ( i + 1 ) ;
stack . push ( Math . sqrt ( val ) ) ;
// Check for factorial after function
if ( tokens [ nextIndex + 1 ] === "!" ) {
stack [ stack . length - 1 ] = factorial ( stack [ stack . length - 1 ] ) ;
nextIndex ++ ;
}
i = nextIndex ;
}
else if ( token === "(" ) {
let [ val , nextIndex ] = helper ( i + 1 ) ;
stack . push ( val ) ;
// Factorial for parentheses
if ( tokens [ nextIndex + 1 ] === "!" ) {
stack [ stack . length - 1 ] = factorial ( stack [ stack . length - 1 ] ) ;
nextIndex ++ ;
}
i = nextIndex ;
}
else if ( token === ")" ) {
break ;
}
else {
// operator
stack . push ( token ) ;
}
i ++ ;
}
// First handle * and /
for ( let j = 0 ; j < stack . length ; j ++ ) {
if ( stack [ j ] === "*" || stack [ j ] === "/" ) {
let left = stack [ j - 1 ] ;
let right = stack [ j + 1 ] ;
let result = stack [ j ] === "*" ? left * right : left / right ;
stack . splice ( j - 1 , 3 , result ) ;
j -- ;
}
}
// Then handle + and -
for ( let j = 0 ; j < stack . length ; j ++ ) {
if ( stack [ j ] === "+" || stack [ j ] === "-" ) {
let left = stack [ j - 1 ] ;
let right = stack [ j + 1 ] ;
let result = stack [ j ] === "+" ? left + right : left - right ;
stack . splice ( j - 1 , 3 , result ) ;
j -- ;
}
}
return [ stack [ 0 ] , i ] ;
}
return helper ( 0 ) [ 0 ] ;
}
function calculate ( expr ) {
let tokens = parseEquation ( expr ) ;
return evaluate ( tokens ) ;
}
elements . calculator = {
canPlace : false ,
onSelect ( ) {
promptInput ( "Input your equation" , ( eq ) => {
try {
let ans = calculate ( eq )
if ( ans == Infinity ) {
logMessage ( "Division by 0 error" )
return ;
}
if ( isNaN ( ans ) ) {
logMessage ( "Error" )
return ;
}
2026-02-02 01:04:25 -05:00
logMessage ( ans . toFixed ( 10 ) )
2025-09-19 06:24:54 -04:00
}
catch ( e ) {
logMessage ( "Invalid Characters Detected" )
console . log ( e )
}
} )
} ,
category : "tools"
}
elements . random _teleporter = {
buttonColor : [ "#5fdaff" , "#dd8500" ] ,
color : "#5fdaff" ,
grain : 0 ,
tick ( pixel ) {
// Color fading
pixel . fadeTo ? ? = "orange"
pixel . colorStay ? ? = 30
if ( pixel . fadeTo === "orange" ) {
if ( pixel . colorStay > 0 ) {
let ratio = pixel . colorStay / 30
pixel . color = fadeColor ( "#dd8500" , "#5fdaff" , ratio )
pixel . colorStay --
} else pixel . fadeTo = "blue" ;
} else {
if ( 30 - pixel . colorStay > 0 ) {
let ratio = ( 30 - pixel . colorStay ) / 30
pixel . color = fadeColor ( "#5fdaff" , "#dd8500" , ratio )
pixel . colorStay ++
} else pixel . fadeTo = "orange" ;
}
2026-02-02 01:04:25 -05:00
shuffleArray ( squareCoordsShuffle )
for ( var i = 0 ; i < squareCoordsShuffle . length ; i ++ ) {
let coord = squareCoordsShuffle [ i ] ;
2025-09-19 06:24:54 -04:00
let x = pixel . x + coord [ 0 ] ;
let y = pixel . y + coord [ 1 ] ;
if ( ! isEmpty ( x , y ) ) {
let p = getPixel ( x , y )
if ( ! p ) return ;
if ( elements [ p . element ] ? . hardness === 1 ) return ;
let availableCoords = [ ] ;
for ( let j = 0 ; j <= width ; j ++ ) {
for ( let k = 0 ; k <= height ; k ++ ) {
if ( isEmpty ( j , k ) ) {
availableCoords . push ( [ j , k ] )
}
}
}
if ( availableCoords . length > 0 ) {
let newCoords = choose ( availableCoords )
tryMove ( p , newCoords [ 0 ] , newCoords [ 1 ] )
}
}
}
} ,
hardness : 1 ,
behavior : behaviors . WALL ,
renderer : renderPresets . BORDER ,
category : "machines"
}
elements . fill _all = {
color : "#ae4cd9" ,
behavior : behaviors . WALL ,
category : "special" ,
reactions : {
"neutron" : { elem1 : "lattice" } ,
"proton" : { elem1 : "vertical" } ,
"electric" : { elem1 : "horizontal" } ,
"positron" : { elem1 : "vertical" } ,
"plasma" : { elem1 : "armageddon" , tempMin : 500 , charged : true }
} ,
density : 1834 ,
tick ( pixel ) {
for ( let x = 0 ; x <= width ; x ++ ) {
for ( let y = 0 ; y <= height ; y ++ ) {
tryCreate ( "filler" , x , y )
}
}
changePixel ( pixel , "filler" )
} ,
maxSize : 1 ,
excludeRandom : true
}
globals . elemFillAll = "sand"
elements . element _fill _all = {
color : "#ae4cd9" ,
behavior : behaviors . WALL ,
category : "special" ,
excludeRandom : true ,
reactions : {
"neutron" : { elem1 : "lattice" } ,
"proton" : { elem1 : "vertical" } ,
"electric" : { elem1 : "horizontal" } ,
"positron" : { elem1 : "vertical" } ,
"plasma" : { elem1 : "armageddon" , tempMin : 500 , charged : true }
} ,
onSelect ( ) {
promptInput ( "What element should this filler fill" , ( elem ) => {
let el = mostSimilarElement ( elem )
if ( el ) {
globals . elemFillAll = el
}
} , "Element Prompt" )
} ,
tick ( pixel ) {
for ( let x = 0 ; x <= width ; x ++ ) {
for ( let y = 0 ; y <= height ; y ++ ) {
tryCreate ( globals . elemFillAll , x , y )
}
}
changePixel ( pixel , globals . elemFillAll )
} ,
maxSize : 1 ,
}
globals . pulsecol1 = "#ffffff"
globals . pulsecol2 = "#000000"
elements . pulsing _color = {
buttonColor : rainbowColor ,
behavior : behaviors . WALL ,
category : "special" ,
onSelect ( ) {
promptInput ( "Input the starting color of the pulse in hex" , ( col1 ) => {
if ( col1 ) {
if ( /^#([A-Fa-f0-9]{6})$/ . test ( col1 ) ) {
globals . pulsecol1 = col1
promptInput ( "Input the second color that it should pulse to" , ( col2 ) => {
if ( col2 ) {
if ( /^#([A-Fa-f0-9]{6})$/ . test ( col2 ) ) {
globals . pulsecol2 = col2
}
}
} )
}
}
} )
} ,
onPlace ( pixel ) {
pixel . color = globals . pulsecol1
} ,
tick ( pixel ) {
// 1 = fade to color 2, 0 = fade to color 1
let frames = 30
pixel . fadeTo ? ? = 1
pixel . colorStay ? ? = frames
pixel . col1 ? ? = globals . pulsecol1
pixel . col2 ? ? = globals . pulsecol2
if ( pixel . fadeTo === 1 ) {
if ( pixel . colorStay > 0 ) {
let ratio = pixel . colorStay / frames
pixel . color = fadeColor ( pixel . col2 , pixel . col1 , ratio )
pixel . colorStay --
} else pixel . fadeTo = 0 ;
} else {
if ( frames - pixel . colorStay > 0 ) {
let ratio = ( frames - pixel . colorStay ) / frames
pixel . color = fadeColor ( pixel . col1 , pixel . col2 , ratio )
pixel . colorStay ++
} else pixel . fadeTo = 1 ;
}
}
}
globals . createElemWDir = "wood"
globals . lineDir = 0
elements . element _line = {
color : "#d9d9d9" ,
behavior : behaviors . WALL ,
category : "special" ,
hidden : true ,
excludeRandom : true ,
insulate : true ,
2025-09-19 07:57:08 -04:00
movable : false ,
2025-09-19 06:24:54 -04:00
onSelect ( ) {
promptInput ( "Input the element it should use" , ( input ) => {
if ( ! input ) return ;
let elem = mostSimilarElement ( input )
if ( elem ) {
globals . createElemWDir = elem
}
promptDir ( "Choose The direction the line should draw in" , ( dir ) => {
globals . lineDir = dir
} , "Direction Input" )
} , "Element Input" )
} ,
onPlace ( pixel ) {
pixel . clone ? ? = globals . createElemWDir
pixel . dir ? ? = globals . lineDir
} ,
tick ( pixel ) {
if ( pixel . dir === 0 ) {
if ( ! tryMove ( pixel , pixel . x + 1 , pixel . y , pixel . clone ) ) {
changePixel ( pixel , pixel . clone , true )
}
}
if ( pixel . dir === 1 ) {
2025-10-15 09:46:02 -04:00
if ( ! tryMove ( pixel , pixel . x , pixel . y + 1 , pixel . clone ) ) {
2025-09-19 06:24:54 -04:00
changePixel ( pixel , pixel . clone , true )
}
}
if ( pixel . dir === 2 ) {
if ( ! tryMove ( pixel , pixel . x + 1 , pixel . y , pixel . clone ) ) {
changePixel ( pixel , pixel . clone , true )
}
}
if ( pixel . dir === 3 ) {
2025-10-15 09:46:02 -04:00
if ( ! tryMove ( pixel , pixel . x , pixel . y - 1 , pixel . clone ) ) {
2025-09-19 06:24:54 -04:00
changePixel ( pixel , pixel . clone , true )
}
}
}
}
globals . replaceElem = "wood"
elements . replace _all _of _element = {
color : [ "#35008a" , "#000000" ] ,
category : "tools" ,
onSelect ( ) {
promptInput ( "What should it change into?" , ( input ) => {
if ( ! input ) return ;
let elem = mostSimilarElement ( input )
if ( elem ) {
globals . replaceElem = elem
}
} , "Element Prompt" )
} ,
tool ( pixel ) {
let elem = pixel . element
if ( elem === globals . replaceElem ) return
for ( let row of pixelMap ) {
for ( let p of row ) {
if ( p ? . element === elem ) {
changePixel ( p , globals . replaceElem )
}
}
}
}
}
2025-09-19 07:57:08 -04:00
2026-02-02 01:04:25 -05:00
/ * *
*
* @ param { ( pixel : Pixel | undefined ) => void } callback
* /
function forEachPixel ( callback ) {
for ( let x = 0 ; x <= width ; x ++ ) {
for ( let y = 0 ; y <= height ; y ++ ) {
callback ( pixelMap [ x ] [ y ] )
}
}
}
2025-09-28 03:46:04 -04:00
2026-02-02 01:04:25 -05:00
elements [ "🐔poolnoodle" ] = {
category : "extras" ,
color : [ "#7700ff" , "#90ff90" , "#ff0000" , "#f700ff" ] ,
buttonColor : rainbowColor ,
behavior : behaviors . STURDYPOWDER ,
density : 30 ,
properties : {
panic : 0 ,
panicTimer : 0
} ,
onClicked ( pixel ) {
pixel . panic = 1
pixel . panicTimer = 60
} ,
tick ( pixel ) {
if ( Math . random ( ) < 0.002 ) {
if ( Math . random ( ) <= 0.1 && ( getPixel ( pixel . x , pixel . y - 1 ) || outOfBounds ( pixel . x , pixel . y + 1 ) ) ) {
tryMove ( pixel , pixel . x , pixel . y - 2 ) // 2 to coutneract gravity
}
Math . random ( ) < 0.5
? tryMove ( pixel , pixel . x + 1 , pixel . y )
: tryMove ( pixel , pixel . x - 1 , pixel . y ) ;
}
if ( ! pixel . panic ) return
if ( pixel . panicTimer <= 0 ) {
pixel . panic = 0
}
pixel . panicTimer --
if ( Math . random ( ) <= 0.1 && ( getPixel ( pixel . x , pixel . y - 1 ) || outOfBounds ( pixel . x , pixel . y + 1 ) ) ) {
tryMove ( pixel , pixel . x , pixel . y - 2 ) // same as above
}
if ( Math . random ( ) <= 0.7 ) {
Math . random ( ) <= 0.5 ? tryMove ( pixel , pixel . x + 1 , pixel . y ) : tryMove ( pixel , pixel . x - 1 , pixel . y )
}
}
}