AWBW Helper

Outils de jeu (unités en attente, prévisualisation de portée) pour AWBW

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

ستحتاج إلى تثبيت إضافة مثل Stylus لتثبيت هذا النمط.

ستحتاج إلى تثبيت إضافة لإدارة أنماط المستخدم لتتمكن من تثبيت هذا النمط.

ستحتاج إلى تثبيت إضافة لإدارة أنماط المستخدم لتثبيت هذا النمط.

ستحتاج إلى تثبيت إضافة لإدارة أنماط المستخدم لتثبيت هذا النمط.

(لدي بالفعل مثبت أنماط للمستخدم، دعني أقم بتثبيته!)

// ==UserScript==
// @name         AWBW Helper
// @version      1.1.0
// @author       StormSheep
// @description  Outils de jeu (unités en attente, prévisualisation de portée) pour AWBW
// @license      MIT
// @match        https://awbw.amarriner.com/*
// @namespace https://greasyfork.org/users/1626573
// ==/UserScript==

(function () {
  'use strict';

  function getNextUnitButton() {
    return nextUnitBtn;
  }
  function isGameReady() {
    return typeof unitsInfo === "object" && typeof playersUnits === "object" && typeof getViewerPId === "function" && typeof unitClickHandler === "function";
  }
  function selectUnit(id) {
    unitClickHandler({ id });
  }
  function unitIconUrl(unit) {
    const unitSlug = unit.units_name.toLowerCase().replace(" ", "");
    return `terrain/ani/${unit.countries_code}${unitSlug}.gif`;
  }
  function unitHpIconUrl(unit) {
    if (unit.units_hit_points === 10) return null;
    return `terrain/ani/${unit.units_hit_points}.gif`;
  }
  const LOWEST_PRIORITY_UNIT_NAMES = /* @__PURE__ */ new Set(["black boat"]);
  const LOW_PRIORITY_UNIT_NAMES = /* @__PURE__ */ new Set(["missile", "pipe runner"]);
  function unitPriority(unit) {
    const name = unit.units_name.toLowerCase();
    if (LOWEST_PRIORITY_UNIT_NAMES.has(name)) return 2;
    if (LOW_PRIORITY_UNIT_NAMES.has(name)) return 1;
    return 0;
  }
  function isViewerTurn() {
    return currentTurn === getViewerPId();
  }
  function getPendingUnits() {
    const viewerId = getViewerPId();
    const viewerUnits = playersUnits[viewerId];
    if (!viewerUnits) return [];
    return Object.keys(viewerUnits).map((id) => unitsInfo[id]).filter((unit) => unit && unit.units_moved === 0 && unit.units_carried === "N").sort((a, b) => unitPriority(a) - unitPriority(b));
  }
  function getPendingMove() {
    var _a;
    if (!moving || !(currentClick == null ? void 0 : currentClick.info) || !((_a = currentClick.path) == null ? void 0 : _a.length)) return null;
    const destNode = currentClick.path[currentClick.path.length - 1];
    const { x, y } = coordsFromNode(destNode);
    return { unit: currentClick.info, destX: x, destY: y };
  }
  function heldPreviewKey() {
    if (!isGameFocused()) return null;
    if (keyboardKeysPressed.get("shift")) return "movement";
    if (keyboardKeysPressed.get("control")) return "range";
    if (keyboardKeysPressed.get("alt")) return "vision";
    return null;
  }
  function previewTilesAt(unit, x, y, type) {
    const previewUnit = { ...unit, units_x: x, units_y: y };
    const original = getUnitAt;
    getUnitAt = (px, py) => px === x && py === y ? previewUnit : original(px, py);
    try {
      addTilesForUnitAt(x, y, type);
    } finally {
      getUnitAt = original;
    }
  }
  function redrawPendingMovePath() {
    if (!(currentClick == null ? void 0 : currentClick.path)) return;
    const lastNode = currentClick.path[currentClick.path.length - 1];
    const { x, y } = coordsFromNode(lastNode);
    currentClick.path = drawPathTiles(movementInfo, x, y, currentClick.path);
  }
  const TICK_MS = 50;
  let lastPreviewKey = null;
  function tick() {
    const move = getPendingMove();
    const type = move ? heldPreviewKey() : null;
    if (!move) {
      lastPreviewKey = null;
      return;
    }
    if (!type) {
      if (lastPreviewKey !== null) {
        lastPreviewKey = null;
        previewTilesAt(move.unit, move.unit.units_x, move.unit.units_y, "movement");
        redrawPendingMovePath();
      }
      return;
    }
    const key = `${type}:${move.destX},${move.destY}`;
    if (key === lastPreviewKey) return;
    lastPreviewKey = key;
    previewTilesAt(move.unit, move.destX, move.destY, type);
    redrawPendingMovePath();
  }
  function initMovePreviewFeature() {
    setInterval(tick, TICK_MS);
  }
  const TILE_SIZE = 16;
  const HIGHLIGHT_KEY = "t";
  const HIGHLIGHT_CLASS = "awbw-pending-highlight";
  function buildPanel(nativeBtn) {
    const btn = document.createElement("div");
    btn.id = "awbw-pending-units-btn";
    btn.className = nativeBtn.className;
    btn.style.cursor = "pointer";
    btn.style.position = "relative";
    const bg = document.createElement("div");
    bg.className = "game-tools-bg";
    bg.style.position = "relative";
    const icon = document.createElement("img");
    icon.style.position = "relative";
    icon.style.left = "-3px";
    bg.appendChild(icon);
    const hpBadge = document.createElement("img");
    hpBadge.style.position = "absolute";
    hpBadge.style.right = "11px";
    hpBadge.style.bottom = "8px";
    bg.appendChild(hpBadge);
    const arrow = document.createElement("span");
    arrow.textContent = "▼";
    arrow.style.position = "absolute";
    arrow.style.right = "1px";
    arrow.style.top = "50%";
    arrow.style.transform = "translateY(-50%)";
    arrow.style.fontSize = "9px";
    arrow.style.lineHeight = "1";
    arrow.style.color = "#fff";
    arrow.style.textShadow = "0 0 2px #000, 0 0 2px #000";
    bg.appendChild(arrow);
    const label = document.createElement("span");
    label.className = "game-tools-btn-text small_text";
    btn.appendChild(bg);
    btn.appendChild(label);
    const list = document.createElement("div");
    list.style.position = "absolute";
    list.style.top = "100%";
    list.style.left = "0";
    list.style.display = "none";
    list.style.flexDirection = "column";
    list.style.background = "#fff";
    list.style.border = "1px solid #999";
    list.style.maxHeight = "300px";
    list.style.overflowY = "auto";
    list.style.zIndex = "1000";
    list.style.whiteSpace = "nowrap";
    const refreshButton = () => {
      const units = getPendingUnits();
      nativeBtn.style.display = "none";
      if (!isViewerTurn() || units.length === 0) {
        btn.style.display = "none";
        list.style.display = "none";
        return;
      }
      btn.style.display = "flex";
      icon.src = units[0] ? unitIconUrl(units[0]) : "";
      icon.style.visibility = units[0] ? "visible" : "hidden";
      const hpUrl = units[0] ? unitHpIconUrl(units[0]) : null;
      hpBadge.src = hpUrl ?? "";
      hpBadge.style.display = hpUrl ? "block" : "none";
      label.textContent = `Unités en attente (${units.length})`;
    };
    const refresh = () => {
      refreshButton();
      const units = getPendingUnits();
      list.innerHTML = "";
      for (const unit of units) {
        const row = document.createElement("div");
        row.style.display = "flex";
        row.style.alignItems = "center";
        row.style.gap = "6px";
        row.style.padding = "4px 8px";
        row.style.cursor = "pointer";
        row.style.fontFamily = "sans-serif";
        row.style.fontSize = "12px";
        row.addEventListener("mouseenter", () => row.style.background = "#eee");
        row.addEventListener("mouseleave", () => row.style.background = "");
        const rowIconWrap = document.createElement("div");
        rowIconWrap.style.position = "relative";
        rowIconWrap.style.width = "16px";
        rowIconWrap.style.height = "16px";
        rowIconWrap.style.flex = "none";
        const rowIcon = document.createElement("img");
        rowIcon.src = unitIconUrl(unit);
        rowIcon.width = 16;
        rowIcon.height = 16;
        rowIconWrap.appendChild(rowIcon);
        const rowHpUrl = unitHpIconUrl(unit);
        if (rowHpUrl) {
          const rowHp = document.createElement("img");
          rowHp.src = rowHpUrl;
          rowHp.style.position = "absolute";
          rowHp.style.right = "-2px";
          rowHp.style.bottom = "-2px";
          rowIconWrap.appendChild(rowHp);
        }
        const rowLabel = document.createElement("span");
        rowLabel.textContent = `(${unit.units_x}, ${unit.units_y})`;
        row.appendChild(rowIconWrap);
        row.appendChild(rowLabel);
        row.addEventListener("click", () => {
          selectUnit(unit.units_id);
          list.style.display = "none";
          refresh();
        });
        list.appendChild(row);
      }
    };
    btn.addEventListener("click", () => {
      const opening = list.style.display === "none";
      if (opening) refresh();
      list.style.display = opening ? "flex" : "none";
    });
    document.addEventListener("click", (event) => {
      if (!btn.contains(event.target) && !list.contains(event.target)) {
        list.style.display = "none";
      }
    });
    refresh();
    setInterval(refreshButton, 500);
    btn.appendChild(list);
    return btn;
  }
  function clearHighlights() {
    const existing = document.querySelectorAll(`.${HIGHLIGHT_CLASS}`);
    existing.forEach((el) => el.remove());
    return existing.length > 0;
  }
  function showHighlights() {
    const gamemap = document.getElementById("gamemap");
    if (!gamemap) return;
    for (const unit of getPendingUnits()) {
      const highlight = document.createElement("div");
      highlight.className = HIGHLIGHT_CLASS;
      highlight.style.position = "absolute";
      highlight.style.left = `${unit.units_x * TILE_SIZE}px`;
      highlight.style.top = `${unit.units_y * TILE_SIZE}px`;
      highlight.style.width = `${TILE_SIZE}px`;
      highlight.style.height = `${TILE_SIZE}px`;
      highlight.style.backgroundColor = "rgba(255, 255, 0, 0.45)";
      highlight.style.boxShadow = "0 0 0 1px rgba(255, 200, 0, 0.9) inset";
      highlight.style.pointerEvents = "none";
      highlight.style.zIndex = "999";
      gamemap.appendChild(highlight);
    }
  }
  function toggleHighlights() {
    if (!clearHighlights()) {
      showHighlights();
    }
  }
  function initPendingUnitsFeature() {
    const nativeBtn = getNextUnitButton();
    const panel = buildPanel(nativeBtn);
    nativeBtn.insertAdjacentElement("beforebegin", panel);
    nativeBtn.style.display = "none";
    document.addEventListener("keydown", (event) => {
      const target = event.target;
      if (target && /^(input|textarea|select)$/i.test(target.tagName)) return;
      if (event.key.toLowerCase() === HIGHLIGHT_KEY) {
        toggleHighlights();
      }
    });
  }
  function waitForGame() {
    if (isGameReady()) {
      initPendingUnitsFeature();
      initMovePreviewFeature();
      return;
    }
    setTimeout(waitForGame, 300);
  }
  waitForGame();

})();