Compare commits
3 Commits
6d094ddc8b
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 1f3addf328 | |||
| 3dd67d776b | |||
| 9bdd5f784f |
12
CHANGELOG.md
12
CHANGELOG.md
@@ -1,5 +1,17 @@
|
||||
# Changelog
|
||||
|
||||
## 1.12.3 (2026-12-07)
|
||||
|
||||
- correction du bug de récupération du token
|
||||
|
||||
## 1.12.2 (2026-12-07)
|
||||
|
||||
- correction du bug sur les villages non trouvés
|
||||
|
||||
## 1.12.1 (2026-12-07)
|
||||
|
||||
- ajout du planificateur autonome d'attaques
|
||||
|
||||
## 1.11.4 (2026-12-03)
|
||||
|
||||
- correction du bug sur le calculateur
|
||||
|
||||
1
images/cancel.svg
Normal file
1
images/cancel.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path fill="#000000" d="M183.1 137.4C170.6 124.9 150.3 124.9 137.8 137.4C125.3 149.9 125.3 170.2 137.8 182.7L275.2 320L137.9 457.4C125.4 469.9 125.4 490.2 137.9 502.7C150.4 515.2 170.7 515.2 183.2 502.7L320.5 365.3L457.9 502.6C470.4 515.1 490.7 515.1 503.2 502.6C515.7 490.1 515.7 469.8 503.2 457.3L365.8 320L503.1 182.6C515.6 170.1 515.6 149.8 503.1 137.3C490.6 124.8 470.3 124.8 457.8 137.3L320.5 274.7L183.1 137.4z"/></svg>
|
||||
|
After Width: | Height: | Size: 640 B |
1
images/play.svg
Normal file
1
images/play.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path fill="#000000" d="M187.2 100.9C174.8 94.1 159.8 94.4 147.6 101.6C135.4 108.8 128 121.9 128 136L128 504C128 518.1 135.5 531.2 147.6 538.4C159.7 545.6 174.8 545.9 187.2 539.1L523.2 355.1C536 348.1 544 334.6 544 320C544 305.4 536 291.9 523.2 284.9L187.2 100.9z"/></svg>
|
||||
|
After Width: | Height: | Size: 486 B |
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"manifest_version": 3,
|
||||
"name": "KAplus",
|
||||
"version": "1.11.4",
|
||||
"version": "1.12.3",
|
||||
|
||||
"developer": {
|
||||
"name": "Samuel Campos",
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
"firefox"
|
||||
],
|
||||
"release_notes": {
|
||||
"fr": "- correction du bug sur le calculateur",
|
||||
"en-US": "- fix bug on attack calculator"
|
||||
"fr": "- correction du bug de récupération du token",
|
||||
"en-US": "- fix bug retrieving token"
|
||||
}
|
||||
}
|
||||
}
|
||||
644
src/kaplus.js
644
src/kaplus.js
@@ -1,7 +1,13 @@
|
||||
const AUTHORIZED_ALLIANCES = {
|
||||
"s58": ["NAZGUL"]
|
||||
"s58-fr": ["NAZGUL"]
|
||||
};
|
||||
|
||||
const MOVING_FACTOR = {
|
||||
"s56-fr": 3,
|
||||
"s57-fr": 4,
|
||||
"s58-fr": 1.98,
|
||||
}
|
||||
|
||||
const BUILDINGS = {
|
||||
"main": "Château",
|
||||
"stone": "Carrière",
|
||||
@@ -116,17 +122,13 @@ function selectVillage(selectRef, inputXRef, inputYRef) {
|
||||
}
|
||||
}
|
||||
|
||||
function storeOrderToken(ownVillages, targetVillage) {
|
||||
function storeOrderToken(ownVillages, targetVillage, recursiveIndex) {
|
||||
let orderToken = sessionStorage.getItem("orderToken");
|
||||
if (orderToken !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
let breakLoop = false;
|
||||
for (let villageId in ownVillages) {
|
||||
if (breakLoop === true) {
|
||||
return;
|
||||
}
|
||||
let villageId = Object.keys(ownVillages)[recursiveIndex];
|
||||
let xhrOrder = new XMLHttpRequest();
|
||||
xhrOrder.addEventListener("readystatechange", function () {
|
||||
if (xhrOrder.readyState === xhrOrder.DONE) {
|
||||
@@ -143,6 +145,9 @@ function storeOrderToken(ownVillages, targetVillage) {
|
||||
}
|
||||
}
|
||||
if (unit === null) {
|
||||
if (recursiveIndex < ownVillages.length - 1) {
|
||||
storeOrderToken(ownVillages, targetVillage, recursiveIndex + 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -171,13 +176,12 @@ function storeOrderToken(ownVillages, targetVillage) {
|
||||
});
|
||||
xhrOrder.open("GET", "/?village=" + villageId + "&s=build_barracks");
|
||||
xhrOrder.send();
|
||||
}
|
||||
}
|
||||
|
||||
function storeTargetVillage(ownVillages) {
|
||||
let targetVillage = sessionStorage.getItem("targetVillage");
|
||||
if (targetVillage !== null) {
|
||||
storeOrderToken(ownVillages, JSON.parse(targetVillage));
|
||||
storeOrderToken(ownVillages, JSON.parse(targetVillage), 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -187,7 +191,7 @@ function storeTargetVillage(ownVillages) {
|
||||
if (xhr.readyState === xhr.DONE) {
|
||||
let parser = new DOMParser();
|
||||
let doc = parser.parseFromString(xhr.responseText, "text/html");
|
||||
let cells = doc.getElementsByClassName("occupied range");
|
||||
let cells = doc.getElementsByClassName("occupied");
|
||||
for (let i = 0; i < cells.length; i ++) {
|
||||
let links = cells[i].getElementsByTagName("a");
|
||||
if (links.length === 0) {
|
||||
@@ -200,7 +204,7 @@ function storeTargetVillage(ownVillages) {
|
||||
let villageXY = links[0].getAttribute("onmouseover").replace(/^.*(\d{3}\|\d{3}).*$/, "$1").split("|");
|
||||
targetVillage = {x: parseInt(villageXY[0]), y: parseInt(villageXY[1])};
|
||||
sessionStorage.setItem("targetVillage", JSON.stringify(targetVillage));
|
||||
storeOrderToken(ownVillages, targetVillage);
|
||||
storeOrderToken(ownVillages, targetVillage, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -286,10 +290,10 @@ function customizeNavbar(layCastleElement) {
|
||||
shortcutContainers[2].classList.add("shortcut_container_right");
|
||||
}
|
||||
|
||||
function countUpMs(tomorrow, after_tomorrow, movingDuration) {
|
||||
function countUpMs(tomorrow, afterTomorrow, movingDuration) {
|
||||
let arrivalDate = new Date(new Date().getTime() + movingDuration * 1000);
|
||||
let prefix = "";
|
||||
if (arrivalDate >= after_tomorrow) {
|
||||
if (arrivalDate >= afterTomorrow) {
|
||||
prefix = "le " + arrivalDate.getDate() + "." + arrivalDate.getMonth() + " ";
|
||||
} else if (arrivalDate > tomorrow) {
|
||||
prefix = "demain ";
|
||||
@@ -305,32 +309,47 @@ function countUpMs(tomorrow, after_tomorrow, movingDuration) {
|
||||
+ Math.floor(arrivalDate.getMilliseconds() / 100);
|
||||
}
|
||||
|
||||
function countdownMS(formattedDate) {
|
||||
function convertTimestamp(timestamp) {
|
||||
let now = new Date();
|
||||
if (formattedDate.startsWith("à")) {
|
||||
let start = new Date();
|
||||
let hms = formattedDate.replace(/^à (\d\d:\d\d:\d\d) heures$/, "$1").split(":");
|
||||
start.setHours(parseInt(hms[0]));
|
||||
start.setMinutes(parseInt(hms[1]));
|
||||
start.setSeconds(parseInt(hms[2]));
|
||||
return start.getTime() - now.getTime();
|
||||
let tomorrow = new Date(now.getTime() + 24*3600*1000);
|
||||
tomorrow.setHours(0);
|
||||
tomorrow.setMinutes(0);
|
||||
tomorrow.setSeconds(0);
|
||||
tomorrow.setMilliseconds(0);
|
||||
let afterTomorrow = new Date(tomorrow.getTime() + 24*3600*1000);
|
||||
let date = new Date(timestamp);
|
||||
|
||||
let prefix = "";
|
||||
if (date >= afterTomorrow) {
|
||||
prefix = "le " + date.getDate() + "." + date.getMonth() + " ";
|
||||
} else if (date > tomorrow) {
|
||||
prefix = "demain ";
|
||||
}
|
||||
if (formattedDate.startsWith("demain")) {
|
||||
let start = new Date(now.getTime() + 24*60*60*1000);
|
||||
let hms = formattedDate.replace(/^demain à (\d\d:\d\d:\d\d) heures$/, "$1").split(":");
|
||||
start.setHours(parseInt(hms[0]));
|
||||
start.setMinutes(parseInt(hms[1]));
|
||||
start.setSeconds(parseInt(hms[2]));
|
||||
return start.getTime() - now.getTime();
|
||||
}
|
||||
let start = new Date();
|
||||
let hms = formattedDate.replace(/^le (\d\d)\.(\d\d) à (\d\d:\d\d:\d\d) heures$/, "$1:$2:$3");
|
||||
start.setDate(parseInt(hms[0]));
|
||||
start.setMonth(parseInt(hms[1]));
|
||||
start.setHours(parseInt(hms[0]));
|
||||
start.setMinutes(parseInt(hms[1]));
|
||||
start.setSeconds(parseInt(hms[2]));
|
||||
return start.getTime() - now.getTime();
|
||||
return prefix
|
||||
+ "à "
|
||||
+ date.getHours().toString().padStart(2, "0")
|
||||
+ ":"
|
||||
+ date.getMinutes().toString().padStart(2, "0")
|
||||
+ ":"
|
||||
+ date.getSeconds().toString().padStart(2, "0")
|
||||
+ "."
|
||||
+ Math.floor(date.getMilliseconds() / 100);
|
||||
}
|
||||
|
||||
function convertDurationUntil(timestamp) {
|
||||
let now = new Date();
|
||||
let duration = timestamp - now.getTime();
|
||||
let hours = Math.floor(duration / (3600*1000));
|
||||
duration -= hours * 3600 * 1000;
|
||||
let minutes = Math.floor(duration / (60*1000));
|
||||
duration -= minutes * 60 * 1000;
|
||||
let seconds = Math.floor(duration / 1000);
|
||||
duration -= seconds * 1000;
|
||||
let tenth = Math.floor(duration / 100);
|
||||
return hours.toString().padStart(2, "0") + ":"
|
||||
+ minutes.toString().padStart(2, "0") + ":"
|
||||
+ seconds.toString().padStart(2, "0") + "."
|
||||
+ tenth.toString();
|
||||
}
|
||||
|
||||
function removeAdsBanner() {
|
||||
@@ -437,13 +456,421 @@ function showAutoPlanerMenu(village, module) {
|
||||
navRow.insertBefore(separatorCell, navCells[6]);
|
||||
}
|
||||
|
||||
function insertAutoPlanedOrder(table, orderId, order) {
|
||||
let row = createCustomElement(
|
||||
"tr",
|
||||
{
|
||||
"data-id": orderId,
|
||||
"data-time": order.start_time,
|
||||
"data-order": JSON.stringify(order),
|
||||
"data-status": "waiting",
|
||||
}
|
||||
);
|
||||
|
||||
let kindCell = createCustomElement("td");
|
||||
let kindImg = createCustomElement("img");
|
||||
switch (order.kind) {
|
||||
case "attack":
|
||||
kindImg.setAttribute("src", "/img/command/attack.png");
|
||||
kindImg.setAttribute("title", "Attaque");
|
||||
break;
|
||||
case "support":
|
||||
kindImg.setAttribute("src", "/img/command/support.png");
|
||||
kindImg.setAttribute("title", "Renfort");
|
||||
break
|
||||
case "spying":
|
||||
kindImg.setAttribute("src", "/img/units/unit_spy-slow.png");
|
||||
kindImg.setAttribute("title", "Espionnage");
|
||||
break;
|
||||
}
|
||||
kindCell.appendChild(kindImg);
|
||||
row.appendChild(kindCell);
|
||||
|
||||
let unitCounts = [];
|
||||
for (let unit in UNITS) {
|
||||
unitCounts.push(order[unit]);
|
||||
}
|
||||
let labelCell = createCustomElement(
|
||||
"td",
|
||||
{"title": "Programmé " + order.occurrences.toString() + " fois"},
|
||||
"(x" + order.occurrences + ") " + order.label,
|
||||
);
|
||||
row.appendChild(labelCell);
|
||||
|
||||
let headCell = createCustomElement(
|
||||
"td",
|
||||
{
|
||||
"onmouseover":
|
||||
"Tip(tipUnitDetails('/img', '" + Object.keys(UNITS).join(":") + "', '" + unitCounts.join(":") + "'))",
|
||||
"onmouseout": "UnTip()",
|
||||
},
|
||||
);
|
||||
let headImg = createCustomElement("img", {"src": "/img/units/unit_" + order.head + ".png"});
|
||||
headCell.appendChild(headImg);
|
||||
row.appendChild(headCell);
|
||||
|
||||
let originCell = createCustomElement("td");
|
||||
let originInfoLink = createCustomElement(
|
||||
"a",
|
||||
{"href": "/?s=info_village&id=" + order.start_id, "title": order.start_name},
|
||||
order.start_name,
|
||||
);
|
||||
let originMapLink = createCustomElement(
|
||||
"a",
|
||||
{"href": "/?s=map&x=" + order.start_x + "&y=" + order.start_y},
|
||||
"(" + order.start_x + "|" + order.start_y + ")",
|
||||
)
|
||||
originCell.appendChild(originInfoLink);
|
||||
originCell.appendChild(originMapLink);
|
||||
row.appendChild(originCell);
|
||||
|
||||
let targetCell = createCustomElement("td");
|
||||
let targetInfoLink = createCustomElement(
|
||||
"a",
|
||||
{"href": "/?s=info_village&id=" + order.target_id, "title": order.target_name},
|
||||
order.target_name,
|
||||
);
|
||||
let targetMapLink = createCustomElement(
|
||||
"a",
|
||||
{"href": "/?s=map&x=" + order.target_x + "&y=" + order.target_y},
|
||||
" (" + order.target_x + "|" + order.target_y + ")",
|
||||
)
|
||||
targetCell.appendChild(targetInfoLink);
|
||||
targetCell.appendChild(targetMapLink);
|
||||
row.appendChild(targetCell);
|
||||
|
||||
row.appendChild(createCustomElement("td", null, convertTimestamp(parseInt(order.start_time))));
|
||||
row.appendChild(createCustomElement("td", null, convertTimestamp(parseInt(order.target_time))));
|
||||
row.appendChild(createCustomElement("td", null, convertDurationUntil(parseInt(order.start_time))));
|
||||
|
||||
let playCell = createCustomElement("td");
|
||||
let playLink = createCustomElement(
|
||||
"a",
|
||||
{
|
||||
"href": "/?village=" + order.start_id + "&s=build_barracks&m=command" +
|
||||
"&send_x=" + order.target_x + "&send_y=" + order.target_y + "&farmer=" + order.farmer +
|
||||
"&sword=" + order.sword + "&spear=" + order.spear + "&axe=" + order.axe + "&bow=" + order.bow +
|
||||
"&spy=" + order.spy + "&light=" + order.light + "&heavy=" + order.heavy + "&ram=" + order.ram +
|
||||
"&kata=" + order.kata + "&snob=" + order.snob,
|
||||
"title": "Lancer manuellement",
|
||||
},
|
||||
);
|
||||
let playImg = createCustomElement(
|
||||
"img", {"src": chrome.runtime.getURL("/images/play.svg")}, null, {"width": "18px"}
|
||||
);
|
||||
playLink.appendChild(playImg);
|
||||
playCell.appendChild(playLink);
|
||||
row.appendChild(playCell);
|
||||
|
||||
let cancelCell = createCustomElement("td");
|
||||
let cancelImg = createCustomElement(
|
||||
"img",
|
||||
{"src": chrome.runtime.getURL("/images/cancel.svg"), "title": "Annuler"},
|
||||
null,
|
||||
{"width": "18px", "cursor": "pointer"},
|
||||
);
|
||||
cancelImg.addEventListener("click", function() {
|
||||
row.remove();
|
||||
let autoPlanedOrders = localStorage.getItem("autoPlanedOrders");
|
||||
if (autoPlanedOrders === null) {
|
||||
return;
|
||||
}
|
||||
autoPlanedOrders = JSON.parse(autoPlanedOrders);
|
||||
delete autoPlanedOrders[orderId];
|
||||
localStorage.setItem("autoPlanedOrders", JSON.stringify(autoPlanedOrders));
|
||||
});
|
||||
cancelCell.appendChild(cancelImg);
|
||||
row.appendChild(cancelCell);
|
||||
|
||||
// Insert row at right time place
|
||||
let rows = table.getElementsByTagName("tr");
|
||||
for (let i = 1; i < rows.length; i ++) {
|
||||
if (parseInt(rows[i].getAttribute("data-time")) > parseInt(order.start_time)) {
|
||||
table.insertBefore(row, rows[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
table.appendChild(row);
|
||||
}
|
||||
|
||||
function autoPlanerInterval() {
|
||||
let now = new Date().getTime();
|
||||
let table = document.getElementById("autoPlanedOrders");
|
||||
let rows = table.getElementsByTagName("tr");
|
||||
let delay = 100;
|
||||
for (let i = 1; i < rows.length; i ++) {
|
||||
if (rows[i].getAttribute("data-status") !== "waiting") {
|
||||
continue;
|
||||
}
|
||||
|
||||
let startTime = parseInt(rows[i].getAttribute("data-time"));
|
||||
let duration = startTime - now;
|
||||
if (duration <= 0) {
|
||||
rows[i].setAttribute("data-status", "done");
|
||||
rows[i].style.opacity = "0.5";
|
||||
let order = JSON.parse(rows[i].getAttribute("data-order"));
|
||||
let orderToken = sessionStorage.getItem("orderToken");
|
||||
let formData = new FormData();
|
||||
for (let unit in UNITS) {
|
||||
formData.set(unit, order[unit]);
|
||||
}
|
||||
switch (order.kind) {
|
||||
case "attack":
|
||||
formData.set("attack", "Attaquer");
|
||||
formData.set("espy", "");
|
||||
if (order.kata !== "0") {
|
||||
formData.set("kata_target", order.building);
|
||||
}
|
||||
break;
|
||||
case "support":
|
||||
formData.set("attack", "");
|
||||
formData.set("espy", "");
|
||||
break;
|
||||
case "spying":
|
||||
formData.set("attack", "");
|
||||
formData.set("espy", "Espionner");
|
||||
break;
|
||||
}
|
||||
formData.set("send_x", order.target_x);
|
||||
formData.set("send_y", order.target_y);
|
||||
formData.set("transport", "none");
|
||||
let formParams = new URLSearchParams(formData);
|
||||
|
||||
for (let j = 0; j < parseInt(order.occurrences); j ++) {
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open(
|
||||
"POST", "/?village=" + order.start_id + "&s=build_barracks&m=command&a=sendTroop&p=" + orderToken
|
||||
);
|
||||
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||
xhr.send(formParams.toString());
|
||||
|
||||
let autoPlanedOrders = localStorage.getItem("autoPlanedOrders");
|
||||
if (autoPlanedOrders === null) {
|
||||
return;
|
||||
}
|
||||
autoPlanedOrders = JSON.parse(autoPlanedOrders);
|
||||
delete autoPlanedOrders[rows[i].getAttribute("data-id")];
|
||||
localStorage.setItem("autoPlanedOrders", JSON.stringify(autoPlanedOrders));
|
||||
}
|
||||
} else {
|
||||
rows[i].getElementsByTagName("td")[7].textContent = convertDurationUntil(startTime);
|
||||
}
|
||||
}
|
||||
setTimeout(autoPlanerInterval, delay);
|
||||
}
|
||||
|
||||
function handleAutoPlanerUnitChange() {
|
||||
let buildingSelect = document.getElementById("autoPlanerBuilding");
|
||||
let unitInputs = document.getElementById("autoPlanerUnitRow").getElementsByTagName("input");
|
||||
let totalUnitCount = 0;
|
||||
let spyCount = 0;
|
||||
let kataCount = 0;
|
||||
let attackButton = document.getElementById("autoPlanerSubmitAttack");
|
||||
let supportButton = document.getElementById("autoPlanerSubmitSupport");
|
||||
let spyingButton = document.getElementById("autoPlanerSubmitSpying");
|
||||
|
||||
for (let i = 0; i < unitInputs.length; i ++) {
|
||||
let unitCount = 0;
|
||||
if (unitInputs[i].value !== "") {
|
||||
unitCount = parseInt(unitInputs[i].value);
|
||||
}
|
||||
if (unitInputs[i].getAttribute("name") === "spy") {
|
||||
spyCount = unitCount;
|
||||
}
|
||||
if (unitInputs[i].getAttribute("name") === "kata") {
|
||||
kataCount = unitCount;
|
||||
}
|
||||
totalUnitCount += unitCount;
|
||||
}
|
||||
|
||||
if (kataCount > 0) {
|
||||
buildingSelect.removeAttribute("disabled");
|
||||
} else {
|
||||
buildingSelect.setAttribute("disabled", "disabled");
|
||||
}
|
||||
|
||||
if (spyCount > 0 && spyCount === totalUnitCount) {
|
||||
spyingButton.removeAttribute("disabled");
|
||||
} else {
|
||||
spyingButton.setAttribute("disabled", "disabled");
|
||||
}
|
||||
|
||||
if (totalUnitCount > 0) {
|
||||
attackButton.removeAttribute("disabled");
|
||||
supportButton.removeAttribute("disabled");
|
||||
} else {
|
||||
attackButton.setAttribute("disabled", "disabled");
|
||||
supportButton.setAttribute("disabled", "disabled");
|
||||
}
|
||||
}
|
||||
|
||||
function handleAutoPlanerSubmit(event) {
|
||||
event.preventDefault();
|
||||
|
||||
let autoPlanerError = document.getElementById("autoPlanerError");
|
||||
autoPlanerError.textContent = " ";
|
||||
|
||||
let nowTime = Date.now();
|
||||
let formData = new FormData(this);
|
||||
formData.set("kind", event.submitter.getAttribute("name"));
|
||||
|
||||
// Check start village
|
||||
let ownVillages = sessionStorage.getItem("ownVillages");
|
||||
if (ownVillages === null) {
|
||||
autoPlanerError.textContent = "Impossible de récupérer la liste de vos propres villages, " +
|
||||
"merci de recharger la page ou de vous reconnecter au jeu si le problème persiste!"
|
||||
return;
|
||||
}
|
||||
ownVillages = JSON.parse(ownVillages);
|
||||
for (let ownVillageId in ownVillages) {
|
||||
let ownVillage = ownVillages[ownVillageId];
|
||||
if (ownVillage.x === parseInt(formData.get("start_x").toString()) &&
|
||||
ownVillage.y === parseInt(formData.get("start_y").toString())) {
|
||||
formData.set("start_id", ownVillageId);
|
||||
formData.set("start_name", ownVillage.name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (! formData.has("start_id")) {
|
||||
autoPlanerError.textContent = "Opération impossible car le village d'origine ne vous appartient pas!";
|
||||
return;
|
||||
}
|
||||
|
||||
// Check target time
|
||||
let targetTime = Date.parse(
|
||||
formData.get("year").toString() + "-" +
|
||||
formData.get("month").toString().padStart(2, "0") + "-" +
|
||||
formData.get("day").toString().padStart(2, "0") + "T" +
|
||||
formData.get("hour").toString().padStart(2, "0") + ":" +
|
||||
formData.get("minute").toString().padStart(2, "0") + ":" +
|
||||
formData.get("second").toString().padStart(2, "0")
|
||||
) + parseInt(formData.get("tenth").toString()) * 100;
|
||||
if (nowTime > targetTime) {
|
||||
autoPlanerError.textContent = "Opération impossible car l'heure d'arrivée est dans le passé!";
|
||||
return;
|
||||
}
|
||||
formData.set("target_time", targetTime.toString());
|
||||
formData.delete("year");
|
||||
formData.delete("month");
|
||||
formData.delete("day");
|
||||
formData.delete("hour");
|
||||
formData.delete("minute");
|
||||
formData.delete("second");
|
||||
formData.delete("tenth");
|
||||
|
||||
// Replace empty unit values by 0
|
||||
for (let unit in UNITS) {
|
||||
if (formData.get(unit) === "") {
|
||||
formData.set(unit, "0");
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate start time
|
||||
let serverId = window.location.hostname.replace(/^([^.]+).*$/, "$1");
|
||||
let moving_factor = 1;
|
||||
if (serverId in MOVING_FACTOR) {
|
||||
moving_factor = MOVING_FACTOR[serverId];
|
||||
}
|
||||
let durationSeconds = Math.sqrt(
|
||||
Math.pow(parseInt(formData.get("target_x").toString()) - parseInt(formData.get("start_x").toString()), 2) +
|
||||
Math.pow(parseInt(formData.get("target_y").toString()) - parseInt(formData.get("start_y").toString()), 2)
|
||||
)
|
||||
if (formData.get("snob") !== "0") {
|
||||
durationSeconds *= 2100 / moving_factor;
|
||||
formData.set("head", "snob");
|
||||
} else if (formData.get("kata") !== "0") {
|
||||
durationSeconds *= 1800 / moving_factor;
|
||||
formData.set("head", "kata");
|
||||
} else if (formData.get("ram") !== "0") {
|
||||
durationSeconds *= 1800 / moving_factor;
|
||||
formData.set("head", "ram");
|
||||
} else if (formData.get("kind") === "spying") {
|
||||
durationSeconds *= 1800 / moving_factor;
|
||||
formData.set("head", "spy");
|
||||
} else if (formData.get("sword") !== "0") {
|
||||
durationSeconds *= 1320 / moving_factor;
|
||||
formData.set("head", "sword");
|
||||
} else if (formData.get("farmer") !== "0") {
|
||||
durationSeconds *= 1200 / moving_factor;
|
||||
formData.set("head", "farmer");
|
||||
} else if (formData.get("spear") !== "0") {
|
||||
durationSeconds *= 1080 / moving_factor;
|
||||
formData.set("head", "spear");
|
||||
} else if (formData.get("axe") !== "0") {
|
||||
durationSeconds *= 1080 / moving_factor;
|
||||
formData.set("head", "axe");
|
||||
} else if (formData.get("bow") !== "0") {
|
||||
durationSeconds *= 1080 / moving_factor;
|
||||
formData.set("head", "bow");
|
||||
} else if (formData.get("heavy") !== "0") {
|
||||
durationSeconds *= 660 / moving_factor;
|
||||
formData.set("head", "heavy");
|
||||
} else if (formData.get("light") !== "0") {
|
||||
durationSeconds *= 600 / moving_factor;
|
||||
formData.set("head", "light");
|
||||
} else if (formData.get("spy") !== "0") {
|
||||
durationSeconds *= 540 / moving_factor;
|
||||
formData.set("head", "spy");
|
||||
} else {
|
||||
autoPlanerError.textContent = "Opération impossible car aucune unité n'a été sélectionnée!";
|
||||
return;
|
||||
}
|
||||
let duration = Math.round(durationSeconds) * 1000;
|
||||
let startTime = targetTime - duration;
|
||||
if (nowTime > startTime) {
|
||||
autoPlanerError.textContent = "Opération impossible car l'heure de départ est dans le passé!";
|
||||
return;
|
||||
}
|
||||
formData.set("start_time", startTime.toString());
|
||||
|
||||
// Check target village
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.addEventListener("readystatechange", function () {
|
||||
if (xhr.readyState === xhr.DONE) {
|
||||
let parser = new DOMParser();
|
||||
let doc = parser.parseFromString(xhr.responseText, "text/html");
|
||||
let mapContainer = doc.getElementById("mapContainer");
|
||||
let map = mapContainer.getElementsByTagName("table")[1];
|
||||
let tbody = map.getElementsByTagName("tbody")[0];
|
||||
let mapCell = tbody.children[6].children[8];
|
||||
let mapLinks = mapCell.getElementsByTagName("a");
|
||||
if (mapLinks.length === 0) {
|
||||
autoPlanerError.textContent = "Opération impossible car le village cible n'existe pas!";
|
||||
return;
|
||||
}
|
||||
formData.set("target_id", mapLinks[0].getAttribute("href").replace(/^.*id=(\d{4}).*$/, "$1"));
|
||||
let targetName = mapLinks[0].getAttribute("onmouseover").replace(/^.*'(.*) \(\d{3}\|\d{3}\).*$/, "$1");
|
||||
targetName = targetName.replace(/ <.*>/, "");
|
||||
formData.set("target_name", targetName);
|
||||
|
||||
// Save attack in localStorage
|
||||
let autoPlanedOrders = localStorage.getItem("autoPlanedOrders");
|
||||
if (autoPlanedOrders === null) {
|
||||
autoPlanedOrders = {};
|
||||
} else {
|
||||
autoPlanedOrders = JSON.parse(autoPlanedOrders);
|
||||
}
|
||||
let orderId = crypto.randomUUID();
|
||||
let order = Object.fromEntries(formData);
|
||||
insertAutoPlanedOrder(document.getElementById("autoPlanedOrders"), orderId, order);
|
||||
autoPlanedOrders[orderId] = order;
|
||||
localStorage.setItem("autoPlanedOrders", JSON.stringify(autoPlanedOrders));
|
||||
}
|
||||
});
|
||||
xhr.open(
|
||||
"GET",
|
||||
"/?s=map&x=" + formData.get("target_x").toString() + "&y=" + formData.get("target_y").toString(),
|
||||
);
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
function showAutoPlanerPage(village) {
|
||||
let mainContentPane = document.getElementsByClassName("contentpane")[1];
|
||||
for (let i = mainContentPane.childNodes.length - 1; i >= 5; i --) {
|
||||
mainContentPane.childNodes[i].remove();
|
||||
}
|
||||
|
||||
let autoPlanerForm = createCustomElement("form", {"name": "kingsage"});
|
||||
let autoPlanerForm = createCustomElement("form", {"name": "kingsage", "id": "autoPlanerForm"});
|
||||
let borderList = createCustomElement("table", {"class": "borderlist", "width": "820"});
|
||||
let titleRow = createCustomElement("tr");
|
||||
let titleCell = createCustomElement("th", {"colspan": "7"}, "Nouvel ordre autonome");
|
||||
@@ -525,7 +952,7 @@ function showAutoPlanerPage(village) {
|
||||
"number",
|
||||
"target_x",
|
||||
null,
|
||||
{"id": "target_x", "required": "required", "min": "1", "max": "999"},
|
||||
{"id": "target_x", "required": "required", "min": "0", "max": "999"},
|
||||
{"width": "50px"},
|
||||
);
|
||||
targetXCell.appendChild(targetXInput);
|
||||
@@ -536,7 +963,7 @@ function showAutoPlanerPage(village) {
|
||||
"number",
|
||||
"target_y",
|
||||
null,
|
||||
{"id": "target_y", "required": "required", "min": "1", "max": "999"},
|
||||
{"id": "target_y", "required": "required", "min": "0", "max": "999"},
|
||||
{"width": "50px"},
|
||||
);
|
||||
targetYCell.appendChild(targetYInput);
|
||||
@@ -572,7 +999,7 @@ function showAutoPlanerPage(village) {
|
||||
dateCell.appendChild(createCustomInput(
|
||||
"number",
|
||||
"month",
|
||||
now.getMonth().toString(),
|
||||
(now.getMonth() + 1).toString(),
|
||||
{"required": "required", "min": "1", "max": "12"},
|
||||
{"width": "40px"},
|
||||
));
|
||||
@@ -631,23 +1058,20 @@ function showAutoPlanerPage(village) {
|
||||
}
|
||||
|
||||
unitBorderList.appendChild(unitTitleRow);
|
||||
let unitInputRow = createCustomElement("tr");
|
||||
let unitInputRow = createCustomElement("tr", {"id": "autoPlanerUnitRow"});
|
||||
for (let unit in UNITS) {
|
||||
let unitInputCell = createCustomElement("td");
|
||||
let unitInput = createCustomInput("number", unit, null, {"min": "0"}, {"width": "61px"});
|
||||
let unitInput = createCustomInput(
|
||||
"number",
|
||||
unit,
|
||||
null,
|
||||
{"id": "autoPlanerUnit" + unit.charAt(0).toUpperCase() + unit.slice(1), "min": "0"}, {"width": "61px"},
|
||||
);
|
||||
unitInput.addEventListener("change", handleAutoPlanerUnitChange);
|
||||
switch (unit) {
|
||||
case "spy": case "light": case "heavy": case "ram": case "snob":
|
||||
unitInput.style.width = "62px";
|
||||
break;
|
||||
case "kata":
|
||||
unitInput.addEventListener("change", function () {
|
||||
if (autoPlanerForm.kata.value !== "0" && autoPlanerForm.genre.value === "attack") {
|
||||
autoPlanerForm.building.removeAttribute("disabled");
|
||||
} else {
|
||||
autoPlanerForm.building.setAttribute("disabled", "disabled");
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
unitInputCell.appendChild(unitInput);
|
||||
unitInputRow.appendChild(unitInputCell);
|
||||
@@ -663,7 +1087,7 @@ function showAutoPlanerPage(village) {
|
||||
labelRow.appendChild(createCustomElement("td", null, "Étiquette:"));
|
||||
let labelCell = createCustomElement("td", {"colspan": "6"});
|
||||
let labelInput = createCustomInput(
|
||||
"text", "label", null, {"maxlength": "10"}, {"width": "100px"}
|
||||
"text", "label", null, {"maxlength": "10", "placeholder": "Optionnel"}, {"width": "100px"}
|
||||
);
|
||||
labelCell.appendChild(labelInput);
|
||||
labelRow.appendChild(labelCell);
|
||||
@@ -679,33 +1103,12 @@ function showAutoPlanerPage(village) {
|
||||
occurrencesRow.appendChild(occurrencesCell);
|
||||
additionalBorderList.appendChild(occurrencesRow);
|
||||
|
||||
let genreRow = createCustomElement("tr");
|
||||
genreRow.appendChild(createCustomElement("td", null, "Type:"));
|
||||
let genreCell = createCustomElement("td", {"colspan": "6"});
|
||||
let genreSelect = createCustomElement(
|
||||
"select", {"name": "genre", "value": "attack"}, {"required": "required"}, {"width": "200px"}
|
||||
);
|
||||
genreSelect.appendChild(createCustomElement("option", {"value": "attack"}, "Attaque"));
|
||||
genreSelect.appendChild(createCustomElement("option", {"value": "support"}, "Renfort"));
|
||||
genreSelect.appendChild(createCustomElement("option", {"value": "spy"}, "Espionnage"));
|
||||
genreSelect.addEventListener("change", function () {
|
||||
if (autoPlanerForm.kata.value !== "0" && autoPlanerForm.genre.value === "attack") {
|
||||
autoPlanerForm.building.removeAttribute("disabled");
|
||||
} else {
|
||||
autoPlanerForm.building.setAttribute("disabled", "disabled");
|
||||
}
|
||||
});
|
||||
genreCell.appendChild(genreSelect);
|
||||
genreRow.appendChild(genreCell);
|
||||
additionalBorderList.appendChild(genreRow);
|
||||
|
||||
let buildingRow = createCustomElement("tr");
|
||||
buildingRow.appendChild(createCustomElement("td", null, "Bâtiment visé:"));
|
||||
let buildingCell = createCustomElement("td", {"colspan": "6"});
|
||||
let buildingSelect = createCustomElement(
|
||||
"select", {"name": "building", "disabled": "disabled"}, null, {"width": "200px"}
|
||||
"select", {"name": "building", "disabled": "disabled", "id": "autoPlanerBuilding"}, null, {"width": "200px"}
|
||||
);
|
||||
buildingSelect.appendChild(createCustomElement("option", null, "Sélectionner bâtiment"));
|
||||
for (let building in BUILDINGS) {
|
||||
buildingSelect.appendChild(createCustomElement("option", {"value": building}, BUILDINGS[building]));
|
||||
}
|
||||
@@ -713,19 +1116,19 @@ function showAutoPlanerPage(village) {
|
||||
buildingRow.appendChild(buildingCell);
|
||||
additionalBorderList.appendChild(buildingRow);
|
||||
|
||||
autoPlanerForm.addEventListener("submit", function (event) {
|
||||
event.preventDefault();
|
||||
let formData = new FormData(this);
|
||||
let autoPlanedAttacks = localStorage.getItem("autoPlanedAttacks");
|
||||
if (autoPlanedAttacks === null) {
|
||||
autoPlanedAttacks = [];
|
||||
} else {
|
||||
autoPlanedAttacks = JSON.parse(autoPlanedAttacks);
|
||||
}
|
||||
autoPlanedAttacks.push(Object.fromEntries(formData));
|
||||
localStorage.setItem("autoPlanedAttacks", JSON.stringify(autoPlanedAttacks));
|
||||
})
|
||||
|
||||
autoPlanerForm.appendChild(createCustomElement(
|
||||
"p",
|
||||
null,
|
||||
"!ATTENTION! Les programmations sur cette page sont sauvegardées sur ce navigateur uniquement. " +
|
||||
"Afin que les troupes soient envoyées automatiquement, il faut garder cette page ouverte sur " +
|
||||
"ce navigateur et rester connecté ici. Vous ne pourrez donc pas voir les programmations d'ici sur " +
|
||||
"un autre navigateur ou un autre appareil. Cependant, les programmations sont persistantes sur " +
|
||||
"votre navigateur, donc vous pouvez le fermer et le rouvrir, vous verrez toujours les programmations ici.",
|
||||
{"font-weight": "bold"},
|
||||
));
|
||||
autoPlanerForm.appendChild(createCustomElement("br"));
|
||||
autoPlanerForm.appendChild(createCustomElement("p", {"class": "error", "id": "autoPlanerError"}, " "));
|
||||
autoPlanerForm.appendChild(createCustomElement("br"));
|
||||
autoPlanerForm.appendChild(borderList);
|
||||
autoPlanerForm.appendChild(createCustomElement("br"));
|
||||
autoPlanerForm.appendChild(unitBorderList);
|
||||
@@ -734,12 +1137,57 @@ function showAutoPlanerPage(village) {
|
||||
autoPlanerForm.appendChild(createCustomElement("br"));
|
||||
autoPlanerForm.appendChild(createCustomInput(
|
||||
"submit",
|
||||
null,
|
||||
"> Ajouter une nouvelle entrée",
|
||||
null,
|
||||
{"font-weight": "bold", "padding": "5px 20px", "cursor": "pointer"}
|
||||
"attack",
|
||||
"> Programmer une nouvelle attaque",
|
||||
{"id": "autoPlanerSubmitAttack", "disabled": "disabled"},
|
||||
{"font-weight": "bold", "width": "250px", "padding": "5px 0", "cursor": "pointer"}
|
||||
));
|
||||
autoPlanerForm.appendChild(createCustomInput(
|
||||
"submit",
|
||||
"support",
|
||||
"> Programmer un nouveau renfort",
|
||||
{"id": "autoPlanerSubmitSupport", "disabled": "disabled"},
|
||||
{"font-weight": "bold", "width": "250px", "padding": "5px 0", "margin": "0 35px", "cursor": "pointer"}
|
||||
));
|
||||
autoPlanerForm.appendChild(createCustomInput(
|
||||
"submit",
|
||||
"spying",
|
||||
"> Programmer un nouvel espionnage",
|
||||
{"id": "autoPlanerSubmitSpying", "disabled": "disabled"},
|
||||
{"font-weight": "bold", "width": "250px", "padding": "5px 0", "cursor": "pointer"}
|
||||
));
|
||||
autoPlanerForm.addEventListener("submit", handleAutoPlanerSubmit);
|
||||
mainContentPane.appendChild(autoPlanerForm);
|
||||
|
||||
let ordersBorderList = createCustomElement(
|
||||
"table", {"id": "autoPlanedOrders", "class": "borderlist"}, null, {"width": "820px"}
|
||||
);
|
||||
let ordersTitleRow = createCustomElement("tr");
|
||||
ordersTitleRow.appendChild(createCustomElement("th", {"colspan": "3"}));
|
||||
ordersTitleRow.appendChild(createCustomElement("th", null, "Village originel"));
|
||||
ordersTitleRow.appendChild(createCustomElement("th", null, "Village cible"));
|
||||
ordersTitleRow.appendChild(createCustomElement("th", null, "Heure du début"));
|
||||
ordersTitleRow.appendChild(createCustomElement("th", null, "Heure d'arrivée"));
|
||||
ordersTitleRow.appendChild(createCustomElement("th", null, "Décompte"));
|
||||
ordersTitleRow.appendChild(createCustomElement("th", {"colspan": "2"}));
|
||||
ordersBorderList.appendChild(ordersTitleRow);
|
||||
|
||||
mainContentPane.appendChild(createCustomElement("br"));
|
||||
mainContentPane.appendChild(createCustomElement("br"));
|
||||
mainContentPane.appendChild(ordersBorderList);
|
||||
|
||||
let autoPlanedOrders = localStorage.getItem("autoPlanedOrders");
|
||||
if (autoPlanedOrders === null) {
|
||||
return;
|
||||
}
|
||||
autoPlanedOrders = JSON.parse(autoPlanedOrders);
|
||||
if (autoPlanedOrders.length === 0) {
|
||||
return;
|
||||
}
|
||||
for (let orderId in autoPlanedOrders) {
|
||||
insertAutoPlanedOrder(ordersBorderList, orderId, autoPlanedOrders[orderId]);
|
||||
}
|
||||
autoPlanerInterval();
|
||||
}
|
||||
|
||||
function showVillageUnitPoints() {
|
||||
@@ -909,16 +1357,16 @@ function showOccurrencesInput() {
|
||||
form.addEventListener("submit", function (event) {
|
||||
event.preventDefault();
|
||||
let formData = new FormData(this);
|
||||
let attackCount = parseInt(formData.get("occurrences").toString());
|
||||
let occurrences = parseInt(formData.get("occurrences").toString());
|
||||
formData.delete("occurrences");
|
||||
let sent = 0;
|
||||
for (let i = 0; i < attackCount; i ++) {
|
||||
for (let i = 0; i < occurrences; i ++) {
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.addEventListener("readystatechange", function () {
|
||||
if (this.readyState === this.DONE) {
|
||||
sent ++;
|
||||
}
|
||||
if (sent === attackCount) {
|
||||
if (sent === occurrences) {
|
||||
window.location.replace(xhr.responseURL);
|
||||
}
|
||||
})
|
||||
@@ -936,7 +1384,8 @@ function fixSelectVillageBug() {
|
||||
return;
|
||||
}
|
||||
selects[0].removeAttribute("onchange");
|
||||
selects[0].addEventListener("change", function () { selectVillage("TODO", "send_x", "send_y") });
|
||||
selects[0].setAttribute("id", "ownlist");
|
||||
selects[0].addEventListener("change", function () { selectVillage("ownlist", "send_x", "send_y") });
|
||||
}
|
||||
|
||||
function showThousandInputs() {
|
||||
@@ -1000,7 +1449,6 @@ function showSecondsAndCalculator() {
|
||||
if (rows[titleRowIndex].getElementsByTagName("th").length === 0) {
|
||||
titleRowIndex = 1;
|
||||
}
|
||||
console.log(titleRowIndex)
|
||||
|
||||
let headCell = createCustomElement("th", null, "Calcul", {"width": "45px"});
|
||||
rows[titleRowIndex].appendChild(headCell);
|
||||
@@ -1064,7 +1512,7 @@ function main() {
|
||||
|
||||
/* Exit immediately if not authorized */
|
||||
let xhrAlly = new XMLHttpRequest();
|
||||
let serverID = window.location.hostname.replace(/^(s\d+)-.*$/, "$1");
|
||||
let serverID = window.location.hostname.replace(/^([^.]+).*$/, "$1");
|
||||
if (serverID in AUTHORIZED_ALLIANCES) {
|
||||
xhrAlly.addEventListener("readystatechange", function () {
|
||||
if (xhrAlly.readyState === xhrAlly.DONE) {
|
||||
|
||||
Reference in New Issue
Block a user