RTS AI fixes and improvements

This commit is contained in:
Anuken
2025-04-22 19:42:05 -04:00
parent bea50d3821
commit 45f8144a2e
7 changed files with 28 additions and 22 deletions

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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;

View File

@@ -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 -> {

View File

@@ -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();

View File

@@ -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;