2020-07-25 13:47:49 +00:00
|
|
|
import addMinutes from 'date-fns/addMinutes';
|
2020-07-24 12:14:43 +00:00
|
|
|
import getTranslations from './i18n/extendedMapPopup';
|
2020-07-24 12:09:33 +00:00
|
|
|
import requestCreator from './libs/requestCreator';
|
2021-01-17 15:21:47 +00:00
|
|
|
import { formatDate } from './utils/date';
|
2020-07-24 12:09:33 +00:00
|
|
|
import getCurrentServer from './utils/getCurrentServer';
|
2020-07-24 14:31:54 +00:00
|
|
|
import { calcDistanceBetweenTwoPoints } from './utils/math';
|
2020-07-25 13:47:49 +00:00
|
|
|
import buildUnitImgURL from './utils/buildUnitImgURL';
|
2020-07-24 12:09:33 +00:00
|
|
|
import { setItem, getItem } from './utils/localStorage';
|
2020-07-25 13:47:49 +00:00
|
|
|
import { calcAttackDuration } from './utils/tribalwars';
|
2021-01-03 12:13:05 +00:00
|
|
|
import calcLoyalty from './utils/calcLoyalty';
|
2020-07-24 12:09:33 +00:00
|
|
|
|
|
|
|
// ==UserScript==
|
2020-08-14 11:53:56 +00:00
|
|
|
// @name Extended map popup
|
2020-07-24 12:09:33 +00:00
|
|
|
// @namespace https://github.com/tribalwarshelp/scripts
|
|
|
|
// @updateURL https://raw.githubusercontent.com/tribalwarshelp/scripts/master/dist/extendedMapPopup.js
|
|
|
|
// @downloadURL https://raw.githubusercontent.com/tribalwarshelp/scripts/master/dist/extendedMapPopup.js
|
2021-06-12 06:21:48 +00:00
|
|
|
// @version ${version}
|
2020-08-14 11:53:56 +00:00
|
|
|
// @description Extended map popup
|
2021-01-17 08:20:19 +00:00
|
|
|
// @author Kichiyaki https://dwysokinski.me/
|
2020-07-24 12:09:33 +00:00
|
|
|
// @match *://*/game.php*screen=map*
|
|
|
|
// @grant none
|
|
|
|
// ==/UserScript==
|
|
|
|
|
|
|
|
const SERVER = getCurrentServer();
|
|
|
|
const CURR_SERVER_CONFIG = `
|
|
|
|
query server($key: String!) {
|
|
|
|
server(key: $key) {
|
|
|
|
config {
|
|
|
|
speed
|
2020-07-25 13:47:49 +00:00
|
|
|
unitSpeed
|
2020-07-24 14:31:54 +00:00
|
|
|
snob {
|
|
|
|
maxDist
|
|
|
|
}
|
2020-07-24 12:09:33 +00:00
|
|
|
}
|
2020-07-25 13:47:49 +00:00
|
|
|
unitConfig {
|
|
|
|
spear {
|
|
|
|
speed
|
|
|
|
}
|
|
|
|
sword {
|
|
|
|
speed
|
|
|
|
}
|
|
|
|
axe {
|
|
|
|
speed
|
|
|
|
}
|
|
|
|
archer {
|
|
|
|
speed
|
|
|
|
}
|
|
|
|
spy {
|
|
|
|
speed
|
|
|
|
}
|
|
|
|
light {
|
|
|
|
speed
|
|
|
|
}
|
|
|
|
marcher {
|
|
|
|
speed
|
|
|
|
}
|
|
|
|
heavy {
|
|
|
|
speed
|
|
|
|
}
|
|
|
|
ram {
|
|
|
|
speed
|
|
|
|
}
|
|
|
|
catapult {
|
|
|
|
speed
|
|
|
|
}
|
|
|
|
knight {
|
|
|
|
speed
|
|
|
|
}
|
|
|
|
snob {
|
|
|
|
speed
|
|
|
|
}
|
|
|
|
}
|
2020-07-24 12:09:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
`;
|
2021-06-12 06:35:01 +00:00
|
|
|
const LAST_CONQUER_QUERY = `
|
2020-11-21 14:01:40 +00:00
|
|
|
query ennoblements($server: String!, $filter: EnnoblementFilter!, $sort: [String!], $limit: Int) {
|
|
|
|
ennoblements(server: $server, filter: $filter, sort: $sort, limit: $limit) {
|
2020-07-24 12:09:33 +00:00
|
|
|
items {
|
|
|
|
ennobledAt
|
|
|
|
village {
|
|
|
|
id
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
`;
|
|
|
|
const SERVER_CONFIG_LOCAL_STORAGE_KEY =
|
|
|
|
'kiszkowaty_extended_map_popup_server_cfg';
|
2020-07-24 12:14:43 +00:00
|
|
|
const translations = getTranslations();
|
2020-07-24 12:09:33 +00:00
|
|
|
|
2020-08-07 13:50:26 +00:00
|
|
|
const loadConfigFromLocalStorage = () => {
|
2020-07-24 12:09:33 +00:00
|
|
|
return getItem(SERVER_CONFIG_LOCAL_STORAGE_KEY);
|
|
|
|
};
|
|
|
|
|
|
|
|
const cacheServerConfig = (data = {}) => {
|
|
|
|
setItem(SERVER_CONFIG_LOCAL_STORAGE_KEY, data);
|
|
|
|
};
|
|
|
|
|
2021-02-26 17:04:05 +00:00
|
|
|
const isConfigExpired = date => {
|
2020-08-07 13:50:26 +00:00
|
|
|
return Math.abs(date.getTime() - new Date().getTime()) > 1000 * 60 * 60 * 24;
|
2020-07-24 12:09:33 +00:00
|
|
|
};
|
|
|
|
|
2020-08-07 13:50:26 +00:00
|
|
|
const loadConfig = async () => {
|
|
|
|
let data = loadConfigFromLocalStorage();
|
2020-07-24 14:31:54 +00:00
|
|
|
if (
|
|
|
|
!data ||
|
|
|
|
!data.server ||
|
|
|
|
isConfigExpired(new Date(data.loadedAt)) ||
|
|
|
|
!data.server.config ||
|
|
|
|
!data.server.config.speed ||
|
|
|
|
!data.server.config.snob ||
|
2020-07-25 13:47:49 +00:00
|
|
|
!data.server.config.snob.maxDist ||
|
|
|
|
!data.server.config.unitSpeed ||
|
|
|
|
!data.server.unitConfig
|
2020-07-24 14:31:54 +00:00
|
|
|
) {
|
2020-07-24 12:09:33 +00:00
|
|
|
data = await requestCreator({
|
|
|
|
query: CURR_SERVER_CONFIG,
|
|
|
|
variables: {
|
|
|
|
key: SERVER,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
data.loadedAt = new Date();
|
|
|
|
cacheServerConfig(data);
|
|
|
|
}
|
2020-07-25 13:47:49 +00:00
|
|
|
return data && data.server && data.server.config
|
|
|
|
? { config: data.server.config, unitConfig: data.server.unitConfig }
|
|
|
|
: {};
|
2020-07-24 12:09:33 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
const loadVillageData = async (id, { cacheOnly = false } = {}) => {
|
2021-06-12 06:35:01 +00:00
|
|
|
if (!id) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-07-24 12:09:33 +00:00
|
|
|
if (cacheOnly || TWMap.popup.extendedMapPopupCache[id]) {
|
|
|
|
return TWMap.popup.extendedMapPopupCache[id];
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
const data = await requestCreator({
|
2021-06-12 06:35:01 +00:00
|
|
|
query: LAST_CONQUER_QUERY,
|
2020-07-24 12:09:33 +00:00
|
|
|
variables: {
|
|
|
|
server: SERVER,
|
2020-11-21 14:01:40 +00:00
|
|
|
sort: ['ennobledAt DESC'],
|
2020-07-24 12:09:33 +00:00
|
|
|
filter: {
|
|
|
|
villageID: [id],
|
|
|
|
},
|
2020-11-21 14:01:40 +00:00
|
|
|
limit: 1,
|
2020-07-24 12:09:33 +00:00
|
|
|
},
|
|
|
|
});
|
|
|
|
TWMap.popup.extendedMapPopupCache[id] = data;
|
|
|
|
return data;
|
|
|
|
} catch (error) {
|
|
|
|
console.log('loadVillageData', error);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-07-25 13:47:49 +00:00
|
|
|
const getAvailableUnits = (unitCfg = {}) => {
|
|
|
|
const units = [];
|
|
|
|
for (let unit in unitCfg) {
|
|
|
|
if (unitCfg[unit].speed !== 0) {
|
|
|
|
units.push({
|
|
|
|
...unitCfg[unit],
|
|
|
|
name: unit,
|
|
|
|
img: buildUnitImgURL(unit),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return units;
|
|
|
|
};
|
|
|
|
|
2021-02-26 17:04:05 +00:00
|
|
|
const getUnitTdBgColor = index => (index % 2 === 0 ? '#f8f4e8' : '#ded3b9;');
|
2020-07-25 13:47:49 +00:00
|
|
|
|
|
|
|
const buildUnitHeader = (unit, index) => {
|
|
|
|
return `
|
|
|
|
<td style="padding: 2px; background-color: ${getUnitTdBgColor(index)};">
|
|
|
|
<img
|
|
|
|
src="${unit.img}"
|
|
|
|
title="${unit.name}"
|
|
|
|
alt="${unit.name}"
|
|
|
|
/>
|
|
|
|
</td>
|
|
|
|
`;
|
|
|
|
};
|
|
|
|
|
|
|
|
const buildUnitArrivalInfo = (t, index) => {
|
|
|
|
return `
|
|
|
|
<td style="padding: 2px; background-color: ${getUnitTdBgColor(index)};">
|
2020-09-17 10:26:43 +00:00
|
|
|
${formatDate(addMinutes(Timing.getCurrentServerTime(), t))}
|
2020-07-25 13:47:49 +00:00
|
|
|
</td>
|
|
|
|
`;
|
|
|
|
};
|
|
|
|
|
|
|
|
const renderAdditionalInfo = (id, data, { config, unitConfig }) => {
|
2020-07-24 14:31:54 +00:00
|
|
|
const coords = TWMap.CoordByXY(TWMap.villageKey[id]);
|
2020-07-25 13:47:49 +00:00
|
|
|
const distance = calcDistanceBetweenTwoPoints(
|
|
|
|
coords[0],
|
|
|
|
coords[1],
|
|
|
|
window.game_data.village.x,
|
|
|
|
window.game_data.village.y
|
|
|
|
);
|
2020-07-24 12:09:33 +00:00
|
|
|
const ennoblement =
|
|
|
|
data &&
|
|
|
|
data.ennoblements &&
|
|
|
|
data.ennoblements.items &&
|
|
|
|
data.ennoblements.items.length > 0
|
|
|
|
? data.ennoblements.items[0]
|
|
|
|
: undefined;
|
|
|
|
const parent = document.querySelector('#map_popup #info_content tbody');
|
|
|
|
|
2020-07-25 13:47:49 +00:00
|
|
|
let unitsEl = parent.querySelector('#units');
|
|
|
|
if (!unitsEl) {
|
|
|
|
unitsEl = document.createElement('tr');
|
|
|
|
unitsEl.id = 'units';
|
|
|
|
parent.appendChild(unitsEl);
|
|
|
|
}
|
|
|
|
const units = getAvailableUnits(unitConfig);
|
|
|
|
unitsEl.innerHTML = `
|
|
|
|
<td colspan="2">
|
|
|
|
<table style="border: 1px solid #ded3b9; max-width: 450px;"
|
|
|
|
width="100%"
|
|
|
|
cellpadding="0"
|
|
|
|
cellspacing="0">
|
|
|
|
<tbody>
|
|
|
|
<tr class="center">
|
|
|
|
${units.map(buildUnitHeader).join('')}
|
|
|
|
</tr>
|
|
|
|
<tr class="center">
|
|
|
|
${units
|
|
|
|
.map((unit, index) => {
|
|
|
|
return buildUnitArrivalInfo(
|
2021-01-03 12:13:05 +00:00
|
|
|
calcAttackDuration(distance, unit.speed),
|
2020-07-25 13:47:49 +00:00
|
|
|
index
|
|
|
|
);
|
|
|
|
})
|
|
|
|
.join('')}
|
|
|
|
</tr>
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
</td>
|
|
|
|
`;
|
|
|
|
|
2020-07-24 12:09:33 +00:00
|
|
|
let lastEnnobledAt = parent.querySelector('#lastEnnobledAt');
|
|
|
|
if (!lastEnnobledAt) {
|
|
|
|
lastEnnobledAt = document.createElement('tr');
|
|
|
|
lastEnnobledAt.id = 'lastEnnobledAt';
|
|
|
|
parent.appendChild(lastEnnobledAt);
|
|
|
|
}
|
|
|
|
lastEnnobledAt.innerHTML = `
|
|
|
|
<td>
|
2020-07-24 12:14:43 +00:00
|
|
|
${translations.ennobledAt}:
|
2020-07-24 12:09:33 +00:00
|
|
|
</td>
|
|
|
|
<td>
|
2020-07-24 12:14:43 +00:00
|
|
|
${
|
|
|
|
ennoblement
|
|
|
|
? formatDate(ennoblement.ennobledAt)
|
|
|
|
: translations.never
|
|
|
|
}
|
2020-07-24 12:09:33 +00:00
|
|
|
</td>
|
|
|
|
`;
|
|
|
|
|
|
|
|
let loyalty = parent.querySelector('#loyalty');
|
|
|
|
if (!loyalty) {
|
|
|
|
loyalty = document.createElement('tr');
|
|
|
|
loyalty.id = 'loyalty';
|
|
|
|
parent.appendChild(loyalty);
|
|
|
|
}
|
|
|
|
loyalty.innerHTML = `
|
|
|
|
<td>
|
2020-07-24 12:14:43 +00:00
|
|
|
${translations.possibleLoyalty}:
|
2020-07-24 12:09:33 +00:00
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
${
|
|
|
|
ennoblement
|
2021-01-03 12:13:05 +00:00
|
|
|
? calcLoyalty(new Date(ennoblement.ennobledAt), config.speed)
|
2020-07-24 12:09:33 +00:00
|
|
|
: 100
|
|
|
|
}
|
|
|
|
</td>
|
|
|
|
`;
|
2020-07-24 14:31:54 +00:00
|
|
|
|
2020-07-24 14:38:57 +00:00
|
|
|
let canSendNoble = parent.querySelector('#canSendNoble');
|
|
|
|
if (!canSendNoble) {
|
|
|
|
canSendNoble = document.createElement('tr');
|
|
|
|
canSendNoble.id = 'canSendNoble';
|
|
|
|
parent.appendChild(canSendNoble);
|
2020-07-24 14:31:54 +00:00
|
|
|
}
|
2020-07-24 14:38:57 +00:00
|
|
|
canSendNoble.innerHTML = `
|
2020-07-24 14:31:54 +00:00
|
|
|
<td>
|
2020-07-24 14:38:57 +00:00
|
|
|
${translations.canSendNoble}:
|
2020-07-24 14:31:54 +00:00
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
${
|
2020-07-25 13:47:49 +00:00
|
|
|
distance < config.snob.maxDist
|
2020-07-24 14:31:54 +00:00
|
|
|
? translations.yes
|
|
|
|
: translations.no
|
|
|
|
}
|
|
|
|
</td>
|
|
|
|
`;
|
2020-07-24 12:09:33 +00:00
|
|
|
};
|
|
|
|
|
2021-02-26 17:04:05 +00:00
|
|
|
const createLoadVillageHandler = cfg => async e => {
|
2020-07-24 12:09:33 +00:00
|
|
|
TWMap.popup._loadVillage(e);
|
|
|
|
const data = await loadVillageData(parseInt(e));
|
2021-06-12 06:35:01 +00:00
|
|
|
if (data) {
|
|
|
|
renderAdditionalInfo(parseInt(e), data, cfg);
|
|
|
|
}
|
2020-07-24 12:09:33 +00:00
|
|
|
};
|
|
|
|
|
2021-02-26 17:04:05 +00:00
|
|
|
const createDisplayForVillageHandler = cfg => async (e, a, t) => {
|
2020-07-24 12:09:33 +00:00
|
|
|
TWMap.popup._displayForVillage(e, a, t);
|
2020-07-24 12:25:42 +00:00
|
|
|
const data = await loadVillageData(parseInt(e.id), {
|
|
|
|
cacheOnly: window.game_data.features.Premium.active,
|
|
|
|
});
|
2021-06-12 06:35:01 +00:00
|
|
|
if (data) {
|
|
|
|
renderAdditionalInfo(parseInt(e.id), data, cfg);
|
|
|
|
}
|
2020-07-24 12:09:33 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
(async function () {
|
|
|
|
try {
|
2020-08-07 13:50:26 +00:00
|
|
|
const configs = await loadConfig();
|
2020-07-24 12:09:33 +00:00
|
|
|
|
|
|
|
TWMap.popup.extendedMapPopupCache = {};
|
|
|
|
TWMap.popup._loadVillage = TWMap.popup.loadVillage;
|
2020-07-25 13:47:49 +00:00
|
|
|
TWMap.popup.loadVillage = createLoadVillageHandler(configs);
|
2020-07-24 12:09:33 +00:00
|
|
|
TWMap.popup._displayForVillage = TWMap.popup.displayForVillage;
|
2020-07-25 13:47:49 +00:00
|
|
|
TWMap.popup.displayForVillage = createDisplayForVillageHandler(configs);
|
2020-07-24 12:09:33 +00:00
|
|
|
} catch (error) {
|
|
|
|
console.log('extended map popup', error);
|
|
|
|
}
|
|
|
|
})();
|