Fixed drones being idiots / Added another PvP map
This commit is contained in:
Binary file not shown.
BIN
core/assets/maps/veins.msav
Normal file
BIN
core/assets/maps/veins.msav
Normal file
Binary file not shown.
@@ -1,29 +1,26 @@
|
|||||||
package io.anuke.mindustry.ai;
|
package io.anuke.mindustry.ai;
|
||||||
|
|
||||||
import io.anuke.arc.Events;
|
import io.anuke.arc.*;
|
||||||
import io.anuke.arc.collection.*;
|
import io.anuke.arc.collection.*;
|
||||||
import io.anuke.arc.function.Predicate;
|
import io.anuke.arc.function.*;
|
||||||
import io.anuke.arc.math.Mathf;
|
import io.anuke.arc.math.*;
|
||||||
import io.anuke.arc.math.geom.Geometry;
|
import io.anuke.arc.math.geom.*;
|
||||||
import io.anuke.mindustry.content.Blocks;
|
import io.anuke.mindustry.content.*;
|
||||||
import io.anuke.mindustry.entities.type.TileEntity;
|
import io.anuke.mindustry.entities.type.*;
|
||||||
import io.anuke.mindustry.game.EventType.TileChangeEvent;
|
import io.anuke.mindustry.game.EventType.*;
|
||||||
import io.anuke.mindustry.game.EventType.WorldLoadEvent;
|
import io.anuke.mindustry.game.*;
|
||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Teams.*;
|
||||||
import io.anuke.mindustry.game.Teams.TeamData;
|
import io.anuke.mindustry.type.*;
|
||||||
import io.anuke.mindustry.type.Item;
|
import io.anuke.mindustry.world.*;
|
||||||
import io.anuke.mindustry.world.Tile;
|
import io.anuke.mindustry.world.meta.*;
|
||||||
import io.anuke.mindustry.world.meta.BlockFlag;
|
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
/** Class used for indexing special target blocks for AI. */
|
/** Class used for indexing special target blocks for AI. */
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public class BlockIndexer{
|
public class BlockIndexer{
|
||||||
/** Size of one ore quadrant. */
|
/** Size of one quadrant. */
|
||||||
private final static int oreQuadrantSize = 20;
|
private final static int quadrantSize = 16;
|
||||||
/** Size of one structure quadrant. */
|
|
||||||
private final static int structQuadrantSize = 12;
|
|
||||||
|
|
||||||
/** Set of all ores that are being scanned. */
|
/** Set of all ores that are being scanned. */
|
||||||
private final ObjectSet<Item> scanOres = ObjectSet.with(Item.getAllOres().toArray(Item.class));
|
private final ObjectSet<Item> scanOres = ObjectSet.with(Item.getAllOres().toArray(Item.class));
|
||||||
@@ -75,7 +72,7 @@ public class BlockIndexer{
|
|||||||
//create bitset for each team type that contains each quadrant
|
//create bitset for each team type that contains each quadrant
|
||||||
structQuadrants = new GridBits[Team.all.length];
|
structQuadrants = new GridBits[Team.all.length];
|
||||||
for(int i = 0; i < Team.all.length; i++){
|
for(int i = 0; i < Team.all.length; i++){
|
||||||
structQuadrants[i] = new GridBits(Mathf.ceil(world.width() / (float)structQuadrantSize), Mathf.ceil(world.height() / (float)structQuadrantSize));
|
structQuadrants[i] = new GridBits(Mathf.ceil(world.width() / (float)quadrantSize), Mathf.ceil(world.height() / (float)quadrantSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int x = 0; x < world.width(); x++){
|
for(int x = 0; x < world.width(); x++){
|
||||||
@@ -94,7 +91,7 @@ public class BlockIndexer{
|
|||||||
|
|
||||||
for(int x = 0; x < quadWidth(); x++){
|
for(int x = 0; x < quadWidth(); x++){
|
||||||
for(int y = 0; y < quadHeight(); y++){
|
for(int y = 0; y < quadHeight(); y++){
|
||||||
updateQuadrant(world.tile(x * structQuadrantSize, y * structQuadrantSize));
|
updateQuadrant(world.tile(x * quadrantSize, y * quadrantSize));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,13 +161,13 @@ public class BlockIndexer{
|
|||||||
TileEntity closest = null;
|
TileEntity closest = null;
|
||||||
float dst = 0;
|
float dst = 0;
|
||||||
|
|
||||||
for(int rx = Math.max((int)((x - range) / tilesize / structQuadrantSize), 0); rx <= (int)((x + range) / tilesize / structQuadrantSize) && rx < quadWidth(); rx++){
|
for(int rx = Math.max((int)((x - range) / tilesize / quadrantSize), 0); rx <= (int)((x + range) / tilesize / quadrantSize) && rx < quadWidth(); rx++){
|
||||||
for(int ry = Math.max((int)((y - range) / tilesize / structQuadrantSize), 0); ry <= (int)((y + range) / tilesize / structQuadrantSize) && ry < quadHeight(); ry++){
|
for(int ry = Math.max((int)((y - range) / tilesize / quadrantSize), 0); ry <= (int)((y + range) / tilesize / quadrantSize) && ry < quadHeight(); ry++){
|
||||||
|
|
||||||
if(!getQuad(team, rx, ry)) continue;
|
if(!getQuad(team, rx, ry)) continue;
|
||||||
|
|
||||||
for(int tx = rx * structQuadrantSize; tx < (rx + 1) * structQuadrantSize && tx < world.width(); tx++){
|
for(int tx = rx * quadrantSize; tx < (rx + 1) * quadrantSize && tx < world.width(); tx++){
|
||||||
for(int ty = ry * structQuadrantSize; ty < (ry + 1) * structQuadrantSize && ty < world.height(); ty++){
|
for(int ty = ry * quadrantSize; ty < (ry + 1) * quadrantSize && ty < world.height(); ty++){
|
||||||
Tile other = world.ltile(tx, ty);
|
Tile other = world.ltile(tx, ty);
|
||||||
|
|
||||||
if(other == null) continue;
|
if(other == null) continue;
|
||||||
@@ -196,7 +193,7 @@ public class BlockIndexer{
|
|||||||
/**
|
/**
|
||||||
* Returns a set of tiles that have ores of the specified type nearby.
|
* Returns a set of tiles that have ores of the specified type nearby.
|
||||||
* While each tile in the set is not guaranteed to have an ore directly on it,
|
* While each tile in the set is not guaranteed to have an ore directly on it,
|
||||||
* each tile will at least have an ore within {@link #oreQuadrantSize} / 2 blocks of it.
|
* each tile will at least have an ore within {@link #quadrantSize} / 2 blocks of it.
|
||||||
* Only specific ore types are scanned. See {@link #scanOres}.
|
* Only specific ore types are scanned. See {@link #scanOres}.
|
||||||
*/
|
*/
|
||||||
public ObjectSet<Tile> getOrePositions(Item item){
|
public ObjectSet<Tile> getOrePositions(Item item){
|
||||||
@@ -205,12 +202,12 @@ public class BlockIndexer{
|
|||||||
|
|
||||||
/** Find the closest ore block relative to a position. */
|
/** Find the closest ore block relative to a position. */
|
||||||
public Tile findClosestOre(float xp, float yp, Item item){
|
public Tile findClosestOre(float xp, float yp, Item item){
|
||||||
Tile tile = Geometry.findClosest(xp, yp, world.indexer.getOrePositions(item));
|
Tile tile = Geometry.findClosest(xp, yp, getOrePositions(item));
|
||||||
|
|
||||||
if(tile == null) return null;
|
if(tile == null) return null;
|
||||||
|
|
||||||
for(int x = Math.max(0, tile.x - oreQuadrantSize / 2); x < tile.x + oreQuadrantSize / 2 && x < world.width(); x++){
|
for(int x = Math.max(0, tile.x - quadrantSize / 2); x < tile.x + quadrantSize / 2 && x < world.width(); x++){
|
||||||
for(int y = Math.max(0, tile.y - oreQuadrantSize / 2); y < tile.y + oreQuadrantSize / 2 && y < world.height(); y++){
|
for(int y = Math.max(0, tile.y - quadrantSize / 2); y < tile.y + quadrantSize / 2 && y < world.height(); y++){
|
||||||
Tile res = world.tile(x, y);
|
Tile res = world.tile(x, y);
|
||||||
if(res.block() == Blocks.air && res.drop() == item){
|
if(res.block() == Blocks.air && res.drop() == item){
|
||||||
return res;
|
return res;
|
||||||
@@ -222,8 +219,7 @@ public class BlockIndexer{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void process(Tile tile){
|
private void process(Tile tile){
|
||||||
if(tile.block().flags.size() > 0 &&
|
if(tile.block().flags.size() > 0 && tile.getTeam() != Team.none){
|
||||||
tile.getTeam() != Team.none){
|
|
||||||
ObjectSet<Tile>[] map = getFlagged(tile.getTeam());
|
ObjectSet<Tile>[] map = getFlagged(tile.getTeam());
|
||||||
|
|
||||||
for(BlockFlag flag : tile.block().flags){
|
for(BlockFlag flag : tile.block().flags){
|
||||||
@@ -239,16 +235,16 @@ public class BlockIndexer{
|
|||||||
|
|
||||||
if(ores == null) return;
|
if(ores == null) return;
|
||||||
|
|
||||||
int quadrantX = tile.x / oreQuadrantSize;
|
int quadrantX = tile.x / quadrantSize;
|
||||||
int quadrantY = tile.y / oreQuadrantSize;
|
int quadrantY = tile.y / quadrantSize;
|
||||||
itemSet.clear();
|
itemSet.clear();
|
||||||
|
|
||||||
Tile rounded = world.tile(Mathf.clamp(quadrantX * oreQuadrantSize + oreQuadrantSize / 2, 0, world.width() - 1),
|
Tile rounded = world.tile(Mathf.clamp(quadrantX * quadrantSize + quadrantSize / 2, 0, world.width() - 1),
|
||||||
Mathf.clamp(quadrantY * oreQuadrantSize + oreQuadrantSize / 2, 0, world.height() - 1));
|
Mathf.clamp(quadrantY * quadrantSize + quadrantSize / 2, 0, world.height() - 1));
|
||||||
|
|
||||||
//find all items that this quadrant contains
|
//find all items that this quadrant contains
|
||||||
for(int x = quadrantX * structQuadrantSize; x < world.width() && x < (quadrantX + 1) * structQuadrantSize; x++){
|
for(int x = quadrantX * quadrantSize; x < world.width() && x < (quadrantX + 1) * quadrantSize; x++){
|
||||||
for(int y = quadrantY * structQuadrantSize; y < world.height() && y < (quadrantY + 1) * structQuadrantSize; y++){
|
for(int y = quadrantY * quadrantSize; y < world.height() && y < (quadrantY + 1) * quadrantSize; y++){
|
||||||
Tile result = world.tile(x, y);
|
Tile result = world.tile(x, y);
|
||||||
if(result == null || result.drop() == null || !scanOres.contains(result.drop())) continue;
|
if(result == null || result.drop() == null || !scanOres.contains(result.drop())) continue;
|
||||||
|
|
||||||
@@ -273,8 +269,8 @@ public class BlockIndexer{
|
|||||||
if(structQuadrants == null) return;
|
if(structQuadrants == null) return;
|
||||||
|
|
||||||
//this quadrant is now 'dirty', re-scan the whole thing
|
//this quadrant is now 'dirty', re-scan the whole thing
|
||||||
int quadrantX = tile.x / structQuadrantSize;
|
int quadrantX = tile.x / quadrantSize;
|
||||||
int quadrantY = tile.y / structQuadrantSize;
|
int quadrantY = tile.y / quadrantSize;
|
||||||
int index = quadrantX + quadrantY * quadWidth();
|
int index = quadrantX + quadrantY * quadWidth();
|
||||||
|
|
||||||
for(Team team : Team.all){
|
for(Team team : Team.all){
|
||||||
@@ -289,8 +285,8 @@ public class BlockIndexer{
|
|||||||
structQuadrants[data.team.ordinal()].set(quadrantX, quadrantY, false);
|
structQuadrants[data.team.ordinal()].set(quadrantX, quadrantY, false);
|
||||||
|
|
||||||
outer:
|
outer:
|
||||||
for(int x = quadrantX * structQuadrantSize; x < world.width() && x < (quadrantX + 1) * structQuadrantSize; x++){
|
for(int x = quadrantX * quadrantSize; x < world.width() && x < (quadrantX + 1) * quadrantSize; x++){
|
||||||
for(int y = quadrantY * structQuadrantSize; y < world.height() && y < (quadrantY + 1) * structQuadrantSize; y++){
|
for(int y = quadrantY * quadrantSize; y < world.height() && y < (quadrantY + 1) * quadrantSize; y++){
|
||||||
Tile result = world.ltile(x, y);
|
Tile result = world.ltile(x, y);
|
||||||
//when a targetable block is found, mark this quadrant as occupied and stop searching
|
//when a targetable block is found, mark this quadrant as occupied and stop searching
|
||||||
if(result.entity != null && result.getTeam() == data.team){
|
if(result.entity != null && result.getTeam() == data.team){
|
||||||
@@ -307,11 +303,11 @@ public class BlockIndexer{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int quadWidth(){
|
private int quadWidth(){
|
||||||
return Mathf.ceil(world.width() / (float)structQuadrantSize);
|
return Mathf.ceil(world.width() / (float)quadrantSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int quadHeight(){
|
private int quadHeight(){
|
||||||
return Mathf.ceil(world.height() / (float)structQuadrantSize);
|
return Mathf.ceil(world.height() / (float)quadrantSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void scanOres(){
|
private void scanOres(){
|
||||||
@@ -324,8 +320,8 @@ public class BlockIndexer{
|
|||||||
|
|
||||||
for(int x = 0; x < world.width(); x++){
|
for(int x = 0; x < world.width(); x++){
|
||||||
for(int y = 0; y < world.height(); y++){
|
for(int y = 0; y < world.height(); y++){
|
||||||
int qx = (x / oreQuadrantSize);
|
int qx = (x / quadrantSize);
|
||||||
int qy = (y / oreQuadrantSize);
|
int qy = (y / quadrantSize);
|
||||||
|
|
||||||
Tile tile = world.tile(x, y);
|
Tile tile = world.tile(x, y);
|
||||||
|
|
||||||
@@ -333,8 +329,8 @@ public class BlockIndexer{
|
|||||||
if(tile.drop() != null && scanOres.contains(tile.drop()) && tile.block() == Blocks.air){
|
if(tile.drop() != null && scanOres.contains(tile.drop()) && tile.block() == Blocks.air){
|
||||||
ores.get(tile.drop()).add(world.tile(
|
ores.get(tile.drop()).add(world.tile(
|
||||||
//make sure to clamp quadrant middle position, since it might go off bounds
|
//make sure to clamp quadrant middle position, since it might go off bounds
|
||||||
Mathf.clamp(qx * oreQuadrantSize + oreQuadrantSize / 2, 0, world.width() - 1),
|
Mathf.clamp(qx * quadrantSize + quadrantSize / 2, 0, world.width() - 1),
|
||||||
Mathf.clamp(qy * oreQuadrantSize + oreQuadrantSize / 2, 0, world.height() - 1)));
|
Mathf.clamp(qy * quadrantSize + quadrantSize / 2, 0, world.height() - 1)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ public class MapGenerateDialog extends FloatingDialog{
|
|||||||
}});
|
}});
|
||||||
visible(() -> generating && !updateEditorOnChange);
|
visible(() -> generating && !updateEditorOnChange);
|
||||||
}}).size(mobile ? 300f : 400f).padRight(10);
|
}}).size(mobile ? 300f : 400f).padRight(10);
|
||||||
t.pane(p -> filterTable = p).width(300f).marginRight(6).update(pane -> {
|
t.pane(p -> filterTable = p.marginRight(6)).width(300f).update(pane -> {
|
||||||
if(Core.scene.getKeyboardFocus() instanceof Dialog && Core.scene.getKeyboardFocus() != this){
|
if(Core.scene.getKeyboardFocus() instanceof Dialog && Core.scene.getKeyboardFocus() != this){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package io.anuke.mindustry.entities.type;
|
package io.anuke.mindustry.entities.type;
|
||||||
|
|
||||||
import io.anuke.annotations.Annotations.Loc;
|
import io.anuke.annotations.Annotations.*;
|
||||||
import io.anuke.annotations.Annotations.Remote;
|
|
||||||
import io.anuke.arc.Core;
|
import io.anuke.arc.Core;
|
||||||
import io.anuke.arc.graphics.g2d.Draw;
|
import io.anuke.arc.graphics.g2d.Draw;
|
||||||
import io.anuke.arc.graphics.g2d.TextureRegion;
|
import io.anuke.arc.graphics.g2d.TextureRegion;
|
||||||
@@ -86,7 +85,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
|||||||
return type.typeID;
|
return type.typeID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Tile getSpawner(){
|
public @Nullable Tile getSpawner(){
|
||||||
return world.tile(spawner);
|
return world.tile(spawner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -74,6 +74,10 @@ public class Map implements Comparable<Map>{
|
|||||||
return tags.get("othercore", "true").equals("true");
|
return tags.get("othercore", "true").equals("true");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean attribute(MapAttribute attr){
|
||||||
|
return tags.getBool(attr.name());
|
||||||
|
}
|
||||||
|
|
||||||
public String author(){
|
public String author(){
|
||||||
return tag("author");
|
return tag("author");
|
||||||
}
|
}
|
||||||
|
|||||||
29
core/src/io/anuke/mindustry/maps/MapAttribute.java
Normal file
29
core/src/io/anuke/mindustry/maps/MapAttribute.java
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package io.anuke.mindustry.maps;
|
||||||
|
|
||||||
|
import io.anuke.arc.collection.*;
|
||||||
|
import io.anuke.arc.function.*;
|
||||||
|
|
||||||
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
|
/** Defines a specific type of attribute for a map, usually whether or not it supports a certain type of mode.*/
|
||||||
|
public enum MapAttribute{
|
||||||
|
/** Whether a map has a player spawnpoint in it.*/
|
||||||
|
spawnpoint(teams -> teams.contains(defaultTeam.ordinal())),
|
||||||
|
/** Whether a map has a wave team core to attack.*/
|
||||||
|
attack(teams -> teams.contains(waveTeam.ordinal())),
|
||||||
|
/** Whether this map supports PvP.*/
|
||||||
|
pvp(teams -> teams.size > 1);
|
||||||
|
|
||||||
|
private final Predicate<IntSet> validator;
|
||||||
|
|
||||||
|
public static final MapAttribute[] all = values();
|
||||||
|
|
||||||
|
MapAttribute(Predicate<IntSet> set){
|
||||||
|
this.validator = set;
|
||||||
|
}
|
||||||
|
|
||||||
|
//todo also take into account enemy spawnpoints
|
||||||
|
public boolean validate(IntSet teams){
|
||||||
|
return validator.test(teams);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,7 +20,7 @@ import static io.anuke.mindustry.Vars.*;
|
|||||||
|
|
||||||
public class Maps implements Disposable{
|
public class Maps implements Disposable{
|
||||||
/** List of all built-in maps. Filenames only. */
|
/** List of all built-in maps. Filenames only. */
|
||||||
private static String[] defaultMapNames = {"fortress", "labyrinth", "islands", "tendrils", "caldera", "glacier"};
|
private static String[] defaultMapNames = {"fortress", "labyrinth", "islands", "tendrils", "caldera", "glacier", "vein"};
|
||||||
/** All maps stored in an ordered array. */
|
/** All maps stored in an ordered array. */
|
||||||
private Array<Map> maps = new Array<>();
|
private Array<Map> maps = new Array<>();
|
||||||
/** Serializer for meta. */
|
/** Serializer for meta. */
|
||||||
|
|||||||
Reference in New Issue
Block a user