118 lines
3.4 KiB
TypeScript
118 lines
3.4 KiB
TypeScript
import * as _ from 'lodash';
|
||
import { harvestEnergyFromTombstone, selectSource } from './common';
|
||
|
||
interface BuilderMemory extends CreepMemory {
|
||
building: boolean | undefined;
|
||
}
|
||
|
||
export function runAsBuilder(creep: Creep) {
|
||
const memory = creep.memory as BuilderMemory;
|
||
|
||
if (memory.building && creep.store[RESOURCE_ENERGY] === 0) {
|
||
memory.building = false;
|
||
memory.repairTargetId = '';
|
||
}
|
||
|
||
if (!memory.building && creep.store.getFreeCapacity() === 0) {
|
||
memory.building = true;
|
||
}
|
||
|
||
if (!memory.sourceId) {
|
||
memory.sourceId = selectSource(creep.room);
|
||
}
|
||
|
||
harvestEnergyFromTombstone(creep);
|
||
|
||
if (memory.building) {
|
||
if (build(creep)) {
|
||
return;
|
||
}
|
||
if (repair(creep)) {
|
||
return;
|
||
}
|
||
const spawns = creep.room.find(FIND_MY_SPAWNS);
|
||
if (spawns.length > 0) {
|
||
creep.say('To spawn');
|
||
creep.moveTo(spawns[0]);
|
||
}
|
||
} else {
|
||
const source = Game.getObjectById(memory.sourceId);
|
||
if (source && creep.harvest(source) == ERR_NOT_IN_RANGE) {
|
||
creep.say('🔄 harvest');
|
||
creep.moveTo(source, { visualizePathStyle: { stroke: '#ffaa00' } });
|
||
}
|
||
}
|
||
}
|
||
|
||
function build(creep: Creep): boolean {
|
||
const targets = creep.room.find(FIND_MY_CONSTRUCTION_SITES);
|
||
if (targets.length === 0) {
|
||
return false;
|
||
}
|
||
if (creep.build(targets[0]) == ERR_NOT_IN_RANGE) {
|
||
creep.say('🚧 build');
|
||
creep.moveTo(targets[0], { visualizePathStyle: { stroke: '#ffffff' } });
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* Починить.
|
||
*
|
||
* Если цель нужно чинить, то дойти до цели и произвести починку.
|
||
* Если цель починена, найти ближайшую цель в радиусе починки и чинить ее.
|
||
*
|
||
* @param creep
|
||
*/
|
||
function repair(creep: Creep) {
|
||
const memory = creep.memory as BuilderMemory;
|
||
let repairTarget;
|
||
// Если уже установлена цель, то получаем объект,
|
||
// иначе ищем подходящую цель для ремонта.
|
||
if (memory.repairTargetId) {
|
||
repairTarget = Game.getObjectById(memory.repairTargetId);
|
||
} else {
|
||
repairTarget = findBestRepairTarget(creep);
|
||
memory.repairTargetId = repairTarget ? repairTarget.id : '';
|
||
}
|
||
// Если цель ремонта не найдена, то ничего не делаем.
|
||
if (!repairTarget) {
|
||
memory.repairTargetId = '';
|
||
return false;
|
||
}
|
||
if (repairTarget.hits < repairTarget.hitsMax) {
|
||
if (creep.repair(repairTarget) == ERR_NOT_IN_RANGE) {
|
||
creep.say('🚧 repair');
|
||
creep.moveTo(repairTarget, { visualizePathStyle: { stroke: '#ffffff' } });
|
||
}
|
||
} else {
|
||
const closestRepairTarget = findClosestRepairTarget(creep);
|
||
if (closestRepairTarget) {
|
||
if (creep.repair(closestRepairTarget) !== OK) {
|
||
memory.repairTargetId = '';
|
||
}
|
||
} else {
|
||
memory.repairTargetId = '';
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
function findBestRepairTarget(creep: Creep): Structure | undefined {
|
||
const targets = creep.room.find(FIND_STRUCTURES, {
|
||
filter: (t) => t.hits < t.hitsMax && t.structureType !== STRUCTURE_ROAD
|
||
});
|
||
if (targets.length > 0) {
|
||
targets.sort((t1, t2) => t1.hits - t2.hits);
|
||
return targets[0];
|
||
}
|
||
return undefined;
|
||
}
|
||
|
||
function findClosestRepairTarget(creep: Creep): Structure | undefined {
|
||
const targets = creep.pos.findInRange(FIND_STRUCTURES, 3, {
|
||
filter: (t) => t.hits < t.hitsMax && t.structureType !== STRUCTURE_ROAD
|
||
});
|
||
return _.first(targets);
|
||
}
|