Files
GrepoAutoRuralResources/GrepoAutoRuralResources.js

169 lines
5.8 KiB
JavaScript

// ==UserScript==
// @name GrepoTweaks-AutoRuralResources (Captain-Free Version)
// @namespace sentinelindicator
// @version 2.2.0
// @description Auto farm loot from rural villages using per-town AJAX requests, no Captain required
// @author Dimitrios
// @match http://*.grepolis.com/game/*
// @match https://*.grepolis.com/game/*
// @grant none
// ==/UserScript==
(function () {
'use strict';
const uw = typeof unsafeWindow !== "undefined" ? unsafeWindow : window;
const timerInterval = 300000; // 5 minutes
const delta_time = 10000;
let loop, lastTime, timer;
let startOnLogin = true;
const buttonHtml =
'<div class="divider"></div>' +
'<div class="activity" id="btbutton" style="filter: brightness(70%) sepia(100%) hue-rotate(-50deg) saturate(1000%) contrast(0.8);">' +
'<p id="ptimer" style="z-index:6; top:-8px; position:relative; font-weight:bold;"></p>' +
'</div>';
function getPolisList() {
const islandList = [];
const polisList = [];
const towns = uw.MM.getCollections().Town[0].models;
for (let town of towns) {
const { on_small_island, island_id, id } = town.attributes;
if (on_small_island) continue;
if (!islandList.includes(island_id)) {
islandList.push(island_id);
polisList.push(id);
}
}
return polisList;
}
function getLootableFarms(town_id) {
const { models: farms } = uw.MM.getOnlyCollectionByName('FarmTown');
const { models: relations } = uw.MM.getOnlyCollectionByName('FarmTownPlayerRelation');
const town = uw.ITowns.towns[town_id];
const x = town.getIslandCoordinateX();
const y = town.getIslandCoordinateY();
const now = Math.floor(Date.now() / 1000);
const result = [];
for (let farm of farms) {
if (farm.attributes.island_x !== x || farm.attributes.island_y !== y) continue;
for (let rel of relations) {
if (
rel.attributes.farm_town_id === farm.attributes.id &&
rel.attributes.relation_status === 1 &&
(!rel.attributes.lootable_at || now >= rel.attributes.lootable_at)
) {
result.push({ town_id, farm_town_id: rel.attributes.farm_town_id, relation_id: rel.id });
}
}
}
return result;
}
function claimSingle(town_id, farm_town_id, relation_id) {
const data = {
model_url: `FarmTownPlayerRelation/${relation_id}`,
action_name: 'claim',
arguments: { farm_town_id: farm_town_id, type: 'resources', option: 1 },
town_id: town_id,
};
uw.gpAjax.ajaxPost('frontend_bridge', 'execute', data);
}
async function claimIndividually(polisList) {
let max = 60;
for (let town_id of polisList) {
const farms = getLootableFarms(town_id);
for (let farm of farms) {
claimSingle(farm.town_id, farm.farm_town_id, farm.relation_id);
await new Promise(r => setTimeout(r, 500));
if (!--max) return;
}
}
}
function getNextCollectionTime() {
const models = uw.MM.getCollections().FarmTownPlayerRelation[0].models;
let lootTimes = {};
for (let m of models) {
const time = m.attributes.lootable_at;
lootTimes[time] = (lootTimes[time] || 0) + 1;
}
let max = 0;
let next = 0;
for (let key in lootTimes) {
if (lootTimes[key] > max) {
max = lootTimes[key];
next = key;
}
}
const seconds = next - Math.floor(Date.now() / 1000);
return seconds > 0 ? seconds * 1000 : 0;
}
async function mainLoop() {
const next = getNextCollectionTime();
if (timer + 2 * delta_time < next) {
timer = next + Math.floor(Math.random() * delta_time);
}
if (timer < 1) {
const polisList = getPolisList();
await claimIndividually(polisList);
timer = timerInterval + Math.floor(Math.random() * delta_time);
setTimeout(() => uw.WMap.removeFarmTownLootCooldownIconAndRefreshLootTimers(), 2000);
}
const now = Date.now();
timer -= now - lastTime;
lastTime = now;
const bt = document.getElementById('ptimer');
bt.innerHTML = timer > 0 ? parseInt(timer / 1000) : '0';
}
function handleClick() {
const isCaptainActive = uw.GameDataPremium.isAdvisorActivated('captain');
if (!loop) {
timer = getNextCollectionTime() + Math.random() * delta_time;
lastTime = Date.now();
loop = setInterval(mainLoop, 1000);
uw.$('#btbutton').css(
'filter',
isCaptainActive
? 'brightness(100%) sepia(100%) hue-rotate(90deg) saturate(1500%) contrast(0.8)'
: 'brightness(294%) sepia(100%) hue-rotate(15deg) saturate(1000%) contrast(0.8)'
);
} else {
clearInterval(loop);
loop = null;
uw.$('#btbutton').css(
'filter',
'brightness(70%) sepia(100%) hue-rotate(-50deg) saturate(1000%) contrast(0.8)'
);
}
}
setTimeout(() => {
if (!document.getElementById('btbutton')) {
uw.$('.tb_activities, .toolbar_activities').find('.middle').append(buttonHtml);
}
if (startOnLogin) handleClick();
}, 4000);
uw.$(document).on('click', '#btbutton', handleClick);
console.log('[GrepoTweaks-AutoRuralResources] Captain-free script loaded 🚀');
})();