Networked unit control / Mimic AI prototype
This commit is contained in:
31
core/src/mindustry/ai/types/MimicAI.java
Normal file
31
core/src/mindustry/ai/types/MimicAI.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package mindustry.ai.types;
|
||||
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import arc.util.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.gen.*;
|
||||
|
||||
public class MimicAI extends AIController{
|
||||
public @Nullable Unitc control;
|
||||
|
||||
public MimicAI(@Nullable Unitc control){
|
||||
this.control = control;
|
||||
}
|
||||
|
||||
public MimicAI(){
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
if(control != null){
|
||||
unit.controlWeapons(control.isRotate(), control.isShooting());
|
||||
//TODO this isn't accurate
|
||||
unit.moveAt(Tmp.v1.set(control.vel()).limit(unit.type().speed));
|
||||
if(control.isShooting()){
|
||||
unit.aimLook(control.aimX(), control.aimY());
|
||||
}else{
|
||||
unit.lookAt(unit.vel().angle());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,8 @@ import static mindustry.Vars.net;
|
||||
|
||||
@Component
|
||||
abstract class FlyingComp implements Posc, Velc, Healthc, Hitboxc{
|
||||
private static final Vec2 tmp1 = new Vec2(), tmp2 = new Vec2();
|
||||
|
||||
@Import float x, y, drag;
|
||||
@Import Vec2 vel;
|
||||
|
||||
@@ -37,9 +39,9 @@ abstract class FlyingComp implements Posc, Velc, Healthc, Hitboxc{
|
||||
}
|
||||
|
||||
void moveAt(Vec2 vector, float acceleration){
|
||||
Vec2 t = Tmp.v3.set(vector).scl(floorSpeedMultiplier()); //target vector
|
||||
Tmp.v1.set(t).sub(vel).limit(acceleration * vector.len()); //delta vector
|
||||
vel.add(Tmp.v1);
|
||||
Vec2 t = tmp1.set(vector).scl(floorSpeedMultiplier()); //target vector
|
||||
tmp2.set(t).sub(vel).limit(acceleration * vector.len()); //delta vector
|
||||
vel.add(tmp2);
|
||||
}
|
||||
|
||||
float floorSpeedMultiplier(){
|
||||
|
||||
@@ -956,6 +956,7 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc{
|
||||
Events.fire(new BlockDestroyEvent(tile));
|
||||
block.breakSound.at(tile);
|
||||
onDestroyed();
|
||||
tile.remove();
|
||||
remove();
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,11 @@ abstract class UnitComp implements Healthc, Velc, Statusc, Teamc, Itemsc, Hitbox
|
||||
lookAt(pos);
|
||||
}
|
||||
|
||||
public void aimLook(float x, float y){
|
||||
aim(x, y);
|
||||
lookAt(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float clipSize(){
|
||||
return type.region.getWidth() * 2f;
|
||||
@@ -109,6 +114,14 @@ abstract class UnitComp implements Healthc, Velc, Statusc, Teamc, Itemsc, Hitbox
|
||||
lookAt(angleTo(pos));
|
||||
}
|
||||
|
||||
public void lookAt(float x, float y){
|
||||
lookAt(angleTo(x, y));
|
||||
}
|
||||
|
||||
public boolean isAI(){
|
||||
return controller instanceof AIController;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterRead(){
|
||||
//set up type info after reading
|
||||
|
||||
@@ -21,7 +21,8 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc{
|
||||
|
||||
/** weapon mount array, never null */
|
||||
@ReadOnly WeaponMount[] mounts = {};
|
||||
@ReadOnly float range;
|
||||
@ReadOnly transient float range, aimX, aimY;
|
||||
@ReadOnly transient boolean isRotate, isShooting;
|
||||
|
||||
boolean inRange(Position other){
|
||||
return within(other, range);
|
||||
@@ -41,6 +42,8 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc{
|
||||
mount.rotate = rotate;
|
||||
mount.shoot = shoot;
|
||||
}
|
||||
isRotate = rotate;
|
||||
isShooting = shoot;
|
||||
}
|
||||
|
||||
void aim(Position pos){
|
||||
@@ -59,6 +62,9 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc{
|
||||
mount.aimX = x;
|
||||
mount.aimY = y;
|
||||
}
|
||||
|
||||
aimX = x;
|
||||
aimY = y;
|
||||
}
|
||||
|
||||
/** Update shooting and rotation for this unit. */
|
||||
|
||||
@@ -4,6 +4,7 @@ import arc.*;
|
||||
import arc.Graphics.*;
|
||||
import arc.Graphics.Cursor.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.input.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.scene.*;
|
||||
@@ -13,6 +14,8 @@ import arc.scene.ui.layout.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import arc.util.*;
|
||||
import mindustry.*;
|
||||
import mindustry.ai.types.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.game.EventType.*;
|
||||
@@ -170,15 +173,25 @@ public class DesktopInput extends InputHandler{
|
||||
Core.camera.position.lerpDelta(player, 0.08f);
|
||||
}
|
||||
|
||||
//TODO remove: debug unit possession
|
||||
if(Core.input.keyTap(Binding.select)){
|
||||
Unitc unit = Units.closest(state.rules.defaultTeam, Core.input.mouseWorld().x, Core.input.mouseWorld().y, 40f, u -> true);
|
||||
if(unit != null){
|
||||
unit.hitbox(Tmp.r1);
|
||||
if(Tmp.r1.contains(Core.input.mouseWorld())){
|
||||
player.unit(unit);
|
||||
if(!scene.hasMouse()){
|
||||
if(Core.input.keyTap(Binding.select)){
|
||||
Unitc unit = Units.closest(player.team(), Core.input.mouseWorld().x, Core.input.mouseWorld().y, 40f, u -> true);
|
||||
if(unit != null){
|
||||
unit.hitbox(Tmp.r1);
|
||||
if(Tmp.r1.contains(Core.input.mouseWorld())){
|
||||
Call.onUnitControl(player, unit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(Core.input.keyTap(KeyCode.Q) && !player.dead()){
|
||||
Fx.commandSend.at(player);
|
||||
Units.nearby(player.team(), player.x(), player.y(), 200f, u -> {
|
||||
if(u.isAI()){
|
||||
u.controller(new MimicAI(player.unit()));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if(!player.dead() && !state.isPaused() && !(Core.scene.getKeyboardFocus() instanceof TextField)){
|
||||
|
||||
@@ -168,6 +168,16 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
Core.app.post(() -> Events.fire(new TapConfigEvent(tile, player, value)));
|
||||
}
|
||||
|
||||
@Remote(targets = Loc.both, called = Loc.server, forward = true)
|
||||
public static void onUnitControl(Playerc player, @Nullable Unitc unit){
|
||||
if(unit == null){
|
||||
player.clearUnit();
|
||||
//make sure it's AI controlled, so players can't overwrite each other
|
||||
}else if(unit.isAI() && unit.team() == player.team()){
|
||||
player.unit(unit);
|
||||
}
|
||||
}
|
||||
|
||||
public Eachable<BuildRequest> allRequests(){
|
||||
return cons -> {
|
||||
for(BuildRequest request : player.builder().requests()) cons.get(request);
|
||||
|
||||
Reference in New Issue
Block a user