166 lines
4.4 KiB
Java
166 lines
4.4 KiB
Java
package mindustry.entities.units;
|
|
|
|
import arc.math.*;
|
|
import arc.math.geom.*;
|
|
import arc.util.*;
|
|
import mindustry.entities.*;
|
|
import mindustry.gen.*;
|
|
import mindustry.type.*;
|
|
import mindustry.world.*;
|
|
import mindustry.world.meta.*;
|
|
|
|
import static mindustry.Vars.*;
|
|
|
|
public class AIController implements UnitController{
|
|
protected static final Vec2 vec = new Vec2();
|
|
protected static final int timerTarget = 0;
|
|
|
|
protected Unit unit;
|
|
protected Interval timer = new Interval(4);
|
|
|
|
/** main target that is being faced */
|
|
protected Teamc target;
|
|
/** targets for each weapon */
|
|
protected Teamc[] targets = {};
|
|
|
|
{
|
|
timer.reset(0, Mathf.random(40f));
|
|
}
|
|
|
|
@Override
|
|
public void updateUnit(){
|
|
updateTargeting();
|
|
updateMovement();
|
|
}
|
|
|
|
protected void updateMovement(){
|
|
|
|
}
|
|
|
|
protected void updateTargeting(){
|
|
if(unit.hasWeapons()){
|
|
|
|
updateWeapons();
|
|
}
|
|
}
|
|
|
|
protected void updateWeapons(){
|
|
if(targets.length != unit.mounts.length) targets = new Teamc[unit.mounts.length];
|
|
|
|
float rotation = unit.rotation - 90;
|
|
boolean ret = retarget();
|
|
|
|
if(ret){
|
|
target = findTarget(unit.x, unit.y, unit.range(), unit.type().targetAir, unit.type().targetGround);
|
|
}
|
|
|
|
if(Units.invalidateTarget(target, unit.team, unit.x, unit.y)){
|
|
target = null;
|
|
}
|
|
|
|
for(int i = 0; i < targets.length; i++){
|
|
WeaponMount mount = unit.mounts[i];
|
|
Weapon weapon = mount.weapon;
|
|
|
|
float mountX = unit.x + Angles.trnsx(rotation, weapon.x, weapon.y),
|
|
mountY = unit.y + Angles.trnsy(rotation, weapon.x, weapon.y);
|
|
|
|
if(unit.type().singleTarget){
|
|
targets[i] = target;
|
|
}else{
|
|
if(ret){
|
|
targets[i] = findTarget(mountX, mountY, weapon.bullet.range(), weapon.bullet.collidesAir, weapon.bullet.collidesGround);
|
|
}
|
|
|
|
if(Units.invalidateTarget(targets[i], unit.team, mountX, mountY, weapon.bullet.range())){
|
|
targets[i] = null;
|
|
}
|
|
}
|
|
|
|
boolean shoot = false;
|
|
|
|
if(targets[i] != null){
|
|
shoot = targets[i].within(mountX, mountY, weapon.bullet.range());
|
|
|
|
if(shoot){
|
|
Vec2 to = Predict.intercept(unit, targets[i], weapon.bullet.speed);
|
|
mount.aimX = to.x;
|
|
mount.aimY = to.y;
|
|
}
|
|
}
|
|
|
|
mount.shoot = shoot;
|
|
mount.rotate = shoot;
|
|
}
|
|
}
|
|
|
|
protected Teamc targetFlag(float x, float y, BlockFlag flag, boolean enemy){
|
|
Tile target = Geometry.findClosest(x, y, enemy ? indexer.getEnemy(unit.team, flag) : indexer.getAllied(unit.team, flag));
|
|
return target == null ? null : target.build;
|
|
}
|
|
|
|
protected Teamc target(float x, float y, float range, boolean air, boolean ground){
|
|
return Units.closestTarget(unit.team, x, y, range, u -> u.checkTarget(air, ground), t -> ground);
|
|
}
|
|
|
|
protected boolean retarget(){
|
|
return timer.get(timerTarget, 30);
|
|
}
|
|
|
|
protected Teamc findTarget(float x, float y, float range, boolean air, boolean ground){
|
|
return target(x, y, range, air, ground);
|
|
}
|
|
|
|
protected void init(){
|
|
|
|
}
|
|
|
|
protected void circle(Position target, float circleLength){
|
|
circle(target, circleLength, unit.type().speed);
|
|
}
|
|
|
|
protected void circle(Position target, float circleLength, float speed){
|
|
if(target == null) return;
|
|
|
|
vec.set(target).sub(unit);
|
|
|
|
if(vec.len() < circleLength){
|
|
vec.rotate((circleLength - vec.len()) / circleLength * 180f);
|
|
}
|
|
|
|
vec.setLength(speed * Time.delta);
|
|
|
|
unit.moveAt(vec);
|
|
}
|
|
|
|
protected void moveTo(Position target, float circleLength){
|
|
if(target == null) return;
|
|
|
|
vec.set(target).sub(unit);
|
|
|
|
float length = circleLength <= 0.001f ? 1f : Mathf.clamp((unit.dst(target) - circleLength) / 100f, -1f, 1f);
|
|
|
|
vec.setLength(unit.type().speed * Time.delta * length);
|
|
if(length < -0.5f){
|
|
vec.rotate(180f);
|
|
}else if(length < 0){
|
|
vec.setZero();
|
|
}
|
|
|
|
unit.moveAt(vec);
|
|
}
|
|
|
|
@Override
|
|
public void unit(Unit unit){
|
|
if(this.unit == unit) return;
|
|
|
|
this.unit = unit;
|
|
init();
|
|
}
|
|
|
|
@Override
|
|
public Unit unit(){
|
|
return unit;
|
|
}
|
|
}
|