sandboxels/mods/crimson.js

425 lines
11 KiB
JavaScript

/*
TODO:
Blood Crawler?
Tweak Vicious Goldfish heavily
Face Monster
Crimera
Herpling
Crimslime
Blood Jelly
Blood Feeder
Blood Mummy
Deathweed
Some drops
Loot items could be implemented as useless powders.
Crimsandstone
Fishing loot fish (as Fish copies)
Not doing:
Mob spawning
Game-like world generation
Crafting stations
Hardmode-exclusive behavior (WoF would be a nightmare to add)
Biome keys
Might not be possible:
Thorny bushes (their breaking behavior would require a way for a pixel to detect when another pixel tryMove'd into its position)
Powders and clentamination (those would require a means of moving through pixels without falsely occupied pixels or other glitches)
Blood crawlers crawling on background walls
Brain of Cthulhu (without the rest of the progression)
*(would be pretty pointless)
Crimson Hearts are probably possible but would be useless without this
Actually usable weapons
Game-like fishing system
Crates breaking into multiple items
Tree shaking behavior
Deadland Comes Alive painting
Floaty Gross, Crimson Axe, Crimson Pigron (same issue as powders)
Probably possible but far beyond my skill level:
Enemy pathfinding
Music boxes
Crimera variants
Multi-pixel enemies other than Face Monsters (which would copy human code)
*/
function includesArray(parentArray, testArray) {
for (let i = 0; i < parentArray.length; i++) {
if (parentArray[i].every(function(value, index) { return value === testArray[index]})) {
return true;
}
}
return false;
}
crimRate = 0.002
function grassSpread(pixel,dirt,grass,chance) {
pixel.dirtArray = [] //initialize dirt neighbor list
for (i = -2; i < 3; i++) { //iterate around
for (j = -2; j < 3; j++) {
if (!isEmpty(pixel.x+i,pixel.y+j,true)) { //check for a pixel to see if it's dirt
if(Array.isArray(dirt)) {
if(dirt.includes(pixelMap[pixel.x+i][pixel.y+j].element)) { //see if it's dirt
if(!includesArray(pixel.dirtArray,[i,j])) { //avoid duplicate dirt entry
pixel.dirtArray.push([i,j]) //store dirt
}
}
} else {
if(pixelMap[pixel.x+i][pixel.y+j].element == dirt) { //see if it's dirt
if(!includesArray(pixel.dirtArray,[i,j])) { //avoid duplicate dirt entry
pixel.dirtArray.push([i,j]) //store dirt
}
}
}
}
}
}
for (k = 0; k < pixel.dirtArray.length; k++) { //iterate through dirt list
if(Math.random() < chance) { //random chance
if(isEmpty(pixel.x+pixel.dirtArray[k][0],pixel.y+pixel.dirtArray[k][1]-1)) { //check for empty space to grow grass
createPixel(grass,pixel.x+pixel.dirtArray[k][0],pixel.y+pixel.dirtArray[k][1]-1) //place grass above dirt
}
}
}
}
crimsonObject = {
grass: "crimson_grass",
rock: "crimstone",
sand: "crimsand",
ice: "red_ice",
gravel: "crimgravel",
water: "crimwater",
snow: "crimsnow",
packed_snow: "crimsnow",
wet_sand: "crimsand",
mud: "dirt",
permafrost: "dirt",
vine: "crimson_vine",
fish: "vicious_goldfish",
sapling: "shadewood_sapling"
};
function crimSpread(pixel) {
for (let i = -2; i < 3; i++) {
for (let j = -2; j < 3; j++) {
if (!isEmpty(pixel.x+j,pixel.y+i,true)) {
var destPixel = pixelMap[pixel.x+j][pixel.y+i];
var elementToCheck = destPixel.element;
if(Math.random() < crimRate) {
if(crimsonObject[elementToCheck]) {
changePixel(destPixel,crimsonObject[elementToCheck]);
};
grassSpread(pixel,"dirt","crimson_grass",0.5);
};
};
};
};
};
eLists.WHL = "water,salt_water,sugar_water,dirty_water,swamp_water,heavy_water,radioactive_water,crimwater,pure_water,chilly_water,honey,magma"
elements.crimson_grass = {
color: ["#e82535","#cc471f","#d6153c","#c20e29","#b81a2c"],
behavior: [
"XX|CR:vicious_mushroom%0.01|XX",
"XX|XX|XX",
"XX|M1|XX",
],
tick: function(pixel) {
crimSpread(pixel)
},
tempHigh: 100,
stateHigh: "dead_plant",
tempLow: -2,
stateLow: "frozen_plant",
burn:50,
burnTime:20,
category:"life",
state: "solid",
density: 1400,
}
elements.crimstone = {
color: ["#cb4444", "#953333", "#611c1c", "#b43434", "#752424"],
behavior: behaviors.POWDER,
tick: function(pixel) {
crimSpread(pixel)
},
tempHigh: 950,
stateHigh: "magma",
category: "land",
state: "solid",
density: 2550,
hardness: 0.5,
breakInto: ["crimsand","crimgravel"],
}
elements.crimsand = {
color: ["#4c4c44", "#6c645c", "#5c544c", "#847c6c", "#24241c", "#4c4c44", "#6c645c", "#5c544c", "#847c6c", "#24241c", "#3c140c", "#842c24"],
behavior: behaviors.POWDER,
tick: function(pixel) {
crimSpread(pixel)
},
tempHigh: 1700,
stateHigh: "molten_glass",
category: "land",
state: "solid",
density: 1602,
}
elements.red_ice = {
color: ["#f0ccc5", "#f7d8d2", "#eba39b"],
behavior: behaviors.WALL,
tick: function(pixel) {
crimSpread(pixel)
},
temp: 0,
tempHigh: 5,
stateHigh: "crimwater",
category: "solids",
state: "solid",
density: 917,
breakInto: "crimsnow",
}
elements.crimgravel = { //break from canon for crimstone breakInto
color: ["#c4533f", "#de6957", "#b84639", "#cf4634", "#db6758", "#d17366", "#ab2b2b"],
behavior: behaviors.POWDER,
tick: function(pixel) {
crimSpread(pixel)
},
category:"land",
tempHigh: 950,
stateHigh: "magma",
state: "solid",
density: 1680,
hardness: 0.2,
},
elements.crimwater = { //you shouldn't be able to purify ice by melting it
color: "#e45c7c",
behavior: behaviors.LIQUID,
tick: function(pixel) {
crimSpread(pixel)
},
tempLow: 0,
stateLow: "red_ice",
tempHigh: 100,
stateHigh: "steam",
viscosity: 1,
category: "liquids",
reactions: {
"quicklime": { "elem1": null, "elem2": "slaked_lime", },
"ruins": { "elem2": "rock", "chance": 0.00035 },
},
state: "liquid",
density: 997,
conduct: 0.02,
stain: 0.02,
}
elements.crimsnow = { //BIG break from canon but you shouldn't be able to purify ice by grinding it either
color: "#fce1e4",
behavior: behaviors.POWDER,
tick: function(pixel) {
crimSpread(pixel)
},
temp: 0,
tempHigh: 5,
stateHigh: "crimwater",
category: "land",
state: "solid",
density: 100,
}
elements.vicious_mushroom = {
color: "#e36554",
behavior: behaviors.POWDER,
tick: function(pixel) {
crimSpread(pixel)
},
category: "life",
hidden: true,
tempHigh: 225,
stateHigh: "fire",
burn: 10,
burnTime: 65,
state: "solid",
density: 90.445,
}
elements.crimtane_ore = {
color: ["#d83a3b", "#85242c", "#5d5d5d", "#540c14"],
behavior: behaviors.POWDER,
category: "land",
tempHigh: 1552, //using palladium's melting point as an upper bound
stateHigh: ["molten_slag","molten_slag","molten_crimtane"], //:sunglasses: can't turn things into slag if you're already slag
state: "solid",
density: 5854, //arbitrarily chosen, average of ((average of gold and palladium densities) + (crimstone density) + (crimstone density))
}
elements.crimtane = {
color: ["#fc141e", "#C62A2F", "#903f3f", "#752E2E", "#5a1c1c", "#5B3C3C", "#5c5c5c"],
behavior: behaviors.SOLID,
category: "solids",
tempHigh: 1200, //i want a behaviors.WALL form of crimtane... and I'm letting the game autogenerate molten_crimtane because I'm going to use it.
//just pretend it got sintered somehow
state: "solid",
hidden: true,
density: 15661,
}
elements.shadewood_tree_branch = {
color: "#677a8f",
behavior: [
"CR:crimson_leaf,shadewood_tree_branch%2|CR:crimson_leaf,crimson_leaf,crimson_leaf,shadewood_tree_branch%2|CR:crimson_leaf,shadewood_tree_branch%2",
"XX|XX|XX",
"XX|XX|XX",
],
tempHigh: 400,
stateHigh: ["fire","sap"],
tempLow: -30,
stateLow: "wood",
category: "solids",
burn: 40,
burnTime: 50,
burnInto: ["sap","ember","charcoal"],
hidden: true,
state: "solid",
density: 1500,
hardness: 0.15,
breakInto: ["sap","sawdust"],
hidden: true,
}
elements.crimson_vine = {
color: "#de3323",
behavior: [
"XX|SP|XX",
"XX|XX|XX",
"XX|CL%1 AND M1|XX",
],
tick: function(pixel) {
crimSpread(pixel)
},
tempHigh: 100,
stateHigh: "dead_plant",
tempLow: -2,
stateLow: "frozen_plant",
burn: 35,
burnTime: 100,
category: "life",
state: "solid",
density: 1050,
}
elements.shadewood = {
color: "#677a8f",
behavior: behaviors.WALL,
tempHigh: 400,
stateHigh: ["ember","charcoal","fire","fire","fire"],
category: "solids",
burn: 5,
burnTime: 300,
burnInto: ["ember","charcoal","fire"],
state: "solid",
hardness: 0.15,
breakInto: "shadewood_sawdust",
density: 930, //used tigerwood
}
elements.shadewood_sapling = {
color: ["#e64029", "#d43b26"],
behavior: [
"XX|M2%2|XX",
"XX|L2:shadewood,shadewood_tree_branch%80|XX",
"XX|M1|XX",
],
tempHigh: 100,
stateHigh: "dead_plant",
tempLow: -2,
stateLow: "frozen_plant",
burn: 65,
burnTime: 15,
category: "life",
state: "solid",
density: 1500,
}
elements.shadewood_sawdust = {
color: ["#95abcf","#8190a3"],
behavior: behaviors.POWDER,
tempHigh: 400,
stateHigh: "fire",
category: "powders",
burn: 25,
burnTime: 150,
burnInto: ["ash","fire","fire","fire"],
state: "solid",
density: 493,
hidden: true,
}
elements.crimson_leaf = {
color: "#de3323",
behavior: behaviors.WALL,
category:"life",
tempHigh: 100,
stateHigh: "dead_plant",
tempLow: -1.66,
stateLow: "frozen_plant",
burn:65,
burnTime:60,
burnInto: "dead_plant",
state: "solid",
density: 500,
hidden: true,
}
elements.ichor = {
color: ["#ffec70", "#ffcb52"],
behavior: behaviors.LIQUID,
reactions: {
"head": { "elem2":"meat" }, //sb has no defense to reduce so i just made it deadly
"body": { "elem2":"meat" },
},
category: "liquids",
viscosity: 1,
state: "liquid",
density: 1010,
stain: 0.02,
}
elements.vicious_goldfish = {
color: "#e64230",
behavior: [
"SW:"+eLists.WHL+",blood%2|M2%5 AND SW:"+eLists.WHL+",blood%1|XX", //this is where M3 would have been useful
"SW:"+eLists.WHL+",blood%40|FX%0.01|BO%1", //i have no idea what i'm doing
"SW:"+eLists.WHL+",blood%2 AND M2|M1|XX",
],
reactions: {
"algae": { "elem2":null, chance:0.5 },
"plant": { "elem2":null, chance:0.125 },
"fly": { "elem2":null, chance:0.5 },
"firefly": { "elem2":null, chance:0.5 },
"worm": { "elem2":null, chance:0.25 },
"head": { "elem2":[null,"blood"], chance:0.25 },
"body": { "elem2":[null,"blood"], chance:0.25 },
"oxygen": { "elem2":"carbon_dioxide", chance:0.5 },
},
tick: function(pixel) {
pixel.color = pixelColorPick(pixel)
},
temp: 20,
tempHigh: 42,
stateHigh: "meat",
tempLow: -20,
stateLow: "frozen_meat",
category:"life",
burn:40,
burnTime:100,
state: "solid",
density: 1080,
conduct: 0.2,
}