Campaign rule for unpredictable wave AI

This commit is contained in:
Anuken
2024-09-13 18:50:46 -04:00
parent 1529c40400
commit 6e5561a36e
6 changed files with 38 additions and 15 deletions

View File

@@ -1399,6 +1399,7 @@ rules.lighting = Lighting
rules.fog = Fog of War rules.fog = Fog of War
rules.invasions = Enemy Sector Invasions rules.invasions = Enemy Sector Invasions
rules.showspawns = Show Enemy Spawns rules.showspawns = Show Enemy Spawns
rules.randomwaveai = Unpredictable Wave AI
rules.fire = Fire rules.fire = Fire
rules.anyenv = <Any> rules.anyenv = <Any>
rules.explosions = Block/Unit Explosion Damage rules.explosions = Block/Unit Explosion Damage

View File

@@ -2,6 +2,7 @@ package mindustry.ai;
import arc.*; import arc.*;
import arc.func.*; import arc.func.*;
import arc.math.*;
import arc.math.geom.*; import arc.math.geom.*;
import arc.struct.*; import arc.struct.*;
import arc.util.*; import arc.util.*;
@@ -16,6 +17,7 @@ import mindustry.world.blocks.storage.*;
import mindustry.world.meta.*; import mindustry.world.meta.*;
import static mindustry.Vars.*; import static mindustry.Vars.*;
import static mindustry.world.meta.BlockFlag.*;
public class Pathfinder implements Runnable{ public class Pathfinder implements Runnable{
private static final long maxUpdate = Time.millisToNanos(8); private static final long maxUpdate = Time.millisToNanos(8);
@@ -454,8 +456,28 @@ public class Pathfinder implements Runnable{
} }
public static class EnemyCoreField extends Flowfield{ public static class EnemyCoreField extends Flowfield{
private final static BlockFlag[] randomTargets = {storage, generator, launchPad, factory, repair, battery, reactor, drill};
private Rand rand = new Rand();
@Override @Override
protected void getPositions(IntSeq out){ protected void getPositions(IntSeq out){
if(state.rules.randomWaveAI && team == state.rules.waveTeam){
rand.setSeed(state.rules.waves ? state.wave : (int)(state.tick / (5400)));
//maximum amount of different target flag types they will attack
int max = 2;
for(int attempt = 0; attempt < 5 && max > 0; attempt++){
var targets = indexer.getEnemy(team, randomTargets[rand.random(randomTargets.length - 1)]);
if(!targets.isEmpty()){
max --;
for(Building other : targets){
out.add(other.tile.array());
}
}
}
}
for(Building other : indexer.getEnemy(team, BlockFlag.core)){ for(Building other : indexer.getEnemy(team, BlockFlag.core)){
out.add(other.tile.array()); out.add(other.tile.array());
} }

View File

@@ -45,7 +45,7 @@ public class FlyingAI extends AIController{
return core; return core;
} }
if(state.rules.randomAirTargeting){ if(state.rules.randomWaveAI){
//when there are no waves, it's just random based on the unit //when there are no waves, it's just random based on the unit
Mathf.rand.setSeed(unit.type.id + (state.rules.waves ? state.wave : unit.id)); Mathf.rand.setSeed(unit.type.id + (state.rules.waves ? state.wave : unit.id));
//try a few random flags first //try a few random flags first
@@ -56,10 +56,7 @@ public class FlyingAI extends AIController{
//try the closest target //try the closest target
Teamc result = target(x, y, range, air, ground); Teamc result = target(x, y, range, air, ground);
if(result != null) return result; if(result != null) return result;
//default to the core }else{
return core;
}
for(var flag : unit.type.targetFlags){ for(var flag : unit.type.targetFlags){
if(flag == null){ if(flag == null){
Teamc result = target(x, y, range, air, ground); Teamc result = target(x, y, range, air, ground);
@@ -69,6 +66,7 @@ public class FlyingAI extends AIController{
if(result != null) return result; if(result != null) return result;
} }
} }
}
return core; return core;
} }

View File

@@ -5,12 +5,13 @@ public class CampaignRules{
public boolean fog; public boolean fog;
public boolean showSpawns; public boolean showSpawns;
public boolean sectorInvasion; public boolean sectorInvasion;
public boolean randomWaveAI;
public void apply(Rules rules){ public void apply(Rules rules){
rules.staticFog = rules.fog = fog; rules.staticFog = rules.fog = fog;
rules.showSpawns = showSpawns; rules.showSpawns = showSpawns;
rules.randomWaveAI = randomWaveAI;
rules.teams.get(rules.waveTeam).blockHealthMultiplier = difficulty.enemyHealthMultiplier; rules.teams.get(rules.waveTeam).blockHealthMultiplier = difficulty.enemyHealthMultiplier;
rules.teams.get(rules.waveTeam).unitHealthMultiplier = difficulty.enemyHealthMultiplier; rules.teams.get(rules.waveTeam).unitHealthMultiplier = difficulty.enemyHealthMultiplier;
rules.randomAirTargeting = difficulty.ordinal() >= Difficulty.hard.ordinal();
} }
} }

View File

@@ -61,8 +61,8 @@ public class Rules{
public boolean fire = true; public boolean fire = true;
/** Whether units use and require ammo. */ /** Whether units use and require ammo. */
public boolean unitAmmo = false; public boolean unitAmmo = false;
/** EXPERIMENTAL! If true, air units target random things each wave instead of only generators. */ /** EXPERIMENTAL! If true, air and ground units target random things each wave instead of only the core/generators. */
public boolean randomAirTargeting = false; public boolean randomWaveAI = false;
/** EXPERIMENTAL! If true, blocks will update in units and share power. */ /** EXPERIMENTAL! If true, blocks will update in units and share power. */
public boolean unitPayloadUpdate = false; public boolean unitPayloadUpdate = false;
/** If true, units' payloads are destroy()ed when the unit is destroyed. */ /** If true, units' payloads are destroy()ed when the unit is destroyed. */

View File

@@ -59,6 +59,7 @@ public class CampaignRulesDialog extends BaseDialog{
check("@rules.fog", b -> rules.fog = b, () -> rules.fog); check("@rules.fog", b -> rules.fog = b, () -> rules.fog);
check("@rules.showspawns", b -> rules.showSpawns = b, () -> rules.showSpawns); check("@rules.showspawns", b -> rules.showSpawns = b, () -> rules.showSpawns);
check("@rules.randomwaveai", b -> rules.randomWaveAI = b, () -> rules.randomWaveAI);
}).growY(); }).growY();
} }