diff --git a/core/src/io/anuke/mindustry/ai/BlockIndexer.java b/core/src/io/anuke/mindustry/ai/BlockIndexer.java index 7fdd7ada51..d8dc3ae8eb 100644 --- a/core/src/io/anuke/mindustry/ai/BlockIndexer.java +++ b/core/src/io/anuke/mindustry/ai/BlockIndexer.java @@ -2,7 +2,7 @@ package io.anuke.mindustry.ai; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.*; -import io.anuke.mindustry.content.Items; +import com.badlogic.gdx.utils.Bits; import io.anuke.mindustry.content.blocks.Blocks; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.game.EventType.TileChangeEvent; @@ -14,10 +14,7 @@ import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.meta.BlockFlag; import io.anuke.ucore.core.Events; import io.anuke.ucore.function.Predicate; -import io.anuke.ucore.util.EnumSet; -import io.anuke.ucore.util.Geometry; -import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.ThreadArray; +import io.anuke.ucore.util.*; import static io.anuke.mindustry.Vars.*; @@ -33,12 +30,14 @@ public class BlockIndexer{ private final static int structQuadrantSize = 12; /**Set of all ores that are being scanned.*/ - private final ObjectSet scanOres = ObjectSet.with(Items.copper, Items.coal, Items.lead, Items.thorium, Items.titanium); + private final ObjectSet scanOres = new ObjectSet(){{addAll(Item.getAllOres());}}; private final ObjectSet itemSet = new ObjectSet<>(); /**Stores all ore quadtrants on the map.*/ private ObjectMap> ores; /**Tags all quadrants.*/ private Bits[] structQuadrants; + /**Stores all damaged tile entities by team.*/ + private ObjectSet[] damagedTiles = new ObjectSet[Team.all.length]; /**Maps teams to a map of flagged tiles by type.*/ private ObjectSet[][] flagMap = new ObjectSet[Team.all.length][BlockFlag.all.length]; @@ -62,7 +61,9 @@ public class BlockIndexer{ }); Events.on(WorldLoadEvent.class, event -> { + damagedTiles = new ObjectSet[Team.all.length]; flagMap = new ObjectSet[Team.all.length][BlockFlag.all.length]; + for(int i = 0; i < flagMap.length; i++){ for(int j = 0; j < BlockFlag.all.length; j++){ flagMap[i][j] = new ObjectSet<>(); @@ -79,7 +80,13 @@ public class BlockIndexer{ for(int x = 0; x < world.width(); x++){ for(int y = 0; y < world.height(); y++){ - process(world.tile(x, y)); + Tile tile = world.tileWorld(x, y); + + process(tile); + + if(tile.entity != null && tile.entity.healthf() < 0.9999f){ + notifyTileDamaged(tile.entity); + } } } @@ -97,6 +104,28 @@ public class BlockIndexer{ return flagMap[team.ordinal()]; } + /**Returns all damaged tiles by team.*/ + public ObjectSet getDamaged(Team team){ + returnArray.clear(); + + if(damagedTiles[team.ordinal()] == null){ + damagedTiles[team.ordinal()] = new ObjectSet<>(); + } + + ObjectSet set = damagedTiles[team.ordinal()]; + for(Tile tile : set){ + if(tile.entity == null || tile.entity.getTeam() != team || tile.entity.healthf() >= 0.9999f){ + returnArray.add(tile); + } + } + + for(Tile tile : returnArray){ + set.remove(tile); + } + + return set; + } + /**Get all allied blocks with a flag.*/ public ObjectSet getAllied(Team team, BlockFlag type){ return flagMap[team.ordinal()][type.ordinal()]; @@ -115,6 +144,15 @@ public class BlockIndexer{ return returnArray; } + public void notifyTileDamaged(TileEntity entity){ + if(damagedTiles[entity.getTeam().ordinal()] == null){ + damagedTiles[entity.getTeam().ordinal()] = new ObjectSet<>(); + } + + ObjectSet set = damagedTiles[entity.getTeam().ordinal()]; + set.add(entity.tile); + } + public TileEntity findTile(Team team, float x, float y, float range, Predicate pred){ TileEntity closest = null; float dst = 0; diff --git a/core/src/io/anuke/mindustry/entities/TileEntity.java b/core/src/io/anuke/mindustry/entities/TileEntity.java index cec34d962d..910d36d10f 100644 --- a/core/src/io/anuke/mindustry/entities/TileEntity.java +++ b/core/src/io/anuke/mindustry/entities/TileEntity.java @@ -143,10 +143,14 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ public void damage(float damage){ if(dead) return; + float preHealth = health; + Call.onTileDamage(tile, health - tile.block().handleDamage(tile, damage)); if(health <= 0){ Call.onTileDestroyed(tile); + }else if(preHealth >= maxHealth() - 0.00001f && health < maxHealth()){ //when just damaged + world.indexer.notifyTileDamaged(this); } } diff --git a/core/src/io/anuke/mindustry/entities/Units.java b/core/src/io/anuke/mindustry/entities/Units.java index f8e271fc5b..e546b727cd 100644 --- a/core/src/io/anuke/mindustry/entities/Units.java +++ b/core/src/io/anuke/mindustry/entities/Units.java @@ -11,8 +11,9 @@ import io.anuke.ucore.entities.EntityGroup; import io.anuke.ucore.entities.EntityQuery; import io.anuke.ucore.function.Consumer; import io.anuke.ucore.function.Predicate; -import io.anuke.ucore.util.Threads; import io.anuke.ucore.util.EnumSet; +import io.anuke.ucore.util.Geometry; +import io.anuke.ucore.util.Threads; import static io.anuke.mindustry.Vars.*; @@ -125,6 +126,12 @@ public class Units{ return value[0]; } + /**Returns the neareset damaged tile.*/ + public static TileEntity findDamagedTile(Team team, float x, float y){ + Tile tile = Geometry.findClosest(x, y, world.indexer.getDamaged(team)); + return tile == null ? null : tile.entity; + } + /**Returns the neareset ally tile in a range.*/ public static TileEntity findAllyTile(Team team, float x, float y, float range, Predicate pred){ return world.indexer.findTile(team, x, y, range, pred); diff --git a/core/src/io/anuke/mindustry/entities/units/types/Drone.java b/core/src/io/anuke/mindustry/entities/units/types/Drone.java index 1af4018725..85a191e65e 100644 --- a/core/src/io/anuke/mindustry/entities/units/types/Drone.java +++ b/core/src/io/anuke/mindustry/entities/units/types/Drone.java @@ -104,22 +104,17 @@ public class Drone extends FlyingUnit implements BuilderTrait{ } public void update(){ - if(target != null && (((TileEntity) target).health >= ((TileEntity) target).tile.block().health - || target.distanceTo(Drone.this) > discoverRange)){ - target = null; - } - if(target == null){ - retarget(() -> { - target = Units.findAllyTile(team, x, y, discoverRange, - tile -> tile.entity != null && tile.entity.health + 0.0001f < tile.block().health); + retarget(() -> { + target = Units.findDamagedTile(team, x, y); - if(target == null){ - setState(mine); - } - }); - }else if(target.distanceTo(Drone.this) > type.range){ - circle(type.range); + if(target == null){ + setState(mine); + } + }); + + if(target.distanceTo(Drone.this) > type.range){ + circle(type.range*0.9f); }else{ TileEntity entity = (TileEntity) target; entity.healBy(type.healSpeed * entity.tile.block().health / 100f * Timers.delta()); @@ -318,7 +313,7 @@ public class Drone extends FlyingUnit implements BuilderTrait{ target = null; } - if(Net.client() && state.is(repair) && target instanceof TileEntity){ + if(Net.client() && state.is(repair) && target instanceof TileEntity && target.distanceTo(this) < type.range){ TileEntity entity = (TileEntity) target; entity.health += type.healSpeed * Timers.delta(); entity.health = Mathf.clamp(entity.health, 0, entity.tile.block().health); @@ -329,7 +324,7 @@ public class Drone extends FlyingUnit implements BuilderTrait{ @Override protected void updateRotation(){ - if(target != null && (state.is(repair) || state.is(mine))){ + if(target != null && ((state.is(repair) && target.distanceTo(this) < type.range) || state.is(mine))){ rotation = Mathf.slerpDelta(rotation, angleTo(target), 0.3f); }else{ rotation = Mathf.slerpDelta(rotation, velocity.angle(), 0.3f); @@ -355,7 +350,7 @@ public class Drone extends FlyingUnit implements BuilderTrait{ TargetTrait entity = target; - if(entity instanceof TileEntity && state.is(repair)){ + if(entity instanceof TileEntity && state.is(repair) && target.distanceTo(this) < type.range){ float len = 5f; Draw.color(Color.BLACK, Color.WHITE, 0.95f + Mathf.absin(Timers.time(), 0.8f, 0.05f)); Shapes.laser("beam", "beam-end", diff --git a/core/src/io/anuke/mindustry/input/InputHandler.java b/core/src/io/anuke/mindustry/input/InputHandler.java index d251b1bd55..84b1563b22 100644 --- a/core/src/io/anuke/mindustry/input/InputHandler.java +++ b/core/src/io/anuke/mindustry/input/InputHandler.java @@ -221,9 +221,7 @@ public abstract class InputHandler extends InputAdapter{ return consumed; } - /** - * Tries to select the player to drop off items, returns true if successful. - */ + /**Tries to select the player to drop off items, returns true if successful.*/ boolean tryTapPlayer(float x, float y){ if(canTapPlayer(x, y)){ droppingItem = true; @@ -236,9 +234,7 @@ public abstract class InputHandler extends InputAdapter{ return Vector2.dst(x, y, player.x, player.y) <= playerSelectRange && player.inventory.hasItem(); } - /** - * Tries to begin mining a tile, returns true if successful. - */ + /**Tries to begin mining a tile, returns true if successful.*/ boolean tryBeginMine(Tile tile){ if(canMine(tile)){ //if a block is clicked twice, reset it diff --git a/core/src/io/anuke/mindustry/world/Tile.java b/core/src/io/anuke/mindustry/world/Tile.java index dff94535ac..c64043c917 100644 --- a/core/src/io/anuke/mindustry/world/Tile.java +++ b/core/src/io/anuke/mindustry/world/Tile.java @@ -101,14 +101,6 @@ public class Tile implements PosTrait, TargetTrait{ return -1; } - public byte sizedRelativeTo(int cx, int cy){ - if(x == cx && y == cy - 1 - block().size / 2) return 1; - if(x == cx && y == cy + 1 + block().size / 2) return 3; - if(x == cx - 1 - block().size / 2 && y == cy) return 0; - if(x == cx + 1 + block().size / 2 && y == cy) return 2; - return -1; - } - public T entity(){ return (T) entity; } diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/ItemBridge.java b/core/src/io/anuke/mindustry/world/blocks/distribution/ItemBridge.java index 20bcb47b7a..9d93f621c3 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/ItemBridge.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/ItemBridge.java @@ -14,6 +14,7 @@ import io.anuke.mindustry.graphics.Layer; import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Edges; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.meta.BlockGroup; import io.anuke.ucore.core.Timers; @@ -265,7 +266,8 @@ public class ItemBridge extends Block{ Tile other = world.tile(entity.link); if(!linkValid(tile, other)){ - int i = tile.absoluteRelativeTo(to.x, to.y); + Tile edge = Edges.getFacingEdge(to, tile); + int i = tile.absoluteRelativeTo(edge.x, edge.y); IntSetIterator it = entity.incoming.iterator();