mirror of
https://github.com/Anuken/Mindustry.git
synced 2025-02-22 04:28:27 +07:00
Splitting of building+mining into separate traits
This commit is contained in:
parent
dc3c27297f
commit
0aee75c1c1
@ -113,9 +113,11 @@ android{
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes{
|
||||
release{
|
||||
signingConfig signingConfigs.release
|
||||
if(project.hasProperty("RELEASE_STORE_FILE")) {
|
||||
buildTypes {
|
||||
release {
|
||||
signingConfig signingConfigs.release
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -113,6 +113,8 @@ allprojects{
|
||||
maven{ url 'https://jitpack.io' }
|
||||
jcenter()
|
||||
}
|
||||
|
||||
tasks.withType(Javadoc).all{ enabled = false }
|
||||
}
|
||||
|
||||
project(":desktop"){
|
||||
@ -175,7 +177,7 @@ project(":core"){
|
||||
}
|
||||
|
||||
dependencies{
|
||||
if(System.properties["user.name"] == "anuke"){
|
||||
if(System.properties["user.name"] == "anuke" && !System.properties["os.name"].contains("Mac")){
|
||||
task cleanGen{
|
||||
doFirst{
|
||||
delete{
|
||||
|
@ -0,0 +1,22 @@
|
||||
package io.anuke.mindustry.entities.traits;
|
||||
|
||||
/** A class for gracefully merging mining and building traits.*/
|
||||
public interface BuilderMinerTrait extends MinerTrait, BuilderTrait{
|
||||
|
||||
default void updateMechanics(){
|
||||
updateBuilding();
|
||||
|
||||
//mine only when not building
|
||||
if(getCurrentRequest() == null){
|
||||
updateMining();
|
||||
}
|
||||
}
|
||||
|
||||
default void drawMechanics(){
|
||||
if(isBuilding()){
|
||||
drawBuilding();
|
||||
}else{
|
||||
drawMining();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,26 +1,18 @@
|
||||
package io.anuke.mindustry.entities.traits;
|
||||
|
||||
import io.anuke.arc.Core;
|
||||
import io.anuke.arc.Events;
|
||||
import io.anuke.arc.collection.Array;
|
||||
import io.anuke.arc.collection.Queue;
|
||||
import io.anuke.arc.graphics.Color;
|
||||
import io.anuke.arc.*;
|
||||
import io.anuke.arc.collection.*;
|
||||
import io.anuke.arc.graphics.g2d.*;
|
||||
import io.anuke.arc.math.Angles;
|
||||
import io.anuke.arc.math.Mathf;
|
||||
import io.anuke.arc.math.*;
|
||||
import io.anuke.arc.math.geom.Vector2;
|
||||
import io.anuke.arc.util.Time;
|
||||
import io.anuke.mindustry.Vars;
|
||||
import io.anuke.mindustry.content.Blocks;
|
||||
import io.anuke.mindustry.content.Fx;
|
||||
import io.anuke.mindustry.entities.Effects;
|
||||
import io.anuke.mindustry.entities.type.*;
|
||||
import io.anuke.mindustry.game.EventType.BuildSelectEvent;
|
||||
import io.anuke.mindustry.gen.Call;
|
||||
import io.anuke.mindustry.graphics.Pal;
|
||||
import io.anuke.mindustry.graphics.Shapes;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.world.*;
|
||||
import io.anuke.mindustry.world.blocks.BuildBlock;
|
||||
import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity;
|
||||
@ -29,21 +21,15 @@ import java.io.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
import static io.anuke.mindustry.entities.traits.BuilderTrait.BuildDataStatic.removal;
|
||||
import static io.anuke.mindustry.entities.traits.BuilderTrait.BuildDataStatic.tmptr;
|
||||
import static io.anuke.mindustry.entities.traits.BuilderTrait.BuildDataStatic.*;
|
||||
|
||||
/**
|
||||
* Interface for units that build, break or mine things.
|
||||
*/
|
||||
/** Interface for units that build things.*/
|
||||
public interface BuilderTrait extends Entity, TeamTrait{
|
||||
//these are not instance variables!
|
||||
float placeDistance = 220f;
|
||||
float mineDistance = 70f;
|
||||
|
||||
/**
|
||||
* Update building mechanism for this unit.
|
||||
* This includes mining.
|
||||
*/
|
||||
/** Updates building mechanism for this unit.*/
|
||||
default void updateBuilding(){
|
||||
float finalPlaceDst = state.rules.infiniteResources ? Float.MAX_VALUE : placeDistance;
|
||||
Unit unit = (Unit)this;
|
||||
@ -65,14 +51,8 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
||||
|
||||
BuildRequest current = getCurrentRequest();
|
||||
|
||||
//update mining here
|
||||
if(current == null){
|
||||
if(getMineTile() != null){
|
||||
updateMining();
|
||||
}
|
||||
return;
|
||||
}else{
|
||||
setMineTile(null);
|
||||
}
|
||||
|
||||
Tile tile = world.tile(current.x, current.y);
|
||||
@ -137,21 +117,9 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
||||
/** Returns the queue for storing build requests. */
|
||||
Queue<BuildRequest> getPlaceQueue();
|
||||
|
||||
/** Returns the tile this builder is currently mining. */
|
||||
Tile getMineTile();
|
||||
|
||||
/** Sets the tile this builder is currently mining. */
|
||||
void setMineTile(Tile tile);
|
||||
|
||||
/** Returns the minining speed of this miner. 1 = standard, 0.5 = half speed, 2 = double speed, etc. */
|
||||
float getMinePower();
|
||||
|
||||
/** Build power, can be any float. 1 = builds recipes in normal time, 0 = doesn't build at all. */
|
||||
float getBuildPower(Tile tile);
|
||||
|
||||
/** Returns whether or not this builder can mine a specific item type. */
|
||||
boolean canMine(Item item);
|
||||
|
||||
/** Whether this type of builder can begin creating new blocks. */
|
||||
default boolean canCreateBlocks(){
|
||||
return true;
|
||||
@ -236,60 +204,18 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
||||
return getPlaceQueue().size == 0 ? null : getPlaceQueue().first();
|
||||
}
|
||||
|
||||
//due to iOS wierdness, this is apparently required
|
||||
//due to iOS weirdness, this is apparently required
|
||||
class BuildDataStatic{
|
||||
static Array<BuildRequest> removal = new Array<>();
|
||||
static Vector2[] tmptr = new Vector2[]{new Vector2(), new Vector2(), new Vector2(), new Vector2()};
|
||||
}
|
||||
|
||||
/** Do not call directly. */
|
||||
default void updateMining(){
|
||||
Unit unit = (Unit)this;
|
||||
Tile tile = getMineTile();
|
||||
TileEntity core = unit.getClosestCore();
|
||||
|
||||
if(core == null || tile.block() != Blocks.air || dst(tile.worldx(), tile.worldy()) > mineDistance
|
||||
|| tile.drop() == null || !unit.acceptsItem(tile.drop()) || !canMine(tile.drop())){
|
||||
setMineTile(null);
|
||||
}else{
|
||||
Item item = tile.drop();
|
||||
unit.rotation = Mathf.slerpDelta(unit.rotation, unit.angleTo(tile.worldx(), tile.worldy()), 0.4f);
|
||||
|
||||
if(Mathf.chance(Time.delta() * (0.06 - item.hardness * 0.01) * getMinePower())){
|
||||
|
||||
if(unit.dst(core) < mineTransferRange && core.tile.block().acceptStack(item, 1, core.tile, unit) == 1){
|
||||
Call.transferItemTo(item, 1,
|
||||
tile.worldx() + Mathf.range(tilesize / 2f),
|
||||
tile.worldy() + Mathf.range(tilesize / 2f), core.tile);
|
||||
}else if(unit.acceptsItem(item)){
|
||||
Call.transferItemToUnit(item,
|
||||
tile.worldx() + Mathf.range(tilesize / 2f),
|
||||
tile.worldy() + Mathf.range(tilesize / 2f),
|
||||
unit);
|
||||
}
|
||||
}
|
||||
|
||||
if(Mathf.chance(0.06 * Time.delta())){
|
||||
Effects.effect(Fx.pulverizeSmall,
|
||||
tile.worldx() + Mathf.range(tilesize / 2f),
|
||||
tile.worldy() + Mathf.range(tilesize / 2f), 0f, item.color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Draw placement effects for an entity. This includes mining */
|
||||
/** Draw placement effects for an entity. */
|
||||
default void drawBuilding(){
|
||||
if(!isBuilding()) return;
|
||||
|
||||
Unit unit = (Unit)this;
|
||||
BuildRequest request;
|
||||
if(!isBuilding()){
|
||||
if(getMineTile() != null){
|
||||
drawMining();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
request = getCurrentRequest();
|
||||
|
||||
BuildRequest request = getCurrentRequest();
|
||||
Tile tile = world.tile(request.x, request.y);
|
||||
|
||||
if(dst(tile) > placeDistance && !state.isEditor()){
|
||||
@ -310,10 +236,10 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
||||
tmptr[3].set(tile.drawx() + sz, tile.drawy() + sz);
|
||||
|
||||
Arrays.sort(tmptr, (a, b) -> -Float.compare(Angles.angleDist(Angles.angle(unit.x, unit.y, a.x, a.y), ang),
|
||||
Angles.angleDist(Angles.angle(unit.x, unit.y, b.x, b.y), ang)));
|
||||
Angles.angleDist(Angles.angle(unit.x, unit.y, b.x, b.y), ang)));
|
||||
|
||||
float x1 = tmptr[0].x, y1 = tmptr[0].y,
|
||||
x3 = tmptr[1].x, y3 = tmptr[1].y;
|
||||
x3 = tmptr[1].x, y3 = tmptr[1].y;
|
||||
|
||||
Draw.alpha(1f);
|
||||
|
||||
@ -325,35 +251,6 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
/** Internal use only. */
|
||||
default void drawMining(){
|
||||
Unit unit = (Unit)this;
|
||||
Tile tile = getMineTile();
|
||||
|
||||
if(tile == null) return;
|
||||
|
||||
float focusLen = 4f + Mathf.absin(Time.time(), 1.1f, 0.5f);
|
||||
float swingScl = 12f, swingMag = tilesize / 8f;
|
||||
float flashScl = 0.3f;
|
||||
|
||||
float px = unit.x + Angles.trnsx(unit.rotation, focusLen);
|
||||
float py = unit.y + Angles.trnsy(unit.rotation, focusLen);
|
||||
|
||||
float ex = tile.worldx() + Mathf.sin(Time.time() + 48, swingScl, swingMag);
|
||||
float ey = tile.worldy() + Mathf.sin(Time.time() + 48, swingScl + 2f, swingMag);
|
||||
|
||||
Draw.color(Color.LIGHT_GRAY, Color.WHITE, 1f - flashScl + Mathf.absin(Time.time(), 0.5f, flashScl));
|
||||
|
||||
Shapes.laser("minelaser", "minelaser-end", px, py, ex, ey, 0.75f);
|
||||
|
||||
if(unit instanceof Player && ((Player)unit).isLocal){
|
||||
Lines.stroke(1f, Pal.accent);
|
||||
Lines.poly(tile.worldx(), tile.worldy(), 4, tilesize / 2f * Mathf.sqrt2, Time.time());
|
||||
}
|
||||
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
/** Class for storing build requests. Can be either a place or remove request. */
|
||||
class BuildRequest{
|
||||
public final int x, y, rotation;
|
||||
|
101
core/src/io/anuke/mindustry/entities/traits/MinerTrait.java
Normal file
101
core/src/io/anuke/mindustry/entities/traits/MinerTrait.java
Normal file
@ -0,0 +1,101 @@
|
||||
package io.anuke.mindustry.entities.traits;
|
||||
|
||||
import io.anuke.arc.graphics.Color;
|
||||
import io.anuke.arc.graphics.g2d.*;
|
||||
import io.anuke.arc.math.*;
|
||||
import io.anuke.arc.util.Time;
|
||||
import io.anuke.mindustry.content.*;
|
||||
import io.anuke.mindustry.entities.Effects;
|
||||
import io.anuke.mindustry.entities.type.*;
|
||||
import io.anuke.mindustry.gen.Call;
|
||||
import io.anuke.mindustry.graphics.*;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
public interface MinerTrait extends Entity{
|
||||
|
||||
/** Returns the range at which this miner can mine blocks.*/
|
||||
default float getMiningRange(){
|
||||
return 70f;
|
||||
}
|
||||
|
||||
default boolean isMining(){
|
||||
return getMineTile() != null;
|
||||
}
|
||||
|
||||
/** Returns the tile this builder is currently mining. */
|
||||
Tile getMineTile();
|
||||
|
||||
/** Sets the tile this builder is currently mining. */
|
||||
void setMineTile(Tile tile);
|
||||
|
||||
/** Returns the mining speed of this miner. 1 = standard, 0.5 = half speed, 2 = double speed, etc. */
|
||||
float getMinePower();
|
||||
|
||||
/** Returns whether or not this builder can mine a specific item type. */
|
||||
boolean canMine(Item item);
|
||||
|
||||
default void updateMining(){
|
||||
Unit unit = (Unit)this;
|
||||
Tile tile = getMineTile();
|
||||
TileEntity core = unit.getClosestCore();
|
||||
|
||||
if(tile == null || core == null || tile.block() != Blocks.air || dst(tile.worldx(), tile.worldy()) > getMiningRange()
|
||||
|| tile.drop() == null || !unit.acceptsItem(tile.drop()) || !canMine(tile.drop())){
|
||||
setMineTile(null);
|
||||
}else{
|
||||
Item item = tile.drop();
|
||||
unit.rotation = Mathf.slerpDelta(unit.rotation, unit.angleTo(tile.worldx(), tile.worldy()), 0.4f);
|
||||
|
||||
if(Mathf.chance(Time.delta() * (0.06 - item.hardness * 0.01) * getMinePower())){
|
||||
|
||||
if(unit.dst(core) < mineTransferRange && core.tile.block().acceptStack(item, 1, core.tile, unit) == 1){
|
||||
Call.transferItemTo(item, 1,
|
||||
tile.worldx() + Mathf.range(tilesize / 2f),
|
||||
tile.worldy() + Mathf.range(tilesize / 2f), core.tile);
|
||||
}else if(unit.acceptsItem(item)){
|
||||
Call.transferItemToUnit(item,
|
||||
tile.worldx() + Mathf.range(tilesize / 2f),
|
||||
tile.worldy() + Mathf.range(tilesize / 2f),
|
||||
unit);
|
||||
}
|
||||
}
|
||||
|
||||
if(Mathf.chance(0.06 * Time.delta())){
|
||||
Effects.effect(Fx.pulverizeSmall,
|
||||
tile.worldx() + Mathf.range(tilesize / 2f),
|
||||
tile.worldy() + Mathf.range(tilesize / 2f), 0f, item.color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
default void drawMining(){
|
||||
Unit unit = (Unit)this;
|
||||
Tile tile = getMineTile();
|
||||
|
||||
if(tile == null) return;
|
||||
|
||||
float focusLen = 4f + Mathf.absin(Time.time(), 1.1f, 0.5f);
|
||||
float swingScl = 12f, swingMag = tilesize / 8f;
|
||||
float flashScl = 0.3f;
|
||||
|
||||
float px = unit.x + Angles.trnsx(unit.rotation, focusLen);
|
||||
float py = unit.y + Angles.trnsy(unit.rotation, focusLen);
|
||||
|
||||
float ex = tile.worldx() + Mathf.sin(Time.time() + 48, swingScl, swingMag);
|
||||
float ey = tile.worldy() + Mathf.sin(Time.time() + 48, swingScl + 2f, swingMag);
|
||||
|
||||
Draw.color(Color.LIGHT_GRAY, Color.WHITE, 1f - flashScl + Mathf.absin(Time.time(), 0.5f, flashScl));
|
||||
|
||||
Shapes.laser("minelaser", "minelaser-end", px, py, ex, ey, 0.75f);
|
||||
|
||||
if(unit instanceof Player && ((Player)unit).isLocal){
|
||||
Lines.stroke(1f, Pal.accent);
|
||||
Lines.poly(tile.worldx(), tile.worldy(), 4, tilesize / 2f * Mathf.sqrt2, Time.time());
|
||||
}
|
||||
|
||||
Draw.color();
|
||||
}
|
||||
}
|
@ -33,7 +33,7 @@ import java.io.*;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
public class Player extends Unit implements BuilderTrait, ShooterTrait{
|
||||
public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
||||
public static final int timerSync = 2;
|
||||
public static final int timerAbility = 3;
|
||||
private static final int timerShootLeft = 0;
|
||||
@ -362,7 +362,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{
|
||||
public void drawOver(){
|
||||
if(dead) return;
|
||||
|
||||
drawBuilding();
|
||||
drawMechanics();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -551,7 +551,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{
|
||||
|
||||
if(!isLocal){
|
||||
interpolate();
|
||||
updateBuilding(); //building happens even with non-locals
|
||||
updateMechanics(); //building happens even with non-locals
|
||||
status.update(this); //status effect updating also happens with non locals for effect purposes
|
||||
updateVelocityStatus(); //velocity too, for visual purposes
|
||||
|
||||
@ -572,7 +572,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{
|
||||
|
||||
isTyping = ui.chatfrag.chatOpen();
|
||||
|
||||
updateBuilding();
|
||||
updateMechanics();
|
||||
|
||||
if(!mech.flying){
|
||||
clampPosition();
|
||||
|
217
core/src/io/anuke/mindustry/entities/type/base/MinerDrone.java
Normal file
217
core/src/io/anuke/mindustry/entities/type/base/MinerDrone.java
Normal file
@ -0,0 +1,217 @@
|
||||
package io.anuke.mindustry.entities.type.base;
|
||||
|
||||
import io.anuke.arc.math.Mathf;
|
||||
import io.anuke.arc.math.geom.Geometry;
|
||||
import io.anuke.arc.util.Structs;
|
||||
import io.anuke.mindustry.content.Blocks;
|
||||
import io.anuke.mindustry.entities.traits.MinerTrait;
|
||||
import io.anuke.mindustry.entities.type.*;
|
||||
import io.anuke.mindustry.entities.units.UnitState;
|
||||
import io.anuke.mindustry.gen.Call;
|
||||
import io.anuke.mindustry.type.*;
|
||||
import io.anuke.mindustry.world.*;
|
||||
import io.anuke.mindustry.world.meta.BlockFlag;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static io.anuke.mindustry.Vars.world;
|
||||
|
||||
/** A drone that only mines.*/
|
||||
public class MinerDrone extends FlyingUnit implements MinerTrait{
|
||||
protected Item targetItem;
|
||||
protected Tile mineTile;
|
||||
|
||||
public final UnitState
|
||||
|
||||
mine = new UnitState(){
|
||||
public void entered(){
|
||||
target = null;
|
||||
}
|
||||
|
||||
public void update(){
|
||||
TileEntity entity = getClosestCore();
|
||||
|
||||
if(entity == null) return;
|
||||
|
||||
if(targetItem == null){
|
||||
findItem();
|
||||
}
|
||||
|
||||
//core full
|
||||
if(targetItem != null && entity.block.acceptStack(targetItem, 1, entity.tile, MinerDrone.this) == 0){
|
||||
MinerDrone.this.clearItem();
|
||||
return;
|
||||
}
|
||||
|
||||
//if inventory is full, drop it off.
|
||||
if(item.amount >= getItemCapacity()){
|
||||
setState(drop);
|
||||
}else{
|
||||
if(targetItem != null && !acceptsItem(targetItem)){
|
||||
setState(drop);
|
||||
return;
|
||||
}
|
||||
|
||||
retarget(() -> {
|
||||
if(getMineTile() == null){
|
||||
findItem();
|
||||
}
|
||||
|
||||
if(targetItem == null) return;
|
||||
|
||||
target = world.indexer.findClosestOre(x, y, targetItem);
|
||||
});
|
||||
|
||||
if(target instanceof Tile){
|
||||
moveTo(type.range / 1.5f);
|
||||
|
||||
if(dst(target) < type.range && mineTile != target){
|
||||
setMineTile((Tile)target);
|
||||
}
|
||||
|
||||
if(((Tile)target).block() != Blocks.air){
|
||||
setState(drop);
|
||||
}
|
||||
}else{
|
||||
//nothing to mine anymore, core full: circle spawnpoint
|
||||
if(getSpawner() != null){
|
||||
target = getSpawner();
|
||||
|
||||
circle(40f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void exited(){
|
||||
setMineTile(null);
|
||||
}
|
||||
},
|
||||
|
||||
drop = new UnitState(){
|
||||
public void entered(){
|
||||
target = null;
|
||||
}
|
||||
|
||||
public void update(){
|
||||
if(item.amount == 0){
|
||||
setState(mine);
|
||||
return;
|
||||
}
|
||||
|
||||
if(item.item.type != ItemType.material){
|
||||
item.amount = 0;
|
||||
setState(mine);
|
||||
return;
|
||||
}
|
||||
|
||||
target = getClosestCore();
|
||||
|
||||
if(target == null) return;
|
||||
|
||||
TileEntity tile = (TileEntity)target;
|
||||
|
||||
if(dst(target) < type.range){
|
||||
if(tile.tile.block().acceptStack(item.item, item.amount, tile.tile, MinerDrone.this) == item.amount){
|
||||
Call.transferItemTo(item.item, item.amount, x, y, tile.tile);
|
||||
item.amount = 0;
|
||||
}
|
||||
|
||||
setState(mine);
|
||||
}
|
||||
|
||||
circle(type.range / 1.8f);
|
||||
}
|
||||
},
|
||||
|
||||
retreat = new UnitState(){
|
||||
public void entered(){
|
||||
target = null;
|
||||
}
|
||||
|
||||
public void update(){
|
||||
if(health >= maxHealth()){
|
||||
state.set(attack);
|
||||
}else if(!targetHasFlag(BlockFlag.repair)){
|
||||
retarget(() -> {
|
||||
Tile repairPoint = Geometry.findClosest(x, y, world.indexer.getAllied(team, BlockFlag.repair));
|
||||
if(repairPoint != null){
|
||||
target = repairPoint;
|
||||
}else{
|
||||
setState(mine);
|
||||
}
|
||||
});
|
||||
}else{
|
||||
circle(40f);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
super.update();
|
||||
|
||||
updateMining();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateRotation(){
|
||||
if(target != null && state.is(mine)){
|
||||
rotation = Mathf.slerpDelta(rotation, angleTo(target), 0.3f);
|
||||
}else{
|
||||
rotation = Mathf.slerpDelta(rotation, velocity.angle(), 0.3f);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void behavior(){
|
||||
if(health <= health * type.retreatPercent){
|
||||
setState(retreat);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawOver(){
|
||||
drawMining();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canMine(Item item){
|
||||
return type.toMine.contains(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMinePower(){
|
||||
return type.minePower;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tile getMineTile(){
|
||||
return mineTile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMineTile(Tile tile){
|
||||
mineTile = tile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DataOutput data) throws IOException{
|
||||
super.write(data);
|
||||
data.writeInt(mineTile == null || !state.is(mine) ? Pos.invalid : mineTile.pos());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput data) throws IOException{
|
||||
super.read(data);
|
||||
mineTile = world.tile(data.readInt());
|
||||
}
|
||||
|
||||
protected void findItem(){
|
||||
TileEntity entity = getClosestCore();
|
||||
if(entity == null){
|
||||
return;
|
||||
}
|
||||
targetItem = Structs.findMin(type.toMine, world.indexer::hasOre, (a, b) -> -Integer.compare(entity.items.get(a), entity.items.get(b)));
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
package io.anuke.mindustry.entities.type.base;
|
||||
|
||||
public class Phantom extends Drone{
|
||||
public class Phantom extends UtilityDrone{
|
||||
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package io.anuke.mindustry.entities.type.base;
|
||||
|
||||
public class Spirit extends Drone{
|
||||
public class Spirit extends UtilityDrone{
|
||||
}
|
||||
|
@ -4,17 +4,11 @@ import io.anuke.arc.Events;
|
||||
import io.anuke.arc.collection.Queue;
|
||||
import io.anuke.arc.math.Mathf;
|
||||
import io.anuke.arc.math.geom.Geometry;
|
||||
import io.anuke.arc.util.Structs;
|
||||
import io.anuke.mindustry.content.Blocks;
|
||||
import io.anuke.mindustry.entities.EntityGroup;
|
||||
import io.anuke.mindustry.entities.Units;
|
||||
import io.anuke.mindustry.entities.*;
|
||||
import io.anuke.mindustry.entities.traits.BuilderTrait;
|
||||
import io.anuke.mindustry.entities.type.*;
|
||||
import io.anuke.mindustry.entities.units.UnitState;
|
||||
import io.anuke.mindustry.game.EventType.BuildSelectEvent;
|
||||
import io.anuke.mindustry.gen.Call;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.type.ItemType;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.BuildBlock;
|
||||
import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity;
|
||||
@ -24,9 +18,8 @@ import java.io.*;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
public class Drone extends FlyingUnit implements BuilderTrait{
|
||||
protected Item targetItem;
|
||||
protected Tile mineTile;
|
||||
/** A drone that only builds and/or repairs.*/
|
||||
public class UtilityDrone extends FlyingUnit implements BuilderTrait{
|
||||
protected Queue<BuildRequest> placeQueue = new Queue<>();
|
||||
protected boolean isBreaking;
|
||||
|
||||
@ -34,6 +27,7 @@ public class Drone extends FlyingUnit implements BuilderTrait{
|
||||
|
||||
build = new UnitState(){
|
||||
|
||||
//TODO follow players
|
||||
public void entered(){
|
||||
if(!(target instanceof BuildEntity)){
|
||||
target = null;
|
||||
@ -78,12 +72,13 @@ public class Drone extends FlyingUnit implements BuilderTrait{
|
||||
retarget(() -> target = Units.findDamagedTile(team, x, y));
|
||||
|
||||
if(target != null){
|
||||
if(target.dst(Drone.this) > type.range){
|
||||
if(target.dst(UtilityDrone.this) > type.range){
|
||||
circle(type.range * 0.9f);
|
||||
}else{
|
||||
getWeapon().update(Drone.this, target.getX(), target.getY());
|
||||
getWeapon().update(UtilityDrone.this, target.getX(), target.getY());
|
||||
}
|
||||
}else{
|
||||
//circle spawner if there's nothing to repair
|
||||
if(getSpawner() != null){
|
||||
target = getSpawner();
|
||||
circle(type.range * 0.9f);
|
||||
@ -91,99 +86,6 @@ public class Drone extends FlyingUnit implements BuilderTrait{
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
mine = new UnitState(){
|
||||
public void entered(){
|
||||
target = null;
|
||||
}
|
||||
|
||||
public void update(){
|
||||
TileEntity entity = getClosestCore();
|
||||
|
||||
if(entity == null) return;
|
||||
|
||||
if(targetItem == null){
|
||||
findItem();
|
||||
}
|
||||
|
||||
//core full
|
||||
if(targetItem != null && entity.block.acceptStack(targetItem, 1, entity.tile, Drone.this) == 0){
|
||||
setState(repair);
|
||||
return;
|
||||
}
|
||||
|
||||
//if inventory is full, drop it off.
|
||||
if(item.amount >= getItemCapacity()){
|
||||
setState(drop);
|
||||
}else{
|
||||
if(targetItem != null && !acceptsItem(targetItem)){
|
||||
setState(drop);
|
||||
return;
|
||||
}
|
||||
|
||||
retarget(() -> {
|
||||
if(getMineTile() == null){
|
||||
findItem();
|
||||
}
|
||||
|
||||
if(targetItem == null) return;
|
||||
|
||||
target = world.indexer.findClosestOre(x, y, targetItem);
|
||||
});
|
||||
|
||||
if(target instanceof Tile){
|
||||
moveTo(type.range / 1.5f);
|
||||
|
||||
if(dst(target) < type.range && mineTile != target){
|
||||
setMineTile((Tile)target);
|
||||
}
|
||||
|
||||
if(((Tile)target).block() != Blocks.air){
|
||||
setState(drop);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void exited(){
|
||||
setMineTile(null);
|
||||
}
|
||||
},
|
||||
drop = new UnitState(){
|
||||
public void entered(){
|
||||
target = null;
|
||||
}
|
||||
|
||||
public void update(){
|
||||
if(item.amount == 0){
|
||||
setState(mine);
|
||||
return;
|
||||
}
|
||||
|
||||
if(item.item.type != ItemType.material){
|
||||
item.amount = 0;
|
||||
setState(mine);
|
||||
return;
|
||||
}
|
||||
|
||||
target = getClosestCore();
|
||||
|
||||
if(target == null) return;
|
||||
|
||||
TileEntity tile = (TileEntity)target;
|
||||
|
||||
if(dst(target) < type.range){
|
||||
if(tile.tile.block().acceptStack(item.item, item.amount, tile.tile, Drone.this) == item.amount){
|
||||
Call.transferItemTo(item.item, item.amount, x, y, tile.tile);
|
||||
item.amount = 0;
|
||||
}
|
||||
|
||||
setState(repair);
|
||||
}
|
||||
|
||||
circle(type.range / 1.8f);
|
||||
}
|
||||
},
|
||||
retreat = new UnitState(){
|
||||
public void entered(){
|
||||
target = null;
|
||||
@ -197,8 +99,8 @@ public class Drone extends FlyingUnit implements BuilderTrait{
|
||||
Tile repairPoint = Geometry.findClosest(x, y, world.indexer.getAllied(team, BlockFlag.repair));
|
||||
if(repairPoint != null){
|
||||
target = repairPoint;
|
||||
}else if(getSpawner() != null){
|
||||
target = getSpawner();
|
||||
}else{
|
||||
setState(repair);
|
||||
}
|
||||
});
|
||||
}else{
|
||||
@ -215,8 +117,8 @@ public class Drone extends FlyingUnit implements BuilderTrait{
|
||||
if(!(event.tile.entity instanceof BuildEntity)) return;
|
||||
|
||||
for(BaseUnit unit : group.all()){
|
||||
if(unit instanceof Drone){
|
||||
Drone drone = (Drone)unit;
|
||||
if(unit instanceof UtilityDrone){
|
||||
UtilityDrone drone = (UtilityDrone)unit;
|
||||
if(drone.isBuilding()){
|
||||
//stop building if opposite building begins.
|
||||
BuildRequest req = drone.getCurrentRequest();
|
||||
@ -230,36 +132,16 @@ public class Drone extends FlyingUnit implements BuilderTrait{
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canMine(Item item){
|
||||
return type.toMine.contains(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getBuildPower(Tile tile){
|
||||
return type.buildPower;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMinePower(){
|
||||
return type.minePower;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Queue<BuildRequest> getPlaceQueue(){
|
||||
return placeQueue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tile getMineTile(){
|
||||
return mineTile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMineTile(Tile tile){
|
||||
mineTile = tile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
super.update();
|
||||
@ -292,7 +174,7 @@ public class Drone extends FlyingUnit implements BuilderTrait{
|
||||
|
||||
@Override
|
||||
protected void updateRotation(){
|
||||
if(target != null && ((state.is(repair) && target.dst(this) < type.range) || state.is(mine))){
|
||||
if(target != null && state.is(repair) && target.dst(this) < type.range){
|
||||
rotation = Mathf.slerpDelta(rotation, angleTo(target), 0.3f);
|
||||
}else{
|
||||
rotation = Mathf.slerpDelta(rotation, velocity.angle(), 0.3f);
|
||||
@ -321,14 +203,6 @@ public class Drone extends FlyingUnit implements BuilderTrait{
|
||||
return isBuilding() ? placeDistance * 2f : 30f;
|
||||
}
|
||||
|
||||
protected void findItem(){
|
||||
TileEntity entity = getClosestCore();
|
||||
if(entity == null){
|
||||
return;
|
||||
}
|
||||
targetItem = Structs.findMin(type.toMine, world.indexer::hasOre, (a, b) -> -Integer.compare(entity.items.get(a), entity.items.get(b)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canCreateBlocks(){
|
||||
return true;
|
||||
@ -337,7 +211,6 @@ public class Drone extends FlyingUnit implements BuilderTrait{
|
||||
@Override
|
||||
public void write(DataOutput data) throws IOException{
|
||||
super.write(data);
|
||||
data.writeInt(mineTile == null || !state.is(mine) ? -1 : mineTile.pos());
|
||||
data.writeInt(state.is(repair) && target instanceof TileEntity ? ((TileEntity)target).tile.pos() : -1);
|
||||
writeBuilding(data);
|
||||
}
|
||||
@ -345,15 +218,10 @@ public class Drone extends FlyingUnit implements BuilderTrait{
|
||||
@Override
|
||||
public void read(DataInput data) throws IOException{
|
||||
super.read(data);
|
||||
int mined = data.readInt();
|
||||
int repairing = data.readInt();
|
||||
|
||||
readBuilding(data);
|
||||
|
||||
if(mined != -1){
|
||||
mineTile = world.tile(mined);
|
||||
}
|
||||
|
||||
if(repairing != -1){
|
||||
Tile tile = world.tile(repairing);
|
||||
target = tile.entity;
|
Loading…
Reference in New Issue
Block a user