Untitled

Anonymous
plain_text
02/07/2026 3:16 PM
32.1 KB
11
Indexable
(() => {
  // Prevent double-inject
  if (window.__ATTACK_POPUP_RUNNING__) {
    alert("Το popup είναι ήδη ανοιχτό.");
    return;
  }
  window.__ATTACK_POPUP_RUNNING__ = true;

  const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

  const setVal = (el, val) => {
    if (!el) return false;
    el.focus();
    el.value = String(val);
    el.dispatchEvent(new Event("input", { bubbles: true }));
    el.dispatchEvent(new Event("change", { bubbles: true }));
    return true;
  };

  const findAddButton = () => {
    return (
      document.querySelector("#new_com") ||
      [...document.querySelectorAll("a.btn.btn-img,button.btn.btn-img")]
        .find((e) => (e.innerText || "").toLowerCase().includes("προσθήκη")) ||
      [...document.querySelectorAll("a,button")]
        .find((e) => (e.querySelector("img")?.src || "").includes("add.png")) ||
      [...document.querySelectorAll("a,button")]
        .find((e) => (e.innerText || "").toLowerCase().includes("προσθήκη"))
    );
  };

  const findAttackAllButton = (contextEl) => {
    const sel = "a.btn.btn-img.nuke_them.tsalbutton";

    if (contextEl) {
      const container =
        contextEl.closest("tr") ||
        contextEl.closest(".command") ||
        contextEl.closest(".row") ||
        contextEl.closest("li") ||
        contextEl.parentElement;

      const local = container?.querySelector?.(sel);
      if (local) return local;
    }

    return document.querySelector(sel);
  };

  const pad3 = (n) => String(n).padStart(3, "0");

  const normalizeWraWithMs = (dt, ms) => {
    if (!dt) return null;
    const t = String(dt).trim();
    const ms3 = pad3(ms);

    const m = t.match(
      /^(\d{2})-(\d{2})-(\d{4})[,\s]+(\d{2}):(\d{2}):(\d{2})(?:\.(\d{3}))?$/
    );
    if (m) {
      const [, dd, mm, yyyy, HH, MM, SS] = m;
      return `${dd}/${mm}/${yyyy}, ${HH}:${MM}:${SS}:${ms3}`;
    }

    const m2 = t.match(
      /^(\d{2})\/(\d{2})\/(\d{4}),\s*(\d{2}):(\d{2}):(\d{2}):(\d{3})$/
    );
    if (m2) {
      const [, dd, mm, yyyy, HH, MM, SS] = m2;
      return `${dd}/${mm}/${yyyy}, ${HH}:${MM}:${SS}:${ms3}`;
    }

    return t;
  };

  const parseAttacks = (raw0) => {
    const lines = (raw0 || "")
      .split(/\r?\n/)
      .map((l) => l.trim())
      .filter(Boolean);

    return lines
      .map((line) => {
        const coords = line.match(/(\d+\|\d+)\s*->\s*(\d+\|\d+)/);
        if (!coords) return null;

        const dt =
          line.match(/\d{2}-\d{2}-\d{4}[,\s]+\d{2}:\d{2}:\d{2}(?:\.\d{3})?/)?.[0] ||
          null;

        return {
          from: coords[1],
          to: coords[2],
          dtRaw: dt,
          raw: line,
        };
      })
      .filter(Boolean);
  };

  // ----- UI Inject -----
  const style = document.createElement("style");
  style.id = "attackPopupStyle";
  style.textContent = `
    #attackPopupOverlay{
      position:fixed; inset:0; z-index:2147483647;
      background:rgba(0,0,0,.55); display:flex; align-items:center; justify-content:center;
      font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;
    }
    #attackPopup{
      width:min(920px, 95vw); background:#111; color:#eee;
      border:1px solid rgba(255,255,255,.15);
      border-radius:14px; box-shadow:0 20px 60px rgba(0,0,0,.55);
      overflow:hidden;
    }
    #attackPopup header{
      display:flex; justify-content:space-between; align-items:center;
      padding:12px 14px; background:rgba(255,255,255,.06);
      border-bottom:1px solid rgba(255,255,255,.10);
    }
    #attackPopup h3{ margin:0; font-size:14px; font-weight:650; letter-spacing:.2px; }
    #attackPopup .xbtn{
      background:transparent; border:0; color:#bbb; font-size:18px; cursor:pointer;
      padding:4px 8px; border-radius:8px;
    }
    #attackPopup .xbtn:hover{ background:rgba(255,255,255,.08); color:#fff; }
    #attackPopup .body{ padding:14px; display:grid; gap:10px; }
    #attackPopup textarea{
      width:100%; min-height:210px; resize:vertical;
      background:#0b0b0b; color:#eaeaea;
      border:1px solid rgba(255,255,255,.14); border-radius:12px;
      padding:10px; outline:none; line-height:1.35;
      font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
      font-size:12px;
    }
    #attackPopup .row{
      display:flex; gap:10px; flex-wrap:wrap; align-items:center; justify-content:space-between;
    }
    #attackPopup .hint{
      color:#bdbdbd; font-size:12px; opacity:.95;
    }
    #attackPopup .btns{ display:flex; gap:10px; }
    #attackPopup button{
      cursor:pointer; border:1px solid rgba(255,255,255,.16);
      background:rgba(255,255,255,.08); color:#fff;
      padding:8px 12px; border-radius:10px; font-weight:650;
    }
    #attackPopup button:hover{ background:rgba(255,255,255,.12); }
    #attackPopup button.primary{
      background:rgba(0,170,255,.20); border-color:rgba(0,170,255,.35);
    }
    #attackPopup button.primary:hover{ background:rgba(0,170,255,.26); }

    #attackPopup .controls{
      display:flex; gap:10px; flex-wrap:wrap; align-items:center;
    }
    #attackPopup label{
      font-size:12px; color:#cfcfcf; display:flex; gap:6px; align-items:center;
      background:rgba(255,255,255,.06);
      border:1px solid rgba(255,255,255,.10);
      padding:6px 10px; border-radius:10px;
    }
    #attackPopup select, #attackPopup input[type="number"]{
      background:#0b0b0b; color:#fff;
      border:1px solid rgba(255,255,255,.14);
      border-radius:8px; padding:4px 8px; outline:none;
      font-size:12px;
    }
    #attackPopup input[type="number"]{ width:90px; }

    #attackPopup .small{
      font-size:12px; color:#bdbdbd; line-height:1.3;
    }
    #attackPopup .status{
      margin-top:2px; font-size:12px; color:#bdbdbd;
      display:flex; gap:10px; flex-wrap:wrap;
    }
    #attackPopup .pill{
      padding:2px 8px; border-radius:999px;
      border:1px solid rgba(255,255,255,.12);
      background:rgba(255,255,255,.06);
    }
    #attackPopup .log{
      max-height:120px; overflow:auto;
      background:#0b0b0b; border:1px solid rgba(255,255,255,.10);
      border-radius:12px; padding:8px;
      font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
      font-size:11px; color:#d7d7d7;
      white-space:pre-wrap;
    }
    #attackPopup .unit-controls{
      display:none; gap:10px; flex-wrap:wrap;
      padding:10px; border-top:1px solid rgba(255,255,255,.08);
      margin-top:4px; background:rgba(255,255,255,.04);
      border-radius:10px;
    }
    #attackPopup .unit-grid{
      display:grid; grid-template-columns:repeat(auto-fill, minmax(120px, 1fr));
      gap:8px; width:100%;
    }
    #attackPopup .unit-controls label{
      background:rgba(255,215,0,.08); border-color:rgba(255,215,0,.25);
      flex-direction:column; padding:8px;
    }
    #attackPopup .unit-controls .unit-name{
      font-weight:bold; font-size:11px; margin-bottom:4px;
    }
    #attackPopup .fake-controls{
      display:none; gap:10px; flex-wrap:wrap;
      padding:8px 0; border-top:1px solid rgba(255,255,255,.08);
      margin-top:4px;
    }
    #attackPopup .fake-controls label{
      background:rgba(255,215,0,.08); border-color:rgba(255,215,0,.25);
      flex-direction:column; padding:8px;
    }
  `;
  document.head.appendChild(style);

  const overlay = document.createElement("div");
  overlay.id = "attackPopupOverlay";
  overlay.innerHTML = `
    <div id="attackPopup" role="dialog" aria-modal="true">
      <header>
        <h3>Attack Builder</h3>
        <button class="xbtn" title="Κλείσιμο">✕</button>
      </header>

      <div class="body">
        <div class="small" id="hintBox">
          Paste γραμμές μορφής: <b>522|542->517|488 ... 07-02-2026 01:59:59.000</b>
          <br/>Ώρα στο <b>input.wra.plano</b>: <b>dd/MM/yyyy, HH:mm:ss:MS</b> (MS από το κουτάκι).
        </div>

        <div class="controls">
          <label>
            🧨 Action
            <select id="actionSelect">
              <option value="attackall">AttackAll</option>
              <option value="fake">Fake Attack</option>
              <option value="custom">Custom Units</option>
              <option value="fefoscustom">Fefos Custom</option>
              <option value="none">None</option>
            </select>
          </label>

          <label>
            ⏱️ MS
            <input id="msInput" type="number" min="0" max="999" step="1" value="250" />
          </label>

          <span class="hint">⏸️ Delay: 10ms ανά εντολή | 🧨 Nuke click sleep: 0.1s</span>
        </div>

        <div class="unit-controls" id="customControls">
          <div class="unit-grid">
            <label>
              <span class="unit-name">⚔️ Spear</span>
              <input id="customSpear" type="number" min="0" value="0" />
            </label>
            <label>
              <span class="unit-name">🗡️ Sword</span>
              <input id="customSword" type="number" min="0" value="0" />
            </label>
            <label>
              <span class="unit-name">🪓 Axe</span>
              <input id="customAxe" type="number" min="0" value="0" />
            </label>
            <label>
              <span class="unit-name">👁️ Spy</span>
              <input id="customSpy" type="number" min="0" value="0" />
            </label>
            <label>
              <span class="unit-name">🐎 Light</span>
              <input id="customLight" type="number" min="0" value="27" />
            </label>
            <label>
              <span class="unit-name">🛡️ Heavy</span>
              <input id="customHeavy" type="number" min="0" value="0" />
            </label>
            <label>
              <span class="unit-name">⚔️ Ram</span>
              <input id="customRam" type="number" min="0" value="1" />
            </label>
            <label>
              <span class="unit-name">🏹 Catapult</span>
              <input id="customCatapult" type="number" min="0" value="0" />
            </label>
            <label>
              <span class="unit-name">👑 Knight</span>
              <input id="customKnight" type="number" min="0" value="0" />
            </label>
            <label>
              <span class="unit-name">👑 Snob</span>
              <input id="customSnob" type="number" min="0" value="0" />
            </label>
          </div>
          <span class="hint">🎯 Custom units για κάθε εντολή (συμπληρώνει όλα τα .monades[name='...'])</span>
        </div>

        <div class="unit-controls" id="fakeControls">
          <div class="unit-grid">
            <label>
              <span class="unit-name">⚔️ Spear</span>
              <input id="fakeSpear" type="number" min="0" value="0" />
            </label>
            <label>
              <span class="unit-name">🗡️ Sword</span>
              <input id="fakeSword" type="number" min="0" value="0" />
            </label>
            <label>
              <span class="unit-name">🪓 Axe</span>
              <input id="fakeAxe" type="number" min="0" value="0" />
            </label>
            <label>
              <span class="unit-name">👁️ Spy</span>
              <input id="fakeSpy" type="number" min="0" value="0" />
            </label>
            <label>
              <span class="unit-name">🐎 Light</span>
              <input id="fakeLight" type="number" min="0" value="27" />
            </label>
            <label>
              <span class="unit-name">🛡️ Heavy</span>
              <input id="fakeHeavy" type="number" min="0" value="0" />
            </label>
            <label>
              <span class="unit-name">⚔️ Ram</span>
              <input id="fakeRam" type="number" min="0" value="1" />
            </label>
            <label>
              <span class="unit-name">🏹 Catapult</span>
              <input id="fakeCatapult" type="number" min="0" value="0" />
            </label>
            <label>
              <span class="unit-name">👑 Knight</span>
              <input id="fakeKnight" type="number" min="0" value="0" />
            </label>
            <label>
              <span class="unit-name">👑 Snob</span>
              <input id="fakeSnob" type="number" min="0" value="0" />
            </label>
          </div>
          <span class="hint">🏹 Fake attack με όλα τα units (Light=27, Ram=1 by default, no AttackAll click)</span>
        </div>

        <textarea id="attackText" placeholder="Π.χ.
522|542->517|488 54.23 Nobleman Attack 07-02-2026 01:59:59.000 ...
..."></textarea>

        <div class="row">
          <div class="btns">
            <button id="attackCancel">Cancel</button>
            <button id="attackStart" class="primary">Start</button>
          </div>
        </div>

        <div class="status">
          <span class="pill" id="attackCount">Attacks: 0</span>
          <span class="pill" id="attackProgress">Progress: 0/0</span>
          <span class="pill" id="attackState">State: idle</span>
          <span class="pill" id="attackActionPill">Action: attackall</span>
          <span class="pill" id="attackMsPill">MS: 250</span>
        </div>

        <div class="log" id="attackLog"></div>
      </div>
    </div>
  `;
  document.body.appendChild(overlay);

  const $ = (sel) => overlay.querySelector(sel);
  const textArea = $("#attackText");
  const startBtn = $("#attackStart");
  const cancelBtn = $("#attackCancel");
  const closeBtn = overlay.querySelector(".xbtn");
  const countEl = $("#attackCount");
  const progEl = $("#attackProgress");
  const stateEl = $("#attackState");
  const logEl = $("#attackLog");

  const actionSelect = $("#actionSelect");
  const msInput = $("#msInput");
  const fakeControls = $("#fakeControls");
  const customControls = $("#customControls");
  const actionPill = $("#attackActionPill");
  const msPill = $("#attackMsPill");

  // Custom unit inputs
  const customSpear = $("#customSpear");
  const customSword = $("#customSword");
  const customAxe = $("#customAxe");
  const customSpy = $("#customSpy");
  const customLight = $("#customLight");
  const customHeavy = $("#customHeavy");
  const customRam = $("#customRam");
  const customCatapult = $("#customCatapult");
  const customKnight = $("#customKnight");
  const customSnob = $("#customSnob");

  // Fake unit inputs
  const fakeSpear = $("#fakeSpear");
  const fakeSword = $("#fakeSword");
  const fakeAxe = $("#fakeAxe");
  const fakeSpy = $("#fakeSpy");
  const fakeLight = $("#fakeLight");
  const fakeHeavy = $("#fakeHeavy");
  const fakeRam = $("#fakeRam");
  const fakeCatapult = $("#fakeCatapult");
  const fakeKnight = $("#fakeKnight");
  const fakeSnob = $("#fakeSnob");

  let isRunning = false;
  let stopRequested = false;

  const log = (msg) => {
    logEl.textContent += msg + "\n";
    logEl.scrollTop = logEl.scrollHeight;
  };

  const cleanup = () => {
    try { overlay.remove(); } catch {}
    try { style.remove(); } catch {}
    window.__ATTACK_POPUP_RUNNING__ = false;
  };

  const getMs = () => {
    let v = Number(msInput.value);
    if (!Number.isFinite(v)) v = 250;
    v = Math.max(0, Math.min(999, Math.floor(v)));
    msInput.value = String(v);
    return v;
  };

  const getCustomUnitValue = (input) => {
    let v = Number(input.value);
    if (!Number.isFinite(v)) v = 0;
    v = Math.max(0, v);
    input.value = String(v);
    return v;
  };

  const refreshMetaPills = () => {
    actionPill.textContent = `Action: ${actionSelect.value}`;
    msPill.textContent = `MS: ${getMs()}`;
  };

  const refreshCount = () => {
    const attacks = parseAttacks(textArea.value);
    countEl.textContent = `Attacks: ${attacks.length}`;
    progEl.textContent = `Progress: 0/${attacks.length}`;
    refreshMetaPills();
  };

  const showHideControls = () => {
    const mode = actionSelect.value;
    
    // Hide all
    fakeControls.style.display = "none";
    customControls.style.display = "none";
    
    // Show based on mode
    if (mode === "fake") {
      fakeControls.style.display = "block";
    } else if (mode === "custom") {
      customControls.style.display = "block";
    }
  };

  textArea.addEventListener("input", refreshCount);
  actionSelect.addEventListener("change", () => {
    refreshMetaPills();
    showHideControls();
  });
  msInput.addEventListener("input", refreshMetaPills);
  
  // Add event listeners for all unit inputs
  const allUnitInputs = [
    customSpear, customSword, customAxe, customSpy, customLight, customHeavy, 
    customRam, customCatapult, customKnight, customSnob,
    fakeSpear, fakeSword, fakeAxe, fakeSpy, fakeLight, fakeHeavy,
    fakeRam, fakeCatapult, fakeKnight, fakeSnob
  ];
  
  allUnitInputs.forEach(input => {
    input.addEventListener("input", () => getCustomUnitValue(input));
  });
  
  refreshCount();
  showHideControls();

  const setState = (s) => (stateEl.textContent = `State: ${s}`);

  const stop = () => {
    if (isRunning) {
      stopRequested = true;
      setState("stopping...");
      log("🛑 Stop requested.");
    } else {
      cleanup();
    }
  };

  cancelBtn.addEventListener("click", stop);
  closeBtn.addEventListener("click", stop);
  overlay.addEventListener("click", (e) => {
    if (e.target === overlay) stop();
  });

  const fillUnitsFromInputs = (containerEl, unitInputs, modeName) => {
    if (!containerEl) return false;
    
    const unitValues = {
      spear: getCustomUnitValue(unitInputs.spear),
      sword: getCustomUnitValue(unitInputs.sword),
      axe: getCustomUnitValue(unitInputs.axe),
      spy: getCustomUnitValue(unitInputs.spy),
      light: getCustomUnitValue(unitInputs.light),
      heavy: getCustomUnitValue(unitInputs.heavy),
      ram: getCustomUnitValue(unitInputs.ram),
      catapult: getCustomUnitValue(unitInputs.catapult),
      knight: getCustomUnitValue(unitInputs.knight),
      snob: getCustomUnitValue(unitInputs.snob)
    };
    
    let filledCount = 0;
    
    for (const [unitName, value] of Object.entries(unitValues)) {
      const selector = `input.monades[type="number"][name="${unitName}"]`;
      const input = containerEl.querySelector(selector);
      if (input) {
        setVal(input, value);
        filledCount++;
        if (value > 0) {
          log(`   ${unitName}: ${value}`);
        }
      }
    }
    
    return filledCount > 0;
  };

  const fillAllUnitsWithZero = (containerEl) => {
    if (!containerEl) return false;
    
    const unitNames = ['spear', 'sword', 'axe', 'spy', 'light', 'heavy', 'ram', 'catapult', 'knight', 'snob'];
    let filledCount = 0;
    
    for (const unitName of unitNames) {
      const selector = `input.monades[type="number"][name="${unitName}"]`;
      const input = containerEl.querySelector(selector);
      if (input) {
        setVal(input, 0);
        filledCount++;
      }
    }
    
    return filledCount > 0;
  };

  startBtn.addEventListener("click", async () => {
    if (isRunning) return;

    const attacks = parseAttacks(textArea.value);
    if (!attacks.length) {
      alert("Δεν βρέθηκαν εντολές τύπου: 522|542->517|488");
      return;
    }

    const addBtn = findAddButton();
    if (!addBtn) {
      alert("Δεν βρήκα το κουμπί Προσθήκη εντολής (selector / text / add.png).");
      return;
    }

    isRunning = true;
    stopRequested = false;
    setState("running");

    const mode = actionSelect.value;
    const ms = getMs();

    progEl.textContent = `Progress: 0/${attacks.length}`;
    log(`🚀 Starting... (${attacks.length} commands) | mode=${mode} | ms=${ms}`);

    for (let i = 0; i < attacks.length; i++) {
      if (stopRequested) break;

      const { from, to, dtRaw } = attacks[i];

      addBtn.click();
      await sleep(300);

      // last created inputs
      const origin = [...document.querySelectorAll("input.syntetagmenes.plano.origin")].pop();
      const dest   = [...document.querySelectorAll("input.syntetagmenes.plano:not(.origin)")].pop();
      const timeIn = [...document.querySelectorAll("input.wra.plano")].pop();

      if (!setVal(origin, from) || !setVal(dest, to)) {
        alert(`Σφάλμα στα coords στο #${i + 1}`);
        log(`❌ Failed at #${i + 1}: ${from} -> ${to}`);
        break;
      }

      const wra = normalizeWraWithMs(dtRaw, ms);

      if (wra && timeIn) {
        setVal(timeIn, wra);
      } else if (!wra) {
        log(`⚠️ #${i + 1}: Δεν βρέθηκε ώρα στη γραμμή (θα μείνει κενό).`);
      } else if (!timeIn) {
        log(`⚠️ #${i + 1}: Δεν βρέθηκε input ώρας (input.wra.plano).`);
      }

      // Find the container for this command
      const container = origin.closest("tr") || origin.closest(".kapo") || origin.parentElement;

      // Handle different modes
      if (mode === "attackall" || mode === "fefoscustom") {
        const atkBtn =
          findAttackAllButton(origin) ||
          findAttackAllButton(dest) ||
          findAttackAllButton(timeIn) ||
          container?.querySelector?.("a.btn.btn-img.nuke_them.tsalbutton");

        if (atkBtn) {
          atkBtn.click();
          await sleep(100);
          log(`🧨 #${i + 1}: AttackAll clicked`);
          
          // Περιμένουμε λίγο για να γεμίσει τα units με τις τιμές από το AttackAll
          await sleep(50);
        } else {
          log(`⚠️ #${i + 1}: Δεν βρέθηκε AttackAll button`);
        }
      }
      
      // Τώρα γεμίζουμε τα units (ανάλογα με το mode)
      if (mode === "fake") {
        const fakeUnitInputs = {
          spear: fakeSpear,
          sword: fakeSword,
          axe: fakeAxe,
          spy: fakeSpy,
          light: fakeLight,
          heavy: fakeHeavy,
          ram: fakeRam,
          catapult: fakeCatapult,
          knight: fakeKnight,
          snob: fakeSnob
        };
        
        log(`🏹 #${i + 1}: Fake attack units:`);
        const filled = fillUnitsFromInputs(container, fakeUnitInputs, "fake");
        if (!filled) {
          log(`   ⚠️ No unit inputs found in container`);
        }
      } 
      else if (mode === "custom") {
        const customUnitInputs = {
          spear: customSpear,
          sword: customSword,
          axe: customAxe,
          spy: customSpy,
          light: customLight,
          heavy: customHeavy,
          ram: customRam,
          catapult: customCatapult,
          knight: customKnight,
          snob: customSnob
        };
        
        log(`🎯 #${i + 1}: Custom units (NO AttackAll):`);
        const filled = fillUnitsFromInputs(container, customUnitInputs, "custom");
        if (!filled) {
          log(`   ⚠️ No unit inputs found in container`);
        }
      }
      else if (mode === "fefoscustom") {
        // Fefos Custom: AttackAll ΠΡΩΤΑ, μετά όλα τα units σε 0
        log(`🎯 #${i + 1}: Fefos Custom (AttackAll first, then all units to 0):`);
        const filled = fillAllUnitsWithZero(container);
        if (!filled) {
          log(`   ⚠️ No unit inputs found in container`);
        } else {
          log(`   Όλα τα units ορισμένα σε 0`);
        }
      }
      else if (mode === "none") {
        log(`⏭️ #${i + 1}: No AttackAll (mode: none)`);
      }

      progEl.textContent = `Progress: ${i + 1}/${attacks.length}`;
      log(
        `✅ #${i + 1}: ${from} -> ${to}` +
        `${wra ? ` @ ${wra}` : ""}`
      );

      await sleep(10);
    }

    if (stopRequested) {
      setState("stopped");
      log("🛑 Stopped by user.");
    } else {
      setState("done");
      log("🎉 Done.");
    }

    isRunning = false;
  });
})();
Editor is loading...
Leave a Comment