Removed BaseAI
This commit is contained in:
@@ -1052,9 +1052,7 @@ rules.schematic = Schematics Allowed
|
|||||||
rules.wavetimer = Wave Timer
|
rules.wavetimer = Wave Timer
|
||||||
rules.waves = Waves
|
rules.waves = Waves
|
||||||
rules.attack = Attack Mode
|
rules.attack = Attack Mode
|
||||||
rules.buildai = AI Building
|
|
||||||
rules.rtsai = RTS AI
|
rules.rtsai = RTS AI
|
||||||
rules.aitier = AI Tier
|
|
||||||
rules.cleanupdeadteams = Clean Up Defeated Team Buildings (PvP)
|
rules.cleanupdeadteams = Clean Up Defeated Team Buildings (PvP)
|
||||||
rules.corecapture = Capture Core On Destruction
|
rules.corecapture = Capture Core On Destruction
|
||||||
rules.polygoncoreprotection = Polygonal Core Protection
|
rules.polygoncoreprotection = Polygonal Core Protection
|
||||||
|
|||||||
@@ -1,315 +0,0 @@
|
|||||||
package mindustry.ai;
|
|
||||||
|
|
||||||
import arc.math.*;
|
|
||||||
import arc.math.geom.*;
|
|
||||||
import arc.struct.*;
|
|
||||||
import arc.util.*;
|
|
||||||
import mindustry.*;
|
|
||||||
import mindustry.ai.BaseRegistry.*;
|
|
||||||
import mindustry.content.*;
|
|
||||||
import mindustry.core.*;
|
|
||||||
import mindustry.game.*;
|
|
||||||
import mindustry.game.Schematic.*;
|
|
||||||
import mindustry.game.Teams.*;
|
|
||||||
import mindustry.gen.*;
|
|
||||||
import mindustry.maps.generators.*;
|
|
||||||
import mindustry.type.*;
|
|
||||||
import mindustry.world.*;
|
|
||||||
import mindustry.world.blocks.defense.*;
|
|
||||||
import mindustry.world.blocks.payloads.*;
|
|
||||||
import mindustry.world.blocks.production.*;
|
|
||||||
import mindustry.world.blocks.storage.*;
|
|
||||||
import mindustry.world.blocks.storage.CoreBlock.*;
|
|
||||||
|
|
||||||
import static mindustry.Vars.*;
|
|
||||||
|
|
||||||
public class BaseAI{
|
|
||||||
private static final Vec2 axis = new Vec2(), rotator = new Vec2();
|
|
||||||
private static final int attempts = 4;
|
|
||||||
private static final float emptyChance = 0.01f;
|
|
||||||
private static final int timerStep = 0, timerSpawn = 1, timerRefreshPath = 2;
|
|
||||||
private static final int pathStep = 50;
|
|
||||||
private static final Seq<Tile> tmpTiles = new Seq<>();
|
|
||||||
|
|
||||||
private static int correct = 0, incorrect = 0;
|
|
||||||
|
|
||||||
private int lastX, lastY, lastW, lastH;
|
|
||||||
private boolean triedWalls, foundPath;
|
|
||||||
|
|
||||||
final TeamData data;
|
|
||||||
final Interval timer = new Interval(4);
|
|
||||||
|
|
||||||
IntSet path = new IntSet();
|
|
||||||
IntSet calcPath = new IntSet();
|
|
||||||
@Nullable Tile calcTile;
|
|
||||||
boolean calculating, startedCalculating;
|
|
||||||
int calcCount = 0;
|
|
||||||
int totalCalcs = 0;
|
|
||||||
Block wallType;
|
|
||||||
|
|
||||||
public BaseAI(TeamData data){
|
|
||||||
this.data = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void update(){
|
|
||||||
|
|
||||||
if(wallType == null){
|
|
||||||
wallType = BaseGenerator.getDifficultyWall(1, data.team.rules().aiTier / 0.8f);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(data.team.rules().aiCoreSpawn && timer.get(timerSpawn, 60 * 6f) && data.hasCore()){
|
|
||||||
CoreBlock block = (CoreBlock)data.core().block;
|
|
||||||
int coreUnits = data.countType(block.unitType);
|
|
||||||
|
|
||||||
//create AI core unit(s)
|
|
||||||
if(!state.isEditor() && coreUnits < data.cores.size){
|
|
||||||
Unit unit = block.unitType.create(data.team);
|
|
||||||
unit.set(data.cores.random());
|
|
||||||
unit.add();
|
|
||||||
Fx.spawn.at(unit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//refresh path
|
|
||||||
if(!calculating && (timer.get(timerRefreshPath, 3f * Time.toMinutes) || !startedCalculating) && data.hasCore()){
|
|
||||||
calculating = true;
|
|
||||||
startedCalculating = true;
|
|
||||||
calcPath.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
//didn't find tile in time
|
|
||||||
if(calculating && calcCount >= world.width() * world.height()){
|
|
||||||
calculating = false;
|
|
||||||
calcCount = 0;
|
|
||||||
calcPath.clear();
|
|
||||||
totalCalcs ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
//calculate path for units so schematics are not placed on it
|
|
||||||
if(calculating){
|
|
||||||
if(calcTile == null){
|
|
||||||
Vars.spawner.eachGroundSpawn((x, y) -> calcTile = world.tile(x, y));
|
|
||||||
if(calcTile == null){
|
|
||||||
calculating = false;
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
var field = pathfinder.getField(data.team, Pathfinder.costGround, Pathfinder.fieldCore);
|
|
||||||
|
|
||||||
if(field.weights != null){
|
|
||||||
int[] weights = field.weights;
|
|
||||||
for(int i = 0; i < pathStep; i++){
|
|
||||||
int minCost = Integer.MAX_VALUE;
|
|
||||||
int cx = calcTile.x, cy = calcTile.y;
|
|
||||||
boolean foundAny = false;
|
|
||||||
for(Point2 p : Geometry.d4){
|
|
||||||
int nx = cx + p.x, ny = cy + p.y, packed = world.packArray(nx, ny);
|
|
||||||
|
|
||||||
Tile other = world.tile(nx, ny);
|
|
||||||
if(other != null && weights[packed] < minCost && weights[packed] != -1){
|
|
||||||
minCost = weights[packed];
|
|
||||||
calcTile = other;
|
|
||||||
foundAny = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//didn't find anything, break out of loop, this will trigger a clear later
|
|
||||||
if(!foundAny){
|
|
||||||
calcCount = Integer.MAX_VALUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
calcPath.add(calcTile.pos());
|
|
||||||
for(Point2 p : Geometry.d8){
|
|
||||||
calcPath.add(Point2.pack(p.x + calcTile.x, p.y + calcTile.y));
|
|
||||||
}
|
|
||||||
|
|
||||||
//found the end.
|
|
||||||
if(calcTile.build instanceof CoreBuild b && b.team != data.team){
|
|
||||||
//clean up calculations and flush results
|
|
||||||
calculating = false;
|
|
||||||
calcCount = 0;
|
|
||||||
path.clear();
|
|
||||||
path.addAll(calcPath);
|
|
||||||
calcPath.clear();
|
|
||||||
calcTile = null;
|
|
||||||
totalCalcs ++;
|
|
||||||
foundPath = true;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
calcCount ++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//only schedule when there's something to build.
|
|
||||||
if(foundPath && data.blocks.isEmpty() && timer.get(timerStep, Mathf.lerp(20f, 4f, data.team.rules().aiTier))){
|
|
||||||
if(!triedWalls){
|
|
||||||
tryWalls();
|
|
||||||
triedWalls = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = 0; i < attempts; i++){
|
|
||||||
int range = 150;
|
|
||||||
|
|
||||||
Position pos = randomPosition();
|
|
||||||
|
|
||||||
//when there are no random positions, do nothing.
|
|
||||||
if(pos == null) return;
|
|
||||||
|
|
||||||
Tmp.v1.rnd(Mathf.random(range));
|
|
||||||
int wx = (int)(World.toTile(pos.getX()) + Tmp.v1.x), wy = (int)(World.toTile(pos.getY()) + Tmp.v1.y);
|
|
||||||
Tile tile = world.tiles.getc(wx, wy);
|
|
||||||
|
|
||||||
//try not to block the spawn point
|
|
||||||
if(spawner.getSpawns().contains(t -> t.within(tile, tilesize * 40f))){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Seq<BasePart> parts = null;
|
|
||||||
|
|
||||||
//pick a completely random base part, and place it a random location
|
|
||||||
//((yes, very intelligent))
|
|
||||||
if(tile.drop() != null && Vars.bases.forResource(tile.drop()).any()){
|
|
||||||
parts = Vars.bases.forResource(tile.drop());
|
|
||||||
}else if(Mathf.chance(emptyChance)){
|
|
||||||
parts = Vars.bases.parts;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(parts != null){
|
|
||||||
BasePart part = parts.random();
|
|
||||||
if(tryPlace(part, tile.x, tile.y)){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return a random position from which to seed building. */
|
|
||||||
private Position randomPosition(){
|
|
||||||
if(data.hasCore()){
|
|
||||||
return data.cores.random();
|
|
||||||
}else if(data.team == state.rules.waveTeam){
|
|
||||||
return spawner.getSpawns().random();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean tryPlace(BasePart part, int x, int y){
|
|
||||||
int rotation = Mathf.range(2);
|
|
||||||
axis.set((int)(part.schematic.width / 2f), (int)(part.schematic.height / 2f));
|
|
||||||
Schematic result = Schematics.rotate(part.schematic, rotation);
|
|
||||||
int rotdeg = rotation*90;
|
|
||||||
rotator.set(part.centerX, part.centerY).rotateAround(axis, rotdeg);
|
|
||||||
//bottom left schematic corner
|
|
||||||
int cx = x - (int)rotator.x;
|
|
||||||
int cy = y - (int)rotator.y;
|
|
||||||
|
|
||||||
//check valid placeability
|
|
||||||
for(Stile tile : result.tiles){
|
|
||||||
int realX = tile.x + cx, realY = tile.y + cy;
|
|
||||||
if(!Build.validPlace(tile.block, data.team, realX, realY, tile.rotation)){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Tile wtile = world.tile(realX, realY);
|
|
||||||
|
|
||||||
if(tile.block instanceof PayloadConveyor || tile.block instanceof PayloadBlock){
|
|
||||||
//near a building
|
|
||||||
for(Point2 point : Edges.getEdges(tile.block.size)){
|
|
||||||
var t = world.build(tile.x + point.x, tile.y + point.y);
|
|
||||||
if(t != null){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//may intersect AI path
|
|
||||||
tmpTiles.clear();
|
|
||||||
if(tile.block.solid && wtile != null && wtile.getLinkedTilesAs(tile.block, tmpTiles).contains(t -> path.contains(t.pos()))){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//make sure at least X% of resource requirements are met
|
|
||||||
correct = incorrect = 0;
|
|
||||||
boolean anyDrills = false;
|
|
||||||
|
|
||||||
if(part.required instanceof Item){
|
|
||||||
for(Stile tile : result.tiles){
|
|
||||||
if(tile.block instanceof Drill){
|
|
||||||
anyDrills = true;
|
|
||||||
|
|
||||||
tile.block.iterateTaken(tile.x + cx, tile.y + cy, (ex, ey) -> {
|
|
||||||
Tile res = world.rawTile(ex, ey);
|
|
||||||
if(res.drop() == part.required){
|
|
||||||
correct ++;
|
|
||||||
}else if(res.drop() != null){
|
|
||||||
incorrect ++;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//fail if not enough fit requirements
|
|
||||||
if(anyDrills && (incorrect != 0 || correct == 0)){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//queue it
|
|
||||||
for(Stile tile : result.tiles){
|
|
||||||
data.blocks.add(new BlockPlan(cx + tile.x, cy + tile.y, tile.rotation, tile.block.id, tile.config));
|
|
||||||
}
|
|
||||||
|
|
||||||
lastX = cx - 1;
|
|
||||||
lastY = cy - 1;
|
|
||||||
lastW = result.width + 2;
|
|
||||||
lastH = result.height + 2;
|
|
||||||
|
|
||||||
triedWalls = false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void tryWalls(){
|
|
||||||
Block wall = wallType;
|
|
||||||
Building spawnt = state.rules.defaultTeam.core() != null ? state.rules.defaultTeam.core() : data.team.core();
|
|
||||||
Tile spawn = spawnt == null ? null : spawnt.tile;
|
|
||||||
|
|
||||||
if(spawn == null) return;
|
|
||||||
|
|
||||||
for(int wx = lastX; wx <= lastX + lastW; wx++){
|
|
||||||
outer:
|
|
||||||
for(int wy = lastY; wy <= lastY + lastH; wy++){
|
|
||||||
Tile tile = world.tile(wx, wy);
|
|
||||||
|
|
||||||
if(tile == null || !tile.block().alwaysReplace) continue;
|
|
||||||
|
|
||||||
boolean any = false;
|
|
||||||
|
|
||||||
for(Point2 p : Geometry.d8){
|
|
||||||
if(Angles.angleDist(Angles.angle(p.x, p.y), spawn.angleTo(tile)) > 70){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Tile o = world.tile(tile.x + p.x, tile.y + p.y);
|
|
||||||
if(o != null && (o.block() instanceof PayloadBlock || o.block() instanceof PayloadConveyor || o.block() instanceof ShockMine)){
|
|
||||||
continue outer;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(o != null && o.team() == data.team && !(o.block() instanceof Wall)){
|
|
||||||
any = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpTiles.clear();
|
|
||||||
if(any && Build.validPlace(wall, data.team, tile.x, tile.y, 0) && !tile.getLinkedTilesAs(wall, tmpTiles).contains(t -> path.contains(t.pos()))){
|
|
||||||
data.blocks.add(new BlockPlan(tile.x, tile.y, (short)0, wall.id, null));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -83,6 +83,7 @@ public class RtsAI{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO atrocious implementation
|
||||||
void checkBuilding(){
|
void checkBuilding(){
|
||||||
if(data.team.rules().aiCoreSpawn && timer.get(timerSpawn, 60 * 7f) && data.hasCore()){
|
if(data.team.rules().aiCoreSpawn && timer.get(timerSpawn, 60 * 7f) && data.hasCore()){
|
||||||
CoreBlock block = (CoreBlock)data.core().block;
|
CoreBlock block = (CoreBlock)data.core().block;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package mindustry.ai.types;
|
package mindustry.ai.types;
|
||||||
|
|
||||||
import arc.math.*;
|
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import mindustry.entities.*;
|
import mindustry.entities.*;
|
||||||
@@ -133,7 +132,8 @@ public class BuilderAI extends AIController{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
float rebuildTime = (unit.team.rules().ai ? Mathf.lerp(15f, 2f, unit.team.rules().aiTier) : 2f) * 60f;
|
//TODO this is bad, rebuild time should not depend on AI here
|
||||||
|
float rebuildTime = (unit.team.rules().rtsAi ? 12f : 2f) * 60f;
|
||||||
|
|
||||||
//find new request
|
//find new request
|
||||||
if(!unit.team.data().blocks.isEmpty() && following == null && timer.get(timerTarget3, rebuildTime)){
|
if(!unit.team.data().blocks.isEmpty() && following == null && timer.get(timerTarget3, rebuildTime)){
|
||||||
@@ -168,7 +168,7 @@ public class BuilderAI extends AIController{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean useFallback(){
|
public boolean useFallback(){
|
||||||
return state.rules.waves && unit.team == state.rules.waveTeam && !unit.team.rules().ai && !unit.team.rules().rtsAi;
|
return state.rules.waves && unit.team == state.rules.waveTeam && !unit.team.rules().rtsAi;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -3707,8 +3707,7 @@ public class Blocks{
|
|||||||
size = 3;
|
size = 3;
|
||||||
reloadTime = 130f;
|
reloadTime = 130f;
|
||||||
chargeTime = 90f;
|
chargeTime = 90f;
|
||||||
//TODO 500 or 400? does it need to be better than the standard mass driver?
|
range = 500f;
|
||||||
range = 450f;
|
|
||||||
maxPayloadSize = 2.5f;
|
maxPayloadSize = 2.5f;
|
||||||
consumePower(0.5f);
|
consumePower(0.5f);
|
||||||
}};
|
}};
|
||||||
|
|||||||
@@ -114,7 +114,6 @@ public class Planets{
|
|||||||
r.attributes.clear();
|
r.attributes.clear();
|
||||||
r.showSpawns = false;
|
r.showSpawns = false;
|
||||||
};
|
};
|
||||||
defaultAI = true;
|
|
||||||
atmosphereColor = Color.valueOf("3c1b8f");
|
atmosphereColor = Color.valueOf("3c1b8f");
|
||||||
atmosphereRadIn = 0.02f;
|
atmosphereRadIn = 0.02f;
|
||||||
atmosphereRadOut = 0.3f;
|
atmosphereRadOut = 0.3f;
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ public class SectorPresets{
|
|||||||
|
|
||||||
saltFlats = new SectorPreset("saltFlats", serpulo, 101){{
|
saltFlats = new SectorPreset("saltFlats", serpulo, 101){{
|
||||||
difficulty = 5;
|
difficulty = 5;
|
||||||
useAI = false;
|
|
||||||
}};
|
}};
|
||||||
|
|
||||||
frozenForest = new SectorPreset("frozenForest", serpulo, 86){{
|
frozenForest = new SectorPreset("frozenForest", serpulo, 86){{
|
||||||
@@ -63,7 +62,6 @@ public class SectorPresets{
|
|||||||
|
|
||||||
extractionOutpost = new SectorPreset("extractionOutpost", serpulo, 165){{
|
extractionOutpost = new SectorPreset("extractionOutpost", serpulo, 165){{
|
||||||
difficulty = 5;
|
difficulty = 5;
|
||||||
useAI = false;
|
|
||||||
}};
|
}};
|
||||||
|
|
||||||
coastline = new SectorPreset("coastline", serpulo, 108){{
|
coastline = new SectorPreset("coastline", serpulo, 108){{
|
||||||
@@ -77,12 +75,10 @@ public class SectorPresets{
|
|||||||
|
|
||||||
fungalPass = new SectorPreset("fungalPass", serpulo, 21){{
|
fungalPass = new SectorPreset("fungalPass", serpulo, 21){{
|
||||||
difficulty = 4;
|
difficulty = 4;
|
||||||
useAI = false;
|
|
||||||
}};
|
}};
|
||||||
|
|
||||||
overgrowth = new SectorPreset("overgrowth", serpulo, 134){{
|
overgrowth = new SectorPreset("overgrowth", serpulo, 134){{
|
||||||
difficulty = 5;
|
difficulty = 5;
|
||||||
useAI = false;
|
|
||||||
}};
|
}};
|
||||||
|
|
||||||
tarFields = new SectorPreset("tarFields", serpulo, 23){{
|
tarFields = new SectorPreset("tarFields", serpulo, 23){{
|
||||||
|
|||||||
@@ -119,13 +119,8 @@ public class Logic implements ApplicationListener{
|
|||||||
|
|
||||||
if(state.isCampaign()){
|
if(state.isCampaign()){
|
||||||
//enable building AI on campaign unless the preset disables it
|
//enable building AI on campaign unless the preset disables it
|
||||||
//TODO should be (more) configurable, I don't want building AI everywhere.
|
|
||||||
if(state.getSector().planet.defaultAI && !(state.getSector().preset != null && !state.getSector().preset.useAI)){
|
|
||||||
state.rules.waveTeam.rules().ai = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
state.rules.coreIncinerates = true;
|
state.rules.coreIncinerates = true;
|
||||||
state.rules.waveTeam.rules().aiTier = state.getSector().threat * 0.8f;
|
|
||||||
state.rules.waveTeam.rules().infiniteResources = true;
|
state.rules.waveTeam.rules().infiniteResources = true;
|
||||||
|
|
||||||
//fill enemy cores by default.
|
//fill enemy cores by default.
|
||||||
@@ -419,11 +414,6 @@ public class Logic implements ApplicationListener{
|
|||||||
updateWeather();
|
updateWeather();
|
||||||
|
|
||||||
for(TeamData data : state.teams.getActive()){
|
for(TeamData data : state.teams.getActive()){
|
||||||
if(data.hasAI()){
|
|
||||||
if(data.baseAi == null) data.baseAi = new BaseAI(data);
|
|
||||||
data.baseAi.update();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(data.team.rules().rtsAi){
|
if(data.team.rules().rtsAi){
|
||||||
if(data.rtsAi == null) data.rtsAi = new RtsAI(data);
|
if(data.rtsAi == null) data.rtsAi = new RtsAI(data);
|
||||||
data.rtsAi.update();
|
data.rtsAi.update();
|
||||||
|
|||||||
@@ -201,11 +201,7 @@ public class Rules{
|
|||||||
|
|
||||||
/** A team-specific ruleset. */
|
/** A team-specific ruleset. */
|
||||||
public static class TeamRule{
|
public static class TeamRule{
|
||||||
/** Whether to use building AI. TODO remove, it is terrible. */
|
/** Whether, when AI is enabled, ships should be spawned from the core. TODO remove / unnecessary? */
|
||||||
public boolean ai;
|
|
||||||
/** TODO Tier of blocks/designs that the AI uses for building. [0, 1] */
|
|
||||||
public float aiTier = 1f;
|
|
||||||
/** Whether, when AI is enabled, ships should be spawned from the core. */
|
|
||||||
public boolean aiCoreSpawn = true;
|
public boolean aiCoreSpawn = true;
|
||||||
/** If true, blocks don't require power or resources. */
|
/** If true, blocks don't require power or resources. */
|
||||||
public boolean cheat;
|
public boolean cheat;
|
||||||
|
|||||||
@@ -223,8 +223,6 @@ public class Teams{
|
|||||||
public final Seq<CoreBuild> cores = new Seq<>();
|
public final Seq<CoreBuild> cores = new Seq<>();
|
||||||
public final Team team;
|
public final Team team;
|
||||||
|
|
||||||
/** Handles building ""bases"". */
|
|
||||||
public @Nullable BaseAI baseAi;
|
|
||||||
/** Handles RTS unit control. */
|
/** Handles RTS unit control. */
|
||||||
public @Nullable RtsAI rtsAi;
|
public @Nullable RtsAI rtsAi;
|
||||||
|
|
||||||
@@ -330,7 +328,7 @@ public class Teams{
|
|||||||
|
|
||||||
/** @return whether this team is controlled by the AI and builds bases. */
|
/** @return whether this team is controlled by the AI and builds bases. */
|
||||||
public boolean hasAI(){
|
public boolean hasAI(){
|
||||||
return team.rules().ai;
|
return team.rules().rtsAi;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -91,8 +91,6 @@ public class Planet extends UnlockableContent{
|
|||||||
public boolean allowWaveSimulation = false;
|
public boolean allowWaveSimulation = false;
|
||||||
/** Whether to simulate sector invasions from enemy bases. */
|
/** Whether to simulate sector invasions from enemy bases. */
|
||||||
public boolean allowSectorInvasion = false;
|
public boolean allowSectorInvasion = false;
|
||||||
/** If true, builder AI is turned on for all sectors on this planet by default. */
|
|
||||||
public boolean defaultAI = false;
|
|
||||||
/** If true, sectors saves are cleared when lost. */
|
/** If true, sectors saves are cleared when lost. */
|
||||||
public boolean clearSectorOnLose = false;
|
public boolean clearSectorOnLose = false;
|
||||||
/** Sets up rules on game load for any sector on this planet. */
|
/** Sets up rules on game load for any sector on this planet. */
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ public class SectorPreset extends UnlockableContent{
|
|||||||
|
|
||||||
public int captureWave = 0;
|
public int captureWave = 0;
|
||||||
public Cons<Rules> rules = rules -> rules.winWave = captureWave;
|
public Cons<Rules> rules = rules -> rules.winWave = captureWave;
|
||||||
public boolean useAI = true;
|
|
||||||
/** Difficulty, 0-10. */
|
/** Difficulty, 0-10. */
|
||||||
public float difficulty;
|
public float difficulty;
|
||||||
public float startWaveTimeMultiplier = 2f;
|
public float startWaveTimeMultiplier = 2f;
|
||||||
|
|||||||
@@ -182,7 +182,6 @@ public class CustomRulesDialog extends BaseDialog{
|
|||||||
|
|
||||||
title("@rules.title.enemy");
|
title("@rules.title.enemy");
|
||||||
check("@rules.attack", b -> rules.attackMode = b, () -> rules.attackMode);
|
check("@rules.attack", b -> rules.attackMode = b, () -> rules.attackMode);
|
||||||
check("@rules.buildai", b -> rules.teams.get(rules.waveTeam).ai = rules.teams.get(rules.waveTeam).infiniteResources = b, () -> rules.teams.get(rules.waveTeam).ai);
|
|
||||||
check("@rules.corecapture", b -> rules.coreCapture = b, () -> rules.coreCapture);
|
check("@rules.corecapture", b -> rules.coreCapture = b, () -> rules.coreCapture);
|
||||||
check("@rules.placerangecheck", b -> rules.placeRangeCheck = b, () -> rules.placeRangeCheck);
|
check("@rules.placerangecheck", b -> rules.placeRangeCheck = b, () -> rules.placeRangeCheck);
|
||||||
check("@rules.polygoncoreprotection", b -> rules.polygonCoreProtection = b, () -> rules.polygonCoreProtection);
|
check("@rules.polygoncoreprotection", b -> rules.polygonCoreProtection = b, () -> rules.polygonCoreProtection);
|
||||||
@@ -257,9 +256,6 @@ public class CustomRulesDialog extends BaseDialog{
|
|||||||
|
|
||||||
check("@rules.rtsai", b -> teams.rtsAi = b, () -> teams.rtsAi, () -> team != rules.defaultTeam);
|
check("@rules.rtsai", b -> teams.rtsAi = b, () -> teams.rtsAi, () -> team != rules.defaultTeam);
|
||||||
|
|
||||||
check("@rules.buildai", b -> teams.ai = b, () -> teams.ai, () -> team != rules.defaultTeam);
|
|
||||||
number("@rules.aitier", false, f -> teams.aiTier = f, () -> teams.aiTier, () -> teams.ai, 0, 1);
|
|
||||||
|
|
||||||
check("@rules.infiniteresources", b -> teams.infiniteResources = b, () -> teams.infiniteResources);
|
check("@rules.infiniteresources", b -> teams.infiniteResources = b, () -> teams.infiniteResources);
|
||||||
number("@rules.buildspeedmultiplier", f -> teams.buildSpeedMultiplier = f, () -> teams.buildSpeedMultiplier, 0.001f, 50f);
|
number("@rules.buildspeedmultiplier", f -> teams.buildSpeedMultiplier = f, () -> teams.buildSpeedMultiplier, 0.001f, 50f);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user