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