Add hero resource switch
This commit is contained in:
parent
6e85f9f443
commit
d85490958b
11
README.md
11
README.md
@ -1,12 +1,13 @@
|
||||
# Travian automation
|
||||
|
||||
- [ ] Автоматическая отправка набегов на учетные записи или автоматическая отправка волн атак
|
||||
- [x] Автоматическая отправка героя в приключение
|
||||
- [x] Автоматическое начало строительства зданий и/или ресурсных полей
|
||||
- [ ] Автоматический скан карты
|
||||
- [ ] Автоматический скан статистики других игроков
|
||||
- [ ] Автоматическая отправка ресурсов на другие учетные записи
|
||||
- [x] Автоматическое обучение войск
|
||||
- [x] Автоматическая отправка героя в приключение
|
||||
- [x] Автоматическое переключение ресурсов героя
|
||||
- [ ] Автоматическая отправка набегов на учетные записи или автоматическая отправка волн атак
|
||||
- [ ] Автоматический скан карты
|
||||
- [ ] Автоматическая отправка ресурсов на другие учетные записи
|
||||
- [ ] Автоматическое размещение ставок на аукционе
|
||||
- [ ] Автоматический запуск празднований
|
||||
- [ ] Сканирование статистики других игроков
|
||||
- [ ] Сканирование собственных деревень для отображения ресурсов и информации в одном месте
|
||||
|
71
src/Action/BalanceHeroResourcesAction.ts
Normal file
71
src/Action/BalanceHeroResourcesAction.ts
Normal file
@ -0,0 +1,71 @@
|
||||
import { ActionController, registerAction } from './ActionController';
|
||||
import { Args } from '../Common';
|
||||
import { Task } from '../Storage/TaskQueue';
|
||||
import { getNumber, trimPrefix } from '../utils';
|
||||
import { AbortTaskError, ActionError } from '../Errors';
|
||||
|
||||
interface Resource {
|
||||
type: number;
|
||||
value: number;
|
||||
}
|
||||
|
||||
const ALL = 0;
|
||||
|
||||
@registerAction
|
||||
export class BalanceHeroResourcesAction extends ActionController {
|
||||
async run(args: Args, task: Task): Promise<any> {
|
||||
const res = this.getResources();
|
||||
const currentType = this.getCurrentHeroResource(task);
|
||||
console.log('RESOURCES', res);
|
||||
console.log('CURRENT TYPE', currentType);
|
||||
const sorted = res.sort((x, y) => x.value - y.value);
|
||||
const min = sorted[0];
|
||||
const max = sorted[sorted.length - 1];
|
||||
const delta = max.value - min.value;
|
||||
const eps = max.value / 10;
|
||||
console.log('MIN', min, 'MAX', max, 'DELTA', delta, 'EPS', eps);
|
||||
const resType = delta > eps ? min.type : ALL;
|
||||
if (resType !== currentType) {
|
||||
this.changeToHeroResource(task, resType);
|
||||
}
|
||||
}
|
||||
|
||||
private getResources(): Array<Resource> {
|
||||
const res = this.state.get('resources');
|
||||
const resList: Array<Resource> = [];
|
||||
for (let r in res) {
|
||||
const type = getNumber(r);
|
||||
const value = getNumber(res[r]);
|
||||
resList.push({ type, value });
|
||||
}
|
||||
return resList;
|
||||
}
|
||||
|
||||
private getCurrentHeroResource(task: Task): number {
|
||||
for (let type of [0, 1, 2, 3, 4]) {
|
||||
const input = jQuery(`#resourceHero${type}`);
|
||||
if (input.length !== 1) {
|
||||
throw new ActionError(task.id, `Hero resource ${type} not found`);
|
||||
}
|
||||
if (input.prop('checked')) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private changeToHeroResource(task: Task, type: number) {
|
||||
const input = jQuery(`#resourceHero${type}`);
|
||||
if (input.length !== 1) {
|
||||
throw new ActionError(task.id, `Hero resource ${type} not found`);
|
||||
}
|
||||
|
||||
const btn = jQuery('#saveHeroAttributes');
|
||||
if (btn.length !== 1) {
|
||||
throw new ActionError(task.id, `Hero resource button not found`);
|
||||
}
|
||||
|
||||
input.trigger('click');
|
||||
btn.trigger('click');
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@ import { ActionController, registerAction } from './ActionController';
|
||||
import { Args } from '../Common';
|
||||
import { Task } from '../Storage/TaskQueue';
|
||||
import { ActionError } from '../Errors';
|
||||
import { getNumber } from '../utils';
|
||||
|
||||
@registerAction
|
||||
export class GrabHeroAttributesAction extends ActionController {
|
||||
@ -10,13 +11,11 @@ export class GrabHeroAttributesAction extends ActionController {
|
||||
if (healthElement.length !== 1) {
|
||||
throw new ActionError(task.id, 'Health dom element not found');
|
||||
}
|
||||
|
||||
const text = healthElement.text();
|
||||
let normalized = text.replace(/[^0-9]/g, '');
|
||||
const value = Number(normalized);
|
||||
if (isNaN(value)) {
|
||||
throw new ActionError(task.id, `Health value "${text}" (${normalized}) couldn't be converted to number`);
|
||||
}
|
||||
|
||||
const value = getNumber(normalized);
|
||||
this.state.set('hero', { health: value });
|
||||
}
|
||||
}
|
||||
|
36
src/Action/GrabVillageResourcesAction.ts
Normal file
36
src/Action/GrabVillageResourcesAction.ts
Normal file
@ -0,0 +1,36 @@
|
||||
import { ActionController, registerAction } from './ActionController';
|
||||
import { Args } from '../Common';
|
||||
import { Task } from '../Storage/TaskQueue';
|
||||
import { getNumber } from '../utils';
|
||||
import { ActionError } from '../Errors';
|
||||
|
||||
const LUMBER = 1;
|
||||
const CLAY = 2;
|
||||
const IRON = 3;
|
||||
const CROP = 4;
|
||||
|
||||
@registerAction
|
||||
export class GrabVillageResourcesAction extends ActionController {
|
||||
async run(args: Args, task: Task): Promise<any> {
|
||||
const lumber = this.grabResource(task, LUMBER);
|
||||
const clay = this.grabResource(task, CLAY);
|
||||
const iron = this.grabResource(task, IRON);
|
||||
const crop = this.grabResource(task, CROP);
|
||||
|
||||
this.state.set('resources', { [LUMBER]: lumber, [CLAY]: clay, [IRON]: iron, [CROP]: crop });
|
||||
}
|
||||
|
||||
private grabResource(task: Task, type: number): number {
|
||||
const stockBarElement = jQuery('#stockBar');
|
||||
if (stockBarElement.length !== 1) {
|
||||
throw new ActionError(task.id, 'Stock Bar not found');
|
||||
}
|
||||
|
||||
const resElement = stockBarElement.find(`#l${type}`);
|
||||
if (resElement.length !== 1) {
|
||||
throw new ActionError(task.id, `Resource #${type} not found`);
|
||||
}
|
||||
|
||||
return getNumber(resElement.text().replace(/[^0-9]/g, ''));
|
||||
}
|
||||
}
|
@ -22,7 +22,7 @@ export class TrainTrooperAction extends ActionController {
|
||||
|
||||
const maxCount = getNumber(countLink.text());
|
||||
if (maxCount < trainCount) {
|
||||
throw new TryLaterError(task.id, 10 * 60, `Max count ${maxCount} less then need ${trainCount}`);
|
||||
throw new TryLaterError(task.id, 20 * 60, `Max count ${maxCount} less then need ${trainCount}`);
|
||||
}
|
||||
|
||||
const input = block.find(`input[name="t${troopId}"]`);
|
||||
|
@ -9,6 +9,7 @@ import { createAction } from './Action/ActionController';
|
||||
import { createTask } from './Task/TaskController';
|
||||
import { SendOnAdventureTask } from './Task/SendOnAdventureTask';
|
||||
import { GameState } from './Storage/GameState';
|
||||
import { BalanceHeroResourcesTask } from './Task/BalanceHeroResourcesTask';
|
||||
|
||||
export class Scheduler {
|
||||
private readonly version: string;
|
||||
@ -33,8 +34,11 @@ export class Scheduler {
|
||||
this.scheduleHeroAdventure();
|
||||
setInterval(() => this.scheduleHeroAdventure(), 3600 * 1000);
|
||||
|
||||
this.scheduleResGrab();
|
||||
setInterval(() => this.scheduleResGrab(), 600 * 1000);
|
||||
|
||||
while (true) {
|
||||
await this.doLoopStep();
|
||||
await this.doTaskProcessingStep();
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,7 +53,13 @@ export class Scheduler {
|
||||
}
|
||||
}
|
||||
|
||||
private async doLoopStep() {
|
||||
private scheduleResGrab() {
|
||||
if (!this.taskQueue.hasNamed(BalanceHeroResourcesTask.name)) {
|
||||
this.taskQueue.push(new Command(BalanceHeroResourcesTask.name, {}), timestamp());
|
||||
}
|
||||
}
|
||||
|
||||
private async doTaskProcessingStep() {
|
||||
await sleepShort();
|
||||
const currentTs = timestamp();
|
||||
const taskCommand = this.taskQueue.get(currentTs);
|
||||
|
22
src/Task/BalanceHeroResourcesTask.ts
Normal file
22
src/Task/BalanceHeroResourcesTask.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { Args, Command } from '../Common';
|
||||
import { Task } from '../Storage/TaskQueue';
|
||||
import { TaskController, registerTask } from './TaskController';
|
||||
import { GoToPageAction } from '../Action/GoToPageAction';
|
||||
import { CompleteTaskAction } from '../Action/CompleteTaskAction';
|
||||
import { TrainTrooperAction } from '../Action/TrainTrooperAction';
|
||||
import { GrabVillageResourcesAction } from '../Action/GrabVillageResourcesAction';
|
||||
import { BalanceHeroResourcesAction } from '../Action/BalanceHeroResourcesAction';
|
||||
|
||||
@registerTask
|
||||
export class BalanceHeroResourcesTask extends TaskController {
|
||||
async run(task: Task) {
|
||||
const args: Args = { ...task.cmd.args, taskId: task.id };
|
||||
this.scheduler.scheduleActions([
|
||||
new Command(GoToPageAction.name, { ...args, path: '/dorf1.php' }),
|
||||
new Command(GrabVillageResourcesAction.name, args),
|
||||
new Command(GoToPageAction.name, { ...args, path: 'hero.php' }),
|
||||
new Command(BalanceHeroResourcesAction.name, args),
|
||||
new Command(CompleteTaskAction.name, args),
|
||||
]);
|
||||
}
|
||||
}
|
@ -4,7 +4,6 @@ import { Scheduler } from '../Scheduler';
|
||||
const taskMap: { [name: string]: Function | undefined } = {};
|
||||
|
||||
export function registerTask(constructor: Function) {
|
||||
console.log('REGISTER TASK', constructor.name);
|
||||
taskMap[constructor.name] = constructor;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user