RTS AI fixes and improvements
This commit is contained in:
@@ -25,16 +25,16 @@ import mindustry.world.meta.*;
|
||||
|
||||
public class RtsAI{
|
||||
static final Seq<Building> targets = new Seq<>();
|
||||
static final Seq<Unit> squad = new Seq<>(false);
|
||||
static final Seq<Unit> squad = new Seq<>(false), stack = new Seq<>();
|
||||
static final IntSet used = new IntSet();
|
||||
static final IntSet assignedTargets = new IntSet(), invalidTarget = new IntSet();
|
||||
static final float squadRadius = 140f;
|
||||
static final float squadRadius = 50f;
|
||||
static final int timeUpdate = 0, timerSpawn = 1, maxTargetsChecked = 15;
|
||||
|
||||
//in order of priority??
|
||||
static final BlockFlag[] flags = {BlockFlag.generator, BlockFlag.factory, BlockFlag.core, BlockFlag.battery, BlockFlag.drill};
|
||||
static final ObjectFloatMap<Building> weights = new ObjectFloatMap<>();
|
||||
static final boolean debug = OS.hasProp("mindustry.debug") && false;
|
||||
static final boolean debug = OS.hasProp("mindustry.debug");
|
||||
|
||||
final Interval timer = new Interval(10);
|
||||
final TeamData data;
|
||||
@@ -109,21 +109,25 @@ public class RtsAI{
|
||||
boolean didDefend = false;
|
||||
|
||||
for(var unit : data.units){
|
||||
if(used.add(unit.id) && unit.isCommandable() && !unit.command().hasCommand() && !unit.command().isAttacking()){
|
||||
if(used.add(unit.id) && unit.controller() instanceof CommandAI cai && !cai.hasCommand() && !cai.isAttacking()){
|
||||
squad.clear();
|
||||
|
||||
stack.clear();
|
||||
stack.add(unit);
|
||||
|
||||
float rad = squadRadius + unit.hitSize*1.5f;
|
||||
data.tree().intersect(unit.x - rad/2f, unit.y - rad/2f, rad, rad, squad);
|
||||
|
||||
squad.truncate(data.team.rules().rtsMaxSquad);
|
||||
while(stack.size > 0){
|
||||
var next = stack.pop();
|
||||
|
||||
//remove overlapping squads
|
||||
squad.removeAll(u -> (u != unit && used.contains(u.id)) || !u.isCommandable() || u.command().hasCommand() || ((u.flag == 0) != (unit.flag == 0)));
|
||||
//mark used so other squads can't steal them
|
||||
for(var item : squad){
|
||||
used.add(item.id);
|
||||
data.tree().intersect(next.x - rad/2f, next.y - rad/2f, rad, rad, u -> {
|
||||
if(u.controller() instanceof CommandAI ai && !ai.hasCommand() && ((u.flag == 0) == (unit.flag == 0)) && used.add(u.id)){
|
||||
squad.add(u);
|
||||
stack.add(u);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//TODO flawed, squads
|
||||
if(handleSquad(squad, !didDefend)){
|
||||
didDefend = true;
|
||||
}
|
||||
@@ -304,7 +308,7 @@ public class RtsAI{
|
||||
);
|
||||
|
||||
float weight = weights.get(result, 0f);
|
||||
if(checkWeight && weight < data.team.rules().rtsMinWeight && total < Units.getCap(data.team)){
|
||||
if(checkWeight && (weight < data.team.rules().rtsMinWeight && total < data.team.rules().rtsMaxSquad) && total < Units.getCap(data.team)){
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,13 +36,13 @@ public class Units{
|
||||
|
||||
public static void notifyUnitSpawn(Unit unit){
|
||||
if(net.server()){
|
||||
Call.unitSpawn(new UnitContainer(unit));
|
||||
Call.unitSpawn(new UnitSyncContainer(unit));
|
||||
}
|
||||
}
|
||||
|
||||
//syncs a unit spawn so that it appears immediately without waiting for a snapshot
|
||||
@Remote(unreliable = true, priority = PacketPriority.low)
|
||||
public static void unitSpawn(UnitContainer container){
|
||||
public static void unitSpawn(UnitSyncContainer container){
|
||||
//doesn't actually do anything, reading calls add()
|
||||
}
|
||||
|
||||
@@ -501,13 +501,13 @@ public class Units{
|
||||
float priority(Building build);
|
||||
}
|
||||
|
||||
public static class UnitContainer{
|
||||
public static class UnitSyncContainer{
|
||||
public Unit unit;
|
||||
|
||||
public UnitContainer(){
|
||||
public UnitSyncContainer(){
|
||||
}
|
||||
|
||||
public UnitContainer(Unit unit){
|
||||
public UnitSyncContainer(Unit unit){
|
||||
this.unit = unit;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ public class UnitSpawnAbility extends Ability{
|
||||
Events.fire(new UnitCreateEvent(u, null, unit));
|
||||
if(!Vars.net.client()){
|
||||
u.add();
|
||||
Units.notifyUnitSpawn(u);
|
||||
}
|
||||
|
||||
timer = 0f;
|
||||
|
||||
@@ -21,7 +21,7 @@ public class CampaignRules{
|
||||
if(planet.showRtsAIRule && rules.attackMode){
|
||||
boolean swapped = rules.teams.get(rules.waveTeam).rtsAi != rtsAI;
|
||||
rules.teams.get(rules.waveTeam).rtsAi = rtsAI;
|
||||
rules.teams.get(rules.waveTeam).rtsMinWeight = 1.2f * difficulty.enemyHealthMultiplier;
|
||||
rules.teams.get(rules.waveTeam).rtsMaxSquad = 15;
|
||||
|
||||
if(swapped && Vars.state.isGame()){
|
||||
Groups.unit.each(u -> {
|
||||
|
||||
@@ -279,14 +279,14 @@ public class TypeIO{
|
||||
return noAbilities;
|
||||
}
|
||||
|
||||
public static void writeUnitContainer(Writes write, Units.UnitContainer cont){
|
||||
public static void writeUnitContainer(Writes write, UnitSyncContainer cont){
|
||||
write.i(cont.unit.id);
|
||||
write.b(cont.unit.classId() & 0xFF);
|
||||
cont.unit.beforeWrite();
|
||||
cont.unit.writeSync(write);
|
||||
}
|
||||
|
||||
public static UnitContainer readUnitContainer(Reads read){
|
||||
public static UnitSyncContainer readUnitContainer(Reads read){
|
||||
int id = read.i();
|
||||
int typeID = read.ub();
|
||||
|
||||
|
||||
@@ -517,6 +517,7 @@ public class UnitAssembler extends PayloadBlock{
|
||||
unit.set(spawn.x + Mathf.range(0.001f), spawn.y + Mathf.range(0.001f));
|
||||
unit.rotation = rotdeg();
|
||||
unit.add();
|
||||
Units.notifyUnitSpawn(unit);
|
||||
}
|
||||
|
||||
progress = 0f;
|
||||
|
||||
Reference in New Issue
Block a user