Unit enemy spawnpoint camping

This commit is contained in:
Anuken
2019-09-20 23:09:11 -04:00
parent 025386af53
commit dda1f18f67
14 changed files with 1581 additions and 1500 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

Before

Width:  |  Height:  |  Size: 95 B

After

Width:  |  Height:  |  Size: 95 B

View File

@ -577,8 +577,8 @@ category.general.name = General
category.view.name = View
category.multiplayer.name = Multiplayer
command.attack = Attack
command.rally = Rally
command.retreat = Retreat
command.patrol = Patrol
keybind.gridMode.name = Block Select
keybind.gridModeShift.name = Category Select
keybind.press = Press a key...
@ -854,6 +854,8 @@ block.solar-panel.name = Solar Panel
block.solar-panel-large.name = Large Solar Panel
block.oil-extractor.name = Oil Extractor
block.command-center.name = Command Center
block.rally-point.name = Rally Point
block.rally-point.description = A marker for units to group up around. Requires issuing the 'Rally' command on the command center to use.
block.draug-factory.name = Draug Miner Drone Factory
block.spirit-factory.name = Spirit Repair Drone Factory
block.phantom-factory.name = Phantom Builder Drone Factory

Binary file not shown.

Before

Width:  |  Height:  |  Size: 718 B

After

Width:  |  Height:  |  Size: 723 B

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 672 KiB

After

Width:  |  Height:  |  Size: 677 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 258 KiB

After

Width:  |  Height:  |  Size: 258 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 577 KiB

After

Width:  |  Height:  |  Size: 587 KiB

View File

