From c17eb932c0c5020eea51019e83958741534494d6 Mon Sep 17 00:00:00 2001
From: voidapex11 <154328367+voidapex11@users.noreply.github.com>
Date: Wed, 15 Jan 2025 10:45:16 +0000
Subject: [PATCH] add guided_rocket.js
---
mod-list.html | 1 +
mods/guided_rocket.js | 106 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 107 insertions(+)
create mode 100644 mods/guided_rocket.js
diff --git a/mod-list.html b/mod-list.html
index 350a4ce8..c00ede85 100644
--- a/mod-list.html
+++ b/mod-list.html
@@ -249,6 +249,7 @@
| Weapons |
| aircrafts.js | Adds aircraft and aircraft part pixels | Jayd |
| c_fighter_jet.js | Adds a controllable fighter jet, wasd to move, q+wasd to shoot, gvbn for missiles. | Jayd |
+| guided_rocket.js | Adds a homing misile. | voidapex11 |
| icb.js | Adds various levels of nested cluster bombs | Alice |
| life_eater.js | Adds Warhammer 40,000’s Life-Eater Virus and Virus Bombs | Alice |
| liquid_void.js | Adds a liquid variant of Void | Alice |
diff --git a/mods/guided_rocket.js b/mods/guided_rocket.js
new file mode 100644
index 00000000..9d6258c5
--- /dev/null
+++ b/mods/guided_rocket.js
@@ -0,0 +1,106 @@
+// from code_libary.js
+function pyth(xA, yA, xB, yB) {
+ var a = Math.abs(xB - xA);
+ var b = Math.abs(yB - yA);
+ var c = Math.sqrt(a ** 2 + b ** 2);
+ return c;
+};
+tgt = ""
+
+elements.guided_misile = {
+ color: "#323333",
+ category: "weapons",
+ behavior: [
+ "EX:10|EX:10|EX:10",
+ "EX:10| XX |EX:10",
+ "EX:10|EX:10|EX:10",
+ ],
+ onSelect: function () {
+ var answer1 = prompt("Please input the target element.", (tgt || undefined));
+ if (!answer1) { return }
+ tgt = answer1;
+ },
+ tick: (pixel) => {
+ let targets = [];
+
+ // find all posible targets
+ for (var x = 1; x < width; x++) {
+ for (var y = 1; y < height; y++) {
+ if (!isEmpty(x, y)) {
+ if (pixelMap[x][y]["element"] === tgt) {
+ pxl = pixelMap[x][y];
+ targets.push(
+ [pxl.x, pxl.y,
+ // calculate distance from target to current pixel
+ pyth(pixel.x, pixel.y, pxl.x, pxl.y)
+ ]);
+ }
+ }
+ }
+ }
+
+ if (targets == []) {
+ return
+ }
+
+ // sort the targets by distance from self
+ targets.sort((a, b) => a[2] - b[2]);
+
+ try {
+ // get the closest target
+ current_best = targets[0];
+
+ target = [current_best[0], current_best[1]];
+ } catch {
+ // no pixels of target found
+ return
+ }
+
+ if (pixel.x != target[0] || pixel.y != target[1]) {
+ let { x, y } = pixel;
+ const empty = checkForEmptyPixels(x, y);
+ const [tX, tY] = target;
+
+ // Separate moves into non-diagonal and diagonal categories
+ const nonDiagonal = [];
+ const diagonal = [];
+
+ for (const [dx, dy] of empty) {
+ if ((dx === 0) || (dy === 0)) {
+ nonDiagonal.push([dx, dy]); // Horizontal or vertical moves
+ } else {
+ diagonal.push([dx, dy]); // Diagonal moves
+ }
+ }
+
+ let prioritizedMoves = []
+
+ // chose whether to move diagonaly
+ if (Math.abs(Math.abs(x - tX) - Math.abs(y - tY)) > 1) {
+ prioritizedMoves = [...nonDiagonal];
+ } else {
+ prioritizedMoves = [...diagonal];
+ }
+
+ let bestVal = pyth(tX, tY, x, y)
+ Math.sqrt(Math.pow(tX - x, 2) + Math.pow(tY - y, 2));
+ let best = null;
+
+ for (const [dx, dy] of prioritizedMoves) {
+ const x_ = x + dx;
+ const y_ = y + dy;
+ const c = Math.sqrt(Math.pow(tX - x_, 2) + Math.pow(tY - y_, 2));
+ if (c < bestVal) {
+ bestVal = c;
+ best = [dx, dy];
+ }
+ }
+
+ if (best) {
+ if (!tryMove(pixel, x + best[0] * 2, y + best[1] * 2, undefined, true)) {
+ tryMove(pixel, x + best[0], y + best[1], undefined, true)
+ };
+ }
+ }
+ }
+}
\ No newline at end of file