diff --git a/lang/es.json b/lang/es.json
index 5d54b999..d4f495f3 100644
--- a/lang/es.json
+++ b/lang/es.json
@@ -521,23 +521,23 @@
"molten_borax":"bórax_fundido",
"molten_epsom_salt":"sal_de_epsom_fundido",
"molten_potassium_salt":"sal_de_potassio_fundido",
-"molten_sodium_acetate":"",
-"frozen_nitro":"",
-"cured_meat": "",
-"nut_oil": "",
-"grease": "",
-"fat": "",
-"potassium": "",
-"molten_potassium": "",
-"magnesium": "",
-"molten_magnesium": "",
-"sandstorm": "",
-"caustic_potash": "",
-"antibomb": "",
-"tornado": "",
-"earthquake": "",
-"tsunami": "",
-"blaster": "",
-"propane_ice": "",
-"molten_caustic_potash": ""
+"molten_sodium_acetate":"acetato_de_sodio_fundido",
+"frozen_nitro":"nitrógeno",
+"cured_meat": "carné_presérvado",
+"nut_oil": "acéite_de_núez",
+"grease": "grasa",
+"fat": "grasa",
+"potassium": "potasio",
+"molten_potassium": "potasio_fundido",
+"magnesium": "magnesio",
+"molten_magnesium": "magnesio_fundido",
+"sandstorm": "tormenta_de_arena",
+"caustic_potash": "cáustico_potasio",
+"antibomb": "anti_bomba",
+"tornado": "tornado",
+"earthquake": "terremoto",
+"tsunami": "tsunami",
+"blaster": "desintegrador",
+"propane_ice": "propano",
+"molten_caustic_potash": "cáustico_potas_fundido"
}
diff --git a/lang/qha.json b/lang/qha.json
new file mode 100644
index 00000000..a2e6aec9
--- /dev/null
+++ b/lang/qha.json
@@ -0,0 +1,548 @@
+{
+"#lang.name": "Halacae",
+"#lang.credit": "Nekonico, R74n",
+"land": "moo",
+"liquids": "mae-e",
+"life": "ma",
+"powders": "mayi-i-e",
+"solids": "maye-e",
+"energy": "pa",
+"weapons": "yo",
+"gases": "lamapa",
+"food": "paema",
+"machines": "yaepe",
+"special": "ayoo",
+"other": "ayoo-e",
+"heat": "mosu",
+"cool": "opasu",
+"erase": "oyu",
+"drag": "yapu",
+"pick": "eyacu",
+"mix": "o-alayu",
+"lookup": "samo-u",
+"shock": "pe",
+"paint": "samocayu",
+"sand": "mayi-i",
+"water": "mae",
+"salt_water": "mae-oopaema-mayi-i",
+"sugar_water": "paema-ae-mayi-i_mae",
+"seltzer": "mape_mae",
+"dirty_water": "mayi-i-e_mae",
+"pool_water": "mae-u-e_mae",
+"dirt": "mayi-i",
+"mud": "mayi-imae",
+"wet_sand": "mae-e_mayi-i",
+"rock": "mayi",
+"rock_wall": "maye_mayi",
+"mudstone": "mayi-e_mayi-imae",
+"packed_sand": "yecaece_mayi-i",
+"plant": "mi",
+"dead_plant": "omi",
+"frozen_plant": "opese_mi",
+"grass": "parusi_mi",
+"algae": "mimae",
+"concrete": "mayiya",
+"wall": "poo-e_yoo",
+"fire": "mo",
+"bomb": "poomoyo",
+"steam": "lamape_mae",
+"ice": "opemae",
+"rime": "opesa",
+"snow": "opemaemapa",
+"slush": "opemae-e_mae",
+"packed_snow": "yecaece_mae",
+"wood": "mi-oosa",
+"smoke": "lamape_omayi-i",
+"magma": "momae",
+"plasma": "mose_mo-oo",
+"cold_fire": "opese_mo",
+"glass": "samomayi-i",
+"molten_glass": "samomayi-i_momae",
+"molten_rad_glass": "po-e_samomayi-i_momae",
+"rad_glass": "po-e_samomayi-i",
+"meat": "paemaca",
+"rotten_meat": "paemaca-o",
+"cooked_meat": "moe-e_paemaca",
+"frozen_meat": "opese_paemaca",
+"salt": "oopaema-mayi-i",
+"molten_salt": "oopaema-mayi-i_momae",
+"sugar": "paema-ae-mayi-i",
+"flour": "oye_miha",
+"wire": "pupayae",
+"battery": "payae",
+"cloner": "ya-a-a-u",
+"sensor": "yasa",
+"heater": "yamosu",
+"cooler": "ya-opaso",
+"random": "ae-o-e",
+"image": "samolami",
+"unpaint": "osamoce",
+"uncharge": "opa",
+"unburn": "omo",
+"smash": "oyi",
+"filler": "oo-u",
+"lattice": "lacooya_oo-u",
+"gravel": "mayi-i",
+"slime": "samoca_mi-u_mae",
+"cement": "mae_mayiya",
+"dust": "mayi-i",
+"void": "o-a-e-a",
+"sun": "moo-oo-o",
+"cell": "isamo-e_macasa",
+"cancer": "isamo-e_macosa",
+"dna": "isamo-e_macasa_i",
+"plague": "oma-ima",
+"worm": "macaimaepa",
+"frozen_worm": "opese_macaimaepa",
+"flea": "paemocamaemura_maco-i",
+"termite": "mi-oosa_paemura_maco-i",
+"ant": "maco-i",
+"fly": "macamape_maco-i",
+"firefly": "samo-e_macamape_maco-i",
+"hive": "maco-i_halayi",
+"bee": "mae-e_paema-ae-mayi-i_macamape_maco-i",
+"stink_bug": "soo_maco-i",
+"dead_bug": "oma_maco-i",
+"human": "ha",
+"body": "hasa",
+"head": "haca",
+"bird": "macamapa",
+"rat": "macimoco-i",
+"frog": "maca-omaepa",
+"frozen_frog": "opese_maca-omaepa",
+"tadpole": "maca-omae-i",
+"fish": "macamae",
+"frozen_fish": "opese_macamae",
+"slug": "omaciyoo_maciyoomaci",
+"snail": "maciyoomaci",
+"burner": "moyae",
+"superheater": "yaemosu-oo",
+"freezer": "yae-opaso-oo",
+"pipe": "mae_yapura",
+"pipe_wall": "mae_yapura_yecaecayae",
+"mixer": "yaru_o-alayu",
+"grinder": "yaru_oyu",
+"ewall": "pa_poo-e_yoo",
+"torch": "yae_mo_a-a-u",
+"spout": "yae_mae_a-a-u",
+"udder": "paemae_a-a-u",
+"bone_marrow": "mocomae-e_omahayi",
+"bone": "omahayi",
+"balloon": "mapa_lacooya-o",
+"antipowder": "o-mayi-i-e",
+"antimolten": "o-mamae",
+"antifire": "o-mo",
+"antifluid": "o-mae-e",
+"antigas": "o-lamapa",
+"vertical": "parusoo",
+"horizontal": "parusae",
+"ash": "omayi-i",
+"molten_ash": "omayi-i_momae",
+"light": "samo",
+"liquid_light": "samo_mae-e",
+"laser": "paruse_samo",
+"ball": "pa_lacooya-o",
+"pointer": "parusu_samo",
+"charcoal": "mayimo",
+"tinder": "mayimo-i",
+"sawdust": "mi-oosa_mayi-i",
+"hail": "opemaemapoo",
+"hydrogen": "lama_a-i",
+"oxygen": "lama_mapa",
+"nitrogen": "lama_ra",
+"helium": "lama_ca",
+"anesthesia": "oca_lamapa",
+"ammonia": "soo_lamapa",
+"liquid_ammonia": "mae-e_soo_lamapa",
+"carbon_dioxide": "hasamapa_lamapa",
+"oil": "mae-e_mayimo",
+"lamp_oil": "samoya_mae-e_mayimo",
+"propane": "lamape_mayimo",
+"methane": "soo_lamape_mayimo",
+"liquid_methane": "mae-e_soo_lamape_mayimo",
+"stained_glass": "samoce_samomayi-i",
+"molten_stained_glass": "samoce_samomayi-i_momae",
+"art": "hala_samolami",
+"rainbow": "samoca_samoo-e_maemapa",
+"static": "ayoo_samoca_mayi",
+"border": "samoo",
+"clay": "yecaecemayi-i",
+"clay_soil": "yecaecemayi-i_mayi-i",
+"brick": "mayiya",
+"ruins": "sami_yoo",
+"porcelain": "opu_mosa_yecaecemayi-i",
+"sapling": "mi-oo-i",
+"pinecone": "mi-oo-emi-oovi",
+"evergreen": "poo-e_misa",
+"cactus": "miyo",
+"kelp": "mimae",
+"seeds": "mi-i",
+"grass_seed": "parusi_mi-i",
+"wheat_seed": "miha_mi-i",
+"straw": "omae-e_miha",
+"paper": "lami",
+"pollen": "mihe_miya",
+"flower_seed": "miya-i",
+"pistil": "miya_misa",
+"petal": "samoce_miya_misa",
+"tree_branch": "mi-oosa",
+"vine": "parusoo_mi",
+"bamboo_plant": "poopu_mi-i",
+"foam": "mae-lacooya-o-oo",
+"bubble": "mae-lacooya-o",
+"acid": "oyu-mae-o",
+"neutral_acid": "o-oyu-mae-o",
+"acid_gas": "lamape_oyu-mae-o",
+"glue": "yecaecuyi",
+"soda": "paema-ae-mayi-i_mape_mae",
+"gray_goo": "hacayi-o-oo",
+"malware": "cuyaeru-o",
+"ecloner": "paya-a-a-u",
+"slow_cloner": "poya-a-a-u",
+"clone_powder": "ya-a-a-u_mayi-i-e",
+"floating_cloner": "macamape_ya-a-a-u",
+"virus": "oma-ima",
+"ice_nine": "poo-o_opemae",
+"strange_matter": "poo-o_oyu",
+"permafrost": "opese_mayi-imae",
+"melted_butter": "o-alaye_paemae_momae",
+"melted_cheese": "maye_paemae_momae",
+"mushroom_spore": "mihe_mi-o",
+"mushroom_stalk": "misa_mi-o",
+"mushroom_gill": "misa_hasamapa_mi-o",
+"mushroom_cap": "lacooyi-ae_misa_mi-o",
+"hyphae": "lacooyi-o_misa_mi-o",
+"mycelium": "mi-o_mayi-i",
+"mulch": "me_mayi-i",
+"ant_wall": "maco-i_maye_mayi-i",
+"lichen": "mayi_mi",
+"antimatter": "o-ayoo-e_a",
+"plastic": "ye-a",
+"molten_plastic": "ye-a_momae",
+"cloth": "miyae",
+"cellulose": "isamo-e_macasa_mae",
+"wax": "moya-i_yemae",
+"melted_wax": "moya-i_yemae_momae",
+"incense": "soo_moya-i",
+"fuse": "mo_miyae-i",
+"dioxin": "lamape_ye-a-o",
+"insulation": "o_mosa",
+"sponge": "omaeyae",
+"bamboo": "poopu_mi",
+"iron": "mayi-ae-oo",
+"copper": "mayipi-ae-oo",
+"gold": "mayipa",
+"steel": "poo_mayi-ae-oo",
+"nickel": "ocehi_mayipi-ae-oo",
+"zinc": "lacooyi_mayi-ae-oo",
+"silver": "samo-e_mayi-ae-oo",
+"tin": "yecaece_samo-e_mayi-ae-oo",
+"lead": "o-ayoo-e_samo-e_mayi-ae-oo",
+"aluminum": "oopaema-mayi-i_mayi-ae-oo",
+"tungsten": "i-oo_mayi-ae-oo",
+"molten_tungsten": "i-oo_mayi-ae-oo_momae",
+"brass": "yecaece_lacooyi_mayipi-ae-oo",
+"bronze": "poo_mayipi-ae-oo",
+"sterling": "lamipu-oo_mayi-ae-oo",
+"gallium": "opese_mae_mayi-ae-oo",
+"molten_gallium": "mae_mayi-ae-oo",
+"gallium_gas": "lamapa_mae_mayi-ae-oo",
+"rose_gold": "samoci_mo-e_mayipa",
+"purple_gold": "samoca_mae-oo-e_mayipa",
+"blue_gold": "samoca_mae-oo-e_mayipa",
+"electrum": "pa_mayipa",
+"pyrite": "ocehi_mayipa",
+"solder": "yecaecu_mayi-ae-oo",
+"molten_copper": "mayipi-ae-oo_momae",
+"molten_gold": "mayipa_momae",
+"molten_silver": "samo-e_mayi-ae-oo_momae",
+"molten_iron": "mayi-ae-oo_momae",
+"molten_nickel": "ocehi_mayipi-ae-oo_momae",
+"molten_tin": "yecaece_samo-e_mayi-ae-oo_momae",
+"molten_lead": "o-ayoo-e_samo-e_mayi-ae-oo_momae",
+"molten_solder": "yecaecu_mayi-ae-oo_momae",
+"juice": "mi-ooyimae",
+"juice_ice": "opese_mi-ooyimae",
+"broth": "paemaca_mae",
+"milk": "paemae",
+"chocolate_milk": "samoca_mayi-i_paema-ae-mayi-i_paemae",
+"fruit_milk": "mi-ooya_paemae",
+"pilk": "caepayehapae",
+"eggnog": "hi_maciyoo_paemae",
+"egg": "hi_maciyoo",
+"yolk": "hi_maciyoo_paema",
+"hard_yolk": "mo-e_hi_maciyoo_paema",
+"nut_milk": "mi-ooyi_paemae",
+"dough": "o_mo-e_mihaya",
+"batter": "o_mo-e_paema-ae-mayi-i_mihaya",
+"homunculus": "yeha",
+"butter": "o-alaye_paemae",
+"cheese": "maye_paemae",
+"rotten_cheese": "maye_paemae-o",
+"chocolate": "samoca_mayi-i_paema-ae-mayi-i",
+"grape": "mi-ooyi",
+"vinegar": "soo-o_ocemae",
+"herb": "misa-i",
+"lettuce": "paemae-e_miha",
+"pickle": "soo-o_ocemae_mi-ooya",
+"tomato": "oo-u_mi-ooya",
+"sauce": "oo-u_mi-ooya_mae",
+"pumpkin": "mi-ooya-oo",
+"pumpkin_seed": "mi-ooya-oo_mi-i",
+"corn": "mayipa_miha",
+"popcorn": "poomo-i_mayipa_miha",
+"corn_seed": "mayipa_miha_mi-i",
+"potato": "lacooyi-o_mi-ooya",
+"baked_potato": "mo-e_lacooyi-o_mi-ooya",
+"mashed_potato": "oye_lacooyi-o_mi-ooya",
+"potato_seed": "lacooyi-o_mi-ooya_mi-i",
+"root": "lacooyi-o_misa",
+"fiber": "miyae-i",
+"yeast": "mihaya_isamo-e_macasa",
+"bread": "mihaya",
+"toast": "mihayamo",
+"gingerbread": "paema-ae-mayi-i_maye_mihaya",
+"crumb": "mihayi",
+"baked_batter": "paema-ae-mayi-i_mihaya",
+"wheat": "miha",
+"candy": "maye_paema-ae-mayi-i",
+"coffee_bean": "pa_mi-ooyi",
+"coffee_ground": "mayi-i_pa_mi-ooyi",
+"nut": "mi-ooyi",
+"nut_meat": "mi-ooyi_paemaca",
+"nut_butter": "mae-e_mi-ooyi",
+"jelly": "mae_paema-ae-mayi-i_mi-ooyi",
+"baking_soda": "oopaema-mayi-i-e_hasamapa_lamapa",
+"yogurt": "paeme_paemae-o",
+"frozen_yogurt": "opese_paeme_paemae-o",
+"ice_cream": "opese_paemae",
+"cream": "paemae-i",
+"beans": "mae_mi-ooyi",
+"dry_ice": "opese_hasamapa_lamapa",
+"nitrogen_ice": "opese_lama_ra",
+"particleboard": "yecaece_mi-oosa",
+"skin": "",
+"hair": "hacasa_miyae-i",
+"alcohol": "ocemae",
+"alcohol_gas": "lamape_ocemae",
+"basalt": "mayamo_mayi",
+"tuff": "omayi-i_mayi",
+"molten_tuff": "omayi-i_mayi_momae",
+"soap": "mae-u-e_mayi",
+"bleach": "mae-e_mae-u-e",
+"chlorine": "lamape_mae-u-e",
+"liquid_chlorine": "mae-e_lamape_mae-u-e",
+"dye": "samocaya",
+"ink": "osamoca_samocaya",
+"mercury": "mae_samo-e_mayi-ae-oo",
+"mercury_gas": "lamape_mae_samo-e_mayi-ae-oo",
+"solid_mercury": "maye_mae_samo-e_mayi-ae-oo",
+"blood": "mocomae",
+"vaccine": "o-oma-ima",
+"antibody": "mocomae_o-oma-ima",
+"infection": "oma_ime",
+"poison": "mae-oma",
+"poison_gas": "lamape_mae-oma",
+"poison_ice": "maye_mae-oma",
+"antidote": "o-oma-ima",
+"tea": "misa_mae",
+"coffee": "mae_pa_mi-ooyi",
+"honey": "mae-e_paema-ae-mayi-i",
+"sap": "mi-oo_mae-e_paema-ae-mayi-i",
+"amber": "maye_mi-oo_mae-e_paema-ae-mayi-",
+"caramel": "paema-ae-mayi_momae",
+"molasses": "",
+"ketchup": "",
+"mayo": "",
+"melted_chocolate": "",
+"liquid_hydrogen": "",
+"liquid_oxygen": "",
+"liquid_nitrogen": "",
+"liquid_helium": "",
+"sodium": "",
+"molten_sodium": "",
+"sodium_gas": "",
+"calcium": "",
+"molten_calcium": "",
+"limestone": "",
+"quicklime": "",
+"slaked_lime": "",
+"thermite": "",
+"molten_thermite": "",
+"slag": "",
+"amalgam": "",
+"molten_aluminum": "",
+"molten_zinc": "",
+"neon": "",
+"liquid_neon": "",
+"smog": "",
+"stench": "",
+"liquid_stench": "",
+"fragrance": "",
+"perfume": "",
+"cyanide": "",
+"cyanide_gas": "",
+"ozone": "",
+"cloud": "",
+"rain_cloud": "",
+"snow_cloud": "",
+"hail_cloud": "",
+"thunder_cloud": "",
+"acid_cloud": "",
+"pyrocumulus": "",
+"fire_cloud": "",
+"color_smoke": "",
+"spray_paint": "",
+"led_r": "",
+"led_g": "",
+"led_b": "",
+"sulfur": "",
+"molten_sulfur": "",
+"sulfur_gas": "",
+"copper_sulfate": "",
+"snake": "",
+"loopy": "",
+"warp": "",
+"radiation": "",
+"rad_steam": "",
+"rad_cloud": "",
+"fallout": "",
+"neutron": "",
+"proton": "",
+"electric": "",
+"uranium": "",
+"molten_uranium": "",
+"diamond": "",
+"gold_coin": "",
+"rust": "",
+"oxidized_copper": "",
+"alga": "",
+"metal_scrap": "",
+"glass_shard": "",
+"rad_shard": "",
+"brick_rubble": "",
+"baked_clay": "",
+"clay_shard": "",
+"porcelain_shard": "",
+"feather": "",
+"confetti": "",
+"glitter": "",
+"bead": "",
+"color_sand": "",
+"borax": "",
+"epsom_salt": "",
+"potassium_salt": "",
+"sodium_acetate": "",
+"lightning": "",
+"bless": "",
+"god_ray": "",
+"heat_ray": "",
+"freeze_ray": "",
+"pop": "",
+"explosion": "",
+"n_explosion": "",
+"supernova": "",
+"cook": "",
+"incinerate": "",
+"room_temp": "",
+"positron": "",
+"tnt": "",
+"c4": "",
+"grenade": "",
+"dynamite": "",
+"gunpowder": "",
+"ember": "",
+"firework": "",
+"fw_ember": "",
+"nuke": "",
+"h_bomb": "",
+"dirty_bomb": "",
+"emp_bomb": "",
+"nitro": "",
+"greek_fire": "",
+"fireball": "",
+"rocket": "",
+"cold_bomb": "",
+"hot_bomb": "",
+"antimatter_bomb": "",
+"party_popper": "",
+"flashbang": "",
+"flash": "",
+"smoke_grenade": "",
+"landmine": "",
+"armageddon": "",
+"tesla_coil": "",
+"light_bulb": "",
+"shocker": "",
+"pressure_plate": "",
+"primordial_soup": "",
+"molten_slag": "",
+"molten_dirt": "",
+"debug": "",
+"prop": "",
+"salt_ice": "",
+"sugar_ice": "",
+"seltzer_ice": "",
+"dirty_ice": "",
+"pool_ice": "",
+"blood_ice": "",
+"antibody_ice": "",
+"infection_ice": "",
+"unknown": "",
+"slime_ice": "",
+"antiice": "",
+"ammonia_ice": "",
+"liquid_propane": "",
+"methane_ice": "",
+"molten_brick": "",
+"acid_ice": "",
+"soda_ice": "",
+"molten_steel": "",
+"molten_brass": "",
+"molten_bronze": "",
+"molten_sterling": "",
+"molten_rose_gold": "",
+"molten_purple_gold": "",
+"molten_blue_gold": "",
+"molten_electrum": "",
+"molten_pyrite": "",
+"broth_ice": "",
+"frozen_vinegar": "",
+"sauce_ice": "",
+"alcohol_ice": "",
+"bleach_ice": "",
+"chlorine_ice": "",
+"frozen_ink": "",
+"tea_ice": "",
+"coffee_ice": "",
+"hydrogen_ice": "",
+"oxygen_ice": "",
+"molten_amalgam": "",
+"neon_ice": "",
+"cyanide_ice": "",
+"molten_copper_sulfate": "",
+"molten_alga": "",
+"molten_metal_scrap": "",
+"molten_borax": "",
+"molten_epsom_salt": "",
+"molten_potassium_salt": "",
+"molten_sodium_acetate": "",
+"frozen_nitro": "",
+"cured_meat": "",
+"nut_oil": "",
+"grease": "",
+"fat": "",
+"potassium": "",
+"molten_potassium": "",
+"magnesium": "",
+"molten_magnesium": "",
+"sandstorm": "",
+"caustic_potash": "",
+"antibomb": "",
+"tornado": "",
+"earthquake": "",
+"tsunami": "",
+"blaster": "",
+"propane_ice": "",
+"molten_caustic_potash": ""
+}
diff --git a/mod-list.html b/mod-list.html
index d820f5ac..4f5b7b1d 100644
--- a/mod-list.html
+++ b/mod-list.html
@@ -157,7 +157,6 @@
| jaydsfunctions.js | Adds extra tools | Jayd |
| insane_random_events.js | Massively buffs random events | Alice |
| invertscroll.js | Inverts the scroll wheel for adjusting brush size | SquareScreamYT |
-| mobile_shift.js | Adds a button for shift on mobile | SquareScreamYT |
| moretools.js | Adds more temperature-modifying tools (±10/tick, ±50/tick, and absolute zero tools) | Sightnado |
| move_tools.js | Adds tools that move pixels | Alice |
| noconfirm.js | Removes all confirmation pop ups | mollthecoder |
@@ -385,9 +384,10 @@
| Broken or Deprecated |
| humans.js | Adds humans. Now part of the base game | R74n |
+| mobile_shift.js | Adds a button for shift on mobile (Now in the base game) | SquareScreamYT |
+| nopixellimit.js | Removes the pixel limit. (now a setting) | Jayd |
| unhide.js | Unhides all elements except molten ones. (This functionality now exists as a vanilla setting) | R74n |
| wheel_fix.js | Attempts to fix the brush scaling too much with the mouse wheel for some people. Deprecated | Nubo318 |
-| nopixellimit.js | Removes the pixel limit. (now a setting) | Jayd |
diff --git a/mods/cursed_shader_by_jayd.js b/mods/cursed_shader_by_jayd.js
new file mode 100644
index 00000000..d020ddf2
--- /dev/null
+++ b/mods/cursed_shader_by_jayd.js
@@ -0,0 +1,82 @@
+function shade(ctx, color, x1, y1, radius=3, opacity) {
+ var offsetCorrection = 0;
+ if (pixelSize === 8){
+ offsetCorrection = 4;
+ }
+ else if (pixelSize === 6){
+ offsetCorrection = 3;
+ }
+ else if (pixelSize === 4){
+ offsetCorrection = 2;
+ }
+ ctx.beginPath();
+ ctx.arc(x1*pixelSize+offsetCorrection, y1*pixelSize+offsetCorrection, radius*pixelSize, 0, 2 * Math.PI, false);
+ ctx.fillStyle = color;
+ ctx.globalAlpha = opacity;
+ ctx.fill();
+}
+
+elements.shader_test = {
+ color: "#FFFFFF",
+ category: "special",
+ renderer: function(pixel,ctx) {
+ shade(ctx, pixel.color, pixel.x, pixel.y, 3, 0.5)
+ }
+}
+elements.fire.renderer = function(pixel,ctx) {
+ shade(ctx, pixel.color, pixel.x, pixel.y, 3, 0.25)
+}
+elements.cold_fire.renderer = function(pixel,ctx) {
+ shade(ctx, pixel.color, pixel.x, pixel.y, 3, 0.25)
+}
+elements.light.renderer = function(pixel,ctx) {
+ shade(ctx, pixel.color, pixel.x, pixel.y, 2, 0.75)
+}
+elements.laser.renderer = function(pixel,ctx) {
+ shade(ctx, pixel.color, pixel.x, pixel.y, 2, 0.75)
+}
+elements.plasma.renderer = function(pixel,ctx) {
+ shade(ctx, pixel.color, pixel.x, pixel.y, 3, 0.5)
+}
+elements.electric.renderer = function(pixel,ctx) {
+ shade(ctx, pixel.color, pixel.x, pixel.y, 2, 0.25)
+}
+elements.heat_ray.renderer = function(pixel,ctx) {
+ shade(ctx, pixel.color, pixel.x, pixel.y, 3, 0.25)
+}
+elements.freeze_ray.renderer = function(pixel,ctx) {
+ shade(ctx, pixel.color, pixel.x, pixel.y, 3, 0.25)
+}
+elements.flash.renderer = function(pixel,ctx) {
+ shade(ctx, pixel.color, pixel.x, pixel.y, 3, 0.7)
+}
+elements.smoke.renderer = function(pixel,ctx) {
+ shade(ctx, pixel.color, pixel.x, pixel.y, 2, 0.25)
+}
+elements.radiation.renderer = function(pixel,ctx) {
+ shade(ctx, pixel.color, pixel.x, pixel.y, 2, 0.25)
+}
+elements.led_r.renderer = function(pixel,ctx) {
+ if (pixel.charge) {
+ shade(ctx, pixel.color, pixel.x, pixel.y, 3, 0.5)
+ }
+ else {
+ shade(ctx, pixel.color, pixel.x, pixel.y, 0, 1)
+ }
+}
+elements.led_g.renderer = function(pixel,ctx) {
+ if (pixel.charge) {
+ shade(ctx, pixel.color, pixel.x, pixel.y, 3, 0.5)
+ }
+ else {
+ shade(ctx, pixel.color, pixel.x, pixel.y, 0, 1)
+ }
+}
+elements.led_b.renderer = function(pixel,ctx) {
+ if (pixel.charge) {
+ shade(ctx, pixel.color, pixel.x, pixel.y, 3, 0.5)
+ }
+ else {
+ shade(ctx, pixel.color, pixel.x, pixel.y, 0, 1)
+ }
+}
diff --git a/mods/element_UI.js b/mods/element_UI.js
new file mode 100644
index 00000000..9ee61e0a
--- /dev/null
+++ b/mods/element_UI.js
@@ -0,0 +1,140 @@
+// element_UI.js - Redbirdly's Mod that adds an alternative square element UI
+
+// Convert any html-valid color into RGB
+function cssColorToRGB(color) {
+ const div = document.createElement('div');
+ div.style.color = color;
+ document.body.appendChild(div);
+ const computedColor = window.getComputedStyle(div).color;
+ document.body.removeChild(div);
+ const rgbValues = computedColor.match(/\d+/g).map(Number);
+ return rgbValues;
+}
+
+function getColorBrightness(color) {
+ const [r, g, b] = cssColorToRGB(color);
+ return (r * 299 + g * 587 + b * 114) / 1000;
+}
+
+function createButtons(elements, inputDivId, currentCategory) {
+ const elementControls = document.getElementById('elementControls');
+ const existingContainer = document.getElementById('grid-container');
+ if (existingContainer) {
+ existingContainer.remove();
+ }
+
+ const container = document.createElement('div');
+ container.id = 'grid-container';
+ Object.assign(container.style, {
+ display: 'grid',
+ gap: '5px',
+ maxHeight: '280px',
+ overflowY: 'hidden',
+ overflowX: 'auto',
+ scrollbarColor: 'rgba(255, 255, 255, 0.25) rgba(255, 255, 255, 0.1)',
+ scrollbarWidth: 'thin'
+ });
+
+ const buttonNames = [];
+ let numButtons = 0;
+ let numColumns = 0;
+
+ for (let index in elements) {
+ if (elements.hasOwnProperty(index) && elements[index].category !== "tools" && elements[index].category === currentCategory) {
+ const name = index.replace(/_/g, ' ');
+ numButtons++;
+ let color = 'gray';
+ if (elements[index].color !== undefined) {
+ if (typeof elements[index].color === 'string') {
+ color = elements[index].color;
+ } else if (Array.isArray(elements[index].color)) {
+ color = elements[index].color[0];
+ }
+ }
+ buttonNames.push({ name, color });
+ }
+ }
+
+ numColumns = Math.ceil(numButtons / 3);
+ container.style.gridTemplateColumns = `repeat(${numColumns}, 60px)`;
+ container.style.gridTemplateRows = 'repeat(3, 60px)';
+
+ buttonNames.forEach((buttonInfo, index) => {
+ const button = document.createElement('div');
+ button.className = 'grid-item';
+ button.style.backgroundColor = buttonInfo.color;
+ button.innerText = buttonInfo.name;
+ const brightness = getColorBrightness(buttonInfo.color);
+ button.style.color = brightness > 210 ? 'black' : 'white';
+ Object.assign(button.style, {
+ width: '60px',
+ height: '60px',
+ display: 'flex',
+ justifyContent: 'center',
+ alignItems: 'center',
+ fontSize: '8px',
+ cursor: 'pointer',
+ border: '4px solid transparent',
+ borderRadius: '0px',
+ textAlign: 'center',
+ wordWrap: 'break-word',
+ transition: 'background-color 0.3s, color 0.3s, border 0.3s'
+ });
+
+ button.addEventListener('click', function() {
+ document.querySelectorAll('.grid-item').forEach(btn => {
+ btn.classList.remove('selected');
+ btn.style.border = '4px solid transparent';
+ });
+ button.classList.add('selected');
+ button.style.border = '4px solid white';
+ currentElement = buttonInfo.name.replace(' ', '_');
+ const element = elements[currentElement];
+ if (element && typeof element.onSelect === 'function') {
+ element.onSelect();
+ }
+ });
+
+ container.appendChild(button);
+ });
+
+ const inputDiv = document.createElement('div');
+ inputDiv.id = inputDivId;
+
+ elementControls.insertAdjacentElement('afterend', container);
+ container.insertAdjacentElement('afterend', inputDiv);
+ elementControls.style.display = 'none';
+}
+
+function getCurrentCategory() {
+ const categoryButtons = document.querySelectorAll('[current="true"]');
+ if (categoryButtons.length === 0) {
+ return null;
+ }
+ return categoryButtons[0].id.replace("categoryButton-", "");
+}
+
+function selectCategory(category) {
+ if (!category) { return; }
+ const categoryButton = document.getElementById("categoryButton-"+category);
+ if (!categoryButton) { return; }
+ if (categoryButton.classList.contains("notify")) {
+ categoryButton.classList.remove("notify");
+ }
+ const categoryDiv = document.getElementById("category-"+category);
+ for (let i = 0; i < categoryButton.parentNode.children.length; i++) {
+ const e = categoryDiv.parentNode.children[i];
+ e.style.display = "none";
+ document.getElementById("categoryButton-"+e.getAttribute("category")).setAttribute("current", false);
+ }
+ categoryDiv.style.display = "block";
+ categoryButton.setAttribute("current", true);
+ createButtons(elements, 'input-div', category);
+}
+
+const initialCategory = getCurrentCategory();
+if (initialCategory) {
+ selectCategory(initialCategory);
+}
+
+selectElement("sand");
\ No newline at end of file
diff --git a/mods/garn47.js b/mods/garn47.js
new file mode 100644
index 00000000..0a0b817d
--- /dev/null
+++ b/mods/garn47.js
@@ -0,0 +1,325 @@
+// mod by nekonico :3
+
+behaviors.CAR_DELETE = function(pixel) {
+ if (carDieSound) { createPixel("car_explosion",pixel.x, pixel.y), carDieSound.play(); }
+},
+
+behaviors.CARFEEDPIXEL = function(pixel) {
+ if (!pixel.food) { pixel.food = 1, carDieSound.play(); }
+ else { pixel.food ++, carDieSound.play(); }
+ if (pixel.food > (elements[pixel.element].foodNeed||30)) {
+ // loop through adjacentCoords and check each pixel to lay an egg
+ for (var i = 0; i < adjacentCoords.length; i++) {
+ var x = pixel.x+adjacentCoords[i][0];
+ var y = pixel.y+adjacentCoords[i][1];
+ if (isEmpty(x, y)) {
+ if (elements[pixel.element].egg) {
+ createPixel(elements[pixel.element].egg,x,y)
+ }
+ else {
+ createPixel("egg",x,y)
+ pixelMap[x][y].animal = elements[pixel.element].baby || pixel.element;
+ if (elements[pixel.element].eggColor) {
+ pixelMap[x][y].color = pixelColorPick(pixelMap[x][y],elements[pixel.element].eggColor)
+ }
+ }
+ pixel.food = 0;
+ break;
+ }
+ }
+ }
+},
+
+document.onkeydown = function(ki)/*keyboard_input*/ {
+ //w
+ if (ki.keyCode == 87) {
+ KW = true;
+ //vY ++;
+ }
+ //s
+ if (ki.keyCode == 83) {
+ KS = true;
+ //vY ++;
+ }
+}
+document.onkeyup = function(i2)/*keyboard_input*/ {
+ //w
+ if (i2.keyCode == 87) {
+ garnWalkSound.pause()
+ KW = false
+ //vY = 0;
+ }
+ //s
+ if (i2.keyCode == 83) {
+ garnWalkSound.pause()
+ KS = false
+ //vY = 0;
+ }
+}
+var KA = false;
+var KD = false;
+var KW = false;
+var KS = false;
+var vX = 1;
+var vY = 1;
+elements.garn = {
+ name: "garn47",
+ color: "#52562B",
+ category: "special",
+ properties: {
+ dead: false,
+ dir: 1,
+ panic: 0
+ },
+ onPlace: function(pixel) {
+ if (isEmpty(pixel.x, pixel.y+1)) {
+ createPixel("garn_body", pixel.x, pixel.y+1);
+ pixel.element = "garn_head";
+ }
+ else if (isEmpty(pixel.x, pixel.y-1)) {
+ createPixel("garn_head", pixel.x, pixel.y-1);
+ pixelMap[pixel.x][pixel.y-1].color = pixel.color;
+ pixel.element = "garn_body";
+ pixel.color = pixelColorPick(pixel)
+ }
+ else {
+ deletePixel(pixel.x, pixel.y);
+ }
+ },
+ related: ["garn_body","garn_head"],
+ cooldown: defaultCooldown,
+ forceSaveColor: true,
+},
+
+elements.garn_body = {
+ name: "garn",
+ tick: function(pixel) {
+ if (tryMove(pixel, pixel.x, pixel.y+1)) { // Fall
+ if (!isEmpty(pixel.x, pixel.y-2, true)) { // Drag head down
+ var headpixel = pixelMap[pixel.x][pixel.y-2];
+ if (headpixel.element == "garn_head") {
+ if (isEmpty(pixel.x, pixel.y-1)) {
+ movePixel(pixelMap[pixel.x][pixel.y-2], pixel.x, pixel.y-1);
+ }
+ else {
+ swapPixels(pixelMap[pixel.x][pixel.y-2], pixelMap[pixel.x][pixel.y-1]);
+ }
+ }
+ }
+ }
+ /*if (vX === 3) {
+ vX --;
+ }
+ if (vY === 3) {
+ vY --;
+ }*/
+ if (KS === true && isEmpty(pixel.x-2, pixel.y-1) && isEmpty(pixel.x-2, pixel.y)) {
+ tryMove (pixel,pixel.x-1,pixel.y)
+ garnWalkSound.play();
+ }
+ if (KW === true && isEmpty(pixel.x+2, pixel.y-1) && isEmpty(pixel.x+2, pixel.y)) {
+ tryMove (pixel,pixel.x+1,pixel.y)
+ garnWalkSound.play();
+ }
+ },
+ category: "special",
+ states:"solid",
+ color:"#52562B",
+}
+
+elements.garn_head = {
+ name: "garn",
+ tick: function(pixel) {
+ /*if (vX === 3) {
+ vX --;
+ }
+ if (vY === 3) {
+ vY --;
+ }*/
+ if (KS === true && isEmpty(pixel.x-2, pixel.y+1) && isEmpty(pixel.x-2, pixel.y)) {
+ tryMove (pixel,pixel.x-1,pixel.y)
+ garnWalkSound.play();
+ }
+ if (KW === true && isEmpty(pixel.x+2, pixel.y+1) && isEmpty(pixel.x+2, pixel.y)) {
+ tryMove (pixel,pixel.x+1,pixel.y)
+ garnWalkSound.play();
+ }
+ },
+ category: "special",
+ states:"solid",
+ color:"#52562B",
+}
+
+elements.car = { // totally carnular
+ color: ["#9F8578","#A07D6A"],
+ behavior: [
+ "XX|XX|XX",
+ "XX|FX%0.25 AND CH:car_slide%1|XX",
+ "XX|M1|XX",
+ ],
+ reactions: {
+ "meat": { elem2:null, chance:0.2, func:behaviors.CARFEEDPIXEL },
+ "cooked_meat": { elem2:null, chance:0.2, func:behaviors.CARFEEDPIXEL },
+ "": { elem2:null, chance:0.2, func:behaviors.CARFEEDPIXEL },
+ "meat": { elem2:null, chance:0.2, func:behaviors.CARFEEDPIXEL },
+ "oxygen": { elem2:"carbon_dioxide", chance:0.3 },
+ "uranium": { elem2:null, chance:0.1, func:behaviors.CARFEEDPIXEL },
+ "milk": { elem2:null, chance:0.1, func:behaviors.CARFEEDPIXEL },
+ },
+ onDelete: behaviors.CAR_DELETE,
+ tick: function(pixel) {
+ if (pixel.start === pixelTicks) {return}
+ if (!tryMove(pixel, pixel.x, pixel.y+1)) {
+ if (pixel.fall < 20) {
+ if (Math.random() < 0.5) {
+ if (!tryMove(pixel, pixel.x+1, pixel.y+1)) {
+ tryMove(pixel, pixel.x-1, pixel.y+1);
+ }
+ } else {
+ if (!tryMove(pixel, pixel.x-1, pixel.y+1)) {
+ tryMove(pixel, pixel.x+1, pixel.y+1);
+ }
+ }
+ pixel.fall = 0;
+ }
+ else if (outOfBounds(pixel.x,pixel.y+1) || (!isEmpty(pixel.x,pixel.y+1,true) && elements.egg.ignore.indexOf(pixelMap[pixel.x][pixel.y+1].element) === -1 && elements[pixelMap[pixel.x][pixel.y+1].element].state === "solid")) {
+ pixel.element = "car_explosion"
+ carDieSound.play();
+ }
+ else {pixel.fall = 0}
+ }
+ else {pixel.fall ++}
+ doDefaults(pixel);
+ },
+ ignore: ["paper","sponge","straw","wheat","rat","frog","pollen","clay","snow","mud","wet_sand","tinder","feather","bread","ice_cream","dough"],
+ innerColor: "#9F8578",
+ properties: { "fall":0 },
+ egg: "car",
+ foodNeed: 100,
+ maxSize: 1,
+ cooldown: 10,
+ temp: 20,
+ tempHigh: 1500,
+ stateHigh: "car_explosion",
+ category:"life",
+ burn:15,
+ burnTime:300,
+ state: "solid",
+ density: 1450,
+ conduct: 0.2
+}
+
+elements.car_slide = {
+ name: "car",
+ hidden: true,
+ color: ["#9F8578","#A07D6A"],
+ behavior: [
+ "XX|XX|XX",
+ "XX|FX%0.25 AND CH:car%10|M2 AND BO",
+ "XX|M1|XX",
+ ],
+ reactions: {
+ "meat": { elem2:null, chance:0.2, func:behaviors.CARFEEDPIXEL },
+ "cooked_meat": { elem2:null, chance:0.2, func:behaviors.CARFEEDPIXEL },
+ "oxygen": { elem2:"carbon_dioxide", chance:0.3 },
+ "uranium": { elem2:null, chance:0.1, func:behaviors.CARFEEDPIXEL },
+ "milk": { elem2:null, chance:0.1, func:behaviors.CARFEEDPIXEL },
+ },
+ onDelete: behaviors.CAR_DELETE,
+ tick: function(pixel) {
+ if (pixel.start === pixelTicks) {return}
+ if (!tryMove(pixel, pixel.x, pixel.y+1)) {
+ if (pixel.fall < 20) {
+ if (Math.random() < 0.5) {
+ if (!tryMove(pixel, pixel.x+1, pixel.y+1)) {
+ tryMove(pixel, pixel.x-1, pixel.y+1);
+ }
+ } else {
+ if (!tryMove(pixel, pixel.x-1, pixel.y+1)) {
+ tryMove(pixel, pixel.x+1, pixel.y+1);
+ }
+ }
+ pixel.fall = 0;
+ }
+ else if (outOfBounds(pixel.x,pixel.y+1) || (!isEmpty(pixel.x,pixel.y+1,true) && elements.egg.ignore.indexOf(pixelMap[pixel.x][pixel.y+1].element) === -1 && elements[pixelMap[pixel.x][pixel.y+1].element].state === "solid")) {
+ pixel.element = "car_explosion"
+ carDieSound.play();
+ }
+ else {pixel.fall = 0}
+ }
+ else {pixel.fall ++}
+ doDefaults(pixel);
+ },
+ ignore: ["paper","sponge","straw","wheat","rat","frog","pollen","clay","snow","mud","wet_sand","tinder","feather","bread","ice_cream","dough"],
+ innerColor: "#9F8578",
+ properties: { "fall":0 },
+ egg: "car",
+ foodNeed: 100,
+ maxSize: 1,
+ cooldown: 10,
+ tempHigh: 1500,
+ stateHigh: "car_explosion",
+ category:"life",
+ burn:15,
+ burnTime:300,
+ state: "solid",
+ density: 1450,
+ conduct: 0.2
+}
+
+elements.car_explosion = {
+ name: "explosion",
+ color: ["#9F8578","#A07D6A"],
+ behavior: [
+ "XX|XX|XX",
+ "XX|EX:5>smoke,fire,smoke,fire,fire,car_shard|XX",
+ "XX|XX|XX",
+ ],
+ temp: 300,
+ category: "energy",
+ state: "gas",
+ density: 1000,
+ excludeRandom: true,
+ noMix: true
+},
+elements.car_shard = {
+ name: "glass_shard",
+ color: ["#9F8578","#A07D6A"],
+ behavior: behaviors.POWDER,
+ reactions: {
+ "radiation": { elem1:"rad_shard", chance:0.33 },
+ "rad_steam": { elem1:"rad_shard", elem2:null, chance:0.33 },
+ "fallout": { elem1:"rad_shard", elem2:"radiation", chance:0.1 }
+ },
+ tempHigh: 1500,
+ stateHigh: "molten_glass",
+ category: "powders",
+ state: "solid",
+ density: 2500
+},
+
+carSound = null;
+carDieSound = null;
+carEatSound = null;
+
+elements.car.onSelect = function() {
+ carSound = new Audio("https://static.wikia.nocookie.net/garn47/images/b/b9/Hello-its-me-car-made-with-Voicemod.mp3/revision/latest?cb=20240824212531");
+ carDieSound = new Audio("https://static.wikia.nocookie.net/garn47/images/3/3e/Car-scream-made-with-Voicemod.mp3/revision/latest?cb=20240824214753");
+ carEatSound = new Audio("https://static.wikia.nocookie.net/garn47/images/1/1e/Car-eating-made-with-Voicemod.mp3/revision/latest?cb=20240824220937");
+}
+elements.car.onMouseDown = function() {
+ if (carSound) { carSound.play(); }
+}
+
+garnSound = null;
+garnWalkSound = null;
+
+elements.garn.onSelect = function() {
+ garnSound = new Audio("https://static.wikia.nocookie.net/garn47/images/1/17/Garnular2.mp3/revision/latest?cb=20240614060855");
+ garnWalkSound = new Audio("https://static.wikia.nocookie.net/garn47/images/8/8b/Garn47-Ingame-Walking.mp3/revision/latest?cb=20240606045834");
+}
+elements.garn.onMouseDown = function() {
+ if (garnSound) { garnSound.play(); }
+}
+
+// totally garnular
\ No newline at end of file
diff --git a/mods/littlejohnny.js b/mods/littlejohnny.js
index abdd452e..8a5a0742 100644
--- a/mods/littlejohnny.js
+++ b/mods/littlejohnny.js
@@ -13,9 +13,12 @@ elements.ecofriendly_wood_veneer = {
burnInto: ["ember","charcoal","fire"],
hardness: 0.15,
breakInto: "sawdust",
+ reactions: {
+ "algae": {elem2: "lichen"},
+ }
};
elements.screws_borrowed_from_aunt = {
- color: "#687281",
+ color: ["#687281", "#e4e7ed", "#687281", "#4f5969", "#939ead"],
behavior: behaviors.POWDER,
category: "powders",
state: "solid",
@@ -24,9 +27,27 @@ elements.screws_borrowed_from_aunt = {
breakInto: "metal_scrap",
hardness: 0.8,
conduct: 0.9,
+ density: 3000,
+ reactions: {
+ "water": {elem1: "rust", chance: 0.002},
+ "salt_water": {elem1: "rust", chance: 0.004},
+ "dirty_water": {elem1: "rust", chance: 0.03},
+ "pool_water": {elem1: "rust", chance: 0.03},
+ "sugar_water": {elem1: "rust", chance: 0.003},
+ "seltzer": {elem1: "rust", chance: 0.005},
+ "salt": {elem1: "rust", chance: 0.003},
+ "blood": {elem1: "rust", chance: 0.002},
+ "infection": {elem1: "rust", chance: 0.002},
+ "antibody": {elem1: "rust", chance: 0.002},
+ "coffee": {elem1: "rust", chance: 0.0002},
+ "tea": {elem1: "rust", chance: 0.0002},
+ "broth": {elem1: "rust", chance: 0.0002},
+ "juice": {elem1: "rust", chance: 0.0002},
+ "nut_milk": {elem1: "rust", chance: 0.0002},
+ }
};
elements.galvanized_square_steel = {
- color: "#4a535c",
+ color: "#545e69",
behavior: behaviors.WALL,
category: "solids",
state: "solid",
@@ -46,4 +67,6 @@ elements.molten_galvanized_square_steel = {
stateLow: "galvanized_square_steel",
conduct: 0.5,
hidden: true
-};
\ No newline at end of file
+};
+if (!elements.steel.reactions) elements.molten_zinc.reactions = {};
+elements.steel.reactions.molten_zinc = { elem1: "galvanized_square_steel", elem2: null }
diff --git a/mods/planet.js b/mods/planet.js
new file mode 100644
index 00000000..d51913a6
--- /dev/null
+++ b/mods/planet.js
@@ -0,0 +1,270 @@
+// Define the corrected biomes with heights
+var mercuryLayers = [
+ { layers: ["basalt", "iron"], height: 0.6 },
+ { layers: ["nickel"], height: 0.2 },
+ { layers: ["iron"], height: 0.2 }
+];
+
+var venusLayers = [
+ { layers: ["basalt", "limestone"], height: 0.5 },
+ { layers: ["sand", "ash", "clay"], height: 0.25 },
+ { layers: ["tuff"], height: 0.15 },
+ { layers: ["sulfur", ["basalt", "sand"]], height: 0.1 }
+];
+
+var earthLayers = [
+ { layers: ["rock", "basalt", "tuff", "limestone"], height: 0.55 },
+ { layers: ["clay", "mudstone", "clay_soil"], height: 0.3 },
+ { layers: [["sand", "wet_sand", "clay"], ["grass", "gravel", "dirt"]], height: 0.15 }
+];
+
+var marsLayers = [
+ { layers: ["iron", "nickel"], height: 0.3 },
+ { layers: ["iron", "nickel", "rust"], height: 0.15 },
+ { layers: ["iron", "nickel", "rust", "rust"], height: 0.15 },
+ { layers: ["rust"], height: 0.4 }
+];
+
+function tryCreateStaticPixel(pixelType, x, y) {
+ var staticPixelType = "static_" + pixelType;
+
+ // Check if the static version of the pixel type exists
+ if (!elements[staticPixelType]) {
+ // Create the static version of the pixel type
+ elements[staticPixelType] = Object.assign({}, elements[pixelType], {
+ behavior: behaviors.WALL,
+ tick: undefined
+ });
+ }
+
+ // Create the static pixel
+ tryCreatePixel(staticPixelType, x, y);
+}
+
+function getRandomWeightedElement(weightedList) {
+ // Parse the input string into an array of objects with name and weight properties
+ const elements = weightedList.split(',').map(item => {
+ const [name, weight] = item.split('%');
+ return { name: name.trim(), weight: parseFloat(weight) };
+ });
+
+ // Calculate the total weight
+ const totalWeight = elements.reduce((total, element) => total + element.weight, 0);
+
+ // Generate a random number between 0 and totalWeight
+ const randomWeight = Math.random() * totalWeight;
+
+ // Find the element corresponding to the random weight
+ let cumulativeWeight = 0;
+ for (const element of elements) {
+ cumulativeWeight += element.weight;
+ if (randomWeight < cumulativeWeight) {
+ return element.name;
+ }
+ }
+}
+
+// Function to load a script dynamically
+function loadScript(url) {
+ var script = document.createElement("script");
+ script.type = "text/javascript";
+ script.src = url;
+ document.head.appendChild(script);
+}
+
+function circleSimplexNoise1D(simplex, theta) {
+ return simplex.noise2D(Math.cos(theta * Math.PI / 180), Math.sin(theta * Math.PI / 180));
+}
+
+// Load the simplex-noise library
+loadScript("https://cdnjs.cloudflare.com/ajax/libs/simplex-noise/2.4.0/simplex-noise.min.js");
+
+function getRandomElement(layer) {
+ if (!layer || layer.length === 0) {
+ return null; // Return null or handle the error case
+ }
+ return layer[Math.floor(Math.random() * layer.length)];
+}
+
+function generatePlanet(config, x, y, radius) {
+ var simplex = new SimplexNoise();
+
+ var centerX = x;
+ var centerY = y;
+ var planetRadius = radius;
+ var cloudStartRadius = planetRadius + 7;
+ var cloudEndRadius = planetRadius + 14;
+
+ // Generate terrain
+ for (var r = 0; r <= planetRadius; r++) {
+ var step = 0.5;
+ if (r <= 50) { step = 1; }
+ if (r <= 20) { step = 2; }
+ for (var theta = 0; theta <= 360; theta += step) {
+ var x = Math.round(centerX + r * Math.cos(theta * Math.PI / 180));
+ var y = Math.round(centerY + r * Math.sin(theta * Math.PI / 180));
+
+ if (x >= 0 && x < width && y >= 0 && y < height) {
+ var distance = Math.sqrt(Math.pow(x - centerX, 2) + Math.pow(y - centerY, 2));
+ var noise = (-Math.abs(circleSimplexNoise1D(simplex, theta * 0.7)) * 0.5) + (-Math.abs(circleSimplexNoise1D(simplex, theta * 2.5)) * 0.3);
+ var noisyDistance = distance - (noise * planetRadius * 0.3);
+
+ if (noisyDistance <= planetRadius) {
+ // Determine the layer based on distance from center
+ var totalHeight = 0;
+ for (var i = 0; i < config.biomes.length; i++) {
+ totalHeight += config.biomes[i].height;
+ }
+
+ var cumulativeHeight = 0;
+ var chosenLayer = null;
+
+ for (var i = 0; i < config.biomes.length; i++) {
+ var biome = config.biomes[i];
+ var layerHeight = (biome.height / totalHeight) * planetRadius;
+
+ if (noisyDistance >= cumulativeHeight && noisyDistance < cumulativeHeight + layerHeight) {
+ chosenLayer = biome.layers;
+
+ // If chosenLayer is a list of lists, pick a sublayer based on noise
+ if (Array.isArray(chosenLayer) && Array.isArray(chosenLayer[0])) {
+ var sublayerNoise = (circleSimplexNoise1D(simplex, theta) + 1) / 2;
+ var sublayerIndex = Math.floor(sublayerNoise * chosenLayer.length);
+ if (sublayerIndex < 0) {
+ sublayerIndex = 0;
+ } else if (sublayerIndex >= chosenLayer.length) {
+ sublayerIndex = chosenLayer.length - 1;
+ }
+ chosenLayer = chosenLayer[sublayerIndex];
+ }
+ break;
+ }
+
+ cumulativeHeight += layerHeight;
+ }
+
+ var element = getRandomElement(chosenLayer);
+ if (element) {
+ tryCreateStaticPixel(element, x, y);
+ }
+ }
+ }
+ }
+ }
+
+ if (config.oceanElements) {
+ for (var i = centerX - planetRadius; i <= centerX + planetRadius; i++) {
+ for (var j = centerY - planetRadius; j <= centerY + planetRadius; j++) {
+ if (i >= 0 && i < width && j >= 0 && j < height) {
+ var distanceFromCenter = Math.sqrt(Math.pow(i - centerX, 2) + Math.pow(j - centerY, 2));
+ if (distanceFromCenter > planetRadius - 40 && distanceFromCenter <= planetRadius - 4) {
+ // Place ocean in the ring around the planet
+ tryCreateStaticPixel(getRandomWeightedElement(config.oceanElements), i, j);
+ }
+ }
+ }
+ }
+ }
+
+ if (config.cloudElements) {
+ for (var r = cloudStartRadius; r <= cloudEndRadius; r++) {
+ var step = 1;
+ for (var theta = 0; theta <= 360; theta += step) {
+ var x = Math.round(centerX + r * Math.cos(theta * Math.PI / 180));
+ var y = Math.round(centerY + r * Math.sin(theta * Math.PI / 180));
+
+ if (x >= 0 && x < width && y >= 0 && y < height) {
+ var distance = Math.sqrt(Math.pow(x - centerX, 2) + Math.pow(y - centerY, 2));
+ var cloudNoise = simplex.noise2D(x * 0.05, y * 0.05) + simplex.noise2D(x * 0.17, y * 0.17);
+
+ // Adjust cloud density based on distance from planet
+ var minCloudThreshold = 0.5 + config.cloudDensityBias; // Minimum threshold closer to the planet
+ var maxCloudThreshold = 0.8 + config.cloudDensityBias; // Maximum threshold further from the planet
+
+ // Interpolate threshold based on distance from planet
+ var t = (r - cloudStartRadius) / (cloudEndRadius - cloudStartRadius);
+ var threshold = minCloudThreshold + t * (maxCloudThreshold - minCloudThreshold);
+
+ if (cloudNoise > threshold) {
+ tryCreateStaticPixel(getRandomWeightedElement(config.cloudElements), x, y);
+ }
+ }
+ }
+ }
+ }
+}
+
+
+var mercuryConfig = {
+ biomes: mercuryLayers,
+ cloudElements: "",
+ cloudDensityBias: 0.0
+};
+
+var venusConfig = {
+ biomes: venusLayers,
+ cloudElements: "ammonia%70,acid_cloud%30",
+ cloudDensityBias: 0.2
+};
+
+var earthConfig = {
+ biomes: earthLayers,
+ oceanElements: "salt_water%80,water%20",
+ cloudElements: "cloud%100",
+ cloudDensityBias: 0.0
+};
+
+var marsConfig = {
+ biomes: marsLayers,
+ cloudElements: "",
+ cloudDensityBias: 0.0
+};
+
+
+elements.planetMercury = {
+ behavior: behaviors.WALL,
+ category: "special",
+ maxSize: 1,
+ tick: function(pixel) {
+ if (pixel.start === pixelTicks) {
+ deletePixel(pixel.x, pixel.y);
+ generatePlanet(mercuryConfig, pixel.x, pixel.y, 13);
+ }
+ }
+};
+
+elements.planetVenus = {
+ behavior: behaviors.WALL,
+ category: "special",
+ maxSize: 1,
+ tick: function(pixel) {
+ if (pixel.start === pixelTicks) {
+ deletePixel(pixel.x, pixel.y);
+ generatePlanet(venusConfig, pixel.x, pixel.y, 30);
+ }
+ }
+};
+
+elements.planetEarth = {
+ behavior: behaviors.WALL,
+ category: "special",
+ maxSize: 1,
+ tick: function(pixel) {
+ if (pixel.start === pixelTicks) {
+ deletePixel(pixel.x, pixel.y);
+ generatePlanet(earthConfig, pixel.x, pixel.y, 33);
+ }
+ }
+};
+
+elements.planetMars = {
+ behavior: behaviors.WALL,
+ category: "special",
+ maxSize: 1,
+ tick: function(pixel) {
+ if (pixel.start === pixelTicks) {
+ deletePixel(pixel.x, pixel.y);
+ generatePlanet(marsConfig, pixel.x, pixel.y, 20);
+ }
+ }
+};
diff --git a/mods/texture_pack_by_jayd.js b/mods/texture_pack_by_jayd.js
index 7c3ced5f..9f8ee49e 100644
--- a/mods/texture_pack_by_jayd.js
+++ b/mods/texture_pack_by_jayd.js
@@ -1,8 +1,25 @@
//texture_pack_by_jayd
document.body.style.backgroundImage = 'url("https://jayd-rubies.github.io/1236951076024877107.png")';
-gameDiv.style.border = "0px solid #ffffff";
+gameDiv.style.border = "1px solid #ffffff00";
+window.addEventListener("load",function(){
+ document.querySelectorAll(".categoryButton").forEach(e => {
+ e.style.backgroundColor = "transparent";
+ })
+});
+
+var offsetCorrection = 0;
+ if (pixelSize === 8){
+ offsetCorrection = 4;
+ }
+ else if (pixelSize === 6){
+ offsetCorrection = 3;
+ }
+ else if (pixelSize === 4){
+ offsetCorrection = 2;
+ }
+
function drawCursor() {
- canvas.style.backgroundColor = "#00000000";
+ canvas.style.backgroundColor = "transparent";
var layerCtx = canvasLayers.gui.getContext('2d');
var mouseOffset = Math.trunc(mouseSize/2);
var topLeft = [mousePos.x-mouseOffset,mousePos.y-mouseOffset];
@@ -10,6 +27,10 @@ function drawCursor() {
// Draw a square around the mouse
layerCtx.strokeStyle = "#FFFFFF80";
layerCtx.strokeRect(topLeft[0]*pixelSize,topLeft[1]*pixelSize,(bottomRight[0]-topLeft[0]+1)*pixelSize,(bottomRight[1]-topLeft[1]+1)*pixelSize);
+ layerCtx.beginPath();
+ layerCtx.arc(mousePos.x*pixelSize+offsetCorrection, mousePos.y*pixelSize+offsetCorrection, mouseSize*pixelSize/2, 0, 2 * Math.PI, false);
+ layerCtx.lineWidth = 1;
+ layerCtx.stroke();
// draw one transparent pixel in the center
if (settings.precision) {
layerCtx.fillStyle = "#ffffffc8";
@@ -19,11 +40,77 @@ function drawCursor() {
if (shaping === 1) { // Draw a white line from shapeStart.x to shapeStart.y
layerCtx.beginPath();
layerCtx.strokeStyle = "#FFFFFF80";
- layerCtx.lineWidth = 2;
+ layerCtx.lineWidth = 1;
layerCtx.moveTo(shapeStart.x*pixelSize+pixelSizeHalf, shapeStart.y*pixelSize+pixelSizeHalf);
layerCtx.lineTo(mousePos.x*pixelSize+pixelSizeHalf, mousePos.y*pixelSize+pixelSizeHalf);
- layerCtx.stroke();
- layerCtx.lineWidth = 1;
}
}
+}
+function pixelColorPick(pixel,customColor=null) {
+ var element = pixel.element;
+ var elementInfo = elements[element];
+ //if (elementInfo.behavior instanceof Array) {
+
+ if (pixel.charge && elementInfo.colorOn) {
+ customColor = elementInfo.colorOn;
+ }
+ if (customColor != null) {
+ if (Array.isArray(customColor)) {
+ customColor = customColor[Math.floor(Math.random() * customColor.length)];
+ }
+ if (customColor.startsWith("#")) {
+ customColor = hexToRGB(customColor);
+ }
+ var rgb = customColor;
+ }
+ else {
+ var rgb = elements[element].colorObject; // {r, g, b}
+ // If rgb is an array, choose a random item
+ if (Array.isArray(rgb)) {
+ rgb = rgb[Math.floor(Math.random() * rgb.length)];
+ }
+ }
+ // Randomly darken or lighten the RGB color
+ var coloroffset = Math.floor(Math.random() * (Math.random() > 0.5 ? -1 : 1) * Math.random() * 5);
+ var r = rgb.r + coloroffset;
+ var g = rgb.g + coloroffset;
+ var b = rgb.b + coloroffset;
+ // Make sure the color is within the RGB range
+ r = Math.max(0, Math.min(255, r));
+ g = Math.max(0, Math.min(255, g));
+ b = Math.max(0, Math.min(255, b));
+ var color = "rgb("+r+","+g+","+b+")";
+
+ /*}
+ else {
+ var color = elementInfo.color;
+ if (Array.isArray(color)) {
+ color = color[Math.floor(Math.random() * color.length)];
+ }
+ }*/
+ return color;
+ }
+
+function renderBall(ctx, color, x1, y1,plus_radius,opacity=1) {
+ ctx.beginPath();
+ ctx.globalAlpha = opacity;
+ ctx.arc(x1*pixelSize+offsetCorrection, y1*pixelSize+offsetCorrection, pixelSize-offsetCorrection+plus_radius, 0, 2 * Math.PI, false);
+ ctx.fillStyle = color;
+ ctx.fill();
+}
+function renderGas(ctx, color, x1, y1,radius,opacity=1) {
+ ctx.beginPath();
+ ctx.globalAlpha = opacity;
+ ctx.arc(x1*pixelSize+offsetCorrection, y1*pixelSize+offsetCorrection, pixelSize*radius, 0, 2 * Math.PI, false);
+ ctx.fillStyle = color;
+ ctx.fill();
+}
+viewInfo[4] = { // Small Pixels
+ name: "Ball",
+ pixel: function(pixel,ctx) {
+ if ((elements[pixel.element].isGas && elements[pixel.element].glow !== false) || elements[pixel.element].glow || pixel.glow) {
+ renderGas(ctx,pixel.color,pixel.x,pixel.y,3,0.5);
+ }
+ else{renderBall(ctx,pixel.color,pixel.x,pixel.y,0,1);}
+ }
}
\ No newline at end of file