Merge branch 'R74nCom:main' into main
This commit is contained in:
commit
2730c17d78
|
|
@ -1,10 +1,3 @@
|
|||
Contributions to the main index.html file will be ignored. Use this repository to officially publish your Sandboxels mods.
|
||||
This repository is no longer accepting contributions or mod submissions.
|
||||
|
||||
Rules for publishing mods:
|
||||
1. Must not focus on something NSFW or illegal.
|
||||
2. Must be tested beforehand on your own. This repo does not accept mods for the sole purpose of you testing them.
|
||||
3. Must contain some meaningful content.
|
||||
|
||||
Failure to follow these rules may result in your pull request being ignored!
|
||||
|
||||
Learn more about [submitting your mod](https://sandboxels.wiki.gg/wiki/Modding/Putting_it_online).
|
||||
**For future mod submissions, please go to the new repository at [R74nCom/Sandboxels-Mods](https://github.com/R74nCom/Sandboxels-Mods).**
|
||||
|
|
|
|||
|
|
@ -8,9 +8,7 @@ Join the [Discord server](https://discord.com/invite/ejUc6YPQuS).
|
|||

|
||||
|
||||
# Modding
|
||||
New to modding? Read the Sandboxels Wiki articles on [getting started with modding](https://sandboxels.wiki.gg/wiki/Modding/Getting_started) or [publishing your mod](https://sandboxels.wiki.gg/wiki/Modding/Putting_it_online).
|
||||
|
||||
Please read the [Contribution Guidelines](https://github.com/R74nCom/sandboxels/tree/main/.github/CONTRIBUTING.md) before submitting your mod.
|
||||
**Mods are no longer accepted in this repository.** Please go to the new one at [R74nCom/Sandboxels-Mods](https://github.com/R74nCom/Sandboxels-Mods/).
|
||||
|
||||
# Controls
|
||||
* Left Click = Draw pixels
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
async function _kBBprompt(message, defaultValue = "") {
|
||||
return new Promise(resolve => {
|
||||
promptInput(message, (result) => {
|
||||
resolve(result);
|
||||
}, "keyBindButton.js is asking you...", defaultValue);
|
||||
|
||||
})
|
||||
}
|
||||
async function _jaydalert(message) {
|
||||
promptText(message, undefined, "Jayd:");
|
||||
}
|
||||
runAfterLoad(async () => {
|
||||
window.setTimeout(async () => {
|
||||
_jaydalert("Warning! keyBindButton.js is in beta, expect bugs.")
|
||||
},)
|
||||
})
|
||||
|
||||
elements.keyBindButton = {
|
||||
color: "#bebfa3",
|
||||
onPlace: async (pixel) => {
|
||||
pixel.thisKeyIsBinded = await _kBBprompt("Select a key to bind.",(pixel.thisKeyIsBinded||undefined))
|
||||
},
|
||||
tick: (pixel) => {
|
||||
document.onkeydown = function(kb)/*keybind*/ {
|
||||
if (kb.key.toLowerCase() == pixel.thisKeyIsBinded.toLowerCase()) {
|
||||
pixel.charge = 1;
|
||||
}
|
||||
},
|
||||
document.onkeyup = function(kb)/*keybind*/ {
|
||||
if (kb.key.toLowerCase() == pixel.thisKeyIsBinded.toLowerCase()) {
|
||||
}
|
||||
}
|
||||
doDefaults(pixel);
|
||||
},
|
||||
perTick: () => {
|
||||
mouseSize = 1;
|
||||
},
|
||||
ignore: ["flash"],
|
||||
conduct: 1,
|
||||
movable: false,
|
||||
category:"machines",
|
||||
darkText: true,
|
||||
maxSize: 1
|
||||
}
|
||||
|
|
@ -304,6 +304,7 @@
|
|||
<tr><td>subspace.js</td><td>The Subspace Tripmine from Roblox</td><td>nousernamefound</td></tr>
|
||||
<tr><td>war_crimes.js</td><td>Tear gas and more</td><td>voidapex11</td></tr>
|
||||
<tr><td>weapons.js</td><td>Variety of different weapons</td><td>Jayd</td></tr>
|
||||
<tr><td>weaponsRewrite.js</td><td>BETA! weapons.js is getting an overhaul, more details soon.(hopefully)</td><td>Jayd</td></tr>
|
||||
|
||||
<!----><tr><td class="modCat" colspan="3">Food & Cooking</td></tr><!---->
|
||||
<tr><td>aChefsDream_beta.js</td><td>Beta testing for aChefsDream.js</td><td>SquareScreamYT</td></tr>
|
||||
|
|
@ -376,6 +377,7 @@
|
|||
<tr><td>allliquids.js</td><td>Made all elements liquids</td><td>Orchid</td></tr>
|
||||
<tr><td>amogus.js</td><td>Small Among Us structure</td><td>Alice</td></tr>
|
||||
<tr><td>bfdi.js</td><td>Several references to Battle for Dream Island</td><td>Taterbob</td></tr>
|
||||
<tr><td>chess.js</td><td>Play chess in Sandboxels [Press U to start game]</td><td>ggod</td></tr>
|
||||
<tr><td>citybuilding.js</td><td>Seeds that create miniature buildings and other city-related items</td><td>SquareScreamYT</td></tr>
|
||||
<tr><td>collab_mod.js</td><td>Created by multiple people, adds random things</td><td>mrapple, ilikepizza, stefanblox</td></tr>
|
||||
<tr><td>cubesstuff.js</td><td>Some random stuff like Disco Ball, Pyrite, and Nordic Gold</td><td>Cube14yt</td></tr>
|
||||
|
|
@ -450,7 +452,6 @@
|
|||
<tr><td>all_stain.js</td><td>Every element stains solids</td><td>stefanblox</td></tr>
|
||||
<tr><td>betterMenuScreens.js</td><td>Library for mods to create their own menus</td><td>ggod</td></tr>
|
||||
<tr><td>changePixelDebug.js</td><td>The changePixel() function aborts and logs to console when it tries to change to a non-existent element</td><td>Alice</td></tr>
|
||||
<tr><td>changeTempReactionParameter.js</td><td>The changeTemp property to modded reactions</td><td>Alice</td></tr>
|
||||
<tr><td>code_library.js</td><td>Functions and variables common to some other mods</td><td>Alice</td></tr>
|
||||
<tr><td>controllable_pixel_test.js</td><td>Pixel that can be controlled with the keyboard keys <a href="https://github.com/R74nCom/sandboxels/commit/58dfa9477f2ed7ec9c44b00a35162e7c63bc129c">[More Info]</a> [PC ONLY]</td><td>Alice</td></tr>
|
||||
<tr><td>customexplosion.js</td><td>Custom explosion element and interface for it</td><td>Orchid</td></tr>
|
||||
|
|
@ -488,6 +489,7 @@
|
|||
<tr class="deprecated"><td>advanced_colonies.js</td><td>Davlers, creatures with complex colonies</td><td>DaviStudios</td></tr>
|
||||
<tr class="deprecated"><td>background_changer.js</td><td>Press 'B' to change canvas background to a URL</td><td><a href="https://R74n.com" class="R74nLink">R74n</a></td></tr>
|
||||
<tr class="deprecated"><td>borders.js</td><td>Black borders around pixels (Use bright background)</td><td><a href="https://R74n.com" class="R74nLink">R74n</a></td></tr>
|
||||
<tr class="deprecated"><td>changeTempReactionParameter.js</td><td>The changeTemp property to modded reactions</td><td>Alice</td></tr>
|
||||
<tr class="deprecated"><td>fast_lightmap.js</td><td>Light sources glow, but faster</td><td>RedBirdly</td></tr>
|
||||
<tr class="deprecated"><td>haseulite.js</td><td>Loona-related materials with various properties</td><td>Alice</td></tr>
|
||||
<tr class="deprecated"><td>humans.js</td><td>Humans. Now part of the base game</td><td><a href="https://R74n.com" class="R74nLink">R74n</a></td></tr>
|
||||
|
|
|
|||
|
|
@ -520,7 +520,7 @@ elements.RandomGen = {
|
|||
elements.view_seed = {
|
||||
category: "edit",
|
||||
onSelect: function(){
|
||||
alert(seed);
|
||||
selectElement("dirt");
|
||||
promptText(seed, undefined, "Seed");
|
||||
selectElement(prevElement);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,125 @@
|
|||
if (typeof elements === "undefined") {
|
||||
var elements = {};
|
||||
}
|
||||
if (typeof behaviors === "undefined") {
|
||||
var behaviors = {};
|
||||
}
|
||||
if (typeof pixelMap === "undefined") {
|
||||
var pixelMap = [];
|
||||
}
|
||||
if (typeof adjacentCoords === "undefined") {
|
||||
var adjacentCoords = [
|
||||
{ x: 1, y: 0 },
|
||||
{ x: -1, y: 0 },
|
||||
{ x: 0, y: 1 },
|
||||
{ x: 0, y: -1 },
|
||||
{ x: 1, y: 1 },
|
||||
{ x: 1, y: -1 },
|
||||
{ x: -1, y: 1 },
|
||||
{ x: -1, y: -1 },
|
||||
];
|
||||
}
|
||||
if (typeof changePixel === "undefined") {
|
||||
var changePixel = function (pixel, elemName) {
|
||||
pixel.element = elemName;
|
||||
};
|
||||
}
|
||||
|
||||
elements.sulfuric_acid = {
|
||||
name: "Sulfuric Acid",
|
||||
color: ["#c8e0ff", "#d4e8ff", "#b8d4ff"],
|
||||
behavior: behaviors.LIQUID,
|
||||
category: "liquids",
|
||||
state: "liquid",
|
||||
density: 1840,
|
||||
tempHigh: 337,
|
||||
stateHigh: "sulfuric_acid_gas",
|
||||
tempLow: 10,
|
||||
stateLow: "frozen_sulfuric_acid",
|
||||
conduct: 1,
|
||||
stain: 0.4,
|
||||
viscosity: 0.02,
|
||||
desc: "A highly corrosive, dense mineral acid. Reacts violently with water and metals.",
|
||||
reactions: {
|
||||
water: { elem1: "steam", elem2: "sulfuric_acid", chance: 0.6, temp1: 80 },
|
||||
ice: { elem1: "water", elem2: "sulfuric_acid", chance: 0.7, temp1: 40 },
|
||||
iron: { elem1: "hydrogen", elem2: "rust", chance: 0.4 },
|
||||
steel: { elem1: "hydrogen", elem2: "corroded_steel", chance: 0.4 },
|
||||
aluminum: { elem1: "hydrogen", elem2: "corroded_aluminum", chance: 0.4 },
|
||||
wood: { elem1: "carbon", elem2: "sulfuric_acid", chance: 0.5 },
|
||||
plant: { elem1: "carbon", elem2: "sulfuric_acid", chance: 0.5 },
|
||||
flesh: { elem1: "carbon", elem2: "sulfuric_acid", chance: 0.5 },
|
||||
},
|
||||
tick: function (pixel) {
|
||||
if (Math.random() < 0.05) {
|
||||
var coord =
|
||||
adjacentCoords[Math.floor(Math.random() * adjacentCoords.length)];
|
||||
var x = pixel.x + coord.x;
|
||||
var y = pixel.y + coord.y;
|
||||
if (pixelMap[x] && pixelMap[x][y]) {
|
||||
var other = pixelMap[x][y];
|
||||
var elemDef = elements[other.element];
|
||||
if (!elemDef) {
|
||||
return;
|
||||
}
|
||||
if (elemDef.state === "solid" && !elemDef.acid_resistant) {
|
||||
if (Math.random() < 0.1) {
|
||||
changePixel(other, "corroded_matter");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
elements.sulfuric_acid_gas = {
|
||||
name: "Sulfuric Acid Gas",
|
||||
color: ["#e0f0ff", "#d0e4ff"],
|
||||
behavior: behaviors.GAS,
|
||||
category: "gases",
|
||||
state: "gas",
|
||||
density: 2,
|
||||
desc: "Vaporized sulfuric acid.",
|
||||
};
|
||||
|
||||
elements.frozen_sulfuric_acid = {
|
||||
name: "Frozen Sulfuric Acid",
|
||||
color: ["#9fb8e0", "#8fa8d0"],
|
||||
behavior: behaviors.WALL,
|
||||
category: "solids",
|
||||
state: "solid",
|
||||
density: 1900,
|
||||
tempHigh: 10,
|
||||
stateHigh: "sulfuric_acid",
|
||||
desc: "Solidified sulfuric acid.",
|
||||
};
|
||||
|
||||
elements.corroded_matter = {
|
||||
name: "Corroded Matter",
|
||||
color: ["#3a3a3a", "#2e2e2e", "#444444"],
|
||||
behavior: behaviors.POWDER,
|
||||
category: "powders",
|
||||
state: "solid",
|
||||
density: 1500,
|
||||
desc: "Generic material heavily corroded by acid.",
|
||||
};
|
||||
|
||||
elements.corroded_steel = {
|
||||
name: "Corroded Steel",
|
||||
color: ["#4b4b4b", "#555555", "#3f3f3f"],
|
||||
behavior: behaviors.POWDER,
|
||||
category: "powders",
|
||||
state: "solid",
|
||||
density: 7700,
|
||||
desc: "Steel degraded by sulfuric acid.",
|
||||
};
|
||||
|
||||
elements.corroded_aluminum = {
|
||||
name: "Corroded Aluminum",
|
||||
color: ["#6f6f6f", "#7a7a7a", "#656565"],
|
||||
behavior: behaviors.POWDER,
|
||||
category: "powders",
|
||||
state: "solid",
|
||||
density: 2600,
|
||||
desc: "Aluminum degraded by sulfuric acid.",
|
||||
};
|
||||
|
|
@ -44986,7 +44986,6 @@ maxPixels (default 1000): Maximum amount of pixels/changes (if xSpacing and ySpa
|
|||
function editDistance(s1, s2) {s1 = s1.toLowerCase();s2 = s2.toLowerCase();var costs = new Array();for (var i = 0; i <= s1.length; i++) {var lastValue = i;for (var j = 0; j <= s2.length; j++) {if (i == 0)costs[j] = j;else {if (j > 0) {var newValue = costs[j - 1];if (s1.charAt(i - 1) != s2.charAt(j - 1))newValue = Math.min(Math.min(newValue, lastValue),costs[j]) + 1;costs[j - 1] = lastValue;lastValue = newValue;}}}if (i > 0)costs[s2.length] = lastValue;}return costs[s2.length];}
|
||||
function similarity(s1, s2) {var longer = s1;var shorter = s2;if (s1.length < s2.length) {longer = s2;shorter = s1;}var longerLength = longer.length;if (longerLength == 0) {return 1.0;}return (longerLength - editDistance(longer, shorter)) / parseFloat(longerLength);}
|
||||
function mostSimilarElement(s) {
|
||||
delete elements;
|
||||
var max = 0;
|
||||
var maxElement = "";
|
||||
for (var e in elements) {
|
||||
|
|
|
|||
288
mods/alchem.js
288
mods/alchem.js
|
|
@ -14,6 +14,17 @@ function findReachable(elems) {
|
|||
}
|
||||
|
||||
|
||||
if(e1 === "oil") {
|
||||
redo = redo || addElement_(elems, "lamp_oil");
|
||||
redo = redo || addElement_(elems, "propane");
|
||||
redo = redo || addElement_(elems, "molten_plastic");
|
||||
}
|
||||
|
||||
if (eLists.SEEDS.includes(e1)) {
|
||||
redo = redo || addElement_(elems, "fiber");
|
||||
}
|
||||
|
||||
|
||||
if(e1 === "thorium" && elems.includes("neutron")) {
|
||||
redo = redo || addElement_(elems, "radium");
|
||||
}
|
||||
|
|
@ -80,6 +91,8 @@ function findReachable(elems) {
|
|||
return elems;
|
||||
}
|
||||
|
||||
worldgentypes = {}
|
||||
|
||||
function addElement_(list, elem) {
|
||||
if(elem instanceof Array)
|
||||
{
|
||||
|
|
@ -102,11 +115,11 @@ let chemMod = document.querySelector("[src=\"mods/chem.js\"]");
|
|||
// unhide oxygen (air), dirt (earth), fire, and water
|
||||
function loadAlchem() {
|
||||
|
||||
if(!elements.hematite) {
|
||||
if (!elements.hematite) {
|
||||
elements.hematite = {
|
||||
color: ["#e0472f","#bf2a2a","#913920"],
|
||||
color: ["#e0472f", "#bf2a2a", "#913920"],
|
||||
behavior: behaviors.POWDER,
|
||||
category: "alchemy mod",
|
||||
category: "land",
|
||||
density: 5250,
|
||||
state: "solid",
|
||||
tempHigh: 1539,
|
||||
|
|
@ -114,7 +127,7 @@ function loadAlchem() {
|
|||
};
|
||||
elements.molten_hematite = {
|
||||
reactions: {
|
||||
"charcoal": { elem1: ["molten_iron","molten_iron","molten_iron","molten_iron","molten_nickel"], elem2: "carbon_dioxide"},
|
||||
"charcoal": { elem1: ["molten_iron", "molten_iron", "molten_iron", "molten_iron", "molten_nickel"], elem2: "carbon_dioxide" },
|
||||
},
|
||||
};
|
||||
elements.molten_slag.ignore.push("hematite");
|
||||
|
|
@ -122,17 +135,17 @@ function loadAlchem() {
|
|||
|
||||
elements.molten_pyrite = {
|
||||
reactions: {
|
||||
"oxygen": { elem1: "iron", elem2: "sulfur_dioxide"},
|
||||
"oxygen": { elem1: "iron", elem2: "sulfur_dioxide" },
|
||||
},
|
||||
};
|
||||
elements.molten_slag.ignore.push("pyrite");
|
||||
|
||||
|
||||
if(!elements.chalcopyrite) {
|
||||
if (!elements.chalcopyrite) {
|
||||
elements.chalcopyrite = {
|
||||
color: ["#e8d7cb","#cdc0af","#726153","#8f775e","#bfaea0",],
|
||||
color: ["#e8d7cb", "#cdc0af", "#726153", "#8f775e", "#bfaea0",],
|
||||
behavior: behaviors.WALL,
|
||||
category: "alchemy mod",
|
||||
category: "land",
|
||||
density: 4200,
|
||||
state: "solid",
|
||||
tempHigh: 950,
|
||||
|
|
@ -140,17 +153,17 @@ function loadAlchem() {
|
|||
};
|
||||
elements.molten_chalcopyrite = {
|
||||
reactions: {
|
||||
"charcoal": { elem1: "molten_copper", elem2: ["molten_slag","molten_slag","sulfur_dioxide","sulfur_dioxide","sulfur_dioxide","molten_iron"]},
|
||||
"charcoal": { elem1: "molten_copper", elem2: ["molten_slag", "molten_slag", "sulfur_dioxide", "sulfur_dioxide", "sulfur_dioxide", "molten_iron"] },
|
||||
},
|
||||
};
|
||||
elements.molten_slag.ignore.push("chalcopyrite");
|
||||
}
|
||||
|
||||
if(!elements.sphalerite) {
|
||||
if (!elements.sphalerite) {
|
||||
elements.sphalerite = {
|
||||
color: ["#7a7a7a","#5c5c5c","#3d3d3d","#363636","#e0e0e0",],
|
||||
color: ["#7a7a7a", "#5c5c5c", "#3d3d3d", "#363636", "#e0e0e0",],
|
||||
behavior: behaviors.WALL,
|
||||
category: "alchemy mod",
|
||||
category: "land",
|
||||
density: 4090,
|
||||
state: "solid",
|
||||
tempHigh: 1850,
|
||||
|
|
@ -158,18 +171,18 @@ function loadAlchem() {
|
|||
};
|
||||
elements.molten_sphalerite = {
|
||||
reactions: {
|
||||
"charcoal": { elem1: "molten_zinc", elem2: ["sulfur_dioxide","sulfur_dioxide","sulfur_dioxide","sulfur_dioxide","sulfur_dioxide","gallium_gas"]},
|
||||
"charcoal": { elem1: "molten_zinc", elem2: ["sulfur_dioxide", "sulfur_dioxide", "sulfur_dioxide", "sulfur_dioxide", "sulfur_dioxide", "gallium_gas"] },
|
||||
},
|
||||
};
|
||||
elements.molten_slag.ignore.push("sphalerite");
|
||||
}
|
||||
|
||||
|
||||
if(!elements.cassiterite) {
|
||||
if (!elements.cassiterite) {
|
||||
elements.cassiterite = {
|
||||
color: ["#5e5b5b","#705a4d","#826f6f","#333030","#e3d8d1"],
|
||||
color: ["#5e5b5b", "#705a4d", "#826f6f", "#333030", "#e3d8d1"],
|
||||
behavior: behaviors.WALL,
|
||||
category: "alchemy mod",
|
||||
category: "land",
|
||||
density: 6950,
|
||||
state: "solid",
|
||||
tempHigh: 1630,
|
||||
|
|
@ -177,17 +190,17 @@ function loadAlchem() {
|
|||
};
|
||||
elements.molten_cassiterite = {
|
||||
reactions: {
|
||||
"charcoal": { elem1: "molten_tin", elem2: "carbon_dioxide"},
|
||||
"charcoal": { elem1: "molten_tin", elem2: "carbon_dioxide" },
|
||||
},
|
||||
};
|
||||
elements.molten_slag.ignore.push("cassiterite");
|
||||
}
|
||||
|
||||
if(!elements.galena) {
|
||||
if (!elements.galena) {
|
||||
elements.galena = {
|
||||
color: ["#e6e6e6","#bdbdbd","#7a7a7a","#737373"],
|
||||
color: ["#e6e6e6", "#bdbdbd", "#7a7a7a", "#737373"],
|
||||
behavior: behaviors.WALL,
|
||||
category: "alchemy mod",
|
||||
category: "land",
|
||||
density: 7600,
|
||||
state: "solid",
|
||||
tempHigh: 1113,
|
||||
|
|
@ -195,24 +208,24 @@ function loadAlchem() {
|
|||
};
|
||||
elements.molten_galena = {
|
||||
reactions: {
|
||||
"charcoal": { elem1: "molten_lead", elem2: "sulfur_dioxide"},
|
||||
"charcoal": { elem1: "molten_lead", elem2: "sulfur_dioxide" },
|
||||
},
|
||||
};
|
||||
elements.molten_slag.ignore.push("galena");
|
||||
}
|
||||
|
||||
let ores = Array(5).fill("molten_hematite")
|
||||
.concat(Array(5).fill("molten_pyrite"))
|
||||
.concat(Array(5).fill("molten_chalcopyrite"))
|
||||
.concat(Array(3).fill("molten_cassiterite"))
|
||||
.concat(Array(5).fill("molten_sphalerite"))
|
||||
.concat(Array(3).fill("molten_galena"))
|
||||
.concat(Array(2).fill("molten_rutile"))
|
||||
.concat(Array(5).fill("molten_bauxite"))
|
||||
.concat(Array(2).fill("molten_silver"))
|
||||
.concat(Array(1).fill("molten_gold"))
|
||||
.concat(Array(3).fill("molten_fluorite"))
|
||||
.concat(Array(3).fill("molten_uraninite"))
|
||||
.concat(Array(5).fill("molten_pyrite"))
|
||||
.concat(Array(5).fill("molten_chalcopyrite"))
|
||||
.concat(Array(3).fill("molten_cassiterite"))
|
||||
.concat(Array(5).fill("molten_sphalerite"))
|
||||
.concat(Array(3).fill("molten_galena"))
|
||||
.concat(Array(2).fill("molten_rutile"))
|
||||
.concat(Array(5).fill("molten_bauxite"))
|
||||
.concat(Array(2).fill("molten_silver"))
|
||||
.concat(Array(1).fill("molten_gold"))
|
||||
.concat(Array(3).fill("molten_fluorite"))
|
||||
.concat(Array(3).fill("molten_uraninite"));
|
||||
|
||||
elements.molten_slag.ignore.push("rutile");
|
||||
elements.molten_slag.ignore.push("bauxite");
|
||||
|
|
@ -220,153 +233,136 @@ function loadAlchem() {
|
|||
elements.molten_slag.ignore.push("gold");
|
||||
|
||||
elements.seltzer.reactions["electric"] =
|
||||
{ elem1: "water", elem2:"methane"};
|
||||
{ elem1: "water", elem2: "methane" };
|
||||
elements.carbon_dioxide.reactions["electric"] =
|
||||
{ elem1:"methane"};
|
||||
{ elem1: "methane" };
|
||||
elements.magma.reactions["magma"] =
|
||||
{ elem2:ores, tempMin:2500, tempMax:3000, chance:0.0001};
|
||||
{ elem2: ores, tempMin: 2500, tempMax: 3000, chance: 0.0001 };
|
||||
|
||||
if (!settings.alchemyUnlocked) {
|
||||
settings.alchemyUnlocked = {
|
||||
"oxygen": true,
|
||||
"dirt": true,
|
||||
"fire": true,
|
||||
"water": true,
|
||||
};
|
||||
}
|
||||
if (settings.unlocked.alchemymod) {
|
||||
for (var element in settings.unlocked) {
|
||||
if (settings.unlocked[element]) {
|
||||
settings.alchemyUnlocked[element] = true
|
||||
}
|
||||
if (!settings.alchemyUnlocked) {
|
||||
settings.alchemyUnlocked = {
|
||||
"oxygen": true,
|
||||
"dirt": true,
|
||||
"fire": true,
|
||||
"water": true,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// loop through the elements object
|
||||
if (elements.explosion) {
|
||||
elements.explosion.category = "tools";
|
||||
}
|
||||
if (elements.room_temp) {
|
||||
elements.room_temp.category = "tools";
|
||||
}
|
||||
if (elements.cook) {
|
||||
elements.cook.category = "tools";
|
||||
}
|
||||
if (elements.incinerate) {
|
||||
elements.incinerate.category = "tools";
|
||||
}
|
||||
for (var element in elements) {
|
||||
if (elements[element].category === "tools") {
|
||||
settings.alchemyUnlocked[element] = true;
|
||||
}
|
||||
if (settings.alchemyUnlocked[element]) {
|
||||
elements[element].hidden = false;
|
||||
if (elements[element].category !== "tools") { elements[element].category = "alchemy mod"; }
|
||||
}
|
||||
else if (elements[element].category !== "tools") {
|
||||
// give the element the hidden attribute true
|
||||
elements[element].hidden = true;
|
||||
// set its category to "alchemy mod"
|
||||
elements[element].category = "alchemy mod";
|
||||
}
|
||||
}
|
||||
|
||||
// set the unhide setting to Unlock as Discovered (2)
|
||||
settings.unhide = 2;
|
||||
|
||||
runAfterLoad(function(){
|
||||
checkUnlock = function(element) {
|
||||
if (elements[element] && elements[element].hidden && !settings.alchemyUnlocked[element]) {
|
||||
settings.alchemyUnlocked[element] = true;
|
||||
if (settings.unhide === 2) {
|
||||
createElementButton(element)
|
||||
var categoryButton = document.querySelector(".categoryButton[current='true']");
|
||||
var currentCategory = categoryButton.getAttribute("category");
|
||||
if (currentCategory !== elements[element].category) {
|
||||
document.getElementById("categoryButton-"+elements[element].category).classList.add("notify");
|
||||
}
|
||||
// add notify to the elementButton of the element
|
||||
document.getElementById("elementButton-"+element).classList.add("notify");
|
||||
if (settings.unlocked.alchemymod) {
|
||||
for (var element in settings.unlocked) {
|
||||
if (settings.unlocked[element]) {
|
||||
settings.alchemyUnlocked[element] = true;
|
||||
}
|
||||
saveSettings();
|
||||
}
|
||||
}
|
||||
})
|
||||
runAfterAutogen(function(){
|
||||
for (var element in elements) {
|
||||
if (elements[element].category === "states") {
|
||||
elements[element].category = "alchemy mod"
|
||||
}
|
||||
}
|
||||
})
|
||||
window.addEventListener("load",function(){
|
||||
for (var element in elements) {
|
||||
if (elements[element].hidden && document.getElementById("elementButton-"+element)) {
|
||||
document.getElementById("elementButton-"+element).remove()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
/*runAfterAutogen(function(){
|
||||
// loop through the elements object
|
||||
if (elements.explosion) {
|
||||
elements.explosion.category = "tools";
|
||||
}
|
||||
if (elements.room_temp) {
|
||||
elements.room_temp.category = "tools";
|
||||
}
|
||||
if (elements.cook) {
|
||||
elements.cook.category = "tools";
|
||||
}
|
||||
if (elements.incinerate) {
|
||||
elements.incinerate.category = "tools";
|
||||
}
|
||||
|
||||
// set the unhide setting to Unlock as Discovered (2)
|
||||
settings.unhide = 2;
|
||||
|
||||
runAfterLoad(function () {
|
||||
checkUnlock = function (element) {
|
||||
if (elements[element] && elements[element].hidden && !settings.alchemyUnlocked[element]) {
|
||||
settings.alchemyUnlocked[element] = true;
|
||||
if (settings.unhide === 2) {
|
||||
createElementButton(element);
|
||||
var categoryButton = document.querySelector(".categoryButton[current='true']");
|
||||
var currentCategory = categoryButton.getAttribute("category");
|
||||
if (currentCategory !== elements[element].category) {
|
||||
document.getElementById("categoryButton-" + elements[element].category).classList.add("notify");
|
||||
}
|
||||
// add notify to the elementButton of the element
|
||||
document.getElementById("elementButton-" + element).classList.add("notify");
|
||||
}
|
||||
saveSettings();
|
||||
}
|
||||
};
|
||||
});
|
||||
window.addEventListener("load", function () {
|
||||
for (var element in elements) {
|
||||
if (elements[element].hidden && document.getElementById("elementButton-" + element)) {
|
||||
document.getElementById("elementButton-" + element).remove();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function lockAll() {
|
||||
for (var element in elements) {
|
||||
if (elements[element].category === "tools") {
|
||||
settings.alchemyUnlocked[element] = true;
|
||||
}
|
||||
if (settings.alchemyUnlocked[element]) {
|
||||
elements[element].hidden = false;
|
||||
}
|
||||
else if (elements[element].category !== "tools") {
|
||||
// give the element the hidden attribute true
|
||||
elements[element].hidden = true;
|
||||
}
|
||||
if (elements[element].category !== "tools") {
|
||||
if (!settings.alchemyUnlocked || Object.keys(settings.alchemyUnlocked).length < 25) {
|
||||
elements[element].category = "alchemy mod";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
runAfterAutogen(() => runAfterAutogen(lockAll));
|
||||
|
||||
|
||||
function printReachable() {
|
||||
let reachable = findReachable(initialElements);
|
||||
console.log(reachable.join(","));
|
||||
let string = "";
|
||||
for(let i in elements)
|
||||
{
|
||||
if(!reachable.includes(i))
|
||||
{
|
||||
if(string === "")
|
||||
{
|
||||
for (let i in elements) {
|
||||
if (!reachable.includes(i)) {
|
||||
if (string === "") {
|
||||
string = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
string += "," + i;
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(string);
|
||||
string = "";
|
||||
for(let i = 0; i < reachable.length; i++)
|
||||
{
|
||||
if(!settings.alchemyUnlocked[reachable[i]])
|
||||
{
|
||||
if(string === "")
|
||||
{
|
||||
for (let i = 0; i < reachable.length; i++) {
|
||||
if (!settings.alchemyUnlocked[reachable[i]]) {
|
||||
if (string === "") {
|
||||
string = reachable[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
string += "," + reachable[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(string);
|
||||
string = "";
|
||||
for(let i in settings.alchemyUnlocked)
|
||||
{
|
||||
if(!reachable.includes(i) && settings.alchemyUnlocked[i] && elements[i].category !== "tools")
|
||||
{
|
||||
if(string === "")
|
||||
{
|
||||
for (let i in settings.alchemyUnlocked) {
|
||||
if (!reachable.includes(i) && settings.alchemyUnlocked[i] && elements[i].category !== "tools") {
|
||||
if (string === "") {
|
||||
string = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
string += "," + i;
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(string);
|
||||
});*/
|
||||
}
|
||||
// runAfterAutogen(() => runAfterAutogen(printReachable));
|
||||
}
|
||||
|
||||
if (chemMod) {
|
||||
if (chemMod.readyState === 'complete') {
|
||||
loadAlchem();
|
||||
} else {
|
||||
chemMod.addEventListener("load", loadAlchem);
|
||||
}
|
||||
} else {
|
||||
loadAlchem();
|
||||
}
|
||||
dependOn("chem.js", () => { return; }, true);
|
||||
|
||||
loadAlchem();
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
var mods_to_include = ["glow.js", "circuitcore.js", "clone_liquid.js", "colored_lightbulbs.js", "combustion.js", "conveyance.js", "coresbyp.js", "datawire.js", "drill.js", "ExtraMachines.js", "fans.js", "fine_tuned_cloner.js", "flipflop.js", "fueled_generators.js", "gameOfLife.js", "heatshield.js", "human_friendly_design.js", "industry.js", "logicgates.js", "note_block_advanced.js", "note_block.js", "nousersthings.js", "portal.js", "pullers.js", "pushers.js", "sandboxels.js", "schematics.js", "scp.js", "spouts.js", "state_voids.js", "switches.js", "thiquovite.js", "ticking_temp_stuff.js", "video.js", "waterspout.js", "WhisperingTheory.js", "wifi_draw.js", "aircrafts.js", "c_fighter_jet.js", "guided_rocket.js", "icb.js", "life_eater.js", "liquid_void.js", "meat_rockets.js", "more_breaking.js", "rays.js", "rays++.js", "scp.js", "subspace.js", "war_crimes.js", "weapons.js", "aChefsDream_beta.js", "aChefsDream.js", "aChefsDream2.js", "bananas.js", "CherrySoda.js", "community_desserts.js", "devsnacks.js", "GrapeSoda.js", "greenitemsandmore.js", "ketchup_mod.js", "lemonade.js", "morefoodsmod.js", "mossstuff.js", "mustard.js", "potato_chips.js", "sbstuff.js", "soups.js", "weAllScreamFor.js", "apioforms_pre.js", "baby.js", "bacteria_mod.js", "bananas.js", "biology.js", "cat.js", "cells.js", "children.js", "coldblooded.js", "colonies.js", "crimson.js", "dogs.js", "eklegems.js", "fairy_chain.js", "fantastic_creatures.js", "fantasy_elements.js", "fey_and_more.js", "fishin.js", "flowers_and_forests.js", "fwibblen.js", "genetics.js", "human_edit.js", "kopalstuff.js", "lizard_mod.js", "lost_souls.js", "miscible_psoup_and_birthpool.js", "mobs.js", "moretrees.js", "no_blood.js", "nocancer.js", "nocancer2.js", "nograssgrow.js", "ocean.js", "ores.js", "petal_dye.js", "plants.js", "primordial_birthpool.js", "scp.js", "spring.js", "the_ground_og.js", "toothpaste.js", "volcanic_expansion.js", "alcohol.js","alkahest.js","alkali_metal.js","bettermetalscrap.js","boiling_things.js","bouncing_balls.js","chalk.js","chem.js","grav_mudstones.js","halogen.js","liquid_mixing.js","lye.js","metals.js","mixture.js","moreliquids.js", "PRNGworldgenlib.js"
|
||||
|
||||
|
||||
|
||||
]
|
||||
|
||||
var mods_included = mods_to_include.map(mod => enabledMods.includes(mod));
|
||||
var all_mods_included = mods_included.reduce(function(a,b) { return a && b });
|
||||
|
||||
if(!all_mods_included) {
|
||||
// var mods_needed = mods_to_include.filter(function(modPath) { return !(enabledMods.includes(modPath)) });
|
||||
|
||||
mods_needed.forEach(function(modName) {
|
||||
// enabledMods.splice(enabledMods.indexOf("allthemods"),0,modPath);
|
||||
dependOn(modPath, ()=>{}, true)
|
||||
});
|
||||
// localStorage.setItem("enabledMods", JSON.stringify(enabledMods));
|
||||
// alert(`The following mods have been inserted: ${mods_needed.join(", ")}
|
||||
// Reload the page for the mods to take effect.`)
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,277 @@
|
|||
/*
|
||||
function loadJsDelivr(url, callback) {
|
||||
const script = document.createElement('script');
|
||||
script.src = url;
|
||||
script.onload = () => {
|
||||
console.log('Loaded:', url);
|
||||
if (callback) callback();
|
||||
};
|
||||
script.onerror = () => {
|
||||
console.error('Failed to load:', url);
|
||||
};
|
||||
document.head.appendChild(script);
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @type {undefined | HTMLAudioElement}
|
||||
*/
|
||||
let currentMusic;
|
||||
const PLAY = "\u25B6";
|
||||
const PAUSE = "\u23F8";
|
||||
/**
|
||||
*
|
||||
* @param {string|File} userAudio
|
||||
*/
|
||||
function setBackgroundMusic(userAudio) {
|
||||
let audioSrc;
|
||||
|
||||
if (typeof userAudio === "string") {
|
||||
if (!isValidAudioUrl(userAudio)) {
|
||||
promptText("Invalid audio URL");
|
||||
return;
|
||||
}
|
||||
audioSrc = new URL(userAudio).href;
|
||||
} else if (userAudio instanceof File) {
|
||||
if (!userAudio.type.startsWith("audio/")) {
|
||||
promptText("Invalid audio file");
|
||||
return;
|
||||
}
|
||||
audioSrc = URL.createObjectURL(userAudio);
|
||||
} else {
|
||||
promptText("Invalid audio input");
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentMusic && currentMusic.src === audioSrc) return;
|
||||
|
||||
if (currentMusic) {
|
||||
currentMusic.pause();
|
||||
currentMusic.remove();
|
||||
}
|
||||
|
||||
const audio = document.createElement('audio');
|
||||
audio.src = audioSrc;
|
||||
audio.loop = true;
|
||||
audio.volume = 0.5;
|
||||
audio.id = "bgm";
|
||||
document.body.appendChild(audio);
|
||||
|
||||
currentMusic = audio;
|
||||
|
||||
// Only save if it's a URL, not a local file
|
||||
if (typeof userAudio === "string") {
|
||||
settings.bgMusic = audioSrc;
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
logMessage(`Now playing: ${audioSrc}`);
|
||||
return audio;
|
||||
}
|
||||
|
||||
|
||||
function isValidAudioUrl(inpurl) {
|
||||
try {
|
||||
const url = new URL(inpurl);
|
||||
if (!['http:', 'https:'].includes(url.protocol)) return false;
|
||||
return /\.(mp3|wav|ogg)$/i.test(url.pathname);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let music_setting;
|
||||
let play;
|
||||
let playing = false;
|
||||
dependOn("betterSettings.js", () => {
|
||||
// @ts-ignore
|
||||
const settings_tab = new SettingsTab("background_music.js")
|
||||
// @ts-ignore
|
||||
music_setting = new Setting("Background Music", "bgm", settingType.TEXT, false)
|
||||
// @ts-ignore
|
||||
play = new Setting("Play", "play", settingType.BOOLEAN, false)
|
||||
settings_tab.registerSettings(undefined, play)
|
||||
settings_tab.registerSettings(undefined, music_setting)
|
||||
// @ts-ignore
|
||||
settingsManager.registerTab(settings_tab)
|
||||
}, true)
|
||||
|
||||
keybinds["KeyK"] = () => {
|
||||
if (playing) {
|
||||
document.getElementById('pauseButton').click()
|
||||
}
|
||||
}
|
||||
|
||||
function addCss() {
|
||||
const CSS = `
|
||||
.songControl {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
padding: 10px;
|
||||
height: 20px;
|
||||
|
||||
pointer-events: none;
|
||||
background-color: transparent;
|
||||
border: 2px solid white;
|
||||
box-shadow: 0 0 8px rgba(0,0,0,0.8);
|
||||
}
|
||||
.pixelArt {
|
||||
image-rendering: pixelated;
|
||||
image-rendering: crisp-edges;
|
||||
width: 15px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
|
||||
`
|
||||
const style_div = document.createElement("style")
|
||||
style_div.innerHTML = CSS
|
||||
|
||||
document.head.appendChild(style_div)
|
||||
}
|
||||
|
||||
function createPauseButton() {
|
||||
const pauseImgLink = "https://raw.githubusercontent.com/Cube14yt/assets/main/images/pause.png"
|
||||
const playImgLink = "https://raw.githubusercontent.com/Cube14yt/assets/main/images/play.png"
|
||||
const pauseButton = document.createElement("button");
|
||||
/**
|
||||
* @this {HTMLButtonElement}
|
||||
*/
|
||||
pauseButton.onclick = function () {
|
||||
if (playing) {
|
||||
this.replaceChildren()
|
||||
let img = document.createElement("img")
|
||||
img.src = playImgLink
|
||||
img.classList.add("pixelArt")
|
||||
this.appendChild(img)
|
||||
playing = !playing
|
||||
currentMusic?.pause();
|
||||
} else {
|
||||
this.replaceChildren()
|
||||
let img = document.createElement("img")
|
||||
img.src = pauseImgLink
|
||||
img.classList.add("pixelArt")
|
||||
this.appendChild(img)
|
||||
playing = !playing
|
||||
const url = music_setting.value;
|
||||
|
||||
if (!currentMusic) {
|
||||
setBackgroundMusic(url);
|
||||
}
|
||||
currentMusic?.play()
|
||||
}
|
||||
}
|
||||
pauseButton.replaceChildren()
|
||||
let img = document.createElement("img")
|
||||
img.src = playImgLink
|
||||
img.classList.add("pixelArt")
|
||||
pauseButton.appendChild(img)
|
||||
pauseButton.style.pointerEvents = 'auto'
|
||||
pauseButton.style.border = '2px solid white'
|
||||
pauseButton.id = 'pauseButton'
|
||||
return pauseButton
|
||||
}
|
||||
|
||||
function createResetButton() {
|
||||
const resetButton = document.createElement("button");
|
||||
/**
|
||||
* @this {HTMLButtonElement}
|
||||
*/
|
||||
resetButton.onclick = function () {
|
||||
if (currentMusic) currentMusic.currentTime = 0
|
||||
}
|
||||
let img = document.createElement("img")
|
||||
img.src = "https://raw.githubusercontent.com/Cube14yt/assets/main/images/reset.png"
|
||||
img.classList.add("pixelArt")
|
||||
resetButton.appendChild(img)
|
||||
resetButton.style.pointerEvents = "auto"
|
||||
resetButton.style.border = '2px solid white'
|
||||
resetButton.id = 'resetButton'
|
||||
return resetButton
|
||||
}
|
||||
|
||||
function createVolumeButton() {
|
||||
const volumeButton = document.createElement("button");
|
||||
/**
|
||||
* @this {HTMLButtonElement}
|
||||
*/
|
||||
volumeButton.onclick = function () {
|
||||
promptInput("Input the new volume of the current music", (vol) => {
|
||||
if (!currentMusic) return;
|
||||
let newVolume = Number(vol)
|
||||
if (!(newVolume >= 0 && newVolume <= 1)) return
|
||||
currentMusic.volume = newVolume
|
||||
})
|
||||
}
|
||||
let img = document.createElement("img")
|
||||
img.src = "https://raw.githubusercontent.com/Cube14yt/assets/main/images/volume.png"
|
||||
img.classList.add("pixelArt")
|
||||
volumeButton.appendChild(img)
|
||||
volumeButton.style.pointerEvents = "auto"
|
||||
volumeButton.style.border = '2px solid white'
|
||||
volumeButton.id = "volumeButton"
|
||||
return volumeButton
|
||||
}
|
||||
|
||||
function createInputButton() {
|
||||
const inputButton = document.createElement('button')
|
||||
inputButton.onclick = function () {
|
||||
promptChoose("How do you want to input your song?", ["URL", "File"], (choice) => {
|
||||
if (choice === "URL") {
|
||||
promptInput("Give the url your song should use", (url) => {
|
||||
music_setting.value = url
|
||||
}, "Input URL")
|
||||
} else if (choice === "File") {
|
||||
const input = document.createElement('input')
|
||||
input.type = "file"
|
||||
input.addEventListener('change', (event) => {
|
||||
// @ts-ignore
|
||||
const file = event.target.files[0];
|
||||
if (file) setBackgroundMusic(file)
|
||||
})
|
||||
input.click()
|
||||
}
|
||||
})
|
||||
}
|
||||
inputButton.textContent = "Input Song"
|
||||
inputButton.style.pointerEvents = "auto"
|
||||
inputButton.style.border = '2px solid white'
|
||||
inputButton.id = 'inputButton'
|
||||
return inputButton
|
||||
}
|
||||
|
||||
function showSongUi() {
|
||||
let songDiv = document.getElementById("songUiParent");
|
||||
|
||||
const canvas_div = document.getElementById("canvasDiv");
|
||||
if (!canvas_div) {
|
||||
requestAnimationFrame(showSongUi)
|
||||
return
|
||||
};
|
||||
|
||||
if (!songDiv) {
|
||||
|
||||
songDiv = document.createElement("div");
|
||||
songDiv.classList.add("songControl");
|
||||
songDiv.id = "songUiParent";
|
||||
songDiv.appendChild(createPauseButton())
|
||||
songDiv.append(createResetButton())
|
||||
songDiv.append(createVolumeButton())
|
||||
songDiv.append(createInputButton())
|
||||
canvas_div.appendChild(songDiv);
|
||||
}
|
||||
console.log("UI loaded sucessfully")
|
||||
}
|
||||
|
||||
addCss()
|
||||
showSongUi()
|
||||
1008
mods/bananas.js
1008
mods/bananas.js
File diff suppressed because it is too large
Load Diff
|
|
@ -1,7 +1,7 @@
|
|||
var modName = "mods/boiling_things.js";
|
||||
var libraryMod = "mods/code_library.js";
|
||||
|
||||
if(enabledMods.includes(libraryMod)) {
|
||||
dependOn("code_library.js", function(){
|
||||
|
||||
//glass {
|
||||
|
||||
|
|
@ -533,8 +533,4 @@ if(enabledMods.includes(libraryMod)) {
|
|||
};
|
||||
|
||||
});
|
||||
} else {
|
||||
alert(`The ${libraryMod} mod is required and has been automatically inserted (reload for this to take effect).`)
|
||||
enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod)
|
||||
localStorage.setItem("enabledMods", JSON.stringify(enabledMods));
|
||||
};
|
||||
}, true);
|
||||
|
|
@ -32,7 +32,7 @@ elements.change = {
|
|||
tool: function(pixel) {
|
||||
changePixel(pixel,changeTo,true);
|
||||
},
|
||||
category: "tools",
|
||||
category: "edit",
|
||||
desc: "Changes any pixels it is used on to a specified type.<br/>Currently replacing pixels with \"" + changeTo + "\".<br/><span onclick=changeElementPrompt() style=\"color: #ff00ff;\";>Press [;] or click here</span> to open the change prompt.",
|
||||
};
|
||||
|
||||
|
|
@ -41,7 +41,7 @@ elements.alt_change = {
|
|||
tool: function(pixel) {
|
||||
pixel.element = changeTo;
|
||||
},
|
||||
category: "tools",
|
||||
category: "edit",
|
||||
desc: "Changes any pixels it is used on to a specified type, but keeping their non-element-based properties.<br/>Currently replacing pixels with \"" + changeTo + "\".<br/><span onclick=changeElementPrompt() style=\"color: #ff00ff;\";>Press [;] or click here</span> to open the change prompt.",
|
||||
hidden: true,
|
||||
};
|
||||
|
|
@ -52,7 +52,7 @@ elements.alt_alt_change = {
|
|||
pixel.element = changeTo;
|
||||
pixel.color = pixelColorPick(pixel);
|
||||
},
|
||||
category: "tools",
|
||||
category: "edit",
|
||||
desc: "Changes any pixels it is used on to a specified type, but keeping their non-element-based properties except for color.<br/>Currently replacing pixels with \"" + changeTo + "\".<br/><span onclick=changeElementPrompt() style=\"color: #ff00ff;\";>Press [;] or click here</span> to open the change prompt.",
|
||||
hidden: true,
|
||||
};
|
||||
|
|
@ -1,3 +1,6 @@
|
|||
// This mod has been deprecated as of 2026-01-22.
|
||||
|
||||
/*
|
||||
function reactPixels(pixel1,pixel2) {
|
||||
var r = elements[pixel1.element].reactions[pixel2.element];
|
||||
if (r.setting && settings[r.setting]===0) {
|
||||
|
|
@ -71,3 +74,4 @@ function reactPixels(pixel1,pixel2) {
|
|||
if (r.func) { r.func(pixel1,pixel2); }
|
||||
return r.elem1!==undefined || r.elem2!==undefined;
|
||||
}
|
||||
*/
|
||||
14933
mods/chem.js
14933
mods/chem.js
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1016
mods/cherries.js
1016
mods/cherries.js
File diff suppressed because it is too large
Load Diff
|
|
@ -1435,7 +1435,7 @@ runAfterLoadList.push(() => {
|
|||
if (!localStorage.getItem("chessjs-tutorial")) {
|
||||
// "might break"
|
||||
// i know damn well it will 100% break on mobile
|
||||
alert("To start or restart chess board press 'u'. Might break on different resolutions and on mobile.");
|
||||
promptText("To start or restart chess board press 'u'. Might break on different resolutions and on mobile.");
|
||||
localStorage.setItem("chessjs-tutorial", true);
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
var modName = "mods/colonies.js";
|
||||
var exoplanetMod = "mods/exoplanet.js";
|
||||
// var exoplanetMod = "mods/exoplanet.js";
|
||||
|
||||
if(enabledMods.includes(exoplanetMod)) {
|
||||
dependOn("exoplanet.js", function(){
|
||||
|
||||
window.addEventListener("load", () => {
|
||||
document.getElementById("elementButton-base")?.remove()
|
||||
|
|
@ -567,8 +567,4 @@ elements.arriving_rocket = {
|
|||
cooldown: defaultCooldown
|
||||
}
|
||||
|
||||
} else {
|
||||
enabledMods.splice(enabledMods.indexOf(modName),0,exoplanetMod)
|
||||
localStorage.setItem("enabledMods", JSON.stringify(enabledMods));
|
||||
alert(`The ${exoplanetMod} mod is required and has been automatically inserted (reload for this to take effect).`)
|
||||
};
|
||||
}, true);
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
var modName = "mods/color_tools.js";
|
||||
var libraryMod = "mods/code_library.js";
|
||||
|
||||
if(enabledMods.includes(libraryMod)) {
|
||||
dependOn("code_library.js", function(){
|
||||
var colorToolCounter = 0;
|
||||
saturationAmount = 1;
|
||||
saturationOp = "add";
|
||||
|
|
@ -290,8 +290,4 @@ if(enabledMods.includes(libraryMod)) {
|
|||
excludeRandom: true,
|
||||
desc: "<span style='color:#FF00FF' onClick=colorToolFilterPrompt()>Click here to configure the element filter (applies to all color tools).</span>",
|
||||
}
|
||||
} else {
|
||||
enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod)
|
||||
alert(`The ${libraryMod} mod is required and has been automatically inserted (reload for this to take effect).`)
|
||||
localStorage.setItem("enabledMods", JSON.stringify(enabledMods));
|
||||
};
|
||||
}, true);
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
Use intellisense for sandboxels modding here:
|
||||
to show availavle functions and show global variables
|
||||
https://github.com/Cube14yt/sandboxels-types
|
||||
https://github.com/R74nCom/sandboxels-types
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -619,37 +619,6 @@ elements.glow_stick_ice = {
|
|||
state: "solid"
|
||||
}
|
||||
|
||||
// Add TPS keybind
|
||||
keybinds["KeyT"] = function () {
|
||||
tpsPrompt()
|
||||
}
|
||||
|
||||
function addRowWhenReady() {
|
||||
const table = document.getElementById("controlsTable");
|
||||
|
||||
if (!table) {
|
||||
// Table not ready yet, try again in 100ms
|
||||
setTimeout(addRowWhenReady, 100);
|
||||
return;
|
||||
}
|
||||
|
||||
// Table exists, add the row
|
||||
const rowCount = table.rows.length;
|
||||
const newRow = table.insertRow(rowCount - 1);
|
||||
|
||||
const cell1 = newRow.insertCell(0);
|
||||
const cell2 = newRow.insertCell(1);
|
||||
|
||||
cell1.textContent = "Change TPS";
|
||||
cell2.innerHTML = "<kbd>T</kbd>";
|
||||
|
||||
console.log("Row added successfully!");
|
||||
}
|
||||
|
||||
// Start the process
|
||||
addRowWhenReady();
|
||||
|
||||
|
||||
elements.randomizer = {
|
||||
buttonColor: rainbowColor,
|
||||
excludeRandom: true,
|
||||
|
|
@ -794,32 +763,32 @@ elements.rgb_led = {
|
|||
stateHigh: ["molten_glass", "molten_glass", "molten_glass", "molten_gallium"],
|
||||
|
||||
onSelect: () => {
|
||||
promptInput("Enter red value (0-255):", function (r_inp) {
|
||||
r_inp = parseInt(r_inp);
|
||||
promptInput("Enter red value (0-255):", function (old_r_inp) {
|
||||
let r_inp = parseInt(old_r_inp);
|
||||
if (r_inp > 255 || r_inp < 0 || isNaN(r_inp)) {
|
||||
logMessage("Red value is invalid, using default/last red value: " + globals.red);
|
||||
} else {
|
||||
globals.red = r_inp;
|
||||
}
|
||||
|
||||
promptInput("Enter green value (0-255):", function (g_inp) {
|
||||
g_inp = parseInt(g_inp);
|
||||
promptInput("Enter green value (0-255):", function (old_g_inp) {
|
||||
let g_inp = parseInt(old_g_inp);
|
||||
if (g_inp > 255 || g_inp < 0 || isNaN(g_inp)) {
|
||||
logMessage("Green value is invalid, using default/last green value: " + globals.green);
|
||||
} else {
|
||||
globals.green = g_inp;
|
||||
}
|
||||
|
||||
promptInput("Enter blue value (0-255):", function (b_inp) {
|
||||
b_inp = parseInt(b_inp);
|
||||
promptInput("Enter blue value (0-255):", function (old_b_inp) {
|
||||
let b_inp = parseInt(old_b_inp);
|
||||
if (b_inp > 255 || b_inp < 0 || isNaN(b_inp)) {
|
||||
logMessage("Blue value is invalid, using default/last blue value: " + globals.blue);
|
||||
} else {
|
||||
globals.blue = b_inp;
|
||||
}
|
||||
}, "Blue Value", globals.blue); // optional default input
|
||||
}, "Green Value", globals.green);
|
||||
}, "Red Value", globals.red);
|
||||
}, "Blue Value", String(globals.blue)); // optional default input
|
||||
}, "Green Value", String(globals.green));
|
||||
}, "Red Value", String(globals.red));
|
||||
},
|
||||
|
||||
onPlace: (pixel) => {
|
||||
|
|
@ -1763,7 +1732,7 @@ globals.heatAmount = 2
|
|||
|
||||
elements.adjustable_heater = {
|
||||
color: "#ff0000",
|
||||
category: "deprecated",
|
||||
category: "machines",
|
||||
insulate: true,
|
||||
behavior: behaviors.WALL,
|
||||
|
||||
|
|
@ -1846,7 +1815,7 @@ globals.coolAmount = 2; // adjustable step
|
|||
|
||||
elements.adjustable_cooler = {
|
||||
color: "#0000ff",
|
||||
category: "deprecated",
|
||||
category: "machines",
|
||||
insulate: true,
|
||||
behavior: behaviors.WALL,
|
||||
|
||||
|
|
@ -2374,6 +2343,7 @@ elements.cacao_stem = {
|
|||
|
||||
|
||||
// --- audio setup ---
|
||||
// @ts-ignore
|
||||
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
|
||||
|
||||
function playNote(frequency, duration = 1, type = "sine", volume = 0.1) {
|
||||
|
|
@ -2738,13 +2708,18 @@ globals.rCircle = false
|
|||
globals.rRGBLed = false
|
||||
globals.rCustomBomb = false
|
||||
dependOn("betterSettings.js", () => {
|
||||
// @ts-ignore
|
||||
var Reset = new SettingsTab("Reset");
|
||||
// @ts-ignore
|
||||
var resetCircle = new Setting("Reset circle value and radius on reset", "Reset circle", settingType.BOOLEAN, false, defaultValue = false);
|
||||
// @ts-ignore
|
||||
var resetRGBLed = new Setting("Reset RGB Led value on reset", "Reset RGB Led", settingType.BOOLEAN, false, defaultValue = false);
|
||||
// @ts-ignore
|
||||
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)
|
||||
// @ts-ignore
|
||||
settingsManager.registerTab(Reset);
|
||||
runEveryTick(() => {
|
||||
if (resetCircle.value == true) {
|
||||
|
|
@ -3032,7 +3007,7 @@ elements.calculator = {
|
|||
logMessage("Error")
|
||||
return;
|
||||
}
|
||||
logMessage(Number(ans.toFixed(10)))
|
||||
logMessage(ans.toFixed(10))
|
||||
}
|
||||
catch (e) {
|
||||
logMessage("Invalid Characters Detected")
|
||||
|
|
@ -3065,8 +3040,9 @@ elements.random_teleporter = {
|
|||
} else pixel.fadeTo = "orange";
|
||||
}
|
||||
|
||||
for (var i = 0; i < squareCoords.length; i++) {
|
||||
let coord = squareCoords[i];
|
||||
shuffleArray(squareCoordsShuffle)
|
||||
for (var i = 0; i < squareCoordsShuffle.length; i++) {
|
||||
let coord = squareCoordsShuffle[i];
|
||||
let x = pixel.x + coord[0];
|
||||
let y = pixel.y + coord[1];
|
||||
if (!isEmpty(x, y)) {
|
||||
|
|
@ -3248,56 +3224,6 @@ elements.element_line = {
|
|||
}
|
||||
}
|
||||
|
||||
function getSquareCoords(pixel) {
|
||||
let x, y;
|
||||
for (let i = 0; i < squareCoords.length; i++) {
|
||||
let coord = squareCoords[i];
|
||||
x = pixel.x + coord[0];
|
||||
y = pixel.y + coord[1];
|
||||
}
|
||||
return { x, y }
|
||||
}
|
||||
|
||||
function getAdjacentCoords(pixel) {
|
||||
let x, y;
|
||||
for (let i = 0; i < adjacentCoords.length; i++) {
|
||||
x = pixel.x + adjacentCoords[i][0];
|
||||
y = pixel.y + adjacentCoords[i][1];
|
||||
}
|
||||
return { x, y }
|
||||
}
|
||||
|
||||
function getSquareCoordsShuffle(pixel) {
|
||||
shuffleArray(squareCoordsShuffle);
|
||||
let x, y;
|
||||
for (var i = 0; i < squareCoordsShuffle.length; i++) {
|
||||
var coord = squareCoordsShuffle[i];
|
||||
x = pixel.x + coord[0];
|
||||
y = pixel.y + coord[1];
|
||||
}
|
||||
return { x, y }
|
||||
}
|
||||
|
||||
function getAdjacentCoordsShuffle(pixel) {
|
||||
shuffleArray(adjacentCoordsShuffle)
|
||||
let x, y
|
||||
for (var i = 0; i < adjacentCoordsShuffle.length; i++) {
|
||||
x = pixel.x + adjacentCoordsShuffle[i][0];
|
||||
y = pixel.y + adjacentCoordsShuffle[i][1];
|
||||
}
|
||||
return { x, y }
|
||||
}
|
||||
|
||||
function getScreenCoords() {
|
||||
let coords = []
|
||||
for (let x = 0; x <= width; x++) {
|
||||
for (let y = 0; y <= height; y++) {
|
||||
coords.push([x, y])
|
||||
}
|
||||
}
|
||||
return coords
|
||||
}
|
||||
|
||||
globals.replaceElem = "wood"
|
||||
elements.replace_all_of_element = {
|
||||
color: ["#35008a", "#000000"],
|
||||
|
|
@ -3325,5 +3251,51 @@ elements.replace_all_of_element = {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @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])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,6 @@ elements.delete_all_of_element = {
|
|||
}
|
||||
}
|
||||
},
|
||||
category: "tools",
|
||||
category: "edit",
|
||||
excludeRandom: true,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -191,3 +191,17 @@ elements.spicy_water = {
|
|||
elements.broth.reactions.spice = { color1:"#ef713f", tempMin:70, chance:0.05 };
|
||||
elements.broth.reactions.spicy_water = { color1:"#ef713f", tempMin:70, chance:0.05 };
|
||||
elements.meat.reactions.spicy_water = { elem2:"broth", color2:"#ef713f", tempMin:70 };
|
||||
|
||||
elements.nut_spread = {
|
||||
color: "#7B4528",
|
||||
behavior: behaviors.LIQUID,
|
||||
viscosity: 200000,
|
||||
tempHigh: 232,
|
||||
stateHigh: ["smoke","smoke","smoke","smoke","salt"],
|
||||
category: "food",
|
||||
state: "liquid",
|
||||
density: 1090.5,
|
||||
isFood: true,
|
||||
hidden: true
|
||||
}
|
||||
elements.nut_meat.reactions.chocolate_powder = { elem1:"nut_spread", elem2:"nut_spread" }
|
||||
|
|
@ -65,19 +65,19 @@
|
|||
|
||||
|
||||
// info element
|
||||
elements.drills_info = {
|
||||
color: "#000000",
|
||||
name: "drills.js",
|
||||
category: "Mods",
|
||||
behavior: behaviors.SELFDELETE,
|
||||
maxSize: 1,
|
||||
tool: function(pixel) {},
|
||||
onSelect: function(pixel) {
|
||||
let mod_info = "The drills.js mod adds different kinds of drills to a new 'drills' category.\n\nMod made by: Necrotic_Phantom. \n With help from: voidapex11."
|
||||
alert(mod_info)
|
||||
return
|
||||
},
|
||||
};
|
||||
// elements.drills_info = {
|
||||
// color: "#000000",
|
||||
// name: "drills.js",
|
||||
// category: "Mods",
|
||||
// behavior: behaviors.SELFDELETE,
|
||||
// maxSize: 1,
|
||||
// tool: function(pixel) {},
|
||||
// onSelect: function(pixel) {
|
||||
// let mod_info = "The drills.js mod adds different kinds of drills to a new 'drills' category.\n\nMod made by: Necrotic_Phantom. \n With help from: voidapex11."
|
||||
// alert(mod_info)
|
||||
// return
|
||||
// },
|
||||
// };
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
elements.dry_acid = {
|
||||
name:"Anhydrous acid",
|
||||
desc:"It's pretty much just acid without water in it.",
|
||||
color: ["#62e36f", "#a5d9aa", "#b3c9b6"],
|
||||
behavior: behaviors.POWDER,
|
||||
category: "powders",
|
||||
state: "solid",
|
||||
reactions: {
|
||||
"water": { elem1:"dry_acid", elem2:"acid", temp2:37.22},
|
||||
"dirty_water": { elem1:null, elem2:"acid", temp2:37.22}
|
||||
},
|
||||
density: 1.522
|
||||
}
|
||||
|
||||
if (elements.acid) {
|
||||
if (!elements.acid.ignore) {
|
||||
elements.acid.ignore = [];
|
||||
}
|
||||
elements.acid.ignore.push('dry_acid');
|
||||
}
|
||||
|
||||
// Ensure the reactions object exists for the element
|
||||
if (!elements.acid.reactions) {
|
||||
elements.acid.reactions = {};
|
||||
}
|
||||
|
||||
// Add the new reaction
|
||||
elements.acid.reactions["dirty_water"] = {
|
||||
elem1: "acid", // What this element turns into
|
||||
elem2: "acid", // What the other element turns into
|
||||
}
|
||||
|
||||
delete elements.acid.reactions.water
|
||||
delete elements.water.reactions.acid
|
||||
|
|
@ -1152,7 +1152,7 @@ if(enabledMods.includes(loonaMod) && enabledMods.includes(fireMod) && enabledMod
|
|||
burnTime: 600,
|
||||
tempHigh: 200,
|
||||
stateHigh: ["steam", "ash"],
|
||||
onTryMoveInto: function(pixel,otherPixel) {
|
||||
onMoveInto: function(pixel,otherPixel) {
|
||||
var otherInfo = elements[otherPixel.element]
|
||||
if(typeof(otherInfo.state) === "string" && otherInfo.state !== "gas") {
|
||||
pixel.attached = false;
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@ function tempToRGB(temp){
|
|||
if (temp <= 6500){
|
||||
return{
|
||||
r: 255,
|
||||
g: Math.max(-325.757*Math.pow(0.999581, temp)+272.879, 0),
|
||||
b: Math.max(-571.403*Math.pow(0.999675, temp)+321.955, 0)
|
||||
g: Math.trunc(Math.max(-325.757*Math.pow(0.999581, temp)+272.879, 0)),
|
||||
b: Math.trunc(Math.max(-571.403*Math.pow(0.999675, temp)+321.955, 0))
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
r: Math.max(604.879*Math.pow(0.999697, temp)+169.618, 0),
|
||||
g: Math.max(719.488*Math.pow(0.999599, temp)+201.788, 0),
|
||||
r: Math.trunc(Math.max(604.879*Math.pow(0.999697, temp)+169.618, 0)),
|
||||
g: Math.trunc(Math.max(719.488*Math.pow(0.999599, temp)+201.788, 0)),
|
||||
b: 255
|
||||
}
|
||||
}
|
||||
|
|
@ -27,7 +27,7 @@ function oldtempToRgb(temp, pixel){
|
|||
}
|
||||
if (ctemp <= 0.5){
|
||||
return{
|
||||
r: (510*ctemp),
|
||||
r: Math.trunc(510*ctemp),
|
||||
g: 0,
|
||||
b: 0,
|
||||
opacity: (ctemp/1.3)
|
||||
|
|
@ -35,8 +35,8 @@ function oldtempToRgb(temp, pixel){
|
|||
} else {
|
||||
return {
|
||||
r: 255,
|
||||
g: ((510*ctemp)-255),
|
||||
b: ((280*ctemp)-140),
|
||||
g: Math.trunc((510*ctemp)-255),
|
||||
b: Math.trunc((280*ctemp)-140),
|
||||
opacity: (ctemp/1.3)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1256
mods/human_edit.js
1256
mods/human_edit.js
File diff suppressed because it is too large
Load Diff
|
|
@ -1,11 +1,7 @@
|
|||
var modName = "mods/life_eater.js";
|
||||
var fireMod = "mods/fire_mod.js";
|
||||
|
||||
if(!enabledMods.includes(fireMod)) {
|
||||
enabledMods.splice(enabledMods.indexOf(modName),0,fireMod);
|
||||
localStorage.setItem("enabledMods", JSON.stringify(enabledMods));
|
||||
alert(`The ${fireMod} mod is required and has been automatically inserted (reload for this to take effect).`);
|
||||
} else {
|
||||
dependOn("fire_mod.js", function() {
|
||||
|
||||
var lifeEaterCategories = ["life","auto creepers","food","fantastic creatures","fey","auto_fey"];
|
||||
var lifeEaterBlacklist = ["life_eater_virus","life_eater_slurry","life_eater_infected_dirt"];
|
||||
|
|
@ -166,4 +162,4 @@ if(!enabledMods.includes(fireMod)) {
|
|||
stateHigh: elements.metal_scrap.stateHigh.concat("life_eater_virus","life_eater_virus","life_eater_virus"),
|
||||
};
|
||||
|
||||
}
|
||||
}, true);
|
||||
|
|
|
|||
|
|
@ -1,29 +1,27 @@
|
|||
function whenAvailable(names, callback) {
|
||||
var interval = 10; // ms
|
||||
window.setTimeout(function() {
|
||||
let bool = true;
|
||||
for(let i = 0; i < names.length; i++)
|
||||
{
|
||||
if(!window[names[i]])
|
||||
{
|
||||
bool = false;
|
||||
}
|
||||
}
|
||||
if (bool) {
|
||||
callback();
|
||||
} else {
|
||||
whenAvailable(names, callback);
|
||||
}
|
||||
}, interval);
|
||||
}
|
||||
// function whenAvailable(names, callback) {
|
||||
// var interval = 10; // ms
|
||||
// window.setTimeout(function() {
|
||||
// let bool = true;
|
||||
// for(let i = 0; i < names.length; i++)
|
||||
// {
|
||||
// if(!window[names[i]])
|
||||
// {
|
||||
// bool = false;
|
||||
// }
|
||||
// }
|
||||
// if (bool) {
|
||||
// callback();
|
||||
// } else {
|
||||
// whenAvailable(names, callback);
|
||||
// }
|
||||
// }, interval);
|
||||
// }
|
||||
|
||||
var modName = "mods/metals.js";
|
||||
var changeTempMod = "mods/changeTempReactionParameter.js";
|
||||
var runAfterAutogenMod = "mods/runAfterAutogen2.js";
|
||||
// var changeTempMod = "mods/changeTempReactionParameter.js";
|
||||
// var runAfterAutogenMod = "mods/runAfterAutogen2.js";
|
||||
var libraryMod = "mods/code_library.js";
|
||||
var onTryMoveIntoMod = "mods/onTryMoveInto.js";
|
||||
if(enabledMods.includes(changeTempMod) && enabledMods.includes(runAfterAutogenMod) && enabledMods.includes(libraryMod) && enabledMods.includes(onTryMoveIntoMod)) {
|
||||
whenAvailable(["runAfterAutogen"], function() {
|
||||
dependOn("code_library.js", function(){
|
||||
elements.iron.hardness = 0.74
|
||||
//https://www.engineeringtoolbox.com/bhn-brinell-hardness-number-d_1365.html
|
||||
//https://en.wikipedia.org/wiki/Hardnesses_of_the_elements_(data_page)
|
||||
|
|
@ -483,7 +481,7 @@ if(enabledMods.includes(changeTempMod) && enabledMods.includes(runAfterAutogenMo
|
|||
properties: {
|
||||
oldColor: null,
|
||||
},
|
||||
onTryMoveInto: function(pixel,otherPixel) {
|
||||
onMoveInto: function(pixel,otherPixel) {
|
||||
neutronAbsorbency(pixel,otherPixel);
|
||||
},
|
||||
tick: function(pixel) {
|
||||
|
|
@ -500,7 +498,7 @@ if(enabledMods.includes(changeTempMod) && enabledMods.includes(runAfterAutogenMo
|
|||
density: 5803,
|
||||
tempHigh: 4409,
|
||||
behavior: behaviors.MOLTEN,
|
||||
onTryMoveInto: function(pixel,otherPixel) {
|
||||
onMoveInto: function(pixel,otherPixel) {
|
||||
neutronAbsorbency(pixel,otherPixel);
|
||||
},
|
||||
tick: function(pixel) {
|
||||
|
|
@ -512,7 +510,7 @@ if(enabledMods.includes(changeTempMod) && enabledMods.includes(runAfterAutogenMo
|
|||
elements.zirconium_gas = {
|
||||
density: 3, //Unknown/Unmeasured value
|
||||
behavior: behaviors.GAS,
|
||||
onTryMoveInto: function(pixel,otherPixel) {
|
||||
onMoveInto: function(pixel,otherPixel) {
|
||||
neutronAbsorbency(pixel,otherPixel);
|
||||
},
|
||||
tick: function(pixel) {
|
||||
|
|
@ -781,11 +779,4 @@ if(enabledMods.includes(changeTempMod) && enabledMods.includes(runAfterAutogenMo
|
|||
conduct: 0.35,
|
||||
hardness: 0.7, //idk lol
|
||||
};
|
||||
});
|
||||
} else {
|
||||
if(!enabledMods.includes(changeTempMod)) { enabledMods.splice(enabledMods.indexOf(modName),0,changeTempMod) };
|
||||
if(!enabledMods.includes(libraryMod)) { enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod) };
|
||||
if(!enabledMods.includes(onTryMoveIntoMod)) { enabledMods.splice(enabledMods.indexOf(modName),0,onTryMoveIntoMod) };
|
||||
localStorage.setItem("enabledMods", JSON.stringify(enabledMods));
|
||||
alert(`The "${changeTempMod}", "${runAfterAutogenMod}" and "${onTryMoveIntoMod}" mods are required; any missing mods in this list have been automatically inserted (reload for this to take effect).`);
|
||||
};
|
||||
},true)
|
||||
|
|
@ -0,0 +1,360 @@
|
|||
function getName(elementList)
|
||||
{
|
||||
if(elementList.filter(function(item, pos, self) {
|
||||
return self.indexOf(item) == pos;
|
||||
}).length == 1)
|
||||
{
|
||||
return elementList[0];
|
||||
}
|
||||
let name = elementList.join("_") + "_mixture";
|
||||
if(nameList[name])
|
||||
{
|
||||
name = nameList[name];
|
||||
};
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
function makeColors(elementList)
|
||||
{
|
||||
return elementList.map((c) => elements[c].color instanceof Array ? elements[c].color : [elements[c].color]);
|
||||
}
|
||||
|
||||
|
||||
function mixture(elementList)
|
||||
{
|
||||
elementList.sort();
|
||||
|
||||
let name = getName(elementList);
|
||||
|
||||
if(!elements[name])
|
||||
{
|
||||
elements[name] = true;
|
||||
let minTempHigh = Infinity;
|
||||
let stateHigh = null;
|
||||
let indexStateHigh = -1;
|
||||
|
||||
let maxTempLow = -Infinity;
|
||||
let stateLow = null;
|
||||
let indexStateLow = -1;
|
||||
|
||||
|
||||
for(let i = 0; i < elementList.length; i++)
|
||||
{
|
||||
if(elements[elementList[i]])
|
||||
{
|
||||
if(typeof elements[elementList[i]].tempHigh === "number" && elements[elementList[i]].stateHigh)
|
||||
{
|
||||
if(elements[elementList[i]].tempHigh < minTempHigh)
|
||||
{
|
||||
minTempHigh = elements[elementList[i]].tempHigh;
|
||||
indexStateHigh = i;
|
||||
stateHigh = elements[elementList[i]].stateHigh;
|
||||
}
|
||||
}
|
||||
|
||||
if(typeof elements[elementList[i]].tempLow === "number" && elements[elementList[i]].stateLow)
|
||||
{
|
||||
if(elements[elementList[i]].tempLow > maxTempLow)
|
||||
{
|
||||
maxTempLow = elements[elementList[i]].tempLow;
|
||||
indexStateLow = i;
|
||||
stateLow = elements[elementList[i]].stateLow;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let elementList2 = elementList.slice();
|
||||
let elementHigh = null;
|
||||
if(indexStateHigh >= 0)
|
||||
{
|
||||
if(stateHigh instanceof Array)
|
||||
{
|
||||
elementHigh = [];
|
||||
for(let i = 0; i < stateHigh.length; i++)
|
||||
{
|
||||
elementList2[indexStateHigh] = stateHigh[i];
|
||||
elementHigh.push(mixture(elementList2));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
elementList2[indexStateHigh] = stateHigh;
|
||||
elementHigh = mixture(elementList2);
|
||||
}
|
||||
}
|
||||
|
||||
let elementList3 = elementList.slice();
|
||||
let elementLow = null;
|
||||
if(indexStateLow >= 0)
|
||||
{
|
||||
if(stateLow instanceof Array)
|
||||
{
|
||||
elementLow = [];
|
||||
for(let i = 0; i < stateLow.length; i++)
|
||||
{
|
||||
elementList3[indexStateLow] = stateLow[i];
|
||||
elementLow.push(mixture(elementList3));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
elementList3[indexStateLow] = stateLow;
|
||||
elementLow = mixture(elementList3);
|
||||
}
|
||||
}
|
||||
|
||||
if(elementHigh instanceof Array && elementHigh.length === 0)
|
||||
{
|
||||
minTempHigh = Infinity;
|
||||
elementHigh = null;
|
||||
}
|
||||
if(elementLow instanceof Array && elementLow.length === 0)
|
||||
{
|
||||
maxTempLow = -Infinity;
|
||||
elementLow = null;
|
||||
}
|
||||
|
||||
let colors = makeColors(elementList.slice());
|
||||
let colors2 = [];
|
||||
let maxLength = Math.max(...(colors.map((c) => c.length)));
|
||||
|
||||
for(let i = 0; i < maxLength; i++)
|
||||
{
|
||||
let colors3 = [];
|
||||
for(let j = 0; j < colors.length; j++)
|
||||
{
|
||||
colors3.push(toObject(colors[j][i%colors[j].length]));
|
||||
}
|
||||
colors2.push(averageRGB(colors3));
|
||||
}
|
||||
let temp = airTemp;
|
||||
if(maxTempLow < airTemp && minTempHigh > airTemp)
|
||||
{
|
||||
|
||||
}
|
||||
else if(maxTempLow > -Infinity && minTempHigh < Infinity)
|
||||
{
|
||||
temp = (maxTempLow + minTempHigh)/2;
|
||||
}
|
||||
else if(maxTempLow > -Infinity)
|
||||
{
|
||||
temp = maxTempLow+20;
|
||||
}
|
||||
else if(minTempHigh < Infinity)
|
||||
{
|
||||
temp = Math.max(minTempHigh-20,absoluteZero);
|
||||
}
|
||||
|
||||
|
||||
let movable = elementList.some((c) => elements[c].movable || elements[c].movable === undefined);
|
||||
|
||||
let density = elementList.map((c) => elements[c].density ? elements[c].density : 0).reduce((a,b)=>a+b)/elementList.length;
|
||||
let stain = elementList.map((c) => elements[c].stain ? elements[c].stain : 0).reduce((a,b)=>a+b)/elementList.length;
|
||||
|
||||
let states = elementList.map((c) => elements[c].state);
|
||||
if(states.includes("gas"))
|
||||
{
|
||||
state = "gas";
|
||||
density = 0;
|
||||
}
|
||||
else if(!movable)
|
||||
{
|
||||
state = "solid";
|
||||
}
|
||||
else if(states.includes("liquid"))
|
||||
{
|
||||
state = "liquid";
|
||||
}
|
||||
else
|
||||
{
|
||||
state = "solid";
|
||||
}
|
||||
addElement(name, {
|
||||
color: colors2.length == 1 ? colors2[0] : colors2,
|
||||
colorObject: colors2.length == 1 ? toObject(colors2[0]) :colors2.map((c) => toObject(c)),
|
||||
tick: function(pixel) {
|
||||
mixtureBehavior(pixel, elementList);
|
||||
},
|
||||
tempHigh: minTempHigh,
|
||||
stateHigh: elementHigh,
|
||||
tempLow: maxTempLow,
|
||||
stateLow: elementLow,
|
||||
temp: temp,
|
||||
category: "mixture",
|
||||
mixture: elementList,
|
||||
movable: movable,
|
||||
density: density,
|
||||
state: state,
|
||||
stain: stain,
|
||||
reactions: {},
|
||||
isGas: state === "gas"
|
||||
});
|
||||
|
||||
for(let i in elements)
|
||||
{
|
||||
for(let j = 0; j < elementList.length; j++)
|
||||
{
|
||||
if(elements[i].reactions && elements[i].reactions[elementList[j]] !== undefined)
|
||||
{
|
||||
if(name === i)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
elements[i].reactions[name] = {elem2: name, func: function(a,b){mixtureReact(b,a,elementList)}}
|
||||
}
|
||||
if(elements[elementList[j]].reactions && elements[elementList[j]].reactions[i] !== undefined)
|
||||
{
|
||||
if(name === i)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
elements[name].reactions[i] = {elem2: i, func: function(a,b){mixtureReact(a,b,elementList)}}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
function mixtureBehavior(pixel, elementList)
|
||||
{
|
||||
let prevCol = pixel.color;
|
||||
let previous = pixel.element;
|
||||
let elem = elementList[Math.floor(Math.random()*elementList.length)];
|
||||
if (elements[elem].tick) { // Run tick function if it exists
|
||||
elements[elem].tick(pixel);
|
||||
}
|
||||
|
||||
if (pixel.del) {return}
|
||||
|
||||
if (elements[elem].behavior) { // Parse behavior if it exists
|
||||
pixelTick(pixel,elements[elem].behavior);
|
||||
}
|
||||
if(pixel.element === previous)
|
||||
{
|
||||
pixel.color = prevCol;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function mixtureReact(pixel, pixel2, elementList)
|
||||
{
|
||||
elementList = elementList.slice();
|
||||
shuffleArray(elementList);
|
||||
let previous = pixel.element;
|
||||
let prevCol = pixel.color;
|
||||
let previous2 = pixel2.element;
|
||||
let prevCol2 = pixel2.color;
|
||||
for(let i = 0; i < elementList.length; i++)
|
||||
{
|
||||
let elem = elementList[i];
|
||||
if(pixel.del)
|
||||
{
|
||||
return;
|
||||
}
|
||||
changePixel(pixel,elem, false);
|
||||
let rr1 = false;
|
||||
if (elements[elem].reactions !== undefined && elements[elem].reactions[pixel2.element] !== undefined) {
|
||||
rr1 = reactPixels(pixel,pixel2);
|
||||
}
|
||||
if (!rr1 && elements[pixel2.element].reactions !== undefined && elements[pixel2.element].reactions[elem] !== undefined && !elements[pixel2.element].reactions[elem].oneway) {
|
||||
reactPixels(pixel2,pixel);
|
||||
}
|
||||
if(pixel2.element === previous2)
|
||||
{
|
||||
pixel2.color = prevCol2;
|
||||
}
|
||||
if(!pixel.del && pixel.element === elem)
|
||||
{
|
||||
}
|
||||
else if(pixel.del)
|
||||
{
|
||||
elementList.splice(elementList.indexOf(elem),1);
|
||||
createPixel(mixture(elementList),pixel.x,pixel.y);
|
||||
currentPixels[currentPixels.length-1].temp = pixel.temp;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
elementList.splice(elementList.indexOf(elem),1)
|
||||
changePixel(pixel, mixture(elementList.concat([pixel.element])), false);
|
||||
return;
|
||||
}
|
||||
if(pixel2.del)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
changePixel(pixel, previous, false);
|
||||
pixel.color = prevCol;
|
||||
}
|
||||
|
||||
nameList = [];
|
||||
|
||||
function toObject(color)
|
||||
{
|
||||
color = color.match(/\d+/g);
|
||||
return {
|
||||
r: parseInt(color[0]),
|
||||
g: parseInt(color[1]),
|
||||
b: parseInt(color[2])
|
||||
};
|
||||
}
|
||||
|
||||
function averageRGB2(colors)
|
||||
{
|
||||
return toObject(averageRGB(colors.map((d) => (toObject(d)))));
|
||||
}
|
||||
|
||||
function averageRGB(rgblist) {
|
||||
var r = 0;
|
||||
var g = 0;
|
||||
var b = 0;
|
||||
for (var i = 0; i < rgblist.length; i++) {
|
||||
var rgb = rgblist[i];
|
||||
r += parseInt(rgb.r);
|
||||
g += parseInt(rgb.g);
|
||||
b += parseInt(rgb.b);
|
||||
}
|
||||
r = Math.floor(r/rgblist.length);
|
||||
g = Math.floor(g/rgblist.length);
|
||||
b = Math.floor(b/rgblist.length);
|
||||
return "rgb("+r+","+g+","+b+")";
|
||||
}
|
||||
|
||||
|
||||
function blendColors(colorA, colorB, amount = 0.5) {
|
||||
const [rA, gA, bA] = colorA.match(/\w\w/g).map((c) => parseInt(c, 16));
|
||||
const [rB, gB, bB] = colorB.match(/\w\w/g).map((c) => parseInt(c, 16));
|
||||
const r = Math.round(rA + (rB - rA) * amount).toString(16).padStart(2, '0');
|
||||
const g = Math.round(gA + (gB - gA) * amount).toString(16).padStart(2, '0');
|
||||
const b = Math.round(bA + (bB - bA) * amount).toString(16).padStart(2, '0');
|
||||
return '#' + r + g + b;
|
||||
}
|
||||
|
||||
elements.mixer2 = {
|
||||
color: "#999999",
|
||||
ignore: ["mixer2"],
|
||||
category:"machines",
|
||||
insulate:true,
|
||||
hardness: 1,
|
||||
tick: function(pixel) {
|
||||
if (!isEmpty(pixel.x-1,pixel.y,true) && !isEmpty(pixel.x+1,pixel.y,true) && isEmpty(pixel.x,pixel.y+1,false))
|
||||
{
|
||||
if(elements.mixer2.ignore.includes(pixelMap[pixel.x-1][pixel.y].element) || elements.mixer2.ignore.includes(pixelMap[pixel.x+1][pixel.y].element))
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
createPixel(mixture([pixelMap[pixel.x-1][pixel.y].element,pixelMap[pixel.x+1][pixel.y].element]),pixel.x,pixel.y+1);
|
||||
deletePixel(pixel.x-1,pixel.y);
|
||||
deletePixel(pixel.x+1,pixel.y);
|
||||
}
|
||||
}
|
||||
doDefaults(pixel);
|
||||
},
|
||||
maxSize: 1
|
||||
};
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
A mod that adds some extra states of the art element.
|
||||
(c) ACrazyPencil 2025
|
||||
And thanks to the people who helped me with the code in the discord server.
|
||||
(c) ACrazyPencil 2025-2026
|
||||
*/
|
||||
|
||||
elements.powder_art = {
|
||||
|
|
@ -15,12 +16,18 @@ elements.powder_art = {
|
|||
canPlace: true,
|
||||
customColor: true,
|
||||
category: "powders",
|
||||
related: ["art", "liquid_art", "gas_art", "breakable_art"],
|
||||
related: ["art", "liquid_art", "gas_art", "breakable_art", "radiated_art"],
|
||||
burn: false,
|
||||
hardness: 1,
|
||||
conduct: false,
|
||||
stain: 0,
|
||||
state: "powder"
|
||||
state: "powder",
|
||||
reactions: {
|
||||
"radiation": { func:function(pixel, pixel2) {
|
||||
pixel.element = "gas_art"
|
||||
pixel2.element = "radiated_art"
|
||||
}}
|
||||
},
|
||||
}
|
||||
|
||||
elements.liquid_art = {
|
||||
|
|
@ -34,7 +41,7 @@ elements.liquid_art = {
|
|||
canPlace: true,
|
||||
customColor: true,
|
||||
category: "liquids",
|
||||
related: ["art", "powder_art", "breakable_art", "gas_art"],
|
||||
related: ["art", "powder_art", "breakable_art", "gas_art", "radiated_art"],
|
||||
burn: false,
|
||||
hardness: 1,
|
||||
conduct: false,
|
||||
|
|
@ -53,7 +60,7 @@ elements.gas_art = {
|
|||
canPlace: true,
|
||||
customColor: true,
|
||||
category: "gases",
|
||||
related: ["art", "powder_art", "liquid_art", "breakable_art"],
|
||||
related: ["art", "powder_art", "liquid_art", "breakable_art", "radiated_art"],
|
||||
burn: false,
|
||||
hardness: 1,
|
||||
conduct: false,
|
||||
|
|
@ -72,7 +79,7 @@ elements.breakable_art = {
|
|||
canPlace: true,
|
||||
customColor: true,
|
||||
category: "solids",
|
||||
related: ["art", "powder_art", "liquid_art"],
|
||||
related: ["art", "powder_art", "liquid_art", "radiated_art", "gas_art"],
|
||||
burn: false,
|
||||
conduct: false,
|
||||
stain: 0,
|
||||
|
|
@ -83,7 +90,31 @@ elements.breakable_art = {
|
|||
stateHigh: "gas_art",
|
||||
breakInto: "powder_art",
|
||||
breakIntoColorMultiplier: [1,1,1],
|
||||
},
|
||||
|
||||
elements.radiated_art = {
|
||||
name: "Radiated Art",
|
||||
color: "#ffffff",
|
||||
behavior: [
|
||||
"XX|XX|XX",
|
||||
"XX|RL:radiation%1|XX",
|
||||
"M2|M1|M2"
|
||||
],
|
||||
tool: function(pixel) {
|
||||
if (pixel.element === "paper") {
|
||||
deletePixel(pixel.x,pixel.y)
|
||||
}
|
||||
},
|
||||
canPlace: true,
|
||||
customColor: true,
|
||||
category: "powders",
|
||||
related: ["art", "liquid_art", "gas_art", "breakable_art", "powder_art"],
|
||||
burn: false,
|
||||
hardness: 1,
|
||||
conduct: false,
|
||||
stain: 0,
|
||||
state: "powder",
|
||||
}
|
||||
|
||||
elements.art.related = ["powder_art", "liquid_art", "gas_art", "breakable_art"]
|
||||
elements.art.related = ["powder_art", "liquid_art", "gas_art", "breakable_art", "radiated_art"]
|
||||
elements.art.hardness = 1
|
||||
|
|
|
|||
|
|
@ -1,27 +1,8 @@
|
|||
function whenAvailable(names, callback) {
|
||||
var interval = 10; // ms
|
||||
window.setTimeout(function() {
|
||||
let bool = true;
|
||||
for(let i = 0; i < names.length; i++)
|
||||
{
|
||||
if(!window[names[i]])
|
||||
{
|
||||
bool = false;
|
||||
}
|
||||
}
|
||||
if (bool) {
|
||||
callback();
|
||||
} else {
|
||||
whenAvailable(names, callback);
|
||||
}
|
||||
}, interval);
|
||||
}
|
||||
var modName = "mods/neutronium_compressor.js";
|
||||
var runAfterAutogenMod = "mods/runAfterAutogen2.js";
|
||||
var libraryMod = "mods/code_library.js";
|
||||
// var runAfterAutogenMod = "mods/runAfterAutogen2.js";
|
||||
// var libraryMod = "mods/code_library.js";
|
||||
|
||||
if(enabledMods.includes(runAfterAutogenMod) && enabledMods.includes(libraryMod)) {
|
||||
whenAvailable(["urlParams","runAfterAutogen"], function() {
|
||||
dependOn("code_library.js", function(){
|
||||
var singularityColorTemplate = ["#202020", "#505050", "#b0b0b0", "#c7c7c7"];
|
||||
|
||||
singularityNumber = 10000;
|
||||
|
|
@ -407,10 +388,4 @@ if(enabledMods.includes(runAfterAutogenMod) && enabledMods.includes(libraryMod))
|
|||
|
||||
//Post-generation tasks
|
||||
|
||||
});
|
||||
} else {
|
||||
if(!enabledMods.includes(runAfterAutogenMod)) { enabledMods.splice(enabledMods.indexOf(modName),0,runAfterAutogenMod) };
|
||||
if(!enabledMods.includes(libraryMod)) { enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod) };
|
||||
alert(`The "${runAfterAutogenMod}" and "${libraryMod}" mods are required; any missing mods in this list have been automatically inserted (reload for this to take effect).`)
|
||||
localStorage.setItem("enabledMods", JSON.stringify(enabledMods));
|
||||
};
|
||||
}, true);
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
elements.grass.tick = null;
|
||||
delete elements.grass.tick;
|
||||
elements.grass.behavior = [
|
||||
["XX", "XX", "XX"],
|
||||
["XX", "XX", "XX"],
|
||||
|
|
|
|||
|
|
@ -2794,6 +2794,9 @@ elements.ray_emitter = {
|
|||
pixelMap[lx][ly].rColor = pixel.color
|
||||
pixelMap[lx][ly].color = pixel.color
|
||||
}
|
||||
if (["pointer", "flash", "explosion"].includes(pixel.rayElement)){
|
||||
pixelMap[lx][ly].color = pixel.color
|
||||
}
|
||||
} else if (!isEmpty(lx, ly, true)){
|
||||
if (pixelMap[lx][ly].element != pixel.rayElement && pixel.rayStoppedByWalls){
|
||||
break;
|
||||
|
|
@ -2901,7 +2904,7 @@ elements.specific_ray_emitter = {
|
|||
}
|
||||
},
|
||||
hoverStat: function(pixel){
|
||||
return (pixel.rayElement.toUpperCase() || "unset") + ", " + (pixel.rayStoppedByWalls.toString().toUpperCase() || "unset") + ", " + (pixel.specificRayStart || "unset") + ", " + (pixel.specificRayEnd || "unset") + ", " + (pixel.specificRayAngle || "unset")
|
||||
return (pixel.rayElement || "unset").toUpperCase() + ", " + (pixel.rayStoppedByWalls || "unset").toString().toUpperCase() + ", " + (pixel.specificRayStart || "unset") + ", " + (pixel.specificRayEnd || "unset") + ", " + (pixel.specificRayAngle || "unset")
|
||||
},
|
||||
tick: function(pixel){
|
||||
if (pixelTicks == pixel.start){
|
||||
|
|
@ -2973,6 +2976,9 @@ elements.specific_ray_emitter = {
|
|||
pixelMap[lx][ly].life = pixel.life
|
||||
pixelMap[lx][ly].maxLife = pixel.life
|
||||
}
|
||||
if (["pointer", "flash", "explosion"].includes(pixel.rayElement)){
|
||||
pixelMap[lx][ly].color = pixel.color
|
||||
}
|
||||
} else if (!isEmpty(lx, ly, true)){
|
||||
if ((pixelMap[lx][ly].element != pixel.rayElement && pixel.rayStoppedByWalls) || pixelMap[lx][ly].element == pixel.stopAtElement){
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ removeMod("pizzasstuff.js");
|
|||
|
||||
reload(); */
|
||||
|
||||
alert("THIS MOD IS NO LONGER SUPPORTED!\nThe mod 'pizzasstuff.s' and all of its contents have been moved to mossstuff.js.\nPlease install mossstuff.js to continue getting updates.");
|
||||
// alert("THIS MOD IS NO LONGER SUPPORTED!\nThe mod 'pizzasstuff.s' and all of its contents have been moved to mossstuff.js.\nPlease install mossstuff.js to continue getting updates.");
|
||||
|
||||
|
||||
elements.freeze_ray = {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
var modName = "mods/portal.js";
|
||||
var onTryMoveIntoMod = "mods/onTryMoveInto.js";
|
||||
// var onTryMoveIntoMod = "mods/onTryMoveInto.js";
|
||||
var libraryMod = "mods/code_library.js";
|
||||
|
||||
if(enabledMods.includes(onTryMoveIntoMod) && enabledMods.includes(libraryMod)) {
|
||||
dependOn("code_library.js", function(){
|
||||
//https://stackoverflow.com/a/60922255
|
||||
if(!enabledMods.includes("mods/mobs.js")) {
|
||||
headBodyObject = {
|
||||
|
|
@ -17,7 +17,7 @@ if(enabledMods.includes(onTryMoveIntoMod) && enabledMods.includes(libraryMod)) {
|
|||
_correspondingPortals: null,
|
||||
},
|
||||
insulate: true,
|
||||
onTryMoveInto: function(pixel,otherPixel) {
|
||||
onMoveInto: function(pixel,otherPixel) {
|
||||
if(pixel._correspondingPortals == null) {
|
||||
return;
|
||||
};
|
||||
|
|
@ -112,9 +112,8 @@ if(enabledMods.includes(onTryMoveIntoMod) && enabledMods.includes(libraryMod)) {
|
|||
state: "solid",
|
||||
insulate: true,
|
||||
}
|
||||
} else {
|
||||
if(!enabledMods.includes(libraryMod)) { enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod) };
|
||||
if(!enabledMods.includes(onTryMoveIntoMod)) { enabledMods.splice(enabledMods.indexOf(modName),0,onTryMoveIntoMod) };
|
||||
localStorage.setItem("enabledMods", JSON.stringify(enabledMods));
|
||||
alert(`The "${libraryMod}" and "${onTryMoveIntoMod}" mods are all required; any missing mods in this list have been automatically inserted (reload for this to take effect).`)
|
||||
};
|
||||
}, true);
|
||||
// if(!enabledMods.includes(libraryMod)) { enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod) };
|
||||
// if(!enabledMods.includes(onTryMoveIntoMod)) { enabledMods.splice(enabledMods.indexOf(modName),0,onTryMoveIntoMod) };
|
||||
// localStorage.setItem("enabledMods", JSON.stringify(enabledMods));
|
||||
// alert(`The "${libraryMod}" and "${onTryMoveIntoMod}" mods are all required; any missing mods in this list have been automatically inserted (reload for this to take effect).`)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ var variablesMod = "mods/prop and prompt variables.js";
|
|||
var promptInputNullishes = ["null","none","","n/a"];
|
||||
var eightSpaces = " ".repeat(8);
|
||||
|
||||
if(enabledMods.includes(variablesMod)) {
|
||||
dependOn("prop and prompt variables.js", function(){
|
||||
commandHelpObject = {
|
||||
"set": "Sets properties for every pixel of a given type.\nUsage: set [property] [element] [value] <type>\nDon't include framing characters []<>.\nThe element can be \"all\" to set the property for every pixel.\nNote: Strings can't have spaces because spaces are the separator used in the parsing split().\nArguments in [brackets] are required and ones in <angle brackets> are optional.",
|
||||
|
||||
|
|
@ -1208,8 +1208,4 @@ Make sure to save your command in a file if you want to add this preset again.`
|
|||
desc: "<span style='color:#FF00FF;' onClick=funniPrompt()>Click here or press Shift+1 to open the command prompt.</span>",
|
||||
category:"special",
|
||||
};
|
||||
} else {
|
||||
alert(`The ${variablesMod} mod is required and has been automatically inserted (reload for this to take effect).`)
|
||||
enabledMods.splice(enabledMods.indexOf(modName),0,variablesMod)
|
||||
localStorage.setItem("enabledMods", JSON.stringify(enabledMods));
|
||||
};
|
||||
}, true);
|
||||
12
mods/prop.js
12
mods/prop.js
|
|
@ -1,7 +1,7 @@
|
|||
var modName = "mods/prop.js";
|
||||
var variablesMod = "mods/prop and prompt variables.js";
|
||||
|
||||
if(enabledMods.includes(variablesMod)) {
|
||||
dependOn("prop and prompt variables.js", function(){
|
||||
propProperty = "element";
|
||||
propValue = "sand";
|
||||
propType = "string";
|
||||
|
|
@ -212,7 +212,7 @@ if(enabledMods.includes(variablesMod)) {
|
|||
};
|
||||
pixelTempCheck(pixel);
|
||||
},
|
||||
category: "tools",
|
||||
category: "edit",
|
||||
desc: `Sets properties of pixels.<br/>Currently setting ${propProperty} to ${propValue} (${propType}).<br/><span onclick=propPrompt() style=\"color: #ff00ff;\";>Press [,] or click here</span> to open the property tool prompt.`,
|
||||
};
|
||||
|
||||
|
|
@ -452,15 +452,11 @@ if(enabledMods.includes(variablesMod)) {
|
|||
pixelTempCheck(pixel);
|
||||
};
|
||||
},
|
||||
category: "tools",
|
||||
category: "edit",
|
||||
desc: `Changes properties of pixels.<br/>Currently ${numberAdjusterVerb} ${numberAdjusterValue} ${numberAdjusterPreposition} ${numberAdjusterProperty}.<br/><span onclick=numberAdjusterPrompt() style=\"color: #ff00ff;\";>Press [Shift+,] or click here</span> to open the adjuster tool prompt.`,
|
||||
};
|
||||
|
||||
function updateNumberAdjusterDescription() {
|
||||
elements.number_adjuster.desc = numberAdjusterReverseOrder ? `Changes numeric properties of pixels.<br/>Currently ${numberAdjusterVerb} ${numberAdjusterProperty} ${numberAdjusterPreposition} ${numberAdjusterValue}.<br/><span onclick=numberAdjusterPrompt() style=\"color: #ff00ff;\";>Press [Shift+,] or click here</span> to open the adjuster tool prompt.` : `Changes numeric properties of pixels.<br/>Currently ${numberAdjusterVerb} ${numberAdjusterValue} ${numberAdjusterPreposition} ${numberAdjusterProperty}.<br/><span onclick=numberAdjusterPrompt() style=\"color: #ff00ff;\";>Press [Shift+,] or click here</span> to open the adjuster tool prompt.`;
|
||||
};
|
||||
} else {
|
||||
alert(`The ${variablesMod} mod is required and has been automatically inserted (reload for this to take effect).`)
|
||||
enabledMods.splice(enabledMods.indexOf(modName),0,variablesMod)
|
||||
localStorage.setItem("enabledMods", JSON.stringify(enabledMods));
|
||||
};
|
||||
}, true);
|
||||
|
|
@ -48,18 +48,18 @@ behaviors.SELFDELETE = [
|
|||
|
||||
pullerColour = '#e0adb6'
|
||||
|
||||
elements.pullersDesc = {
|
||||
color: pullerColour,
|
||||
name: 'pullers.js',
|
||||
category: "Mods",
|
||||
behavior: behaviors.SELFDELETE,
|
||||
tool: function(pixel) {},
|
||||
onSelect: function(pixel) {
|
||||
let info1stMod = `pullers.js is a mod made by voidapex11 that adds pullers to sandboxels`
|
||||
alert(info1stMod)
|
||||
return
|
||||
},
|
||||
};
|
||||
// elements.pullersDesc = {
|
||||
// color: pullerColour,
|
||||
// name: 'pullers.js',
|
||||
// category: "Mods",
|
||||
// behavior: behaviors.SELFDELETE,
|
||||
// tool: function(pixel) {},
|
||||
// onSelect: function(pixel) {
|
||||
// let info1stMod = `pullers.js is a mod made by voidapex11 that adds pullers to sandboxels`
|
||||
// alert(info1stMod)
|
||||
// return
|
||||
// },
|
||||
// };
|
||||
|
||||
// for the inator reference: if you know you know
|
||||
elements.immovable_inator = {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
var modName = "mods/random_liquids.js";
|
||||
var libraryMod = "mods/code_library.js";
|
||||
|
||||
if(enabledMods.includes(libraryMod)) {
|
||||
dependOn("code_library.js", function(){
|
||||
if(urlParams.get('liquidAmount') != null) { //null check
|
||||
liquidAmount = urlParams.get('liquidAmount')
|
||||
if(isNaN(liquidAmount) || liquidAmount === "" || liquidAmount === null) { //NaN check
|
||||
|
|
@ -213,8 +213,4 @@ if(enabledMods.includes(libraryMod)) {
|
|||
if(makeLiquidString == true) {
|
||||
console.log(`Liquids added to liquidString (length ${liquidString.length})`)
|
||||
}
|
||||
} else {
|
||||
alert(`The ${libraryMod} mod is required and has been automatically inserted (reload for this to take effect).`)
|
||||
enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod)
|
||||
localStorage.setItem("enabledMods", JSON.stringify(enabledMods));
|
||||
};
|
||||
}, true);
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
var modName = "mods/random_rocks.js";
|
||||
var libraryMod = "mods/code_library.js";
|
||||
|
||||
if(enabledMods.includes(libraryMod)) {
|
||||
dependOn("code_library.js", function(){
|
||||
if(urlParams.get('rockAmount') != null) { //null check
|
||||
rockAmount = urlParams.get('rockAmount')
|
||||
if(isNaN(rockAmount) || rockAmount === "" || rockAmount === null) { //NaN check
|
||||
|
|
@ -157,8 +157,4 @@ if(enabledMods.includes(libraryMod)) {
|
|||
if(makeRockString == true) {
|
||||
console.log(`Rocks added to rockString (length ${rockString.length})`)
|
||||
}
|
||||
} else {
|
||||
alert(`The ${libraryMod} mod is required and has been automatically inserted (reload for this to take effect).`)
|
||||
enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod)
|
||||
localStorage.setItem("enabledMods", JSON.stringify(enabledMods));
|
||||
};
|
||||
}, true);
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
var modName = "mods/randomness.js";
|
||||
var libraryMod = "mods/code_library.js";
|
||||
|
||||
if(enabledMods.includes(libraryMod)) {
|
||||
dependOn("code_library.js", function(){
|
||||
//i made some stupid things
|
||||
|
||||
//TPT reference
|
||||
|
|
@ -723,8 +723,4 @@ if(enabledMods.includes(libraryMod)) {
|
|||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if(!enabledMods.includes(libraryMod)) { enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod) };
|
||||
alert(`The "${libraryMod}" mod is required and has been automatically inserted (reload for this to take effect).`)
|
||||
localStorage.setItem("enabledMods", JSON.stringify(enabledMods));
|
||||
};
|
||||
}, true);
|
||||
51
mods/rays.js
51
mods/rays.js
|
|
@ -1,28 +1,27 @@
|
|||
function whenAvailable(names, callback) {
|
||||
var interval = 10; // ms
|
||||
window.setTimeout(function() {
|
||||
let bool = true;
|
||||
for(let i = 0; i < names.length; i++)
|
||||
{
|
||||
if(!window[names[i]])
|
||||
{
|
||||
bool = false;
|
||||
}
|
||||
}
|
||||
if (bool) {
|
||||
callback();
|
||||
} else {
|
||||
whenAvailable(names, callback);
|
||||
}
|
||||
}, interval);
|
||||
}
|
||||
// function whenAvailable(names, callback) {
|
||||
// var interval = 10; // ms
|
||||
// window.setTimeout(function() {
|
||||
// let bool = true;
|
||||
// for(let i = 0; i < names.length; i++)
|
||||
// {
|
||||
// if(!window[names[i]])
|
||||
// {
|
||||
// bool = false;
|
||||
// }
|
||||
// }
|
||||
// if (bool) {
|
||||
// callback();
|
||||
// } else {
|
||||
// whenAvailable(names, callback);
|
||||
// }
|
||||
// }, interval);
|
||||
// }
|
||||
|
||||
var modName = "mods/rays.js";
|
||||
var runAfterAutogenMod = "mods/runAfterAutogen2.js";
|
||||
var libraryMod = "mods/code_library.js";
|
||||
// var runAfterAutogenMod = "mods/runAfterAutogen2.js";
|
||||
// var libraryMod = "mods/code_library.js";
|
||||
|
||||
if(enabledMods.includes(runAfterAutogenMod) && enabledMods.includes(libraryMod)) {
|
||||
whenAvailable(["raaLoaded","libraryLoaded"], function() {
|
||||
dependOn("code_library.js", function(){
|
||||
runAfterAutogen(function() {
|
||||
snowAndIceCache = Object.keys(elements).filter(function(name) {
|
||||
return name.endsWith("snow") || name.endsWith("ice") || name == "rime"
|
||||
|
|
@ -455,10 +454,4 @@ whenAvailable(["raaLoaded","libraryLoaded"], function() {
|
|||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
} else {
|
||||
if(!enabledMods.includes(libraryMod)) { enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod) };
|
||||
if(!enabledMods.includes(runAfterAutogenMod)) { enabledMods.splice(enabledMods.indexOf(modName),0,runAfterAutogenMod) };
|
||||
localStorage.setItem("enabledMods", JSON.stringify(enabledMods));
|
||||
alert(`The "${runAfterAutogenMod}" and "${libraryMod}" mods are required and have been automatically inserted (reload for this to take effect).`);
|
||||
};
|
||||
},true);
|
||||
|
|
@ -49,7 +49,7 @@ elements.replace = {
|
|||
changePixel(pixel,replaceTo,true);
|
||||
};
|
||||
},
|
||||
category: "tools",
|
||||
category: "edit",
|
||||
desc: "Changes pixels of a specified type to another specified type.<br/>Currently replacing \"" + replaceFrom + "\" with \"" + replaceTo + "\".<br/><span onclick=replaceElementPrompt() style=\"color: #ff00ff;\";>Press [\"] or click here</span> to open the replace prompt.",
|
||||
};
|
||||
|
||||
|
|
@ -60,7 +60,7 @@ elements.alt_replace = {
|
|||
pixel.element = replaceTo;
|
||||
};
|
||||
},
|
||||
category: "tools",
|
||||
category: "edit",
|
||||
desc: "Changes pixels of a specified type to another specified type, but keeping their non-element-based properties.<br/>Currently replacing \"" + replaceFrom + "\" with \"" + replaceTo + "\".<br/><span onclick=replaceElementPrompt() style=\"color: #ff00ff;\";>Press [\"] or click here</span> to open the replace prompt.",
|
||||
hidden: true,
|
||||
};
|
||||
|
|
@ -73,7 +73,7 @@ elements.alt_alt_replace = {
|
|||
pixel.color = pixelColorPick(pixel);
|
||||
};
|
||||
},
|
||||
category: "tools",
|
||||
category: "edit",
|
||||
desc: "Changes pixels of a specified type to another specified type, but keeping their non-element-based properties except for color.<br/>Currently replacing \"" + replaceFrom + "\" with \"" + replaceTo + "\".<br/><span onclick=replaceElementPrompt() style=\"color: #ff00ff;\";>Press [\"] or click here</span> to open the replace prompt.",
|
||||
hidden: true,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
var modName = "mods/roseyiede.js";
|
||||
var libraryMod = "mods/code_library.js";
|
||||
|
||||
if(enabledMods.includes(libraryMod)) {
|
||||
dependOn("code_library.js", function(){
|
||||
/*
|
||||
//arbitrarily picked
|
||||
binitialArrayL = ["m","n","p","t","ch","k","b","d","j","g","f","th","s","sh","h","l","r","y","w","z"] //:eggTF:
|
||||
|
|
@ -356,8 +356,4 @@ if(enabledMods.includes(libraryMod)) {
|
|||
density: 956,
|
||||
temp: 120,
|
||||
}
|
||||
} else {
|
||||
alert(`The ${libraryMod} mod is required and has been automatically inserted (reload for this to take effect).`)
|
||||
enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod)
|
||||
localStorage.setItem("enabledMods", JSON.stringify(enabledMods));
|
||||
};
|
||||
}, true);
|
||||
|
|
@ -1,74 +1,71 @@
|
|||
var modName = "mods/random_rocks.js";
|
||||
var onTryMoveIntoMod = "mods/onTryMoveInto.js";
|
||||
var libraryMod = "mods/code_library.js";
|
||||
// var onTryMoveIntoMod = "mods/onTryMoveInto.js";
|
||||
// var libraryMod = "mods/code_library.js";
|
||||
|
||||
if(enabledMods.includes(onTryMoveIntoMod) && enabledMods.includes(libraryMod)) {
|
||||
elements.solid_rock = {
|
||||
color: ["#808080","#4f4f4f","#949494"],
|
||||
behavior: behaviors.WALL,
|
||||
reactions: {
|
||||
"water": {elem1: "wet_sand", chance: 0.00035},
|
||||
"salt_water": {elem1: "wet_sand", chance: 0.0005},
|
||||
"sugar_water": {elem1: "wet_sand", chance: 0.0004},
|
||||
"seltzer": {elem1: "wet_sand", chance: 0.0004},
|
||||
"dirty_water": {elem1: "wet_sand", chance: 0.0004},
|
||||
"soda": {elem1: "wet_sand", chance: 0.0004},
|
||||
"lichen": {elem1: "dirt", chance: 0.0025},
|
||||
"grape": {elem2: "juice", chance: 0.1, color2: "#291824"},
|
||||
"root": {elem1: "sand", chance: 0.0004},
|
||||
"wheat": {elem2: "flour"},
|
||||
"primordial_soup": {elem1: "wet_sand", chance: 0.001}
|
||||
},
|
||||
onTryMoveInto: function(pixel,otherPixel) {
|
||||
if(elements[otherPixel.element].category === "corruption") {
|
||||
if(Math.random() < 0.05) {
|
||||
changePixel(pixel,"corrupt_solid_rock");
|
||||
return;
|
||||
};
|
||||
} else {
|
||||
reactionStealer(pixel,otherPixel,"rock");
|
||||
dependOn("code_library.js", function(){
|
||||
|
||||
elements.solid_rock = {
|
||||
color: ["#808080","#4f4f4f","#949494"],
|
||||
behavior: behaviors.WALL,
|
||||
reactions: {
|
||||
"water": {elem1: "wet_sand", chance: 0.00035},
|
||||
"salt_water": {elem1: "wet_sand", chance: 0.0005},
|
||||
"sugar_water": {elem1: "wet_sand", chance: 0.0004},
|
||||
"seltzer": {elem1: "wet_sand", chance: 0.0004},
|
||||
"dirty_water": {elem1: "wet_sand", chance: 0.0004},
|
||||
"soda": {elem1: "wet_sand", chance: 0.0004},
|
||||
"lichen": {elem1: "dirt", chance: 0.0025},
|
||||
"grape": {elem2: "juice", chance: 0.1, color2: "#291824"},
|
||||
"root": {elem1: "sand", chance: 0.0004},
|
||||
"wheat": {elem2: "flour"},
|
||||
"primordial_soup": {elem1: "wet_sand", chance: 0.001}
|
||||
},
|
||||
onMoveInto: function(pixel,otherPixel) {
|
||||
if(elements[otherPixel.element].category === "corruption") {
|
||||
if(Math.random() < 0.05) {
|
||||
changePixel(pixel,"corrupt_solid_rock");
|
||||
return;
|
||||
};
|
||||
},
|
||||
tempHigh: 950,
|
||||
stateHigh: "magma",
|
||||
category: "land",
|
||||
state: "solid",
|
||||
density: 2600,
|
||||
hardness: 0.55,
|
||||
breakInto: "rock",
|
||||
}
|
||||
} else {
|
||||
reactionStealer(pixel,otherPixel,"rock");
|
||||
};
|
||||
},
|
||||
tempHigh: 950,
|
||||
stateHigh: "magma",
|
||||
category: "land",
|
||||
state: "solid",
|
||||
density: 2600,
|
||||
hardness: 0.55,
|
||||
breakInto: "rock",
|
||||
}
|
||||
|
||||
if(enabledMods.includes("mods/fey_and_more.js")) {
|
||||
elements.corrupt_solid_rock = {
|
||||
color: ["#514c78","#514c78","#2a264d","#2a264d","#514c78","#514c78"],
|
||||
behavior: behaviors.WALL,
|
||||
tempHigh: 1200,
|
||||
category: "corruption",
|
||||
state: "solid",
|
||||
density: 1250,
|
||||
breakInto: "corrupt_rock",
|
||||
tick: function(pixel) {
|
||||
var randomNeighborOffset = adjacentCoords[Math.floor(Math.random() * adjacentCoords.length)];
|
||||
var rfX = pixel.x+randomNeighborOffset[0];
|
||||
var rfY = pixel.y+randomNeighborOffset[1];
|
||||
if(!isEmpty(rfX,rfY,true)) {
|
||||
var otherPixel = pixelMap[rfX][rfY];
|
||||
if(otherPixel.element === "solid_rock") {
|
||||
if(Math.random() < 0.05) {
|
||||
changePixel(otherPixel,"corrupt_solid_rock")
|
||||
};
|
||||
if(enabledMods.includes("mods/fey_and_more.js")) {
|
||||
elements.corrupt_solid_rock = {
|
||||
color: ["#514c78","#514c78","#2a264d","#2a264d","#514c78","#514c78"],
|
||||
behavior: behaviors.WALL,
|
||||
tempHigh: 1200,
|
||||
category: "corruption",
|
||||
state: "solid",
|
||||
density: 1250,
|
||||
breakInto: "corrupt_rock",
|
||||
tick: function(pixel) {
|
||||
var randomNeighborOffset = adjacentCoords[Math.floor(Math.random() * adjacentCoords.length)];
|
||||
var rfX = pixel.x+randomNeighborOffset[0];
|
||||
var rfY = pixel.y+randomNeighborOffset[1];
|
||||
if(!isEmpty(rfX,rfY,true)) {
|
||||
var otherPixel = pixelMap[rfX][rfY];
|
||||
if(otherPixel.element === "solid_rock") {
|
||||
if(Math.random() < 0.05) {
|
||||
changePixel(otherPixel,"corrupt_solid_rock")
|
||||
};
|
||||
};
|
||||
},
|
||||
};
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
runAfterLoad(function() {
|
||||
elements.corrupt_solid_rock.reactions = elements.corrupt_land.reactions;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if(!enabledMods.includes(libraryMod)) { enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod) };
|
||||
if(!enabledMods.includes(onTryMoveIntoMod)) { enabledMods.splice(enabledMods.indexOf(modName),0,onTryMoveIntoMod) };
|
||||
localStorage.setItem("enabledMods", JSON.stringify(enabledMods));
|
||||
alert(`The "${libraryMod}" and "${onTryMoveIntoMod}" mods are all required; any missing mods in this list have been automatically inserted (reload for this to take effect).`)
|
||||
};
|
||||
runAfterLoad(function() {
|
||||
elements.corrupt_solid_rock.reactions = elements.corrupt_land.reactions;
|
||||
});
|
||||
}
|
||||
|
||||
},true);
|
||||
|
|
@ -1,8 +1,10 @@
|
|||
var modName = "mods/sponge_edit.js";
|
||||
var onTryMoveIntoMod = "mods/onTryMoveInto.js";
|
||||
// var onTryMoveIntoMod = "mods/onTryMoveInto.js";
|
||||
var libraryMod = "mods/code_library.js";
|
||||
|
||||
if(enabledMods.includes(onTryMoveIntoMod) && enabledMods.includes(libraryMod)) {
|
||||
|
||||
|
||||
dependOn("code_library.js", function(){
|
||||
elements.sponge.properties ??= {};
|
||||
elements.sponge.properties.maxAbsorb = 250;
|
||||
|
||||
|
|
@ -34,7 +36,7 @@ if(enabledMods.includes(onTryMoveIntoMod) && enabledMods.includes(libraryMod)) {
|
|||
};
|
||||
};
|
||||
|
||||
elements.sponge.onTryMoveInto = function(pixel,otherPixel) {
|
||||
elements.sponge.onMoveInto = function(pixel,otherPixel) {
|
||||
var absorbedElements = Object.keys(pixel.absorbed);
|
||||
if(absorbedElements.length == 0) {
|
||||
return false;
|
||||
|
|
@ -68,9 +70,4 @@ if(enabledMods.includes(onTryMoveIntoMod) && enabledMods.includes(libraryMod)) {
|
|||
};
|
||||
};
|
||||
};
|
||||
} else {
|
||||
enabledMods.splice(enabledMods.indexOf(modName),0,onTryMoveIntoMod);
|
||||
enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod);
|
||||
localStorage.setItem("enabledMods", JSON.stringify(enabledMods));
|
||||
alert(`The ${onTryMoveIntoMod} mod and ${libraryMod} mods are required and have been automatically inserted (reload for this to take effect).`);
|
||||
};
|
||||
}, true);
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
var modName = "mods/color_tools.js";
|
||||
var libraryMod = "mods/code_library.js";
|
||||
|
||||
if(enabledMods.includes(libraryMod)) {
|
||||
dependOn("code_library.js", function(){
|
||||
stripeFixedDefaultProperties = {
|
||||
color2: "rgb(0,0,0)",
|
||||
phase: 0,
|
||||
|
|
@ -103,8 +103,4 @@ if(enabledMods.includes(libraryMod)) {
|
|||
},
|
||||
desc: stripePaintDesc
|
||||
};
|
||||
} else {
|
||||
alert(`The ${libraryMod} mod is required and has been automatically inserted (reload for this to take effect).`)
|
||||
enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod)
|
||||
localStorage.setItem("enabledMods", JSON.stringify(enabledMods));
|
||||
};
|
||||
}, true);
|
||||
|
|
@ -1,10 +1,7 @@
|
|||
var modName = "mods/structure_test.js";
|
||||
var libraryMod = "mods/code_library.js";
|
||||
|
||||
if(!enabledMods.includes(libraryMod)) {
|
||||
enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod);
|
||||
alert(`The ${libraryMod} mod is required and has been automatically inserted (reload for this to take effect).`);
|
||||
} else {
|
||||
dependOn("code_library.js", function(){
|
||||
arrayLoaderVoids = ["air", "null", null];
|
||||
buildingOneSegmentDoor = ["concrete","wood_plank","concrete","wood_plank","concrete"];
|
||||
buildingOneSegmentWindows = ["concrete","glass_pane","concrete","glass_pane","concrete"];
|
||||
|
|
@ -752,4 +749,4 @@ if(!enabledMods.includes(libraryMod)) {
|
|||
worldgentypes.desert.layers.shift();
|
||||
};
|
||||
};
|
||||
};
|
||||
}, true);
|
||||
|
|
@ -76,13 +76,19 @@ runAfterAutogen(function(){
|
|||
for (var element in elements) {
|
||||
if (elements[element].category !== "tools") {
|
||||
elements[element].hidden = true;
|
||||
elements[element].category = "inventory";
|
||||
if (!settings.survival || Object.keys(settings.survival).length < 25) {
|
||||
elements[element].category = "inventory";
|
||||
}
|
||||
}
|
||||
if (elements[element].onShiftSelect) delete elements[element].onShiftSelect;
|
||||
}
|
||||
for (var element in settings.survival) {
|
||||
if (!elements[element]) { continue; }
|
||||
if (elements[element].category === "tools") { continue; }
|
||||
if (!elements[element].colorObject) {
|
||||
elements[element].color = "#ffffff";
|
||||
elements[element].colorObject = {"r": 255,"g": 255,"b": 255};
|
||||
}
|
||||
createElementButton(element);
|
||||
document.getElementById("elementButton-"+element).innerHTML += "("+settings.survival[element]+")";
|
||||
}
|
||||
|
|
@ -120,7 +126,7 @@ elements.cloner.ignore = elements.cloner.ignore.concat(["gold","gold_coin","molt
|
|||
elements.cloner.desc = "You can only clone one element at a time!"
|
||||
|
||||
elements.smash.tool = function(pixel) {
|
||||
if (elements[pixel.element].seed === true && pixel.element !== "cactus") { return }
|
||||
if (elements[pixel.element].seed === true) { return }
|
||||
if (elements[pixel.element].breakInto !== undefined || (elements[pixel.element].seed !== undefined && elements[pixel.element].seed !== true)) {
|
||||
// times 0.25 if not shiftDown else 1
|
||||
if (Math.random() < (elements[pixel.element].hardness || 1) * (shiftDown ? 1 : 0.25)) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
var modName = "mods/wifi.js";
|
||||
var libraryMod = "mods/code_library.js";
|
||||
|
||||
if(enabledMods.includes(libraryMod)) {
|
||||
dependOn("code_library.js", function(){
|
||||
//https://stackoverflow.com/a/60922255
|
||||
elements.wifi = {
|
||||
color: "#bfff7f",
|
||||
|
|
@ -155,8 +155,4 @@ if(enabledMods.includes(libraryMod)) {
|
|||
state: "solid",
|
||||
}
|
||||
|
||||
} else {
|
||||
if(!enabledMods.includes(libraryMod)) { enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod) };
|
||||
localStorage.setItem("enabledMods", JSON.stringify(enabledMods));
|
||||
alert(`The "${libraryMod}" mods is required; and has been automatically inserted (reload for this to take effect).`)
|
||||
};
|
||||
}, true);
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
var modName = "mods/wirelike_test.js";
|
||||
var libraryMod = "mods/code_library.js";
|
||||
|
||||
if(enabledMods.includes(libraryMod)) {
|
||||
dependOn("code_library.js", function(){
|
||||
//The CMYK is symbolic
|
||||
elements.start_test = {
|
||||
color: "#dddddd",
|
||||
|
|
@ -674,8 +674,4 @@ if(enabledMods.includes(libraryMod)) {
|
|||
};
|
||||
},
|
||||
};
|
||||
} else {
|
||||
alert(`The ${libraryMod} mod is required and has been automatically inserted (reload for this to take effect).`)
|
||||
enabledMods.splice(enabledMods.indexOf(modName),0,libraryMod)
|
||||
localStorage.setItem("enabledMods", JSON.stringify(enabledMods));
|
||||
};
|
||||
}, true)
|
||||
1008
mods/yumcherries.js
1008
mods/yumcherries.js
File diff suppressed because it is too large
Load Diff
900
mods/zoom.js
900
mods/zoom.js
|
|
@ -1,322 +1,606 @@
|
|||
const zoom_levels = [
|
||||
0.5,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
6,
|
||||
12
|
||||
]
|
||||
window.zoom_data_div = null
|
||||
window.zoom_level = 1
|
||||
window.zoom_panning = [0,0]
|
||||
// zoom.js
|
||||
"use strict";
|
||||
(() => {
|
||||
// src/custom_setting_types.ts
|
||||
var def_classes = () => {
|
||||
class Numlist2 extends Setting {
|
||||
step;
|
||||
input_container = null;
|
||||
push_btn = null;
|
||||
pop_btn = null;
|
||||
constructor(name, storage_name, desc, options) {
|
||||
super(
|
||||
name,
|
||||
storage_name,
|
||||
[5, 0],
|
||||
options.disabled,
|
||||
options.default_values,
|
||||
desc,
|
||||
options.custom_validator
|
||||
);
|
||||
this.step = options.step ?? 1;
|
||||
}
|
||||
#new_input(value, i) {
|
||||
const elem = document.createElement("input");
|
||||
elem.type = "number";
|
||||
elem.value = value.toString();
|
||||
elem.step = this.step.toString();
|
||||
elem.onchange = (ev) => {
|
||||
const parsed = Number.parseFloat(ev.target.value);
|
||||
if (!Number.isNaN(parsed)) {
|
||||
this.value[i] = parsed;
|
||||
this.set(this.value);
|
||||
}
|
||||
};
|
||||
return elem;
|
||||
}
|
||||
#push_pop_btns() {
|
||||
this.push_btn = document.createElement("button");
|
||||
this.push_btn.style.color = "#0F0";
|
||||
this.push_btn.innerText = "+";
|
||||
this.pop_btn = document.createElement("button");
|
||||
this.pop_btn.style.color = "#F00";
|
||||
this.pop_btn.innerText = "-";
|
||||
this.push_btn.onclick = () => {
|
||||
this.value.push(1);
|
||||
this.input_container.append(this.#new_input(1, this.value.length));
|
||||
};
|
||||
this.pop_btn.onclick = () => {
|
||||
this.value.pop();
|
||||
if (this.input_container.lastChild) {
|
||||
this.input_container.removeChild(this.input_container.lastChild);
|
||||
}
|
||||
};
|
||||
return [this.push_btn, this.pop_btn];
|
||||
}
|
||||
disable() {
|
||||
this.push_btn?.setAttribute("disabled", "true");
|
||||
this.pop_btn?.setAttribute("disabled", "true");
|
||||
}
|
||||
enable() {
|
||||
this.push_btn?.removeAttribute("disabled");
|
||||
this.pop_btn?.removeAttribute("disabled");
|
||||
}
|
||||
build() {
|
||||
const value = this.get();
|
||||
const container = document.createElement("span");
|
||||
container.classList.add("setting-span", "zm_nml_setting");
|
||||
const l_container = document.createElement("span");
|
||||
const label = document.createElement("span");
|
||||
label.innerText = this.name;
|
||||
const btn_container = document.createElement("span");
|
||||
btn_container.classList.add("zm_nml_btn_container");
|
||||
btn_container.append(...this.#push_pop_btns());
|
||||
l_container.append(label, document.createElement("br"), btn_container);
|
||||
this.input_container = document.createElement("span");
|
||||
this.input_container.classList.add("zm_nml_icontainer");
|
||||
const elems = [];
|
||||
value.forEach((x, i) => {
|
||||
elems.push(this.#new_input(x, i));
|
||||
});
|
||||
this.input_container.append(...elems);
|
||||
container.append(l_container, this.input_container);
|
||||
return container;
|
||||
}
|
||||
}
|
||||
class MultiSetting extends Setting {
|
||||
settings;
|
||||
elements = [];
|
||||
multi_input_name;
|
||||
rows = [];
|
||||
constructor(name, storage_name, extra_opts, ...settings) {
|
||||
super(
|
||||
name,
|
||||
storage_name,
|
||||
[255],
|
||||
extra_opts.disabled,
|
||||
extra_opts.default_value ?? 0,
|
||||
extra_opts.desc,
|
||||
void 0
|
||||
);
|
||||
this.settings = settings;
|
||||
this.multi_input_name = crypto.randomUUID();
|
||||
}
|
||||
build() {
|
||||
const container = document.createElement("span");
|
||||
this.settings.forEach((setting, i) => {
|
||||
const row_container = document.createElement("div");
|
||||
row_container.classList.add("zm_ms_row");
|
||||
this.rows.push(row_container);
|
||||
const select_btn = document.createElement("button");
|
||||
select_btn.classList.add("zm_ms_selbtn");
|
||||
select_btn.innerText = "#";
|
||||
const built_item = setting.build();
|
||||
built_item.classList.add("zm_ms_item");
|
||||
built_item.dataset.index = i.toString();
|
||||
row_container.dataset.current = i == this.value ? "true" : "false";
|
||||
select_btn.onclick = () => {
|
||||
this.set(i);
|
||||
setting.enable();
|
||||
for (const setting2 of this.settings) setting2.disable();
|
||||
for (const row of this.rows) {
|
||||
row.dataset.current = "false";
|
||||
row.querySelectorAll(".zm_ms_item input").forEach((x) => x.setAttribute("disabled", "true"));
|
||||
}
|
||||
built_item.querySelectorAll("input").forEach((x) => x.removeAttribute("disabled"));
|
||||
row_container.dataset.current = "true";
|
||||
};
|
||||
row_container.append(select_btn, built_item);
|
||||
container.appendChild(row_container);
|
||||
});
|
||||
return container;
|
||||
}
|
||||
}
|
||||
class SettingGroup extends Setting {
|
||||
settings;
|
||||
constructor(settings) {
|
||||
super(
|
||||
"",
|
||||
"",
|
||||
[2763],
|
||||
false
|
||||
);
|
||||
this.settings = settings;
|
||||
}
|
||||
enable() {
|
||||
for (const x of Object.values(this.settings)) {
|
||||
x.enable();
|
||||
}
|
||||
}
|
||||
disable() {
|
||||
for (const x of Object.values(this.settings)) {
|
||||
x.disable();
|
||||
}
|
||||
}
|
||||
build() {
|
||||
const container = document.createElement("div");
|
||||
for (const x of Object.values(this.settings)) {
|
||||
container.appendChild(x.build());
|
||||
}
|
||||
return container;
|
||||
}
|
||||
get() {
|
||||
return this.settings;
|
||||
}
|
||||
// Override these so the defaults don't do anything
|
||||
set() {
|
||||
}
|
||||
update() {
|
||||
}
|
||||
onUpdate() {
|
||||
}
|
||||
}
|
||||
return {
|
||||
Numlist: Numlist2,
|
||||
MultiSetting,
|
||||
SettingGroup
|
||||
};
|
||||
};
|
||||
|
||||
let colour_setting;
|
||||
|
||||
dependOn("betterSettings.js", () => {
|
||||
const settings_tab = new SettingsTab("zoom.js");
|
||||
colour_setting = new Setting(
|
||||
// src/custom_settings.ts
|
||||
var CustomSettingsManager = class {
|
||||
canvas_bkg;
|
||||
zoom;
|
||||
unl_zoom;
|
||||
fpan_speed;
|
||||
cpan_speed;
|
||||
upan_speed;
|
||||
use_ijkl;
|
||||
show_floater;
|
||||
pan_zeroing_en;
|
||||
zoom_zeroing_en;
|
||||
constructor(on_edit) {
|
||||
const { Numlist: Numlist2, MultiSetting, SettingGroup } = def_classes();
|
||||
const settings_tab = new SettingsTab("zoom.js");
|
||||
const validator = () => {
|
||||
on_edit.cb(this);
|
||||
return true;
|
||||
};
|
||||
this.canvas_bkg = new Setting(
|
||||
"Canvas background",
|
||||
"canvas_bkg",
|
||||
settingType.COLOR,
|
||||
false,
|
||||
defaultValue="#252525"
|
||||
);
|
||||
|
||||
settings_tab.registerSettings(undefined, colour_setting)
|
||||
settingsManager.registerTab(settings_tab)
|
||||
})
|
||||
|
||||
function handle_zoom(direction){
|
||||
switch (direction){
|
||||
case "in":
|
||||
if (!(zoom_level+1 in zoom_levels)) { break; }
|
||||
window.zoom_level += 1
|
||||
break;
|
||||
case "out":
|
||||
if (!(zoom_level-1 in zoom_levels)) { break; }
|
||||
window.zoom_level -= 1
|
||||
break;
|
||||
}
|
||||
rescale()
|
||||
}
|
||||
|
||||
function handle_pan(direction, speed){
|
||||
switch (direction){
|
||||
case "right":
|
||||
zoom_panning[0] -= speed
|
||||
break;
|
||||
case "left":
|
||||
zoom_panning[0] += speed
|
||||
break;
|
||||
case "up":
|
||||
zoom_panning[1] += speed
|
||||
break;
|
||||
case "down":
|
||||
zoom_panning[1] -= speed
|
||||
break;
|
||||
}
|
||||
rescale()
|
||||
}
|
||||
|
||||
function gen_button(row, col, html, click, nopos, id){
|
||||
const elem = document.createElement("button")
|
||||
|
||||
|
||||
if (!nopos){
|
||||
elem.style.gridColumn = row
|
||||
elem.style.gridRow = col
|
||||
}
|
||||
if (id) { elem.id = id }
|
||||
|
||||
// Table for the data-pos to assign (row major). If null, don't add.
|
||||
const data_pos_map = [
|
||||
["tl", null, "tr"],
|
||||
[null, null, null],
|
||||
["bl", null, "br"]
|
||||
]
|
||||
|
||||
elem.innerHTML = html
|
||||
elem.onclick = click
|
||||
|
||||
if (data_pos_map[row-1][col-1] !== null) {
|
||||
elem.dataset.pos = data_pos_map[row-1][col-1]
|
||||
}
|
||||
|
||||
return elem
|
||||
}
|
||||
|
||||
function add_css(){
|
||||
const CSS = `
|
||||
#zm_data_div { margin-bottom: 10px }
|
||||
#canvasDiv { overflow: hidden; background-color: var(--opac-85) }
|
||||
|
||||
@media(pointer=coarse){
|
||||
#zm_floater_container#zm_floater_container {
|
||||
width: 40%;
|
||||
height: auto;
|
||||
}
|
||||
#zm_floater_container:has(#zm_collapse[data-collapsed="true"]){
|
||||
width: calc(40% / 3);
|
||||
}
|
||||
}
|
||||
|
||||
@media(pointer:coarse) and (orientation:landscape){
|
||||
#zm_floater_container#zm_floater_container {
|
||||
width: auto;
|
||||
top: 5px;
|
||||
}
|
||||
#zm_floater_container:has(#zm_collapse[data-collapsed="true"]){
|
||||
width: calc(40% / 3);
|
||||
}
|
||||
}
|
||||
|
||||
#colorSelector { z-index: 1; right: 5px }
|
||||
#zm_floater_container {
|
||||
position: absolute;
|
||||
display: grid;
|
||||
|
||||
right: 5px;
|
||||
bottom: 5px;
|
||||
height: 100px;
|
||||
aspect-ratio: 1;
|
||||
|
||||
max-width: 200px;
|
||||
max-height: 200px;
|
||||
|
||||
border: 2px solid white;
|
||||
background-color: black;
|
||||
font-size: 120%;
|
||||
|
||||
button { text-align: center; border: 0px solid white }
|
||||
|
||||
button:where([data-pos="tl"]) { border-width: 0px 2px 2px 0px };
|
||||
button:where([data-pos="tr"]) { border-width: 2px 2px 0px 0px };
|
||||
button:where([data-pos="bl"]) { border-width: 0px 0px 2px 2px };
|
||||
button:where([data-pos="br"]) { border-width: 2px 0px 0px 2px };
|
||||
}
|
||||
#zm_floater_container:has(#zm_collapse[data-collapsed="true"]) {
|
||||
height: 50px;
|
||||
|
||||
button:not(#zm_collapse) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
#canvasDiv:has(#colorSelector[style *= "block"]) #zm_floater_container {
|
||||
bottom: 50px;
|
||||
}
|
||||
|
||||
.zm_corner { border: 2px solid white; }
|
||||
|
||||
#zm_collapse {
|
||||
grid-row: 3;
|
||||
grid-column: 3;
|
||||
}
|
||||
#zm_collapse[data-collapsed="true"] {
|
||||
grid-row: 1;
|
||||
grid-column: 1;
|
||||
border-width: 0px;
|
||||
}
|
||||
`
|
||||
|
||||
const style_div = document.createElement("style")
|
||||
style_div.innerHTML = CSS
|
||||
|
||||
document.head.appendChild(style_div)
|
||||
}
|
||||
|
||||
function add_zoom_floaters(){
|
||||
const container = document.createElement("div")
|
||||
container.id = "zm_floater_container"
|
||||
|
||||
// Pan mode selector (C: Coarse F: Fine)
|
||||
const pan_mode_sel = gen_button(
|
||||
1,3, "C",
|
||||
(evt) => {
|
||||
evt.target.dataset.mode = evt.target.dataset.mode == "F" ? "C" : "F"
|
||||
evt.target.innerText = evt.target.dataset.mode
|
||||
},
|
||||
"#252525",
|
||||
"The colour for the area around the canvas",
|
||||
validator
|
||||
);
|
||||
this.cpan_speed = new Setting(
|
||||
"Coarse pan speed",
|
||||
"cpan_speed",
|
||||
settingType.NUMBER,
|
||||
false,
|
||||
"zm_panmode_sel"
|
||||
)
|
||||
|
||||
const speed = () =>
|
||||
(window.zoom_level > 3 ? 5 : 10) * // More granular at higher zoom levels
|
||||
(pan_mode_sel.dataset.mode == "F" ? 0.25 : 1) // Increase granularity in fine mode
|
||||
|
||||
container.append(
|
||||
// Direction buttons
|
||||
gen_button(2,1, "↑", () => handle_pan("up" ,speed())),
|
||||
gen_button(1,2, "←", () => handle_pan("left" ,speed())),
|
||||
gen_button(3,2, "→", () => handle_pan("right" ,speed())),
|
||||
gen_button(2,3, "↓", () => handle_pan("down" ,speed())),
|
||||
|
||||
// Zoom buttons
|
||||
gen_button(1,1, "+", () => handle_zoom("in")),
|
||||
gen_button(3,1, "-", () => handle_zoom("out")),
|
||||
|
||||
// Collapse button
|
||||
gen_button(
|
||||
3,3, "#",
|
||||
(evt) => {
|
||||
evt.target.dataset.collapsed = evt.target.dataset.collapsed == "true"
|
||||
? "false"
|
||||
: "true"
|
||||
},
|
||||
true,
|
||||
"zm_collapse"
|
||||
10,
|
||||
"The default pan speed",
|
||||
validator
|
||||
);
|
||||
this.fpan_speed = new Setting(
|
||||
"Fine pan speed",
|
||||
"fpan_speed",
|
||||
settingType.NUMBER,
|
||||
false,
|
||||
3,
|
||||
"The pan speed when holding shift (F in the floater)",
|
||||
validator
|
||||
);
|
||||
this.upan_speed = new Setting(
|
||||
"Ultrafine pan speed",
|
||||
"upan_speed",
|
||||
settingType.NUMBER,
|
||||
false,
|
||||
1,
|
||||
"The pan speed when holding alt (U in the floater)",
|
||||
validator
|
||||
);
|
||||
this.show_floater = new Setting(
|
||||
"Show floater",
|
||||
"show_floater",
|
||||
settingType.BOOLEAN,
|
||||
false,
|
||||
true,
|
||||
"Whether to show the floater or not",
|
||||
validator
|
||||
);
|
||||
this.use_ijkl = new Setting(
|
||||
"Use IJKL",
|
||||
"use_ijkl",
|
||||
settingType.BOOLEAN,
|
||||
false,
|
||||
false,
|
||||
"Makes the mod use IJKL instead of WASD for panning (requires refresh)",
|
||||
validator
|
||||
);
|
||||
this.pan_zeroing_en = new Setting(
|
||||
"Enable pan zeroing",
|
||||
"en_pzero",
|
||||
settingType.BOOLEAN,
|
||||
false,
|
||||
true,
|
||||
"Allows the Q key to reset pan (requires refresh)",
|
||||
validator
|
||||
);
|
||||
this.zoom_zeroing_en = new Setting(
|
||||
"Enable zoom zeroing",
|
||||
"en_zzero",
|
||||
settingType.BOOLEAN,
|
||||
false,
|
||||
true,
|
||||
"Allows the P key to reset zoom. Doesn't work with set zoom levels (requires refresh)",
|
||||
validator
|
||||
);
|
||||
const zoom_levels = new Numlist2(
|
||||
"Zoom levels",
|
||||
"zoom_levels",
|
||||
"Zoom levels",
|
||||
{
|
||||
default_values: [0.5, 1, 2, 3, 6, 12],
|
||||
step: 0.1,
|
||||
custom_validator: validator
|
||||
}
|
||||
);
|
||||
this.unl_zoom = new SettingGroup({
|
||||
speed: new Setting(
|
||||
"Zoom speed",
|
||||
"unl_zoom_speed",
|
||||
settingType.NUMBER,
|
||||
false,
|
||||
2,
|
||||
"The zoom magnitude (as the multiplier to the zoom level every time zoom is used)",
|
||||
validator
|
||||
),
|
||||
pan_mode_sel
|
||||
)
|
||||
|
||||
const canvas_div = document.getElementById("canvasDiv")
|
||||
canvas_div.style.backgroundColor = colour_setting?.value ?? "#252525"
|
||||
canvas_div.appendChild(container)
|
||||
}
|
||||
|
||||
function rescale(){
|
||||
log_info()
|
||||
|
||||
const scale = zoom_levels[zoom_level]
|
||||
const x = zoom_panning[0] * (pixelSize * scale)
|
||||
const y = zoom_panning[1] * (pixelSize * scale)
|
||||
|
||||
gameCanvas.style.transform = `translate(${x}px, ${y}px) translateX(-50%) scale(${scale})`
|
||||
}
|
||||
|
||||
function log_info(){
|
||||
// Values are negated to make them more intuitive
|
||||
const x_pan = (-zoom_panning[0]).toString().padEnd(4)
|
||||
const y_pan = (-zoom_panning[1]).toString().padEnd(4)
|
||||
|
||||
if (zoom_data_div === null){ return; }
|
||||
|
||||
zoom_data_div.innerText = ""
|
||||
zoom_data_div.innerText += `Scale: ${zoom_levels[zoom_level]}x\n`
|
||||
zoom_data_div.innerText += `Pan : ${x_pan}, ${y_pan}`
|
||||
}
|
||||
|
||||
function patch_keybinds(){
|
||||
// Be more granular at higher zoom levels
|
||||
const speed_a = () => zoom_level > 3 ? 5 : 10
|
||||
const speed_b = () => zoom_level > 3 ? 10 : 20
|
||||
|
||||
keybinds["9"] = () => handle_zoom("in")
|
||||
keybinds["0"] = () => handle_zoom("out")
|
||||
|
||||
keybinds["w"] = () => handle_pan("up", speed_a())
|
||||
keybinds["a"] = () => handle_pan("left", speed_a())
|
||||
keybinds["s"] = () => handle_pan("down", speed_a())
|
||||
keybinds["d"] = () => handle_pan("right", speed_a())
|
||||
|
||||
keybinds["W"] = () => handle_pan("up", speed_b())
|
||||
keybinds["A"] = () => handle_pan("left", speed_b())
|
||||
keybinds["S"] = () => handle_pan("down", speed_b())
|
||||
keybinds["D"] = () => handle_pan("right", speed_b())
|
||||
}
|
||||
|
||||
function patch_ui(){
|
||||
add_css()
|
||||
add_zoom_floaters()
|
||||
|
||||
zoom_data_div = document.createElement("div")
|
||||
zoom_data_div.id = "zm_data_div"
|
||||
document.getElementById("logDiv").prepend(zoom_data_div)
|
||||
|
||||
const controls_table = document.getElementById("controlsTable").lastElementChild
|
||||
controls_table.insertAdjacentHTML("beforeBegin",`
|
||||
<tr>
|
||||
<td>Zoom in/out</td>
|
||||
<td>
|
||||
<kbd>9</kbd>/
|
||||
<kbd>0</kbd>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Pan</td>
|
||||
<td>
|
||||
<kbd>W</kbd>
|
||||
<kbd>A</kbd>
|
||||
<kbd>S</kbd>
|
||||
<kbd>D</kbd>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Pan (fast)</td>
|
||||
<td>
|
||||
<kbd>Shift</kbd> +
|
||||
<kbd>W</kbd>
|
||||
<kbd>A</kbd>
|
||||
<kbd>S</kbd>
|
||||
<kbd>D</kbd>
|
||||
</td>
|
||||
</tr>
|
||||
`)
|
||||
}
|
||||
|
||||
// Redefine to give correct numbers when zoomed
|
||||
window.getMousePos = (canvas, evt) => {
|
||||
if (evt.touches) {
|
||||
evt.preventDefault();
|
||||
evt = evt.touches[0];
|
||||
isMobile = true;
|
||||
min: new Setting(
|
||||
"Zoom limit (min)",
|
||||
"unl_zlim_min",
|
||||
settingType.NUMBER,
|
||||
false,
|
||||
0.25,
|
||||
"The lower zoom limit (reducing may lead to rounding error coming back from very low levels)",
|
||||
validator
|
||||
),
|
||||
max: new Setting(
|
||||
"Zoom limit (max)",
|
||||
"unl_zlim_max",
|
||||
settingType.NUMBER,
|
||||
false,
|
||||
25,
|
||||
"The upper zoom limit (reducing may lead to rounding error coming back from very high levels)",
|
||||
validator
|
||||
)
|
||||
});
|
||||
this.zoom = new MultiSetting(
|
||||
"Zoom mode",
|
||||
"zoom_mode",
|
||||
{},
|
||||
zoom_levels,
|
||||
this.unl_zoom
|
||||
);
|
||||
settings_tab.registerSettings(
|
||||
void 0,
|
||||
this.canvas_bkg
|
||||
);
|
||||
settings_tab.registerSettings(
|
||||
"Controls",
|
||||
this.use_ijkl,
|
||||
this.show_floater,
|
||||
this.pan_zeroing_en,
|
||||
this.zoom_zeroing_en
|
||||
);
|
||||
settings_tab.registerSettings(
|
||||
"Zoom",
|
||||
this.zoom
|
||||
);
|
||||
settings_tab.registerSettings(
|
||||
"Panning",
|
||||
this.cpan_speed,
|
||||
this.fpan_speed,
|
||||
this.upan_speed
|
||||
);
|
||||
settingsManager.registerTab(settings_tab);
|
||||
}
|
||||
const rect = canvas.getBoundingClientRect();
|
||||
};
|
||||
|
||||
let x = (evt.clientX - rect.left) / zoom_levels[zoom_level];
|
||||
let y = (evt.clientY - rect.top) / zoom_levels[zoom_level];
|
||||
// src/handler.ts
|
||||
var Handler = class {
|
||||
settings;
|
||||
patcher;
|
||||
zoom_panning = [0, 0];
|
||||
zoom_level;
|
||||
constructor(settings, patcher) {
|
||||
this.settings = settings;
|
||||
this.patcher = patcher;
|
||||
this.zoom_level = 1;
|
||||
this.patch_keybinds();
|
||||
this.patch_floater();
|
||||
window.getMousePos = (canvas2, evt) => {
|
||||
if (evt.touches) {
|
||||
evt.preventDefault();
|
||||
evt = evt.touches[0];
|
||||
isMobile = true;
|
||||
}
|
||||
const rect = canvas2.getBoundingClientRect();
|
||||
const clx = evt.clientX;
|
||||
const cly = evt.clientY;
|
||||
let x = (clx - rect.left) / this.scale();
|
||||
let y = (cly - rect.top) / this.scale();
|
||||
x = Math.floor(x / canvas2.clientWidth * (width + 1));
|
||||
y = Math.floor(y / canvas2.clientHeight * (height + 1));
|
||||
return { x, y };
|
||||
};
|
||||
runAfterReset(() => {
|
||||
this.zoom_level = 1;
|
||||
this.zoom_panning = [0, 0];
|
||||
this.update();
|
||||
});
|
||||
}
|
||||
handle_zoom(direction) {
|
||||
if (this.settings.zoom.value == 0) {
|
||||
switch (direction) {
|
||||
case "in":
|
||||
if (!(this.zoom_level + 1 in this.settings.zoom.settings[0].value)) {
|
||||
break;
|
||||
}
|
||||
this.zoom_level += 1;
|
||||
break;
|
||||
case "out":
|
||||
if (!(this.zoom_level - 1 in this.settings.zoom.settings[0].value)) {
|
||||
break;
|
||||
}
|
||||
this.zoom_level -= 1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
const settings = this.settings.zoom.settings[1].settings;
|
||||
const speed = settings.speed.value;
|
||||
const min = settings.min.value;
|
||||
const max = settings.max.value;
|
||||
switch (direction) {
|
||||
case "in":
|
||||
if (this.zoom_level * speed > max) break;
|
||||
this.zoom_level *= speed;
|
||||
break;
|
||||
case "out":
|
||||
if (this.zoom_level / speed < min) break;
|
||||
this.zoom_level /= speed;
|
||||
break;
|
||||
}
|
||||
this.zoom_level = Number(this.zoom_level.toPrecision(3));
|
||||
}
|
||||
this.update();
|
||||
}
|
||||
handle_pan(direction, speed) {
|
||||
switch (direction) {
|
||||
case "right":
|
||||
this.zoom_panning[0] -= speed;
|
||||
break;
|
||||
case "left":
|
||||
this.zoom_panning[0] += speed;
|
||||
break;
|
||||
case "up":
|
||||
this.zoom_panning[1] += speed;
|
||||
break;
|
||||
case "down":
|
||||
this.zoom_panning[1] -= speed;
|
||||
break;
|
||||
}
|
||||
this.update();
|
||||
}
|
||||
scale() {
|
||||
return this.settings.zoom.value == 0 ? this.settings.zoom.settings[0].value[this.zoom_level] : this.zoom_level;
|
||||
}
|
||||
update() {
|
||||
this.log_info();
|
||||
const x = this.zoom_panning[0] * (pixelSize * this.scale());
|
||||
const y = this.zoom_panning[1] * (pixelSize * this.scale());
|
||||
canvas.style.transform = `translate(${x}px, ${y}px) translateX(-50%) scale(${this.scale()})`;
|
||||
}
|
||||
log_info() {
|
||||
const x_pan = (-this.zoom_panning[0]).toString().padEnd(4);
|
||||
const y_pan = (-this.zoom_panning[1]).toString().padEnd(4);
|
||||
this.patcher.zoom_data_div.innerText = "";
|
||||
this.patcher.zoom_data_div.innerText += `Scale: ${this.scale()}x
|
||||
`;
|
||||
this.patcher.zoom_data_div.innerText += `Pan : ${x_pan}, ${y_pan}`;
|
||||
}
|
||||
kbd_speed_noshift(ev) {
|
||||
return ev.altKey ? this.settings.upan_speed.value : this.settings.cpan_speed.value;
|
||||
}
|
||||
patch_keybinds() {
|
||||
const pan_keys = this.settings.use_ijkl.value ? ["i", "j", "k", "l"] : ["w", "a", "s", "d"];
|
||||
const pan_keys_upper = this.settings.use_ijkl.value ? ["I", "J", "K", "L"] : ["W", "A", "S", "D"];
|
||||
keybinds["9"] = () => this.handle_zoom("in");
|
||||
keybinds["0"] = () => this.handle_zoom("out");
|
||||
keybinds[pan_keys[0]] = (ev) => this.handle_pan("up", this.kbd_speed_noshift(ev));
|
||||
keybinds[pan_keys[1]] = (ev) => this.handle_pan("left", this.kbd_speed_noshift(ev));
|
||||
keybinds[pan_keys[2]] = (ev) => this.handle_pan("down", this.kbd_speed_noshift(ev));
|
||||
keybinds[pan_keys[3]] = (ev) => this.handle_pan("right", this.kbd_speed_noshift(ev));
|
||||
keybinds[pan_keys_upper[0]] = () => this.handle_pan("up", this.settings.fpan_speed.value);
|
||||
keybinds[pan_keys_upper[1]] = () => this.handle_pan("left", this.settings.fpan_speed.value);
|
||||
keybinds[pan_keys_upper[2]] = () => this.handle_pan("down", this.settings.fpan_speed.value);
|
||||
keybinds[pan_keys_upper[3]] = () => this.handle_pan("right", this.settings.fpan_speed.value);
|
||||
if (this.settings.pan_zeroing_en.value) {
|
||||
keybinds["q"] = () => {
|
||||
this.zoom_panning = [0, 0];
|
||||
this.update();
|
||||
};
|
||||
}
|
||||
if (this.settings.zoom_zeroing_en.value) {
|
||||
keybinds["p"] = () => {
|
||||
if (this.settings.zoom.value == 1) this.zoom_level = 1;
|
||||
this.update();
|
||||
};
|
||||
}
|
||||
}
|
||||
floater_speed() {
|
||||
switch (this.patcher.panmode_sel.innerText) {
|
||||
case "C":
|
||||
return this.settings.cpan_speed.value;
|
||||
case "F":
|
||||
return this.settings.fpan_speed.value;
|
||||
case "U":
|
||||
return this.settings.upan_speed.value;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
patch_floater() {
|
||||
function patch(id, fn) {
|
||||
document.getElementById(id).onclick = fn;
|
||||
}
|
||||
patch("zm_floater_zi", () => this.handle_zoom("in"));
|
||||
patch("zm_floater_zo", () => this.handle_zoom("out"));
|
||||
patch("zm_floater_u", () => this.handle_pan("up", this.floater_speed()));
|
||||
patch("zm_floater_d", () => this.handle_pan("down", this.floater_speed()));
|
||||
patch("zm_floater_l", () => this.handle_pan("left", this.floater_speed()));
|
||||
patch("zm_floater_r", () => this.handle_pan("right", this.floater_speed()));
|
||||
}
|
||||
};
|
||||
|
||||
x = Math.floor((x / canvas.clientWidth) * (width+1));
|
||||
y = Math.floor((y / canvas.clientHeight) * (height+1));
|
||||
// assets/numlist.css
|
||||
var numlist_default = "#settingsMenu .zm_nml_btn_container button { font-size: 2em; padding: 0px; margin: 0px;}\r\n#settingsMenu .zm_nml_icontainer { align-self: center }\r\n#settingsMenu .zm_nml_setting { display: grid; grid-template-columns: 7em 1fr;}\r\n\r\n#settingsMenu .zm_nml_setting span {\r\n input { width: 2em; margin-right: 4px; margin-bottom: 4px;}\r\n \r\n input:focus {\r\n outline: none;\r\n box-shadow: none;\r\n border-color: white;\r\n }\r\n}";
|
||||
|
||||
return {x:x, y:y};
|
||||
// assets/main.css
|
||||
var main_default = '#zm_data_div { margin-bottom: 10px }\r\n#canvasDiv { overflow: hidden; background-color: var(--opac-85) }\r\n\r\n@media(pointer=coarse){\r\n #zm_floater_container#zm_floater_container { \r\n width: 40%;\r\n height: auto;\r\n }\r\n #zm_floater_container:has(#zm_collapse[data-collapsed="true"]){\r\n width: calc(40% / 3);\r\n }\r\n}\r\n\r\n@media(pointer:coarse) and (orientation:landscape){\r\n #zm_floater_container#zm_floater_container {\r\n width: auto;\r\n top: 5px;\r\n }\r\n #zm_floater_container:has(#zm_collapse[data-collapsed="true"]){\r\n width: calc(40% / 3);\r\n }\r\n}\r\n\r\n#colorSelector { z-index: 1; right: 5px }\r\n#zm_floater_container {\r\n position: absolute;\r\n display: grid;\r\n\r\n right: 5px;\r\n bottom: 5px;\r\n height: 100px;\r\n aspect-ratio: 1;\r\n\r\n max-width: 200px;\r\n max-height: 200px;\r\n\r\n border: 2px solid white;\r\n background-color: black;\r\n font-size: 120%;\r\n\r\n button { text-align: center; border: 0px solid white }\r\n\r\n button:where([data-pos="tl"]) { border-width: 0px 2px 2px 0px };\r\n button:where([data-pos="tr"]) { border-width: 2px 2px 0px 0px };\r\n button:where([data-pos="bl"]) { border-width: 0px 0px 2px 2px };\r\n button:where([data-pos="br"]) { border-width: 2px 0px 0px 2px };\r\n}\r\n#zm_floater_container:has(#zm_collapse[data-collapsed="true"]) {\r\n height: 50px;\r\n \r\n button:not(#zm_collapse) { display: none; }\r\n}\r\n#canvasDiv:has(#colorSelector[style *= "block"]) #zm_floater_container {\r\n bottom: 50px;\r\n}\r\n\r\n.zm_corner { border: 2px solid white; }\r\n\r\n#zm_collapse {\r\n grid-row: 3;\r\n grid-column: 3;\r\n}\r\n#zm_collapse[data-collapsed="true"] {\r\n grid-row: 1;\r\n grid-column: 1;\r\n border-width: 0px;\r\n}';
|
||||
|
||||
// assets/multisetting.css
|
||||
var multisetting_default = '.zm_ms_row {\r\n display: grid;\r\n grid-template-columns: 2.2em 1fr; \r\n}\r\n\r\n.zm_ms_row[data-current="false"] {\r\n .zm_ms_selbtn { color: transparent }\r\n}\r\n\r\n.zm_ms_selbtn.zm_ms_selbtn:not(#_) {\r\n height: 100%;\r\n width: calc(100% - 10px);\r\n\r\n margin-right: 2px;\r\n padding: 0px;\r\n\r\n border: 2px solid var(--theme);\r\n font-size: 1.5em;\r\n}';
|
||||
|
||||
// assets/ctrl_info.html
|
||||
var ctrl_info_default = "<tr>\r\n <td>Zoom in/out</td>\r\n <td>\r\n <kbd>9</kbd>/\r\n <kbd>0</kbd>\r\n </td>\r\n</tr>\r\n<tr>\r\n <td>Pan</td>\r\n <td>\r\n <kbd>W</kbd>\r\n <kbd>A</kbd>\r\n <kbd>S</kbd>\r\n <kbd>D</kbd>\r\n </td>\r\n</tr>\r\n<tr>\r\n <td>Pan (fast)</td>\r\n <td>\r\n <kbd>Shift</kbd> + \r\n <kbd>W</kbd>\r\n <kbd>A</kbd>\r\n <kbd>S</kbd>\r\n <kbd>D</kbd>\r\n </td>\r\n</tr>";
|
||||
|
||||
// assets/floater.html
|
||||
var floater_default = '<div id="zm_floater_container">\r\n <button id="zm_floater_u" style="grid-area: 1 / 2;">↑</button>\r\n <button id="zm_floater_d" style="grid-area: 3 / 2;">↓</button>\r\n <button id="zm_floater_l" style="grid-area: 2 / 1;">←</button>\r\n <button id="zm_floater_r" style="grid-area: 2 / 3;">→</button>\r\n \r\n <button id="zm_floater_zi" data-pos="tl" style="grid-area: 1 / 1;">+</button>\r\n <button id="zm_floater_zo" data-pos="bl" style="grid-area: 1 / 3;">-</button>\r\n\r\n <button id="zm_collapse" data-pos="br">#</button>\r\n <button id="zm_panmode_sel" data-pos="tr" style="grid-area: 3 / 1;">C</button>\r\n</div>';
|
||||
|
||||
// assets/nlist_spinner.png
|
||||
var nlist_spinner_default = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAYCAYAAADH2bwQAAAAcklEQVQokcWSXQrAIAyDv8oOoPe/49wJzB7coIg/jA2WPhQ1TdOiATsThNmjJ8QV4XjdokIkRHqiEAF2NAgoSw8GlCuD3K3zYEzgFdSQBbA15LaYQN1i9lU+3y16CgDqjSl/MKBoMIk5DyNk46sf9SfhBITwI86iGhy9AAAAAElFTkSuQmCC";
|
||||
|
||||
// assets/spinner.css.ts
|
||||
var CSS = `
|
||||
#betterSettings\\/div\\/zoom\\.js input::-webkit-inner-spin-button,
|
||||
#betterSettings\\/div\\/zoom\\.js input::-webkit-outer-spin-button {
|
||||
-webkit-appearance: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 0.75em;
|
||||
background: #000 url(${nlist_spinner_default}) no-repeat center center;
|
||||
background-size: 100%;
|
||||
border-left: 2px solid var(--theme);
|
||||
image-rendering: pixelated;
|
||||
opacity: 0.8;
|
||||
}
|
||||
#betterSettings\\/div\\/zoom\\.js input::-webkit-inner-spin-button:hover,
|
||||
#betterSettings\\/div\\/zoom\\.js input::-webkit-outer-spin-button:active {
|
||||
border-left: 2px solid white;
|
||||
opacity: 1;
|
||||
}
|
||||
`;
|
||||
var spinner_css_default = CSS;
|
||||
|
||||
runAfterReset(() => {
|
||||
window.zoom_level = 1
|
||||
rescale()
|
||||
})
|
||||
// src/patcher.ts
|
||||
var Patcher = class {
|
||||
zoom_data_div;
|
||||
floater_div;
|
||||
canvas_div;
|
||||
settings;
|
||||
panmode_sel;
|
||||
constructor(settings) {
|
||||
this.settings = settings;
|
||||
const style_div = document.createElement("style");
|
||||
style_div.innerHTML = main_default;
|
||||
document.head.appendChild(style_div);
|
||||
dependOn("betterSettings.js", () => {
|
||||
const style_div2 = document.createElement("style");
|
||||
style_div2.innerHTML = numlist_default + multisetting_default + spinner_css_default;
|
||||
document.head.appendChild(style_div2);
|
||||
});
|
||||
this.canvas_div = document.getElementById("canvasDiv");
|
||||
this.canvas_div.insertAdjacentHTML("beforeend", floater_default);
|
||||
this.floater_div = document.getElementById("zm_floater_container");
|
||||
this.panmode_sel = document.getElementById("zm_panmode_sel");
|
||||
this.panmode_sel.onclick = () => {
|
||||
switch (this.panmode_sel.innerText) {
|
||||
case "C":
|
||||
this.panmode_sel.innerText = "F";
|
||||
break;
|
||||
case "F":
|
||||
this.panmode_sel.innerText = "U";
|
||||
break;
|
||||
case "U":
|
||||
this.panmode_sel.innerText = "C";
|
||||
break;
|
||||
}
|
||||
};
|
||||
const collapse_btn = document.getElementById("zm_collapse");
|
||||
collapse_btn.onclick = () => {
|
||||
collapse_btn.dataset.collapsed = collapse_btn.dataset.collapsed == "true" ? "false" : "true";
|
||||
};
|
||||
this.zoom_data_div = document.createElement("div");
|
||||
this.zoom_data_div.id = "zm_data_div";
|
||||
document.getElementById("logDiv")?.prepend(this.zoom_data_div);
|
||||
document.getElementById("controlsTable")?.lastElementChild?.insertAdjacentHTML("beforebegin", ctrl_info_default);
|
||||
this.update_from_settings();
|
||||
runAfterLoad(() => {
|
||||
const cb = this.update_from_settings.bind(this);
|
||||
for (const elem of document.querySelectorAll("#betterSettings\\/div\\/zoom\\.js span.setting-span input")) {
|
||||
elem.addEventListener(elem.classList.contains("toggleInput") ? "click" : "change", cb);
|
||||
}
|
||||
});
|
||||
}
|
||||
update_from_settings() {
|
||||
this.floater_div.style.display = this.settings.show_floater.value ? "grid" : "none";
|
||||
this.canvas_div.style.backgroundColor = this.settings.canvas_bkg.value ?? "#252525";
|
||||
}
|
||||
};
|
||||
|
||||
runAfterLoad(() => {
|
||||
patch_keybinds()
|
||||
patch_ui()
|
||||
})
|
||||
// src/main.ts
|
||||
dependOn("betterSettings.js", () => {
|
||||
const on_change = { cb: () => {
|
||||
} };
|
||||
const settings_manager = new CustomSettingsManager(on_change);
|
||||
runAfterLoad(() => {
|
||||
const patcher = new Patcher(settings_manager);
|
||||
const handler = new Handler(settings_manager, patcher);
|
||||
});
|
||||
}, true);
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,322 @@
|
|||
const zoom_levels = [
|
||||
0.5,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
6,
|
||||
12
|
||||
]
|
||||
window.zoom_data_div = null
|
||||
window.zoom_level = 1
|
||||
window.zoom_panning = [0,0]
|
||||
|
||||
let colour_setting;
|
||||
|
||||
dependOn("betterSettings.js", () => {
|
||||
const settings_tab = new SettingsTab("zoom.js");
|
||||
colour_setting = new Setting(
|
||||
"Canvas background",
|
||||
"canvas_bkg",
|
||||
settingType.COLOR,
|
||||
false,
|
||||
defaultValue="#252525"
|
||||
);
|
||||
|
||||
settings_tab.registerSettings(undefined, colour_setting)
|
||||
settingsManager.registerTab(settings_tab)
|
||||
})
|
||||
|
||||
function handle_zoom(direction){
|
||||
switch (direction){
|
||||
case "in":
|
||||
if (!(zoom_level+1 in zoom_levels)) { break; }
|
||||
window.zoom_level += 1
|
||||
break;
|
||||
case "out":
|
||||
if (!(zoom_level-1 in zoom_levels)) { break; }
|
||||
window.zoom_level -= 1
|
||||
break;
|
||||
}
|
||||
rescale()
|
||||
}
|
||||
|
||||
function handle_pan(direction, speed){
|
||||
switch (direction){
|
||||
case "right":
|
||||
zoom_panning[0] -= speed
|
||||
break;
|
||||
case "left":
|
||||
zoom_panning[0] += speed
|
||||
break;
|
||||
case "up":
|
||||
zoom_panning[1] += speed
|
||||
break;
|
||||
case "down":
|
||||
zoom_panning[1] -= speed
|
||||
break;
|
||||
}
|
||||
rescale()
|
||||
}
|
||||
|
||||
function gen_button(row, col, html, click, nopos, id){
|
||||
const elem = document.createElement("button")
|
||||
|
||||
|
||||
if (!nopos){
|
||||
elem.style.gridColumn = row
|
||||
elem.style.gridRow = col
|
||||
}
|
||||
if (id) { elem.id = id }
|
||||
|
||||
// Table for the data-pos to assign (row major). If null, don't add.
|
||||
const data_pos_map = [
|
||||
["tl", null, "tr"],
|
||||
[null, null, null],
|
||||
["bl", null, "br"]
|
||||
]
|
||||
|
||||
elem.innerHTML = html
|
||||
elem.onclick = click
|
||||
|
||||
if (data_pos_map[row-1][col-1] !== null) {
|
||||
elem.dataset.pos = data_pos_map[row-1][col-1]
|
||||
}
|
||||
|
||||
return elem
|
||||
}
|
||||
|
||||
function add_css(){
|
||||
const CSS = `
|
||||
#zm_data_div { margin-bottom: 10px }
|
||||
#canvasDiv { overflow: hidden; background-color: var(--opac-85) }
|
||||
|
||||
@media(pointer=coarse){
|
||||
#zm_floater_container#zm_floater_container {
|
||||
width: 40%;
|
||||
height: auto;
|
||||
}
|
||||
#zm_floater_container:has(#zm_collapse[data-collapsed="true"]){
|
||||
width: calc(40% / 3);
|
||||
}
|
||||
}
|
||||
|
||||
@media(pointer:coarse) and (orientation:landscape){
|
||||
#zm_floater_container#zm_floater_container {
|
||||
width: auto;
|
||||
top: 5px;
|
||||
}
|
||||
#zm_floater_container:has(#zm_collapse[data-collapsed="true"]){
|
||||
width: calc(40% / 3);
|
||||
}
|
||||
}
|
||||
|
||||
#colorSelector { z-index: 1; right: 5px }
|
||||
#zm_floater_container {
|
||||
position: absolute;
|
||||
display: grid;
|
||||
|
||||
right: 5px;
|
||||
bottom: 5px;
|
||||
height: 100px;
|
||||
aspect-ratio: 1;
|
||||
|
||||
max-width: 200px;
|
||||
max-height: 200px;
|
||||
|
||||
border: 2px solid white;
|
||||
background-color: black;
|
||||
font-size: 120%;
|
||||
|
||||
button { text-align: center; border: 0px solid white }
|
||||
|
||||
button:where([data-pos="tl"]) { border-width: 0px 2px 2px 0px };
|
||||
button:where([data-pos="tr"]) { border-width: 2px 2px 0px 0px };
|
||||
button:where([data-pos="bl"]) { border-width: 0px 0px 2px 2px };
|
||||
button:where([data-pos="br"]) { border-width: 2px 0px 0px 2px };
|
||||
}
|
||||
#zm_floater_container:has(#zm_collapse[data-collapsed="true"]) {
|
||||
height: 50px;
|
||||
|
||||
button:not(#zm_collapse) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
#canvasDiv:has(#colorSelector[style *= "block"]) #zm_floater_container {
|
||||
bottom: 50px;
|
||||
}
|
||||
|
||||
.zm_corner { border: 2px solid white; }
|
||||
|
||||
#zm_collapse {
|
||||
grid-row: 3;
|
||||
grid-column: 3;
|
||||
}
|
||||
#zm_collapse[data-collapsed="true"] {
|
||||
grid-row: 1;
|
||||
grid-column: 1;
|
||||
border-width: 0px;
|
||||
}
|
||||
`
|
||||
|
||||
const style_div = document.createElement("style")
|
||||
style_div.innerHTML = CSS
|
||||
|
||||
document.head.appendChild(style_div)
|
||||
}
|
||||
|
||||
function add_zoom_floaters(){
|
||||
const container = document.createElement("div")
|
||||
container.id = "zm_floater_container"
|
||||
|
||||
// Pan mode selector (C: Coarse F: Fine)
|
||||
const pan_mode_sel = gen_button(
|
||||
1,3, "C",
|
||||
(evt) => {
|
||||
evt.target.dataset.mode = evt.target.dataset.mode == "F" ? "C" : "F"
|
||||
evt.target.innerText = evt.target.dataset.mode
|
||||
},
|
||||
false,
|
||||
"zm_panmode_sel"
|
||||
)
|
||||
|
||||
const speed = () =>
|
||||
(window.zoom_level > 3 ? 5 : 10) * // More granular at higher zoom levels
|
||||
(pan_mode_sel.dataset.mode == "F" ? 0.25 : 1) // Increase granularity in fine mode
|
||||
|
||||
container.append(
|
||||
// Direction buttons
|
||||
gen_button(2,1, "↑", () => handle_pan("up" ,speed())),
|
||||
gen_button(1,2, "←", () => handle_pan("left" ,speed())),
|
||||
gen_button(3,2, "→", () => handle_pan("right" ,speed())),
|
||||
gen_button(2,3, "↓", () => handle_pan("down" ,speed())),
|
||||
|
||||
// Zoom buttons
|
||||
gen_button(1,1, "+", () => handle_zoom("in")),
|
||||
gen_button(3,1, "-", () => handle_zoom("out")),
|
||||
|
||||
// Collapse button
|
||||
gen_button(
|
||||
3,3, "#",
|
||||
(evt) => {
|
||||
evt.target.dataset.collapsed = evt.target.dataset.collapsed == "true"
|
||||
? "false"
|
||||
: "true"
|
||||
},
|
||||
true,
|
||||
"zm_collapse"
|
||||
),
|
||||
pan_mode_sel
|
||||
)
|
||||
|
||||
const canvas_div = document.getElementById("canvasDiv")
|
||||
canvas_div.style.backgroundColor = colour_setting?.value ?? "#252525"
|
||||
canvas_div.appendChild(container)
|
||||
}
|
||||
|
||||
function rescale(){
|
||||
log_info()
|
||||
|
||||
const scale = zoom_levels[zoom_level]
|
||||
const x = zoom_panning[0] * (pixelSize * scale)
|
||||
const y = zoom_panning[1] * (pixelSize * scale)
|
||||
|
||||
gameCanvas.style.transform = `translate(${x}px, ${y}px) translateX(-50%) scale(${scale})`
|
||||
}
|
||||
|
||||
function log_info(){
|
||||
// Values are negated to make them more intuitive
|
||||
const x_pan = (-zoom_panning[0]).toString().padEnd(4)
|
||||
const y_pan = (-zoom_panning[1]).toString().padEnd(4)
|
||||
|
||||
if (zoom_data_div === null){ return; }
|
||||
|
||||
zoom_data_div.innerText = ""
|
||||
zoom_data_div.innerText += `Scale: ${zoom_levels[zoom_level]}x\n`
|
||||
zoom_data_div.innerText += `Pan : ${x_pan}, ${y_pan}`
|
||||
}
|
||||
|
||||
function patch_keybinds(){
|
||||
// Be more granular at higher zoom levels
|
||||
const speed_a = () => zoom_level > 3 ? 5 : 10
|
||||
const speed_b = () => zoom_level > 3 ? 10 : 20
|
||||
|
||||
keybinds["9"] = () => handle_zoom("in")
|
||||
keybinds["0"] = () => handle_zoom("out")
|
||||
|
||||
keybinds["w"] = () => handle_pan("up", speed_a())
|
||||
keybinds["a"] = () => handle_pan("left", speed_a())
|
||||
keybinds["s"] = () => handle_pan("down", speed_a())
|
||||
keybinds["d"] = () => handle_pan("right", speed_a())
|
||||
|
||||
keybinds["W"] = () => handle_pan("up", speed_b())
|
||||
keybinds["A"] = () => handle_pan("left", speed_b())
|
||||
keybinds["S"] = () => handle_pan("down", speed_b())
|
||||
keybinds["D"] = () => handle_pan("right", speed_b())
|
||||
}
|
||||
|
||||
function patch_ui(){
|
||||
add_css()
|
||||
add_zoom_floaters()
|
||||
|
||||
zoom_data_div = document.createElement("div")
|
||||
zoom_data_div.id = "zm_data_div"
|
||||
document.getElementById("logDiv").prepend(zoom_data_div)
|
||||
|
||||
const controls_table = document.getElementById("controlsTable").lastElementChild
|
||||
controls_table.insertAdjacentHTML("beforeBegin",`
|
||||
<tr>
|
||||
<td>Zoom in/out</td>
|
||||
<td>
|
||||
<kbd>9</kbd>/
|
||||
<kbd>0</kbd>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Pan</td>
|
||||
<td>
|
||||
<kbd>W</kbd>
|
||||
<kbd>A</kbd>
|
||||
<kbd>S</kbd>
|
||||
<kbd>D</kbd>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Pan (fast)</td>
|
||||
<td>
|
||||
<kbd>Shift</kbd> +
|
||||
<kbd>W</kbd>
|
||||
<kbd>A</kbd>
|
||||
<kbd>S</kbd>
|
||||
<kbd>D</kbd>
|
||||
</td>
|
||||
</tr>
|
||||
`)
|
||||
}
|
||||
|
||||
// Redefine to give correct numbers when zoomed
|
||||
window.getMousePos = (canvas, evt) => {
|
||||
if (evt.touches) {
|
||||
evt.preventDefault();
|
||||
evt = evt.touches[0];
|
||||
isMobile = true;
|
||||
}
|
||||
const rect = canvas.getBoundingClientRect();
|
||||
|
||||
let x = (evt.clientX - rect.left) / zoom_levels[zoom_level];
|
||||
let y = (evt.clientY - rect.top) / zoom_levels[zoom_level];
|
||||
|
||||
x = Math.floor((x / canvas.clientWidth) * (width+1));
|
||||
y = Math.floor((y / canvas.clientHeight) * (height+1));
|
||||
|
||||
return {x:x, y:y};
|
||||
}
|
||||
|
||||
runAfterReset(() => {
|
||||
window.zoom_level = 1
|
||||
rescale()
|
||||
})
|
||||
|
||||
runAfterLoad(() => {
|
||||
patch_keybinds()
|
||||
patch_ui()
|
||||
})
|
||||
|
|
@ -0,0 +1,233 @@
|
|||
dependOn("betterSettings.js", () => {
|
||||
const tabweapons = new SettingsTab("weapons.js");
|
||||
enablestartupprompt = new Setting("Startup prompt", "startup_prompt", settingType.BOOLEAN, false, defaultValue=true, "The prompt requesting you to add velocity.js, (unavailable for steam edition)");
|
||||
|
||||
tabweapons.registerSetting(enablestartupprompt);
|
||||
settingsManager.registerTab(tabweapons);
|
||||
|
||||
runAfterLoad(async () => {
|
||||
window.setTimeout(async () => {
|
||||
if (!enabledMods.includes("mods/velocity.js") && standaloneType !== "steam" && enablestartupprompt.value === true){
|
||||
_jaydalert("velocity.js is recommended for weapons.js to function in its intended way.");
|
||||
}
|
||||
},)
|
||||
})
|
||||
},true)
|
||||
async function _weaponsjsprompt(message, defaultValue = "") {
|
||||
return new Promise(resolve => {
|
||||
promptInput(message, (result) => {
|
||||
resolve(result);
|
||||
}, "weapons.js is asking you...", defaultValue);
|
||||
|
||||
})
|
||||
}
|
||||
async function _jaydalert(message) {
|
||||
promptText(message, undefined, "Jayd:");
|
||||
}
|
||||
async function _weaponsjsdir(message) {
|
||||
promptDir(message, undefined, "weapons.js is asking you...");
|
||||
}
|
||||
|
||||
elements.tsar_bomba = {
|
||||
color: "#969696",
|
||||
tick: (pixel) => {
|
||||
tryMove(pixel, pixel.x, pixel.y+1)
|
||||
for (var y = 1; y < 4; y++) {
|
||||
if (!isEmpty(pixel.x, pixel.y + y, false)) {
|
||||
explodeAt(pixel.x,pixel.y,150,"plasma")
|
||||
}
|
||||
}
|
||||
},
|
||||
category: "weapons.js",
|
||||
state: "solid",
|
||||
density: 1300,
|
||||
excludeRandom: true,
|
||||
cooldown: defaultCooldown
|
||||
},
|
||||
elements.missile_left = {
|
||||
color: "#313131",
|
||||
category: "weapons.js",
|
||||
state: "solid",
|
||||
behavior: [
|
||||
"EX:20>missile_shrapnel|XX|XX|XX|XX|XX|CR:smoke"
|
||||
],
|
||||
ignore: "missile_left",
|
||||
tick: function(pixel) {
|
||||
var circlec = circleCoords(pixel.x, pixel.y, 3)
|
||||
for (var i = 0; i < circlec.length; i++){
|
||||
var coord = circlec[i]
|
||||
var x = coord.x
|
||||
var y = coord.y
|
||||
if (!(isEmpty(x, y, true) || (x == pixel.x && y == pixel.y) || elements[pixelMap[x][y].element].state == "gas" || pixelMap[x][y].element == "missile_left")){
|
||||
explodeAt(pixel.x,pixel.y,20,"missile_shrapnel")
|
||||
}
|
||||
}
|
||||
for (var i=0; i<3; i++) {
|
||||
tryMove(pixel, pixel.x-1, pixel.y)
|
||||
}
|
||||
},
|
||||
density: 1300,
|
||||
excludeRandom: true,
|
||||
cooldown: defaultCooldown
|
||||
},
|
||||
elements.missile_right = {
|
||||
color: "#313131",
|
||||
category: "weapons.js",
|
||||
state: "solid",
|
||||
behavior: [
|
||||
"CR:smoke|XX|XX|XX|XX|XX|EX:20>missile_shrapnel"
|
||||
],
|
||||
ignore: "missile_right",
|
||||
tick: function(pixel) {
|
||||
var circlec = circleCoords(pixel.x, pixel.y, 3)
|
||||
for (var i = 0; i < circlec.length; i++){
|
||||
var coord = circlec[i]
|
||||
var x = coord.x
|
||||
var y = coord.y
|
||||
if (!(isEmpty(x, y, true) || (x == pixel.x && y == pixel.y) || elements[pixelMap[x][y].element].state == "gas")){
|
||||
explodeAt(pixel.x,pixel.y,20,"missile_shrapnel")
|
||||
}
|
||||
}
|
||||
for (var i=0; i<3; i++) {
|
||||
tryMove(pixel, pixel.x+1, pixel.y)
|
||||
}
|
||||
},
|
||||
density: 1300,
|
||||
excludeRandom: true,
|
||||
cooldown: defaultCooldown
|
||||
}
|
||||
var target = [,];
|
||||
var tgt = "head";
|
||||
elements.tracking_missile = {
|
||||
color: "#323232",
|
||||
category: "weapons.js",
|
||||
behavior: [
|
||||
"XX","XX","CR:smoke"
|
||||
],
|
||||
onSelect: async () => {
|
||||
var answer1 = await _weaponsjsprompt("Please input the target.",(tgt||undefined));
|
||||
if (!answer1) {return}
|
||||
tgt = answer1;
|
||||
},
|
||||
tick: (pixel) => {
|
||||
var circlec = circleCoords(pixel.x, pixel.y, 3)
|
||||
for (var i = 0; i < circlec.length; i++){
|
||||
var coord = circlec[i]
|
||||
var xe = coord.x
|
||||
var ye = coord.y
|
||||
if (!(isEmpty(xe, ye, true) || (xe == pixel.x && ye == pixel.y) || elements[pixelMap[xe][ye].element].state == "gas" || pixelMap[xe][ye].element == "tracking_missile")){
|
||||
explodeAt(pixel.x,pixel.y,20,"missile_shrapnel")
|
||||
}
|
||||
}
|
||||
for (var x = 1; x < width; x++) {
|
||||
for (var y = 1; y < height; y++) {
|
||||
if (!isEmpty(x,y)) {
|
||||
if (pixelMap[x][y].element===tgt) {
|
||||
target = [pixelMap[x][y].x, pixelMap[x][y].y];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pixel.x != target[0] || pixel.y != target[1]) {
|
||||
let {x, y} = pixel;
|
||||
const empty = checkForEmptyPixels(x, y);
|
||||
const [tX, tY] = target;
|
||||
let bestVal = Math.sqrt(Math.pow(tX - x, 2) + Math.pow(tY - y, 2));
|
||||
let best = null;
|
||||
for (const pixelPair of empty) {
|
||||
const [x_, y_] = [x + pixelPair[0], y + pixelPair[1]];
|
||||
const c = Math.sqrt(Math.pow(tX - x_, 2) + Math.pow(tY - y_, 2));
|
||||
if (c < bestVal) {
|
||||
bestVal = c;
|
||||
best = pixelPair;
|
||||
}
|
||||
}
|
||||
if (best) {
|
||||
tryMove(pixel, x + best[0]*2, y + best[1]*2, undefined, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
elements.missile_shrapnel = {
|
||||
color: "#979ea3",
|
||||
behavior: [
|
||||
"XX|XX|XX",
|
||||
"XX|EX:5 %20|XX",
|
||||
"M2%20|M1%20|M2%20",
|
||||
],
|
||||
burn: 90,
|
||||
burnTime: 100,
|
||||
density: 2000,
|
||||
conduct: 1,
|
||||
state: "solid",
|
||||
category: "weapons.js"
|
||||
},
|
||||
elements.cluster_nuke = {
|
||||
color: "#323232",
|
||||
category: "weapons.js",
|
||||
behavior: behaviors.POWDER,
|
||||
maxSize: 1,
|
||||
cooldown: defaultCooldown,
|
||||
tick: (pixel) => {
|
||||
for (var y = 1; y < 25; y++) {
|
||||
if (!isEmpty(pixel.x, pixel.y + y, false)) {
|
||||
explodeAt(pixel.x,pixel.y,25,["dirty_bomb","dirty_bomb","dirty_bomb","dirty_bomb","dirty_bomb","dirty_bomb","dirty_bomb","dirty_bomb","dirty_bomb","dirty_bomb","dirty_bomb","dirty_bomb","dirty_bomb","dirty_bomb","dirty_bomb","dirty_bomb","dirty_bomb","dirty_bomb","dirty_bomb","dirty_bomb","dirty_bomb","dirty_bomb","dirty_bomb","dirty_bomb","dirty_bomb","dirty_bomb","dirty_bomb","dirty_bomb","dirty_bomb","nuke",])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// let ammo1 = 1;
|
||||
// let rdir = 1;
|
||||
// let ammoLoaded = "";
|
||||
// elements.railgun = {
|
||||
// category: "weapons.js",
|
||||
// behavior: behaviors.WALL,
|
||||
// onSelect: async (pixel) => {
|
||||
// var answer1 = await _weaponsjsprompt("Please input the ammo type. \n \n <1 for Armor-Piercing ammo> \n <2 for High-Explosive ammo.>",(ammo1||undefined));
|
||||
// if (!answer1) {return}
|
||||
// ammo1 = answer1;
|
||||
// var answer2 = await _weaponsjsdir("Please input the direction.",(rdir||undefined));
|
||||
// if (!answer2) {
|
||||
// console.log(answer2)
|
||||
// return}
|
||||
// rdir = answer2;
|
||||
// },
|
||||
// tick: async (pixel) => {
|
||||
// ammoLoaded = "armor_piercing_shell";
|
||||
// if(ammo1 === 1){
|
||||
// ammoLoaded = "armor_piercing_shell"
|
||||
// }
|
||||
// else if (ammo1 === 2){
|
||||
// ammoLoaded = "high_explosive_shell"
|
||||
// }
|
||||
|
||||
// if (pixel.charge){
|
||||
// if(rdir === 1){
|
||||
// createPixel(ammoLoaded, pixel.x, pixel.y-1);
|
||||
// }
|
||||
// if (rdir === 2){
|
||||
// createPixel(ammoLoaded, pixel.x, pixel.y+1);
|
||||
// }
|
||||
// if (rdir === 3){
|
||||
// createPixel(ammoLoaded, pixel.x-1, pixel.y);
|
||||
// }
|
||||
// if (rdir === 4){
|
||||
// createPixel(ammoLoaded, pixel.x+1, pixel.y);
|
||||
// }
|
||||
// }
|
||||
// doDefaults(pixel);
|
||||
// },
|
||||
// color: "#c9c9c9",
|
||||
// conduct: 1,
|
||||
// hardness: 8,
|
||||
// },
|
||||
// elements.armor_piercing_shell = {
|
||||
// category: "ammunition",
|
||||
// color: "#ffc954",
|
||||
// hardness: 0.9,
|
||||
// }
|
||||
// elements.high_explosive_shell = {
|
||||
// category: "ammunition",
|
||||
// color: "#ffc954",
|
||||
// hardness: 0.6,
|
||||
// }
|
||||
Loading…
Reference in New Issue