Wave balancing & AI tweaks
This commit is contained in:
@@ -17,13 +17,17 @@ public class BuilderAI extends AIController{
|
|||||||
@Nullable Builderc following;
|
@Nullable Builderc following;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateUnit(){
|
public void updateMovement(){
|
||||||
Builderc builder = (Builderc)unit;
|
Builderc builder = (Builderc)unit;
|
||||||
|
|
||||||
if(builder.moving()){
|
if(builder.moving()){
|
||||||
builder.lookAt(builder.vel().angle());
|
builder.lookAt(builder.vel().angle());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(target != null && shouldShoot()){
|
||||||
|
unit.lookAt(target);
|
||||||
|
}
|
||||||
|
|
||||||
builder.updateBuilding(true);
|
builder.updateBuilding(true);
|
||||||
|
|
||||||
if(following != null){
|
if(following != null){
|
||||||
@@ -95,13 +99,29 @@ public class BuilderAI extends AIController{
|
|||||||
}else if(Build.validPlace(content.block(block.block), unit.team(), block.x, block.y, block.rotation)){ //it's valid.
|
}else if(Build.validPlace(content.block(block.block), unit.team(), block.x, block.y, block.rotation)){ //it's valid.
|
||||||
//add build request.
|
//add build request.
|
||||||
builder.addBuild(new BuildPlan(block.x, block.y, block.rotation, content.block(block.block), block.config));
|
builder.addBuild(new BuildPlan(block.x, block.y, block.rotation, content.block(block.block), block.config));
|
||||||
|
//shift build plan to tail so next unit builds something else.
|
||||||
|
blocks.addLast(blocks.removeFirst());
|
||||||
}else{
|
}else{
|
||||||
//shift head of queue to tail, try something else next time
|
//shift head of queue to tail, try something else next time
|
||||||
blocks.removeFirst();
|
blocks.removeFirst();
|
||||||
blocks.addLast(block);
|
blocks.addLast(block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AIController fallback(){
|
||||||
|
return unit.type().flying ? new FlyingAI() : new GroundAI();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean useFallback(){
|
||||||
|
return state.rules.waves && unit.team == state.rules.waveTeam && !unit.team.rules().ai;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldShoot(){
|
||||||
|
return !((Builderc)unit).isBuilding();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,27 +2,33 @@ package mindustry.ai.types;
|
|||||||
|
|
||||||
import mindustry.entities.*;
|
import mindustry.entities.*;
|
||||||
import mindustry.entities.units.*;
|
import mindustry.entities.units.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
import mindustry.world.blocks.ConstructBlock.*;
|
import mindustry.world.blocks.ConstructBlock.*;
|
||||||
|
|
||||||
//note that repair AI doesn't attack anything even if it theoretically can
|
|
||||||
public class RepairAI extends AIController{
|
public class RepairAI extends AIController{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void updateMovement(){
|
protected void updateMovement(){
|
||||||
boolean shoot = false;
|
if(target instanceof Building){
|
||||||
|
boolean shoot = false;
|
||||||
if(target != null){
|
|
||||||
if(!target.within(unit, unit.type().range * 0.8f)){
|
|
||||||
moveTo(target, unit.type().range * 0.8f);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(target.within(unit, unit.type().range)){
|
if(target.within(unit, unit.type().range)){
|
||||||
unit.aim(target);
|
unit.aim(target);
|
||||||
shoot = true;
|
shoot = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unit.controlWeapons(shoot);
|
||||||
|
}else if(target == null){
|
||||||
|
unit.controlWeapons(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
unit.controlWeapons(shoot);
|
if(target != null){
|
||||||
|
if(!target.within(unit, unit.type().range * 0.65f)){
|
||||||
|
moveTo(target, unit.type().range * 0.65f);
|
||||||
|
}
|
||||||
|
|
||||||
|
unit.lookAt(target);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -30,5 +36,10 @@ public class RepairAI extends AIController{
|
|||||||
target = Units.findDamagedTile(unit.team, unit.x, unit.y);
|
target = Units.findDamagedTile(unit.team, unit.x, unit.y);
|
||||||
|
|
||||||
if(target instanceof ConstructBuild) target = null;
|
if(target instanceof ConstructBuild) target = null;
|
||||||
|
|
||||||
|
if(target == null){
|
||||||
|
super.updateTargeting();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1145,7 +1145,7 @@ public class UnitTypes implements ContentList{
|
|||||||
speed = 1.9f;
|
speed = 1.9f;
|
||||||
rotateSpeed = 15f;
|
rotateSpeed = 15f;
|
||||||
accel = 0.1f;
|
accel = 0.1f;
|
||||||
range = 70f;
|
range = 130f;
|
||||||
health = 400;
|
health = 400;
|
||||||
buildSpeed = 0.5f;
|
buildSpeed = 0.5f;
|
||||||
engineOffset = 6.5f;
|
engineOffset = 6.5f;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ public class AIController implements UnitController{
|
|||||||
|
|
||||||
protected Unit unit;
|
protected Unit unit;
|
||||||
protected Interval timer = new Interval(4);
|
protected Interval timer = new Interval(4);
|
||||||
|
protected AIController fallback;
|
||||||
|
|
||||||
/** main target that is being faced */
|
/** main target that is being faced */
|
||||||
protected Teamc target;
|
protected Teamc target;
|
||||||
@@ -34,11 +35,27 @@ public class AIController implements UnitController{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateUnit(){
|
public void updateUnit(){
|
||||||
|
//use fallback AI when possible
|
||||||
|
if(useFallback() && (fallback != null || (fallback = fallback()) != null)){
|
||||||
|
if(fallback.unit != unit) fallback.unit(unit);
|
||||||
|
fallback.updateUnit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
updateVisuals();
|
updateVisuals();
|
||||||
updateTargeting();
|
updateTargeting();
|
||||||
updateMovement();
|
updateMovement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
protected AIController fallback(){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean useFallback(){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
protected UnitCommand command(){
|
protected UnitCommand command(){
|
||||||
return unit.team.data().command;
|
return unit.team.data().command;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ public class DefaultWaves{
|
|||||||
unitAmount = 2;
|
unitAmount = 2;
|
||||||
unitScaling = 2;
|
unitScaling = 2;
|
||||||
max = 20;
|
max = 20;
|
||||||
|
shieldScaling = 30;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(dagger){{
|
new SpawnGroup(dagger){{
|
||||||
@@ -144,6 +145,7 @@ public class DefaultWaves{
|
|||||||
unitAmount = 2;
|
unitAmount = 2;
|
||||||
spacing = 2;
|
spacing = 2;
|
||||||
unitScaling = 2;
|
unitScaling = 2;
|
||||||
|
shieldScaling = 20;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(flare){{
|
new SpawnGroup(flare){{
|
||||||
@@ -162,6 +164,7 @@ public class DefaultWaves{
|
|||||||
unitScaling = 3;
|
unitScaling = 3;
|
||||||
spacing = 5;
|
spacing = 5;
|
||||||
max = 16;
|
max = 16;
|
||||||
|
shieldScaling = 30;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(nova){{
|
new SpawnGroup(nova){{
|
||||||
@@ -169,6 +172,7 @@ public class DefaultWaves{
|
|||||||
unitAmount = 2;
|
unitAmount = 2;
|
||||||
unitScaling = 3;
|
unitScaling = 3;
|
||||||
spacing = 4;
|
spacing = 4;
|
||||||
|
shieldScaling = 20;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(atrax){{
|
new SpawnGroup(atrax){{
|
||||||
@@ -192,15 +196,15 @@ public class DefaultWaves{
|
|||||||
unitAmount = 1;
|
unitAmount = 1;
|
||||||
unitScaling = 1;
|
unitScaling = 1;
|
||||||
spacing = 40;
|
spacing = 40;
|
||||||
shieldScaling = 10f;
|
shieldScaling = 20f;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(antumbra){{
|
new SpawnGroup(antumbra){{
|
||||||
begin = 131;
|
begin = 120;
|
||||||
unitAmount = 1;
|
unitAmount = 1;
|
||||||
unitScaling = 1;
|
unitScaling = 1;
|
||||||
spacing = 40;
|
spacing = 40;
|
||||||
shieldScaling = 10f;
|
shieldScaling = 20f;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(vela){{
|
new SpawnGroup(vela){{
|
||||||
@@ -211,6 +215,15 @@ public class DefaultWaves{
|
|||||||
shieldScaling = 20f;
|
shieldScaling = 20f;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
|
new SpawnGroup(corvus){{
|
||||||
|
begin = 145;
|
||||||
|
unitAmount = 1;
|
||||||
|
unitScaling = 1;
|
||||||
|
spacing = 35;
|
||||||
|
shieldScaling = 30f;
|
||||||
|
shields = 100;
|
||||||
|
}},
|
||||||
|
|
||||||
new SpawnGroup(horizon){{
|
new SpawnGroup(horizon){{
|
||||||
begin = 90;
|
begin = 90;
|
||||||
unitAmount = 2;
|
unitAmount = 2;
|
||||||
@@ -252,7 +265,7 @@ public class DefaultWaves{
|
|||||||
//max reasonable wave, after which everything gets boring
|
//max reasonable wave, after which everything gets boring
|
||||||
int cap = 200;
|
int cap = 200;
|
||||||
|
|
||||||
float shieldStart = 30, shieldsPerWave = 15 + difficulty*20f;
|
float shieldStart = 30, shieldsPerWave = 20 + difficulty*30f;
|
||||||
|
|
||||||
Intc createProgression = start -> {
|
Intc createProgression = start -> {
|
||||||
//main sequence
|
//main sequence
|
||||||
@@ -314,8 +327,8 @@ public class DefaultWaves{
|
|||||||
step += (int)(Mathf.random(12, 25) * Mathf.lerp(1f, 0.4f, difficulty));
|
step += (int)(Mathf.random(12, 25) * Mathf.lerp(1f, 0.4f, difficulty));
|
||||||
}
|
}
|
||||||
|
|
||||||
int bossWave = Mathf.random(30, 60);
|
int bossWave = (int)(Mathf.random(30, 60) * Mathf.lerp(1f, 0.7f, difficulty));
|
||||||
int bossSpacing = Mathf.random(30, 50);
|
int bossSpacing = (int)(Mathf.random(25, 40) * Mathf.lerp(1f, 0.6f, difficulty));
|
||||||
|
|
||||||
//main boss progression
|
//main boss progression
|
||||||
out.add(new SpawnGroup(Structs.random(species)[4]){{
|
out.add(new SpawnGroup(Structs.random(species)[4]){{
|
||||||
|
|||||||
Reference in New Issue
Block a user