This commit is contained in:
JustAGenericUsername 2024-07-12 18:49:06 -04:00
commit be963153e0
7 changed files with 204 additions and 57 deletions

View File

@ -6,7 +6,7 @@ Play at [Sandboxels.R74n.com](https://sandboxels.r74n.com/).
Join the [Discord server](https://discord.com/invite/ejUc6YPQuS).
![Landscape made in Sandboxels](https://raw.githubusercontent.com/R74nCom/sandboxels/main/icons/wallpaper.png)
# Controls
* Left Click = Draw pixels
* Right Click = Erase pixels

View File

@ -16459,7 +16459,7 @@ window.onload = function() {
<div id="categoryControls"></div>
<div id="elementControls"></div>
</div>
<div id="extraInfo"><small><a href="https://sandboxels.r74n.com/changelog" id="changelogButton" target="_blank">Changelog</a><a href="https://sandboxels.R74n.com/feedback" target="_blank" style="color:lime;">Feedback</a><a href="https://sandboxels.wiki.gg/" target="_blank" id="wikiButton" title="Official Sandboxels Wiki - wiki.gg" style="color:white;">Wiki</a><a id="moreSocial" href="https://twitter.com/R74nCom" rel="me" target="_blank">Twitter</a><a href="https://discord.gg/ejUc6YPQuS" target="_blank" style="color:#2f60ff;">Discord</a><span id="install-button" style="display:none">&nbsp;<a onclick="deferredPrompt.prompt(); return false" href="#" style="text-shadow: 0px 2px 10px #ff00ff; cursor:pointer">Install Offline</a></span><br><br><a style="color:lime" target="_blank" href="https://docs.google.com/forms/d/e/1FAIpQLSeYMbngtbBHZ7hkz8jpbHl7TiAItqukrhtntKgAHjH30fY08A/viewform?usp=sf_link">FILL OUT THE CENSUS<span style="color:red">(NEW)</span></a></small></div>
<div id="extraInfo"><small><a href="https://sandboxels.r74n.com/changelog" id="changelogButton" target="_blank">Changelog</a><a href="https://sandboxels.R74n.com/feedback" target="_blank" style="color:lime;">Feedback</a><a href="https://sandboxels.wiki.gg/" target="_blank" id="wikiButton" title="Official Sandboxels Wiki - wiki.gg" style="color:white;">Wiki</a><a id="moreSocial" href="https://twitter.com/R74nCom" rel="me" target="_blank">Twitter</a><a href="https://discord.gg/ejUc6YPQuS" target="_blank" style="color:#2f60ff;">Discord</a><span id="install-button" style="display:none">&nbsp;<a onclick="deferredPrompt.prompt(); return false" href="#" style="text-shadow: 0px 2px 10px #ff00ff; cursor:pointer">Install Offline</a></span><!--<br><br><a style="color:lime" target="_blank" href="https://docs.google.com/forms/d/e/1FAIpQLSeYMbngtbBHZ7hkz8jpbHl7TiAItqukrhtntKgAHjH30fY08A/viewform?usp=sf_link">FILL OUT THE CENSUS<span style="color:red">(NEW)</span></a>--></small></div>
<script>
// version check
if (!settings["lastversion"] || settings["lastversion"]!==currentversion) {

View File

@ -91,6 +91,20 @@
<tbody>
<!----><tr><td class="modCat" colspan="3">Top-rated Mods</td></tr><!---->
<!--2024:-->
<tr><td>chem.js</td><td>Adds several chemistry and physics-related elements</td><td>lllllllllwith10ls</td></tr>
<tr><td>aChefsDream.js</td><td>More foods, animals, tools, and other cooking items. See the <a href="https://www.youtube.com/watch?v=pQFTtlNPODQ&list=PLWHqGb75vC8o7CLv-pMoVb56JL9BY9F0t">YouTube Playlist</a> for updates</td><td>SquareScreamYT</td></tr>
<tr><td>delete_all_of_element.js</td><td>Adds a tool that deletes every pixel of the element(s) the user clicks on</td><td>Alice</td></tr>
<tr><td>survival.js</td><td>With limited resources, you must craft, sell, and buy to progress</td><td><a href="https://R74n.com" class="R74nLink">R74n</a></td></tr>
<tr><td>alchemy.js</td><td>Start with only 4 elements and unlock more by reacting them together. (Most are not possible)</td><td><a href="https://R74n.com" class="R74nLink">R74n</a></td></tr>
<tr><td>nousersthings.js</td><td>Adds many chemical elements, compounds, and more</td><td>nousernamefound</td></tr>
<tr><td>spring.js</td><td>Many nature elements, like sakura trees, butterflies, beehives, and more</td><td><a href="https://R74n.com" class="R74nLink">R74n</a></td></tr>
<tr><td>weapons.js</td><td>Adds a variety of different weapons</td><td>Jayd</td></tr>
<tr><td>elementsManager.js</td><td>Create and edit custom elements</td><td>ggod</td></tr>
<tr><td>fey_and_more.js</td><td>Adds fairies, magic, and a lot of other things</td><td>Melecie</td></tr>
<!--2023:-->
<!--
<tr><td>alchemy.js</td><td>Start with only 4 elements and unlock more by reacting them together. (Most are not possible)</td><td><a href="https://R74n.com" class="R74nLink">R74n</a></td></tr>
<tr><td>chem.js</td><td>Adds several chemistry and physics-related elements</td><td>lllllllllwith10ls</td></tr>
<tr><td>delete_all_of_element.js</td><td>Adds a tool that deletes every pixel of the element(s) the user clicks on</td><td>Alice</td></tr>
@ -101,6 +115,7 @@
<tr><td>the_ground_og.js</td><td>Adds several rock types, worldgen settings, and gemstones</td><td>Alice</td></tr>
<tr><td>fey_and_more.js</td><td>Adds fairies, magic, and a lot of other things</td><td>Melecie</td></tr>
<tr><td>velocity.js</td><td>Beta for explosion velocity, and later wind, which may come to the base game in the future</td><td><a href="https://R74n.com" class="R74nLink">R74n</a></td></tr>
-->
<!----><tr><td class="modCat" colspan="3">Official</td></tr><!---->
<tr><td>alchemy.js</td><td>Start with only 4 elements and unlock more by reacting them together. (Most are not possible)</td><td><a href="https://R74n.com" class="R74nLink">R74n</a></td></tr>
@ -170,6 +185,7 @@
<tr><td>chalcopyrite.js</td><td>Adds the chalcopyrite ore</td><td>Sophie</td></tr>
<tr><td>chem.js</td><td>Adds several chemistry and physics-related elements</td><td>lllllllllwith10ls</td></tr>
<tr><td>clf3.js</td><td>Adds Chlorine Trifluoride</td><td>Alice</td></tr>
<tr><td>fire_extinguisher.js</td><td>Adds fire extinguisher blocks and realistic firefighting foam to put out nearly anything</td><td>Dr_Lego</td></tr>
<tr><td>fire_mod.js</td><td>Adds various properties to change fire behavior, & a radioactive version of fire</td><td>Alice</td></tr>
<tr><td>fire_slime.js</td><td>Adds a pyrogenic version of slime</td><td>Alice</td></tr>
<tr><td>Gemstones.js</td><td>Adds more gemstones</td><td>Schweeny</td></tr>
@ -229,11 +245,11 @@
<tr><td>rays.js</td><td>Adds more Ray types</td><td>Alice</td></tr>
<tr><td>rays++.js</td><td>Adds a couple more rays</td><td>uptzik</td></tr>
<tr><td>subspace.js</td><td>Adds the Subspace Tripmine from Roblox</td><td>nousernamefound</td></tr>
<tr><td>weapons.js</td><td>Adds varieties of different weapons </td><td>Jayd</td></tr>
<tr><td>weapons.js</td><td>Adds a variety of different weapons</td><td>Jayd</td></tr>
<tr><td>war_crimes.js</td><td>Adds tear gas & more</td><td>voidapex11</td></tr>
<!----><tr><td class="modCat" colspan="3">Food & Cooking</td></tr><!---->
<tr><td>aChefsDream.js</td><td>Adds more foods, animals, tools and many other cooking related items. Updates can be found in <a href="https://www.youtube.com/watch?v=pQFTtlNPODQ&list=PLWHqGb75vC8o7CLv-pMoVb56JL9BY9F0t">this YouTube Playlist</a></td><td>SquareScreamYT</td></tr>
<tr><td>aChefsDream.js</td><td>More foods, animals, tools, and other cooking items. See the <a href="https://www.youtube.com/watch?v=pQFTtlNPODQ&list=PLWHqGb75vC8o7CLv-pMoVb56JL9BY9F0t">YouTube Playlist</a> for updates</td><td>SquareScreamYT</td></tr>
<tr><td>aChefsDream_beta.js</td><td>Beta testing for aChefsDream. The code can be found <a href="https://www.github.com/SquareScreamYT/aChefsDream.js">on GitHub</a></td><td>SquareScreamYT</td></tr>
<tr><td>bananas.js</td><td>Adds bananas and banana plants</td><td>Alice</td></tr>
<tr><td>CherrySoda.js</td><td>Adds materials to make Cherry soda. Benzaldehyde + seltzer = Cherrysoda.</td><td>guzzo86</td></tr>

View File

@ -6,9 +6,9 @@ var nextLightmap = [];
var lightmapWidth, lightmapHeight;
var lightmapScale = 3;
var pixelSizeQuarter = pixelSizeHalf / 2;
var falloff = 0.7;
// Define RGB colors
var fireColor = [255, 69, 0];
var coldFireColor = [0, 191, 255];
var fireflyColor = [240, 255, 70];
var radColor = [75, 100, 30];
@ -27,10 +27,8 @@ if (!rgbToArray) {
}
if (colorString.startsWith('rgb')) {
// Handle RGB format
return colorString.slice(4, -1).split(',').map(val => parseInt(val.trim()));
} else if (colorString.startsWith('#')) {
// Handle HEX format
let hex = colorString.slice(1);
// Handle shorthand hex (e.g., #03F)
@ -59,18 +57,20 @@ function scaleList(numbers, scale) {
return numbers.map(number => number * scale);
}
function initializeLightmap(width, height) {
lightmapWidth = Math.ceil(width / lightmapScale);
lightmapHeight = Math.ceil(height / lightmapScale);
function initializeLightmap(_width, _height) {
const lightmapWidth = Math.ceil(_width / lightmapScale);
const lightmapHeight = Math.ceil(_height / lightmapScale);
for (var y = 0; y < lightmapHeight; y++) {
lightmap[y] = [];
nextLightmap[y] = [];
for (var x = 0; x < lightmapWidth; x++) {
lightmap[y][x] = { color: [0, 0, 0] };
nextLightmap[y][x] = { color: [0, 0, 0] };
}
}
const createLightmapArray = (width, height) =>
Array.from({ length: height }, () =>
Array.from({ length: width }, () => ({ color: [0, 0, 0] }))
);
const newLightmap = createLightmapArray(lightmapWidth, lightmapHeight);
const newNextLightmap = createLightmapArray(lightmapWidth, lightmapHeight);
lightmap = newLightmap;
nextLightmap = newNextLightmap;
}
function deepCopy(source, target) {
@ -113,9 +113,9 @@ function propagateLightmap() {
nextLightmap[y][x] = {
color: [
Math.min(Math.max(0, totalColor[0] / neighborCount * 0.8), 255 * 8),
Math.min(Math.max(0, totalColor[1] / neighborCount * 0.8), 255 * 8),
Math.min(Math.max(0, totalColor[2] / neighborCount * 0.8), 255 * 8)
Math.min(Math.max(0, totalColor[0] / neighborCount * falloff), 255 * 8),
Math.min(Math.max(0, totalColor[1] / neighborCount * falloff), 255 * 8),
Math.min(Math.max(0, totalColor[2] / neighborCount * falloff), 255 * 8)
]
};
}
@ -172,15 +172,15 @@ function renderLightmap() {
if (!lightmap || !lightmap[0]) return;
var context = canvas.getContext('2d');
var width = lightmap[0].length;
var height = lightmap.length;
var _width = lightmap[0].length;
var _height = lightmap.length;
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
for (var y = 0; y < _height; y++) {
for (var x = 0; x < _width; x++) {
var { color } = lightmap[y][x];
var [r, g, b] = color;
if (r > 0 || g > 0 || b > 0) {
if (r > 16 || g > 16 || b > 16) {
var [h, s, v] = rgbToHsv(r, g, b);
var newColor = hsvToRgb(h, s, 1);
var alpha = v;
@ -262,7 +262,7 @@ elements.laser.tick = function(pixel) {
var originalFireTick2 = elements.fire.tick;
elements.fire.tick = function(pixel) {
originalFireTick2(pixel);
glowColor(pixel, fireColor);
glowItsOwnColor(pixel);
};
var originalFlashTick = elements.flash.tick;
@ -320,13 +320,15 @@ radioactiveElements.forEach(element => {
elements[element].tick = glowRadiationColor;
});
window.addEventListener('load', () => initializeLightmap(width, height));
window.addEventListener('load', () => {
initializeLightmap(width, height);
var originalResizeCanvas = resizeCanvas;
resizeCanvas = function(newHeight, newWidth, newPixelSize, clear) {
originalResizeCanvas(newHeight, newWidth, newPixelSize, clear);
initializeLightmap(newHeight, newWidth);
};
var originalResizeCanvas = resizeCanvas;
resizeCanvas = function(newHeight, newWidth, newPixelSize, clear) {
originalResizeCanvas(newHeight, newWidth, newPixelSize, clear);
initializeLightmap(width, height);
};
});
var originalTick = tick;
tick = function() {

128
mods/fire_extinguisher.js Normal file
View File

@ -0,0 +1,128 @@
elements.firefighting_foam = {
color: ["#E6F3FF", "#F0F8FF", "#F8FBFF"],
behavior: [
"XX|CR:foam%2.5|XX",
"M2 AND CR:foam%2.5|CH:foam%0.2|M2 AND CR:foam%2.5",
"M1|M1|M1",
],
category: "liquids",
state: "liquid",
density: 0.9,
temp: 10,
conduct: 0.01,
stain: 0.01,
viscosity: 3000,
reactions: {
"greek_fire": { elem2: null, chance: 0.2 },
"water": { elem1: "foam", elem2: "salt_water", chance: 0.1 },
"acid": { elem1: "foam", elem2: "neutral_acid", chance: 0.05 },
"acid_gas": { elem1: "foam", elem2: "neutral_acid", chance: 0.05 },
},
tick: function (pixel) {
// Extinguish fire and smoke, remove burning state, and cool down pixels in a 6-pixel radius
let radius = 6
for (let dx = -radius; dx <= radius; dx++) {
for (let dy = -radius; dy <= radius; dy++) {
let nx = pixel.x + dx;
let ny = pixel.y + dy;
if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
let neighborPixel = pixelMap[nx][ny];
if (neighborPixel && neighborPixel.element) {
if (neighborPixel.element === "fire" || neighborPixel.element === "smoke") {
deletePixel(nx, ny);
} else {
// Remove burning state
if (neighborPixel.burning) {
neighborPixel.burning = false;
}
// Cool down the pixel
if (neighborPixel.temp > 10) {
neighborPixel.temp = Math.max(10, neighborPixel.temp - 5);
}
}
}
}
}
}
// Decay over time
if (Math.random() < 0.005) {
changePixel(pixel, "foam");
}
if (Math.random() < 0.0002) {
deletePixel(pixel.x, pixel.y);
}
}
};
elements.fire_extinguisher = {
color: "#ce2029",
behavior: [
"XX|XX|XX",
"XX|XX|XX",
"XX|XX|XX"
],
category: "machines",
state: "solid",
density: 2,
temp: 20,
conduct: 0.1,
tick: function (pixel) {
let shouldExplode = false;
// Check for fire or smoke within a 10-pixel radius
let checkRadius = 10;
for (let dx = -checkRadius; dx <= checkRadius; dx++) {
for (let dy = -checkRadius; dy <= checkRadius; dy++) {
let nx = pixel.x + dx;
let ny = pixel.y + dy;
if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
let neighborPixel = pixelMap[nx][ny];
if (neighborPixel && (neighborPixel.element === "fire" || neighborPixel.element === "smoke")) {
shouldExplode = true;
break;
}
}
}
if (shouldExplode) break;
}
if (shouldExplode) {
// Calculate the size of the fire extinguisher block
let blockSize = 1;
for (let dx = 0; dx < 3; dx++) {
for (let dy = 0; dy < 3; dy++) {
let nx = pixel.x + dx - 1;
let ny = pixel.y + dy - 1;
if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
let neighborPixel = pixelMap[nx][ny];
if (neighborPixel && neighborPixel.element === "fire_extinguisher") {
blockSize++;
}
}
}
}
// Calculate explosion radius based on block size
let explosionRadius = Math.max(blockSize * 5, 10);
// Create a large explosion of foam
for (let dx = -explosionRadius; dx <= explosionRadius; dx++) {
for (let dy = -explosionRadius; dy <= explosionRadius; dy++) {
// Check if the pixel is within the circular radius
if (dx * dx + dy * dy <= explosionRadius * explosionRadius) {
let fx = pixel.x + dx;
let fy = pixel.y + dy;
if (fx >= 0 && fx < width && fy >= 0 && fy < height) {
let targetPixel = pixelMap[fx][fy];
if (!targetPixel || targetPixel.element === "air") {
createPixel("firefighting_foam", fx, fy);
}
}
}
}
}
}
}
};

View File

@ -6,9 +6,9 @@ var nextLightmap = [];
var lightmapWidth, lightmapHeight;
var lightmapScale = 2;
var pixelSizeQuarter = pixelSizeHalf / 2;
var falloff = 0.8;
// Define RGB colors
var fireColor = [255, 69, 0];
var coldFireColor = [0, 191, 255];
var fireflyColor = [240, 255, 70];
var radColor = [75, 100, 30];
@ -27,10 +27,8 @@ if (!rgbToArray) {
}
if (colorString.startsWith('rgb')) {
// Handle RGB format
return colorString.slice(4, -1).split(',').map(val => parseInt(val.trim()));
} else if (colorString.startsWith('#')) {
// Handle HEX format
let hex = colorString.slice(1);
// Handle shorthand hex (e.g., #03F)
@ -59,18 +57,20 @@ function scaleList(numbers, scale) {
return numbers.map(number => number * scale);
}
function initializeLightmap(width, height) {
lightmapWidth = Math.ceil(width / lightmapScale);
lightmapHeight = Math.ceil(height / lightmapScale);
function initializeLightmap(_width, _height) {
const lightmapWidth = Math.ceil(_width / lightmapScale);
const lightmapHeight = Math.ceil(_height / lightmapScale);
for (var y = 0; y < lightmapHeight; y++) {
lightmap[y] = [];
nextLightmap[y] = [];
for (var x = 0; x < lightmapWidth; x++) {
lightmap[y][x] = { color: [0, 0, 0] };
nextLightmap[y][x] = { color: [0, 0, 0] };
}
}
const createLightmapArray = (width, height) =>
Array.from({ length: height }, () =>
Array.from({ length: width }, () => ({ color: [0, 0, 0] }))
);
const newLightmap = createLightmapArray(lightmapWidth, lightmapHeight);
const newNextLightmap = createLightmapArray(lightmapWidth, lightmapHeight);
lightmap = newLightmap;
nextLightmap = newNextLightmap;
}
function deepCopy(source, target) {
@ -113,9 +113,9 @@ function propagateLightmap() {
nextLightmap[y][x] = {
color: [
Math.min(Math.max(0, totalColor[0] / neighborCount * 0.8), 255 * 8),
Math.min(Math.max(0, totalColor[1] / neighborCount * 0.8), 255 * 8),
Math.min(Math.max(0, totalColor[2] / neighborCount * 0.8), 255 * 8)
Math.min(Math.max(0, totalColor[0] / neighborCount * falloff), 255 * 8),
Math.min(Math.max(0, totalColor[1] / neighborCount * falloff), 255 * 8),
Math.min(Math.max(0, totalColor[2] / neighborCount * falloff), 255 * 8)
]
};
}
@ -172,15 +172,15 @@ function renderLightmap() {
if (!lightmap || !lightmap[0]) return;
var context = canvas.getContext('2d');
var width = lightmap[0].length;
var height = lightmap.length;
var _width = lightmap[0].length;
var _height = lightmap.length;
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
for (var y = 0; y < _height; y++) {
for (var x = 0; x < _width; x++) {
var { color } = lightmap[y][x];
var [r, g, b] = color;
if (r > 0 || g > 0 || b > 0) {
if (r > 16 || g > 16 || b > 16) {
var [h, s, v] = rgbToHsv(r, g, b);
var newColor = hsvToRgb(h, s, 1);
var alpha = v;
@ -262,7 +262,7 @@ elements.laser.tick = function(pixel) {
var originalFireTick2 = elements.fire.tick;
elements.fire.tick = function(pixel) {
originalFireTick2(pixel);
glowColor(pixel, fireColor);
glowItsOwnColor(pixel);
};
var originalFlashTick = elements.flash.tick;
@ -326,7 +326,7 @@ window.addEventListener('load', () => {
var originalResizeCanvas = resizeCanvas;
resizeCanvas = function(newHeight, newWidth, newPixelSize, clear) {
originalResizeCanvas(newHeight, newWidth, newPixelSize, clear);
initializeLightmap(newHeight, newWidth);
initializeLightmap(width, height);
};
});

View File

@ -75,3 +75,4 @@ drawPixels = function(forceTick=false) {
updateLogicLists();
drawLinks();
};
resetInterval(tps);