Misc RTS AI intelligence fixes

This commit is contained in:
Anuken
2022-10-21 18:29:29 -04:00
parent 46e5f55e9c
commit 7331704a13
6 changed files with 24 additions and 14 deletions

View File

@ -9,6 +9,7 @@ import arc.util.*;
import mindustry.*;
import mindustry.ai.types.*;
import mindustry.content.*;
import mindustry.core.*;
import mindustry.entities.*;
import mindustry.game.EventType.*;
import mindustry.game.Teams.*;
@ -107,7 +108,7 @@ public class RtsAI{
boolean didDefend = false;
for(var unit : data.units){
if(unit.isCommandable() && !unit.command().hasCommand() && used.add(unit.id)){
if(used.add(unit.id) && unit.isCommandable() && !unit.command().hasCommand() && !unit.command().isAttacking()){
squad.clear();
data.tree().intersect(unit.x - squadRadius/2f, unit.y - squadRadius/2f, squadRadius, squadRadius, squad);
@ -178,7 +179,7 @@ public class RtsAI{
//defend when close, or this is the only squad defending
//TODO will always rush to defense no matter what
if(best != null && (best instanceof CoreBuild || (units.size >= data.team.rules().rtsMinSquad || (units.size > 0 && units.first().flag != 0)) || best.within(ax, ay, 500f))){
if(best != null && (best instanceof CoreBuild || (units.size >= data.team.rules().rtsMinSquad || (units.size > 0 && units.first().flag != 0)) || best.within(ax, ay, 1000f))){
defend = best;
if(debug){
@ -197,7 +198,7 @@ public class RtsAI{
Vec2 defendPos = null;
Teamc defendTarget = null;
if(defend != null){
float checkRange = 260f;
float checkRange = 350f;
//TODO could be made faster by storing bullet shooter
Unit aggressor = Units.closestEnemy(data.team, defend.x, defend.y, checkRange, u -> u.checkTarget(tair, tground));
@ -205,6 +206,7 @@ public class RtsAI{
//do not target it directly - target the position?
//defendTarget = aggressor;
defendPos = new Vec2(aggressor.x, aggressor.y);
defendTarget = aggressor;
}else if(false){ //TODO currently ignored, no use defending against nothing
//should it even go there if there's no aggressor found?
Tile closest = defend.findClosestEdge(units.first(), Tile::solid);
@ -247,7 +249,7 @@ public class RtsAI{
if(build != null || anyDefend){
for(var unit : units){
if(unit.isCommandable() && !unit.command().hasCommand()){
if(defendPos != null){
if(defendPos != null && !unit.isPathImpassable(World.toTile(defendPos.x), World.toTile(defendPos.y))){
unit.command().commandPosition(defendPos, true);
}else{
//TODO stopAtTarget parameter could be false, could be tweaked

View File

@ -6,6 +6,7 @@ import arc.struct.*;
import arc.util.*;
import mindustry.*;
import mindustry.ai.*;
import mindustry.core.*;
import mindustry.entities.*;
import mindustry.entities.units.*;
import mindustry.gen.*;
@ -48,6 +49,10 @@ public class CommandAI extends AIController{
}
}
public boolean isAttacking(){
return target != null && unit.within(target, unit.range() + 10f);
}
@Override
public void updateUnit(){
@ -139,7 +144,7 @@ public class CommandAI extends AIController{
move = Vars.controlPath.getPathPosition(unit, pathId, targetPos, vecOut, noFound);
//if the path is invalid, stop trying and record the end as unreachable
if(unit.team.isAI() && noFound[0]){
if(unit.team.isAI() && (noFound[0] || unit.isPathImpassable(World.toTile(targetPos.x), World.toTile(targetPos.y)) )){
if(attackTarget instanceof Building build){
unreachableBuildings.addUnique(build.pos());
}
@ -194,7 +199,7 @@ public class CommandAI extends AIController{
}
}
if(stopWhenInRange && targetPos != null && unit.within(targetPos, engageRange - 1f)){
if(stopWhenInRange && targetPos != null && unit.within(targetPos, engageRange * 0.9f)){
targetPos = null;
stopWhenInRange = false;
}

View File

@ -61,7 +61,7 @@ public class ErekirTechTree{
costMultipliers.put(Items.graphite, 9);
//oxide is hard to make
costMultipliers.put(Items.oxide, 0.5f);
costMultipliers.put(Items.carbide, 0.6f);
costMultipliers.put(Items.carbide, 0.4f);
//TODO remove
Objective tmpNever = new Research(Items.fissileMatter);

View File

@ -2666,7 +2666,7 @@ public class UnitTypes{
heatColor = Color.valueOf("f9350f");
cooldownTime = 80f;
bullet = new BasicBulletType(8f, 150){{
bullet = new BasicBulletType(8f, 160){{
sprite = "missile-large";
width = 9.5f;
height = 13f;
@ -3254,7 +3254,7 @@ public class UnitTypes{
drag = 0.1f;
speed = 0.6f;
hitSize = 23f;
health = 7000;
health = 6700;
armor = 5f;
lockLegBase = true;
@ -3315,7 +3315,7 @@ public class UnitTypes{
velocityRnd = 0.33f;
heatColor = Color.red;
bullet = new MissileBulletType(4.2f, 50){{
bullet = new MissileBulletType(4.2f, 47){{
homingPower = 0.2f;
weaveMag = 4;
weaveScale = 4;
@ -3839,7 +3839,7 @@ public class UnitTypes{
rotateSpeed = 2f;
accel = 0.1f;
health = 12000f;
armor = 7f;
armor = 9f;
hitSize = 46f;
payloadCapacity = Mathf.sqr(6f) * tilePayload;

View File

@ -77,7 +77,6 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
rotateMove(movement);
}
}
public void moveAt(Vec2 vector){
moveAt(vector, type.accel);
}
@ -85,7 +84,6 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
public void approach(Vec2 vector){
vel.approachDelta(vector, type.accel * speed());
}
public void rotateMove(Vec2 vec){
moveAt(Tmp.v2.trns(rotation, vec.len()));
@ -104,6 +102,11 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
lookAt(x, y);
}
public boolean isPathImpassable(int tileX, int tileY){
return !type.flying && type.pathCost.getCost(team.id, pathfinder.get(tileX, tileY)) == -1;
}
/** @return approx. square size of the physical hitbox for physics */
public float physicSize(){
return hitSize * 0.7f;

View File

@ -25,4 +25,4 @@ org.gradle.caching=true
#used for slow jitpack builds; TODO see if this actually works
org.gradle.internal.http.socketTimeout=100000
org.gradle.internal.http.connectionTimeout=100000
archash=8793e01874
archash=5a1cbb8b59