@ -7,7 +7,6 @@ import io.anuke.arc.function.*;
import io.anuke.arc.math.geom.*;
import io.anuke.arc.util.*;
import io.anuke.arc.util.async.*;
import io.anuke.mindustry.core.GameState.*;
import io.anuke.mindustry.game.EventType.*;
import io.anuke.mindustry.game.*;
import io.anuke.mindustry.gen.*;
@ -39,6 +38,7 @@ public class Pathfinder implements Runnable{
Events.on(WorldLoadEvent.class, event -> {
stop();
//reset and update internal tile array
tiles = new int[world.width()][world.height()];
pathMap = new PathData[Team.all.length][PathTarget.all.length];
created = new GridBits(Team.all.length, PathTarget.all.length);
@ -50,9 +50,14 @@ public class Pathfinder implements Runnable{
}
}
//special preset which may help speed things up; this is optional
preloadPath(waveTeam, PathTarget.enemyCores);
start();
});
Events.on(ResetEvent.class, event -> stop());
Events.on(TileChangeEvent.class, event -> updateTile(event.tile));
}
@ -84,12 +89,13 @@ public class Pathfinder implements Runnable{
int x = tile.x, y = tile.y;
tiles[x][y] = packed;
//can't iterate through array so use the map, which should not lead to problems
for(PathData[] arr : pathMap){
for(PathData path : arr){
if(path != null){
synchronized(path.targets){
path.targets.clear();
path.target.getTargets(tile.getTeam(), path.targets);
path.target.getTargets(path.team, path.targets);
}
}
}
@ -97,7 +103,7 @@ public class Pathfinder implements Runnable{
queue.post(() -> {
for(PathData data : list){
updateTargets(data, x, y, packed);
updateTargets(data, x, y);
}
});
}
@ -106,7 +112,7 @@ public class Pathfinder implements Runnable{
@Override
public void run(){
while(true){
if(net.client() || state.is(State.menu)) return;
if(net.client()) return;
queue.run();
@ -126,7 +132,7 @@ public class Pathfinder implements Runnable{
/** Gets next tile to travel to. Main thread only. */
public Tile getTargetTile(Tile tile, Team team, PathTarget target){
if(tile == null) return tile;
if(tile == null) return null;
PathData data = pathMap[team.ordinal()][target.ordinal()];
@ -136,7 +142,7 @@ public class Pathfinder implements Runnable{
created.set(team.ordinal(), target.ordinal());
//grab targets since this is run on main thread
IntArray targets = target.getTargets(team, new IntArray());
queue.post(() -> createFor(team, target, targets));
queue.post(() -> createPath(team, target, targets));
}
return tile;
}
@ -174,7 +180,7 @@ public class Pathfinder implements Runnable{
* Clears the frontier, increments the search and sets up all flow sources.
* This only occurs for active teams.
*/
private void updateTargets(PathData path, int x, int y, int tile){
private void updateTargets(PathData path, int x, int y){
if(!Structs.inBounds(x, y, path.weights)) return;
if(path.weights[x][y] == 0){
@ -207,9 +213,13 @@ public class Pathfinder implements Runnable{
}
}
private void preloadPath(Team team, PathTarget target){
updateFrontier(createPath(team, target, target.getTargets(team, new IntArray())), -1);
}
/** Created a new flowfield that aims to get to a certain target for a certain team.
* Pathfinding thread only. */
private void createFor(Team team, PathTarget target, IntArray targets){
private PathData createPath(Team team, PathTarget target, IntArray targets){
PathData path = new PathData(team, target, world.width(), world.height());
list.add(path);
@ -234,6 +244,8 @@ public class Pathfinder implements Runnable{
path.weights[Pos.x(pos)][Pos.y(pos)] = 0;
path.frontier.addFirst(pos);
}
return path;
}
/** Update the frontier for a path. Pathfinding thread only. */
@ -274,6 +286,13 @@ public class Pathfinder implements Runnable{
for(Tile other : indexer.getEnemy(team, BlockFlag.core)){
out.add(other.pos());
}
//spawn points are also enemies.
if(state.rules.waves && team == defaultTeam){
for(Tile other : spawner.getGroundSpawns()){
out.add(other.pos());
}
}
}),
rallyPoints((team, out) -> {
for(Tile other : indexer.getAllied(team, BlockFlag.rally)){

View File

@ -75,7 +75,7 @@ public class Blocks implements ContentList{
duo, scatter, scorch, hail, arc, wave, lancer, swarmer, salvo, fuse, ripple, cyclone, spectre, meltdown,
//units
commandCenter, draugFactory, spiritFactory, phantomFactory, wraithFactory, ghoulFactory, revenantFactory, daggerFactory, crawlerFactory, titanFactory,
commandCenter, rallyPoint, draugFactory, spiritFactory, phantomFactory, wraithFactory, ghoulFactory, revenantFactory, daggerFactory, crawlerFactory, titanFactory,
fortressFactory, repairPoint,
//upgrades
@ -1650,6 +1650,12 @@ public class Blocks implements ContentList{
health = size * size * 55;
}};
rallyPoint = new RallyPoint("rally-point"){{
requirements(Category.units, ItemStack.with(Items.lead, 100, Items.silicon, 100, Items.graphite, 50));
size = 2;
health = size * size * 85;
}};
wraithFactory = new UnitFactory("wraith-factory"){{
requirements(Category.units, ItemStack.with(Items.titanium, 30, Items.lead, 40, Items.silicon, 45));
type = UnitTypes.wraith;

View File

@ -174,8 +174,15 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
}
}
public TileEntity getClosestEnemyCore(){
public Tile getClosest(BlockFlag flag){
return Geometry.findClosest(x, y, indexer.getAllied(team, flag));
}
public Tile getClosestSpawner(){
return Geometry.findClosest(x, y, Vars.spawner.getGroundSpawns());
}
public TileEntity getClosestEnemyCore(){
for(Team enemy : Vars.state.teams.enemiesOf(team)){
Tile tile = Geometry.findClosest(x, y, Vars.state.teams.get(enemy).cores);
if(tile != null){

View File

@ -5,6 +5,7 @@ import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.math.*;
import io.anuke.arc.math.geom.*;
import io.anuke.arc.util.*;
import io.anuke.mindustry.*;
import io.anuke.mindustry.entities.*;
import io.anuke.mindustry.entities.bullet.*;
import io.anuke.mindustry.entities.units.*;
@ -35,13 +36,15 @@ public abstract class FlyingUnit extends BaseUnit{
if(target == null) targetClosestEnemyFlag(BlockFlag.producer);
if(target == null) targetClosestEnemyFlag(BlockFlag.turret);
if(target == null){
setState(patrol);
}
}
if(target != null){
if(target == null){
target = getSpawner();
}
if(target == getSpawner() && getSpawner() != null){
circle(80f + Mathf.randomSeed(id) * 120);
}else if(target != null){
attack(type.attackLength);
if((Angles.near(angleTo(target), rotation, type.shootCone) || getWeapon().ignoreRotation) //bombers and such don't care about rotation
@ -64,22 +67,24 @@ public abstract class FlyingUnit extends BaseUnit{
getWeapon().update(FlyingUnit.this, to.x, to.y);
}
}
}else{
target = getClosestSpawner();
moveTo(Vars.state.rules.dropZoneRadius + 80f);
}
}
},
patrol = new UnitState(){
rally = new UnitState(){
public void update(){
if(retarget()){
targetClosestAllyFlag(BlockFlag.rally);
targetClosest();
targetClosestEnemyFlag(BlockFlag.core);
if(target != null && !Units.invalidateTarget(target, team, x, y)){
setState(attack);
return;
}
target = getSpawner();
if(target == null) target = getClosestCore();
if(target == null) target = getSpawner();
}
if(target != null){
@ -109,7 +114,7 @@ public abstract class FlyingUnit extends BaseUnit{
public void onCommand(UnitCommand command){
state.set(command == UnitCommand.retreat ? retreat :
command == UnitCommand.attack ? attack :
command == UnitCommand.patrol ? patrol :
command == UnitCommand.rally ? rally :
null);
}

View File

@ -14,6 +14,7 @@ import io.anuke.mindustry.game.*;
import io.anuke.mindustry.type.*;
import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.blocks.*;
import io.anuke.mindustry.world.meta.*;
import static io.anuke.mindustry.Vars.*;
@ -35,31 +36,30 @@ public abstract class GroundUnit extends BaseUnit{
TileEntity core = getClosestEnemyCore();
if(core == null){
setState(patrol);
return;
}
Tile closestSpawn = getClosestSpawner();
if(closestSpawn == null || !withinDst(closestSpawn, Vars.state.rules.dropZoneRadius + 75f)){
moveToCore(PathTarget.enemyCores);
}
}else{
float dst = dst(core);
float dst = dst(core);
if(dst < getWeapon().bullet.range() / 1.1f){
target = core;
}
if(dst < getWeapon().bullet.range() / 1.1f){
target = core;
}
if(dst > getWeapon().bullet.range() * 0.5f){
moveToCore();
if(dst > getWeapon().bullet.range() * 0.5f){
moveToCore(PathTarget.enemyCores);
}
}
}
},
patrol = new UnitState(){
rally = new UnitState(){
public void update(){
TileEntity target = getClosestCore();
Tile target = getClosest(BlockFlag.rally);
if(target != null){
if(dst(target) > 400f){
moveAwayFromCore();
}else if(!(!Units.invalidateTarget(GroundUnit.this.target, GroundUnit.this) && dst(GroundUnit.this.target) < getWeapon().bullet.range())){
patrol();
}
if(target != null && dst(target) > 100f){
moveToCore(PathTarget.rallyPoints);
}
}
},
@ -77,7 +77,7 @@ public abstract class GroundUnit extends BaseUnit{
public void onCommand(UnitCommand command){
state.set(command == UnitCommand.retreat ? retreat :
command == UnitCommand.attack ? attack :
command == UnitCommand.patrol ? patrol :
command == UnitCommand.rally ? rally :
null);
}
@ -221,10 +221,10 @@ public abstract class GroundUnit extends BaseUnit{
velocity.add(vec);
}
protected void moveToCore(){
protected void moveToCore(PathTarget path){
Tile tile = world.tileWorld(x, y);
if(tile == null) return;
Tile targetTile = pathfinder.getTargetTile(tile, team, PathTarget.enemyCores);
Tile targetTile = pathfinder.getTargetTile(tile, team, path);
if(tile == targetTile) return;

View File

@ -3,7 +3,7 @@ package io.anuke.mindustry.entities.units;
import io.anuke.arc.*;
public enum UnitCommand{
attack, retreat, patrol;
attack, retreat, rally;
private final String localized;
public static final UnitCommand[] all = values();