diff --git a/mods/advanced_colonies.js b/mods/advanced_colonies.js new file mode 100644 index 00000000..de46a7f5 --- /dev/null +++ b/mods/advanced_colonies.js @@ -0,0 +1,146 @@ +elements.male_davler = { + color: "#afe7ed", + behavior: behaviors.CRAWLER, + category: "davlers", + state: "solid", + tempHigh: 125, + stateHigh: "dead_bug", + breakInto: "davler_remains", + reactions: { + "sugar": { elem2: null }, + "meat": { elem2: null }, + "rotten_meat": { elem2: null }, + "cooked_meat": { elem1: "davler_remains" }, + "dough": { elem2: null }, + "baking_soda": { elem1: "davler_remains" } + } +}; + +elements.female_davler = { + color: "#c1ecf1", + behavior: behaviors.CRAWLER, + category: "davlers", + state: "solid", + tempHigh: 125, + stateHigh: "dead_bug", + breakInto: "davler_remains", + reactions: { + "sugar": { elem2: null }, + "meat": { elem2: null }, + "rotten_meat": { elem2: null }, + "cooked_meat": { elem1: "davler_remains" }, + "dough": { elem2: null }, + "baking_soda": { elem1: "davler_remains" } + } +}; + +elements.davler_queen = { + color: "#3495eb", + behavior: behaviors.CRAWLER, + category: "davlers", + state: "solid", + tempHigh: 150, + stateHigh: "davler_remains", + breakInto: "davler_remains", + properties: { + "eaten": 0 + }, + tick: function(pixel) { + if (pixel.eaten > 2) { + pixel.eaten = 0 + createPixel('larvae', pixel.x + 1, pixel.y) + } + }, + reactions: { + "sugar": { elem2: null, func: function(pixel){pixel.eaten = pixel.eaten +1} }, + "meat": { elem2: null }, + "rotten_meat": { elem2: null }, + "cooked_meat": { elem1: "dead_bug" }, + "dough": { elem2: null }, + "baking_soda": { elem1: "dead_bug" } + } +}; + +elements.larvae = { + color: ["#f2e9c9", "#ebd798"], + behavior: behaviors.POWDER, + category: "davlers", + state: "solid", + tempHigh: 150, + stateHigh: "dead_bug", + breakInto: "yolk", + properties: { + "hatch": 300, + "fertilized": false + }, + tick: function(pixel) { + if (pixel.hatch < 1) { + const nX = pixel.x + const nY = pixel.y + deletePixel(pixel.x, pixel.y) + const chance = Math.floor(Math.random() * ( 2 - 1 + 1)) + 1 + if (chance == 1) { + createPixel('female_davler', nX, nY) + } else { + createPixel('male_davler', nX, nY) + } + } else { + if (pixel.fertilized == true) { + pixel.hatch = pixel.hatch - 1 + } + } + }, + reactions: { + "baking_soda": { elem1: "dead_bug" }, + "male_davler": { func: function(pixel){pixel.fertilized = true } } + } +}; + +elements.davler_remains = { + color: elements.dead_bug.color, + behavior: behaviors.POWDER, + state: "solid", + tempHigh: 150, + stateHigh: ["ash", "fire"], + category: "davlers", + reactions: { + "yolk": { elem2: "artificial_larvae", elem1: null } + } +}; + +elements.artificial_larvae = { + color: ["#f2e9c9", "#ebd798"], + behavior: behaviors.POWDER, + category: "davlers", + state: "solid", + tempHigh: 150, + stateHigh: "dead_bug", + breakInto: "yolk", + properties: { + "hatch": 450, + "fertilized": false + }, + tick: function(pixel) { + if (pixel.hatch < 1) { + const nX = pixel.x + const nY = pixel.y + deletePixel(pixel.x, pixel.y) + const chance = Math.floor(Math.random() * ( 4 - 1 + 1)) + 1 + if (chance == 1) { + createPixel('female_davler', nX, nY) + } else if ( chance == 2 ) { + createPixel('male_davler', nX, nY) + } else { + createPixel('dead_bug', nX, nY) + } + } else { + if (pixel.fertilized == true) { + pixel.hatch = pixel.hatch - 1 + } + } + }, + reactions: { + "baking_soda": { elem1: "dead_bug" }, + "male_davler": { func: function(pixel){pixel.fertilized = true } } + } +}; diff --git a/mods/fine_tuned_cloner.js b/mods/fine_tuned_cloner.js new file mode 100644 index 00000000..5bf0f2c1 --- /dev/null +++ b/mods/fine_tuned_cloner.js @@ -0,0 +1,121 @@ +/* +MIT License + +Copyright (c) 2024 BatteRaquette58 (a.k.a BatteRaquette581) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +const isFloat = /^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)$/ // https://stackoverflow.com/questions/12643009/regular-expression-for-floating-point-numbers +const isIDList = /^\d+(,\d+)*$/ + +let cloner_elements = [] +// makes cloner elements ignore the new cloner, and vice versa +const update_ignore_list = () => { + const hasCloner = /cloner/ // don't ask why out of all methods to detect a substring in a string, i chose regex + let element_keys = Object.keys(elements) + cloner_elements = element_keys.filter(element => hasCloner.test(element)) // all elements with "cloner" in their name + if (element_keys.includes("liquid_void")) // support for liquid_void.js + cloner_elements.push("liquid_void") + if (element_keys.includes("destroyable_cloner")) // support for nousersthings.js + cloner_elements.push("destroyable_cloner") + cloner_elements.forEach(element => { + if (elements[element].ignore == null) + elements[element].ignore = [] + elements[element].ignore.push("fine_tuned_cloner") + }) // add the new cloner into the ignore list of the cloners +} +setTimeout(update_ignore_list, 2000) // i hate the way of doing this, but it's pretty much the only way to make this work... + +// check if position has no pixel, if yes, create a new pixel at this position +const try_place = (element, x, y) => { + let succeeded = checkForEmptyPixels(x, y) + if (succeeded) + createPixel(element, x, y) + return succeeded +} + +let FTC_cloning_frequency = null // store cloning frequency +let FTC_blacklist = null +elements.fine_tuned_cloner = { + color: "#dddd00", + behavior: behaviors.WALL, + category: "machines", + state: "solid", + darkText: true, + + onSelect: _ => { + let cloning_frequency = prompt("Cloning frequency (how often the cloner clones, 1 being always, 0 being never, can be decimal):") + if (isFloat.test(cloning_frequency)) // make sure the user isn't putting something non-numeric + cloning_frequency = parseFloat(cloning_frequency) + else { + alert("Cloning frequency is not a number. Try again.") + selectElement("unknown") + return + } + if (!(0 <= cloning_frequency && cloning_frequency <= 1)) { // if not 0-1 + alert("Cloning frequency is not between 0 and 1. Try again.") + selectElement("unknown") + return + } + FTC_cloning_frequency = cloning_frequency + + let blacklist = prompt("Element blacklist (element IDs that the cloner cannot clone, seperated by commas, no trailing commas, leave empty if no blacklist):") + if (isIDList.test(blacklist)) + blacklist = blacklist.split(",") // split blacklist by comma, to make a list of IDs + else if (blacklist === "") // if empty, empty blacklist list + blacklist = [] + else { + alert("Invalid blacklist. Try again.") + selectElement("unknown") + return + } + FTC_blacklist = blacklist + }, + + tick: pixel => { + if (pixel.element === "fine_tuned_cloner") { + if (pixel.FTC_element == null) { + // assign FTC variables if not done already + if (pixel.FTC_cloning_frequency == null) + pixel.FTC_cloning_frequency = FTC_cloning_frequency + if (pixel.FTC_blacklist == null) + pixel.FTC_blacklist = FTC_blacklist + + let neighbors = getNeighbors(pixel) + if (neighbors.length > 0) { // if there's neighbors + neighbors.forEach(neighbor => { + // make sure it's not a cloner element nor a blacklist element + if ((!cloner_elements.includes(neighbor.element)) && (!pixel.FTC_blacklist.includes(elements[neighbor.element].id))) { + pixel.FTC_element = neighbor.element // set clone element + } + }) + } + } + + if (Math.random() < pixel.FTC_cloning_frequency && pixel.FTC_element != null) { // if cloner already has its cloning element, and it's ready to clone: + if (!try_place(pixel.FTC_element, pixel.x, pixel.y - 1)) // try above + if (!try_place(pixel.FTC_element, pixel.x - 1, pixel.y)) // try at the left + if (!try_place(pixel.FTC_element, pixel.x + 1, pixel.y)) // try at the right + if (!try_place(pixel.FTC_element, pixel.x, pixel.y + 1)) // try under + ; // pass, spots are already taken :p + } + } + }, +}; diff --git a/mods/pizzasstuff.js b/mods/pizzasstuff.js index 7e4fb53b..cc28b4ce 100644 --- a/mods/pizzasstuff.js +++ b/mods/pizzasstuff.js @@ -1,5 +1,5 @@ elements.freeze_ray = { - color: ["#9ae4f5","#84d6e8"], + color: ["#8cf9ff","#5c59ff"], tick: function(pixel) { var x = pixel.x; for (var y = pixel.y; y < height; y++) { @@ -9,7 +9,7 @@ elements.freeze_ray = { if (isEmpty(x, y)) { if (Math.random() > 0.05) { continue } createPixel("flash", x, y); - pixelMap[x][y].color = "#aedbe6"; + pixelMap[x][y].color = "#96b6ff"; pixelMap[x][y].temp = -257; } else { @@ -29,6 +29,38 @@ elements.freeze_ray = { noMix: true }; +elements.devil_ray = { + color: ["#ba0000","#8f0000"], + tick: function(pixel) { + var x = pixel.x; + for (var y = pixel.y+1; y < height; y++) { + if (outOfBounds(x, y)) { + break; + } + if (isEmpty(x, y)) { + if (Math.random() > 0.1) { continue } + createPixel("flash", x, y); + pixelMap[x][y].color = ["#990000"]; + } + else { + if (elements[pixelMap[x][y].element].id === elements.flash.id) { continue } + if (elements[pixelMap[x][y].element].id === elements.god_ray.id) { break } + if (!elements[pixelMap[x][y].element].isGas && isEmpty(x, y-1)) { + createPixel("curse", x, y-1); + } + if (Math.random() > 0.1) { continue } + elements.bless.tool(pixelMap[x][y]) + } + } + deletePixel(pixel.x, pixel.y); + }, + category: "energy", + state: "gas", + density: 1, + excludeRandom: true, + noMix: true +}; + elements.beer = { color: ["#ffc43d","#ffc43d"], behavior: behaviors.LIQUID, @@ -197,7 +229,7 @@ elements.frozen_chocolate_yogurt = { temp: 0, }; -elements.cooking_oil = { +elements.frying_oil = { color: "#c4ab4f", behavior: behaviors.LIQUID, category: "liquids", @@ -447,7 +479,7 @@ elements.moss = { stateHigh: "dead_plant", tempLow: -4, stateLow: "frozen_plant", - + alias: "mercedes benz", reactions: { "dna": { elem1: "moth", elem2: null }, } @@ -469,6 +501,126 @@ elements.moth = { stateLow: "dead_bug", }; +elements.holy_fire = { + color: ["#FEFFF8","#FFF0CE","#FFE792"], + behavior: [ + "M1|M1|M1", + "M2|CH:bless%8|M2", + "XX|M2|XX", + ], + reactions: { + "fire": { elem1: "bless", elem2: "bless" }, + "plasma": { elem1: "light", elem2: "light" } + }, + temp:750, + tempLow:200, + tempHigh:1200, + stateLow: "bless", + stateHigh: "bless", + category: "energy", + state: "gas", + density: 0.1, + ignoreAir: true +}; + +elements.curse = { + color: ["#d27979","#bf4040","#752727"], + tool: function(pixel) { + if (elements.bless.ignore.indexOf(pixel.element) !== -1) { return; } + if (pixel.burning) { // stop burning + delete pixel.burning; + delete pixel.burnStart; + } + if (pixel.temp > 100) { + pixel.temp = (pixel.temp+100)/2; + pixelTempCheck(pixel); + if (pixel.del) {return} + } + if (pixel.temp < -200) { + pixel.temp = (pixel.temp-200)/2; + pixelTempCheck(pixel); + if (pixel.del) {return} + } + if (pixel.origColor) { + pixel.color = "rgb("+pixel.origColor.join(",")+")"; + delete pixel.origColor; + } + if (pixel.charge) { + delete pixel.charge; + pixel.chargeCD = 16; + } + if (elements.bless.reactions[pixel.element] && Math.random()<0.25) { + var r = elements.bless.reactions[pixel.element]; + var elem2 = r.elem2; + if (elem2 !== undefined) { + if (Array.isArray(elem2)) { elem2 = elem2[Math.floor(Math.random()*elem2.length)]; } + if (elem2 === null) { deletePixel(pixel.x,pixel.y) } + else { changePixel(pixel, elem2); } + } + if (r.func) { r.func(pixel,pixel) } + } + }, + ignore: ["sun"], + behavior: [ + "M2|M1|M2", + "M1|DL%25|M1", + "M2|M1|M2", + ], + reactions: { + "cell": { elem2: "cancer" }, + "iron": { elem2: "rust" }, + "copper": { elem2: "oxidized_copper" }, + "antibody": { elem2:["blood",null] }, + "antibody_ice": { elem2:"blood_ice" }, + "dirty_water": { elem2: "water" }, + "dna": { elem2: "plague" }, + "antibody": { elem2: ["infection",null] }, + "infection": { elem2: ["infection",null] }, + "antidote": { elem2: "poison" }, + "meat": { elem2: "rotten_meat" }, + "cheese": { elem2: "rotten_cheese" }, + "oxygen": { elem2: "carbon_dioxide" }, + "hydrogen": { elem2: "acid_gas" }, + "cloud": { elem2: "fire_cloud" }, + "perfume": { elem2: "liquid_stench" }, + "fragrance": { elem2: "stench" }, + "seltzer": { elem2: "soda" }, + "cloud": { elem2: "smog" }, + "water": { elem2: "broth" }, + "bless": { elem2: "plasma" }, + "metal_scrap": { elem2: "grenade" }, + "smoke": { elem2: "greek_fire" }, + "rock": { elem2: "uranium", chance: 0.01}, + "magma": { elem2: "molten_uranium", chance: 0.01}, + "ice": { elem2: "ice_nine", chance: 0.01}, + "frog": { elem2: "frozen_frog" }, + "worm": { elem2: "frozen_worm" }, + "rock": { elem2: "molten_thermite", chance: 0.01}, + "glass": { elem2: "rad_glass", chance: 0.2 }, + "shard": { elem2: "rad_shard", chance: 0.2 }, + "steam": { elem2: "rad_steam", chance: 0.2 }, + "rain_cloud": { elem2: "rad_cloud", chance: 0.2 }, + "ball": { elem2: "ball", chance: 0.2 }, + "bone": { elem2: "bone_marrow", chance: 0.2 }, + "plant": { elem2: "dead_plant" }, + "rock": { elem2: "rock", chance: 0.01 }, + "magma": { elem2: "molten_slag", chance: 0.01 }, + "light": { elem2: "laser", chance: 0.2 }, + "flash": { elem2: "light", chance: 0.2 }, + "wood": { elem2: "torch", chance: 0.01 }, + "gold": { elem2: "lead", chance: 0.2 }, + "molten_gold": { elem2: "molten_lead", chance: 0.2 }, + "grass": { elem2: null }, + "rainbow": { elem2: "static" }, + }, + temp:20, + state: "gas", + density: 0.001, + canPlace: true, + category: "energy", + stain: -0.5 +}; + elements.parrot = { color: ["#234d20","#36802d","#77ab59","#c9df8a","#f0f7da","#f90f0b","#f7ab4d","#fdfc0d","#0564b2","#60a3e6"], behavior: behaviors.FLY, @@ -1097,8 +1249,7 @@ elements.olive = { behavior: behaviors.POWDER, category: "food", state: "solid", - breakInto: "juice", - breakIntoColor: ["#d1ef71","#c1d64d"], + breakInto: "olive_oil", }; elements.eggplant = { @@ -1146,6 +1297,19 @@ elements.garlic_clove = { hidden: "TRUE", }; +elements.carrot = { + color: ["#ea820b","#e89116","#e8a32b","#efb538"], + density: 675, + behavior: behaviors.POWDER, + category: "food", + state: "solid", + burnInto: "ash", + burn: 10, + burnTime: 300, + breakInto: "juice", + breakIntoColor: "#f1b956", +}; + elements.asparagus = { color: ["#77ab56","#92bc78","#adcd9a"], density: 675, @@ -1215,6 +1379,16 @@ elements.whipped_cream = { } }; +elements.olive_oil = { + color: ["#efcc3f","#efd672","#f1e09a"], + density: 675, + behavior: behaviors.LIQUID, + category: "liquids", + state: "liquid", + burn: 10, + burnTime: 300, +}; + elements.cream_coffee = { color: ["#dbc1ac","#967259","#634832"], behavior: behaviors.LIQUID, @@ -1242,7 +1416,7 @@ elements.pipis = { }; elements.frog_bomb = { - color: "#0f2105", + color: ["#0f2105","#274e13","#6aa84f"], behavior: [ "XX|EX:10>frog|XX", "XX|XX|XX", @@ -1258,7 +1432,7 @@ elements.frog_bomb = { }, elements.cash_bomb = { - color: "#665411", + color: ["#e69138","#f1c232","#f6b26b"], behavior: [ "XX|EX:10>gold_coin|XX", "XX|XX|XX", @@ -1274,18 +1448,41 @@ elements.cash_bomb = { }, elements.pi_pis = { - color: ["#007299","003849"], + color: ["#0b5394","#073763","#3d85c6"], behavior: [ "XX|EX:10>pipis|XX", "XX|XX|XX", "M2|M1 AND EX:10>pipis|M2", ], + behaviorOn: [ + "XX|XX|XX", + "XX|EX:6>metal_scrap,fire,fire,fire%1|XX", + "XX|XX|XX", + ], category: "weapons", state: "solid", density: 1300, tempHigh: 1455.5, stateHigh: "molten_steel", excludeRandom: true, + conduct: 1, + cooldown: defaultCooldown, + nocheer: true +}, + +elements.holy_hand_grenade = { + color: ["#ffd966","#ffc000","#fff2cc"], + behavior: [ + "XX|EX:20>bless,holy_fire%1|XX", + "XX|XX|XX", + "M2|M1 AND EX:20>bless,holy_fire%1|M2", + ], + category: "weapons", + state: "solid", + density: 1300, + tempHigh: 1455.5, + stateHigh: "bless", + excludeRandom: true, cooldown: defaultCooldown }, @@ -1477,6 +1674,18 @@ elements.quartz = { } }; +elements.ruby = { + color: ["#850014","#ae001a","#e10531","#a50727","#6b0015"], + behavior: behaviors.POWDER, + category: "powders", + tempHigh: 900, + stateHigh: "carbon_dioxide", + state: "solid", + density: 3515, + hardness: 1, + alias: "Lamp Oil, Rope, Bombs, you want it? It's yours my friend, as long as you have enough rubies.", +}; + elements.slushy_ice = { color: ["#f6fff9","#f3f9f9","#f6fcf9","#fefefe","#fdfffe"], behavior: behaviors.WALL, diff --git a/mods/soups.js b/mods/soups.js index 19152bf5..0459bb18 100644 --- a/mods/soups.js +++ b/mods/soups.js @@ -4,25 +4,31 @@ // added seasoning // added seasoned_water +// 1.1 update - soup update +// adds soup +// changed seasoning to a SUPPORT behaviour +// seasoned water at high temp is soup +// changed seasoning density + elements.seasoning = { color: "#876461", - behavior: behaviors.POWDER, + behavior: behaviors.SUPPORT, category: "food", - tempHigh: 900, - stateHigh: "salt", + tempHigh: 9000, + stateHigh: "ash", state: "solid", reactions: { - "water": { elem1: "null", elem2: "seasoned_water" }, - "salt_water": { elem1: "null", elem2: "seasoned_water" }, + "water": { elem1: "seasoned_water", elem2: "null" }, + "salt_water": { elem1: "seasoned_water", elem2: "null" }, }, - density: 2, + density: 3000, }; elements.seasoned_water = { color: "#73d627", behavior: behaviors.LIQUID, tempHigh: 100, - stateHigh: "steam", + stateHigh: "soup", tempLow: 0, stateLow: "ice", category: "liquids", @@ -88,3 +94,11 @@ elements.seasoned_water = { stain: -0.9, extinguish: true }; + +elements.soup = { + color: "#e8c238", + behavior: behaviors.LIQUID, + category: "food", + state: "solid", + density: 7000, +}; diff --git a/mods/weapons.js b/mods/weapons.js index d66596a7..99831ad9 100644 --- a/mods/weapons.js +++ b/mods/weapons.js @@ -397,4 +397,62 @@ elements.fast_bullet_right = { category: "ammunition", state: "solid", insulate: true, +}, +elements.flak_cannon = { + color: "#C0C0C0", + behavior: behaviors.WALL, + behaviorOn: [ + "XX|CR:flak|XX", + "XX|XX|XX", + "XX|XX|XX", + ], + category: "weapons", + state: "solid", + density: 1300, + conduct: 1, +}, + elements.flak = { + color: "#f0f0f0", + tick: function(pixel) { + if ((pixel.temp > 1000 || pixel.charge) && !pixel.burning) { + pixel.burning = true; + pixel.burnStart = pixelTicks; + } + if (pixel.burning) { + if (!tryMove(pixel, pixel.x, pixel.y-1)) { + // tryMove again to the top left or top right + tryMove(pixel, pixel.x+(Math.random() < 0.5 ? -1 : 1), pixel.y-1); + } + if (pixelTicks-pixel.burnStart > 50 && Math.random() < 0.005) { + explodeAt(pixel.x, pixel.y, 10, "flak_shrapnel"); + } + } + else { + if (!tryMove(pixel, pixel.x, pixel.y+1)) { + // tryMove again to the bottom left or bottom right + tryMove(pixel, pixel.x+(Math.random() < 0.5 ? -1 : 1), pixel.y+1); + } + } + doDefaults(pixel); + }, + burn: 90, + burnTime: 100, + density: 2000, + conduct: 1, + state: "solid", + category: "ammunition" +}, + elements.flak_shrapnel = { + color: "#71797E", + behavior: [ + "XX|XX|XX", + "XX|EX:5 %10|XX", + "M2|M1|M2", + ], + burn: 90, + burnTime: 100, + density: 2000, + conduct: 1, + state: "solid", + category: "ammunition" } \ No newline at end of file