Further targeting improvements for AI
This commit is contained in:
@@ -46,6 +46,9 @@ public interface BlockBuilder {
|
||||
/**Sets the tile this builder is currently mining.*/
|
||||
void setMineTile(Tile tile);
|
||||
|
||||
/**Build power, can be any float. 1 = builds recipes in normal time, 0 = doesn't build at all.*/
|
||||
float getBuildPower(Tile tile);
|
||||
|
||||
/**Return whether this builder's place queue contains items.*/
|
||||
default boolean isBuilding(){
|
||||
return getPlaceQueue().size != 0;
|
||||
|
||||
@@ -77,6 +77,12 @@ public class Player extends Unit implements BlockBuilder {
|
||||
|
||||
//region unit and event overrides, utility methods
|
||||
|
||||
|
||||
@Override
|
||||
public float getBuildPower(Tile tile) {
|
||||
return 1f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMaxHealth() {
|
||||
return 200;
|
||||
@@ -507,6 +513,8 @@ public class Player extends Unit implements BlockBuilder {
|
||||
inventory.clear();
|
||||
upgrades.clear();
|
||||
placeQueue.clear();
|
||||
dead = true;
|
||||
respawning = false;
|
||||
|
||||
add();
|
||||
heal();
|
||||
|
||||
@@ -14,6 +14,7 @@ public class UnitInventory {
|
||||
private Array<AmmoEntry> ammos = new Array<>();
|
||||
private int totalAmmo;
|
||||
private ItemStack item;
|
||||
//TODO move these somewhere else so they're not variables?
|
||||
private int capacity, ammoCapacity;
|
||||
private boolean infiniteAmmo;
|
||||
|
||||
@@ -22,6 +23,10 @@ public class UnitInventory {
|
||||
this.ammoCapacity = ammoCapacity;
|
||||
}
|
||||
|
||||
public boolean isFull(){
|
||||
return item != null && item.amount >= capacity;
|
||||
}
|
||||
|
||||
public boolean isInfiniteAmmo() {
|
||||
return infiniteAmmo;
|
||||
}
|
||||
|
||||
@@ -29,11 +29,7 @@ public class Units {
|
||||
* @return whether the target is invalid
|
||||
*/
|
||||
public static boolean invalidateTarget(Targetable target, Team team, float x, float y, float range) {
|
||||
if (target == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (!(range != Float.MAX_VALUE) || !(target.distanceTo(x, y) > range)) && (target.getTeam() == team || !target.isValid());
|
||||
return target == null || (range != Float.MAX_VALUE && target.distanceTo(x, y) > range) || target.getTeam() == team || !target.isValid();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import io.anuke.mindustry.content.fx.ExplosionFx;
|
||||
import io.anuke.mindustry.entities.Targetable;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.entities.Unit;
|
||||
import io.anuke.mindustry.entities.Units;
|
||||
import io.anuke.mindustry.entities.bullet.Bullet;
|
||||
import io.anuke.mindustry.entities.bullet.BulletType;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
@@ -95,10 +96,25 @@ public abstract class BaseUnit extends Unit{
|
||||
}
|
||||
|
||||
public void targetClosestAllyFlag(BlockFlag flag){
|
||||
if(target != null) return;
|
||||
|
||||
Tile target = Geometry.findClosest(x, y, world.indexer().getAllied(team, flag));
|
||||
if (target != null) this.target = target.entity;
|
||||
}
|
||||
|
||||
public void targetClosestEnemyFlag(BlockFlag flag){
|
||||
if(target != null) return;
|
||||
|
||||
Tile target = Geometry.findClosest(x, y, world.indexer().getEnemy(team, flag));
|
||||
if (target != null) this.target = target.entity;
|
||||
}
|
||||
|
||||
public void targetClosest(){
|
||||
if(target != null) return;
|
||||
|
||||
target = Units.getClosestTarget(team, x, y, inventory.getAmmoRange());
|
||||
}
|
||||
|
||||
public UnitState getStartState(){
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package io.anuke.mindustry.entities.units;
|
||||
|
||||
import io.anuke.mindustry.entities.Unit;
|
||||
import io.anuke.mindustry.entities.Units;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.graphics.Palette;
|
||||
@@ -48,7 +47,7 @@ public class FlyingUnit extends BaseUnit {
|
||||
|
||||
@Override
|
||||
public void drawOver() {
|
||||
trail.draw(Palette.lighterOrange, Palette.lightishOrange, 5f);
|
||||
trail.draw(Palette.lightFlame, Palette.lightOrange, 5f);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -65,6 +64,11 @@ public class FlyingUnit extends BaseUnit {
|
||||
return attack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float drawSize() {
|
||||
return 60;
|
||||
}
|
||||
|
||||
protected void circle(float circleLength){
|
||||
vec.set(target.getX() - x, target.getY() - y);
|
||||
|
||||
@@ -111,6 +115,24 @@ public class FlyingUnit extends BaseUnit {
|
||||
}
|
||||
}
|
||||
},
|
||||
idle = new UnitState() {
|
||||
public void update() {
|
||||
retarget(() -> {
|
||||
targetClosest();
|
||||
targetClosestEnemyFlag(BlockFlag.target);
|
||||
|
||||
if(target != null){
|
||||
setState(attack);
|
||||
}
|
||||
});
|
||||
|
||||
target = getClosestCore();
|
||||
if(target != null){
|
||||
circle(50f);
|
||||
}
|
||||
velocity.scl(0.8f);
|
||||
}
|
||||
},
|
||||
attack = new UnitState(){
|
||||
public void entered() {
|
||||
target = null;
|
||||
@@ -124,16 +146,15 @@ public class FlyingUnit extends BaseUnit {
|
||||
if(!inventory.hasAmmo()) {
|
||||
state.set(resupply);
|
||||
}else if (target == null){
|
||||
if(timer.get(timerTarget, 20)) {
|
||||
Unit closest = Units.getClosestEnemy(team, x, y,
|
||||
inventory.getAmmo().getRange(), other -> distanceTo(other) < 60f);
|
||||
if(closest != null){
|
||||
target = closest;
|
||||
}else {
|
||||
Tile target = Geometry.findClosest(x, y, world.indexer().getEnemy(team, BlockFlag.target));
|
||||
if (target != null) FlyingUnit.this.target = target.entity;
|
||||
retarget(() -> {
|
||||
targetClosest();
|
||||
targetClosestEnemyFlag(BlockFlag.target);
|
||||
targetClosestEnemyFlag(BlockFlag.producer);
|
||||
|
||||
if(target == null){
|
||||
setState(idle);
|
||||
}
|
||||
}
|
||||
});
|
||||
}else{
|
||||
attack(150f);
|
||||
|
||||
@@ -153,7 +174,7 @@ public class FlyingUnit extends BaseUnit {
|
||||
}
|
||||
|
||||
public void update() {
|
||||
if(health >= health){
|
||||
if(health >= getMaxHealth()){
|
||||
state.set(attack);
|
||||
}else if(!targetHasFlag(BlockFlag.repair)){
|
||||
retarget(() -> {
|
||||
|
||||
+11
-21
@@ -2,7 +2,6 @@ package io.anuke.mindustry.entities.units;
|
||||
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import io.anuke.mindustry.Vars;
|
||||
import io.anuke.mindustry.entities.Unit;
|
||||
import io.anuke.mindustry.entities.Units;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.type.AmmoType;
|
||||
@@ -12,20 +11,17 @@ import io.anuke.mindustry.world.blocks.types.Floor;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
import io.anuke.ucore.graphics.Hue;
|
||||
import io.anuke.ucore.util.Angles;
|
||||
import io.anuke.ucore.util.Geometry;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
import io.anuke.ucore.util.Translator;
|
||||
import io.anuke.ucore.util.*;
|
||||
|
||||
import static io.anuke.mindustry.Vars.world;
|
||||
|
||||
public abstract class GroundUnitType extends BaseUnit {
|
||||
public abstract class GroundUnit extends BaseUnit {
|
||||
protected static Translator vec = new Translator();
|
||||
protected static float maxAim = 30f;
|
||||
|
||||
protected float walkTime;
|
||||
|
||||
public GroundUnitType(UnitType type, Team team) {
|
||||
public GroundUnit(UnitType type, Team team) {
|
||||
super(type, team);
|
||||
}
|
||||
|
||||
@@ -38,9 +34,8 @@ public abstract class GroundUnitType extends BaseUnit {
|
||||
public void update() {
|
||||
super.update();
|
||||
|
||||
if(!velocity.isZero(0.0001f) && (target == null
|
||||
|| (inventory.hasAmmo() && distanceTo(target) > inventory.getAmmo().getRange()))){
|
||||
rotation = velocity.angle();
|
||||
if(target == null){
|
||||
rotation = Mathf.lerpDelta(rotation, velocity.angle(), 0.2f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,7 +84,8 @@ public abstract class GroundUnitType extends BaseUnit {
|
||||
public void updateTargeting() {
|
||||
super.updateTargeting();
|
||||
|
||||
if(Units.invalidateTarget(target, this)){
|
||||
if(Units.invalidateTarget(target, team, x, y, Float.MAX_VALUE)){
|
||||
if(target != null) Log.info("Invalidating target {0}", target);
|
||||
target = null;
|
||||
}
|
||||
}
|
||||
@@ -146,19 +142,11 @@ public abstract class GroundUnitType extends BaseUnit {
|
||||
}
|
||||
|
||||
public void update() {
|
||||
retarget(() -> {
|
||||
Unit closest = Units.getClosestEnemy(team, x, y, inventory.getAmmo().getRange(), other -> true);
|
||||
if(closest != null){
|
||||
target = closest;
|
||||
}else {
|
||||
Tile target = Geometry.findClosest(x, y, world.indexer().getEnemy(team, BlockFlag.target));
|
||||
if (target != null) GroundUnitType.this.target = target.entity;
|
||||
}
|
||||
});
|
||||
retarget(() -> targetClosest());
|
||||
|
||||
if(!inventory.hasAmmo()) {
|
||||
state.set(resupply);
|
||||
}else{
|
||||
}else if(target != null){
|
||||
if(distanceTo(target) > inventory.getAmmo().getRange() * 0.7f){
|
||||
moveToCore();
|
||||
}else{
|
||||
@@ -173,6 +161,8 @@ public abstract class GroundUnitType extends BaseUnit {
|
||||
|
||||
shoot(ammo, Angles.moveToward(rotation, angleTo(target), maxAim), 4f);
|
||||
}
|
||||
}else{
|
||||
moveToCore();
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2,6 +2,7 @@ package io.anuke.mindustry.entities.units.types;
|
||||
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.utils.Queue;
|
||||
import io.anuke.mindustry.content.Items;
|
||||
import io.anuke.mindustry.entities.BlockBuilder;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.entities.Units;
|
||||
@@ -36,6 +37,8 @@ public class Drone extends FlyingUnit implements BlockBuilder{
|
||||
protected Tile mineTile;
|
||||
protected Queue<BuildRequest> placeQueue = new Queue<>();
|
||||
|
||||
/**Initialize placement event notifier system.
|
||||
* Static initialization is to be avoided, thus, this is done lazily.*/
|
||||
private static void initEvents(){
|
||||
Events.on(BlockBuildEvent.class, (team, tile) -> {
|
||||
EntityGroup<BaseUnit> group = unitGroups[team.ordinal()];
|
||||
@@ -70,6 +73,11 @@ public class Drone extends FlyingUnit implements BlockBuilder{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getBuildPower(Tile tile) {
|
||||
return 0.3f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Queue<BuildRequest> getPlaceQueue() {
|
||||
return placeQueue;
|
||||
@@ -176,6 +184,10 @@ public class Drone extends FlyingUnit implements BlockBuilder{
|
||||
retarget(() -> {
|
||||
target = Units.findAllyTile(team, x, y, discoverRange,
|
||||
tile -> tile.entity != null && tile.entity.health + 0.0001f < tile.block().health);
|
||||
|
||||
if(target == null){
|
||||
setState(mine);
|
||||
}
|
||||
});
|
||||
}else if(target.distanceTo(Drone.this) > type.range){
|
||||
circle(type.range);
|
||||
@@ -186,6 +198,22 @@ public class Drone extends FlyingUnit implements BlockBuilder{
|
||||
}
|
||||
}
|
||||
},
|
||||
mine = new UnitState() {
|
||||
public void update() {
|
||||
//if inventory is full, drop it off.
|
||||
if(inventory.isFull()){
|
||||
setState(drop);
|
||||
}else{
|
||||
//only mines iron for now
|
||||
retarget(() -> target = Geometry.findClosest(x, y, world.indexer().getOrePositions(Items.iron)));
|
||||
}
|
||||
}
|
||||
},
|
||||
drop = new UnitState() {
|
||||
public void update() {
|
||||
|
||||
}
|
||||
},
|
||||
retreat = new UnitState() {
|
||||
public void entered() {
|
||||
target = null;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package io.anuke.mindustry.entities.units.types;
|
||||
|
||||
import io.anuke.mindustry.entities.units.GroundUnitType;
|
||||
import io.anuke.mindustry.entities.units.GroundUnit;
|
||||
import io.anuke.mindustry.entities.units.UnitType;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
|
||||
public class Scout extends GroundUnitType {
|
||||
public class Scout extends GroundUnit {
|
||||
|
||||
public Scout(UnitType type, Team team) {
|
||||
super(type, team);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package io.anuke.mindustry.entities.units.types;
|
||||
|
||||
import io.anuke.mindustry.content.fx.UnitFx;
|
||||
import io.anuke.mindustry.entities.units.FlyingUnit;
|
||||
import io.anuke.mindustry.entities.units.UnitType;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
@@ -54,10 +53,6 @@ public class Vtol extends FlyingUnit {
|
||||
if(velocity.len() <= 0.2f){
|
||||
rotation += Mathf.sin(Timers.time() + id * 99, 10f, 8f);
|
||||
}
|
||||
|
||||
if(timer.get(timerBoost, 2)){
|
||||
effectAt(UnitFx.vtolHover, rotation + 180f, 4f, 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user