New team system / Prototype dedicated PvP gamemode
This commit is contained in:
@@ -26,7 +26,7 @@ allprojects {
|
|||||||
appName = 'Mindustry'
|
appName = 'Mindustry'
|
||||||
gdxVersion = '1.9.8'
|
gdxVersion = '1.9.8'
|
||||||
roboVMVersion = '2.3.0'
|
roboVMVersion = '2.3.0'
|
||||||
uCoreVersion = 'e492954e86'
|
uCoreVersion = 'd30ec505beb78da25fea3a5aa78f79260f2fb65b'
|
||||||
|
|
||||||
getVersionString = {
|
getVersionString = {
|
||||||
String buildVersion = getBuildVersion()
|
String buildVersion = getBuildVersion()
|
||||||
|
|||||||
@@ -34,6 +34,10 @@ public class Vars{
|
|||||||
public static final float wavespace = 60 * 60 * 1.5f;
|
public static final float wavespace = 60 * 60 * 1.5f;
|
||||||
//set ridiculously high for now
|
//set ridiculously high for now
|
||||||
public static final float coreBuildRange = 800999f;
|
public static final float coreBuildRange = 800999f;
|
||||||
|
//team of the player by default
|
||||||
|
public static final Team defaultTeam = Team.blue;
|
||||||
|
//team of the enemy in waves
|
||||||
|
public static final Team waveTeam = Team.red;
|
||||||
|
|
||||||
public static final float enemyCoreBuildRange = 400f;
|
public static final float enemyCoreBuildRange = 400f;
|
||||||
//discord group URL
|
//discord group URL
|
||||||
|
|||||||
@@ -1,17 +1,14 @@
|
|||||||
package io.anuke.mindustry.ai;
|
package io.anuke.mindustry.ai;
|
||||||
|
|
||||||
import com.badlogic.gdx.math.Vector2;
|
import com.badlogic.gdx.math.Vector2;
|
||||||
import com.badlogic.gdx.utils.Bits;
|
import com.badlogic.gdx.utils.*;
|
||||||
import com.badlogic.gdx.utils.IntMap;
|
|
||||||
import com.badlogic.gdx.utils.ObjectMap;
|
|
||||||
import com.badlogic.gdx.utils.ObjectSet;
|
|
||||||
import io.anuke.mindustry.content.Items;
|
import io.anuke.mindustry.content.Items;
|
||||||
import io.anuke.mindustry.content.blocks.Blocks;
|
import io.anuke.mindustry.content.blocks.Blocks;
|
||||||
import io.anuke.mindustry.entities.TileEntity;
|
import io.anuke.mindustry.entities.TileEntity;
|
||||||
import io.anuke.mindustry.game.EventType.TileChangeEvent;
|
import io.anuke.mindustry.game.EventType.TileChangeEvent;
|
||||||
import io.anuke.mindustry.game.EventType.WorldLoadEvent;
|
import io.anuke.mindustry.game.EventType.WorldLoadEvent;
|
||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
import io.anuke.mindustry.game.TeamInfo.TeamData;
|
import io.anuke.mindustry.game.Teams.TeamData;
|
||||||
import io.anuke.mindustry.type.Item;
|
import io.anuke.mindustry.type.Item;
|
||||||
import io.anuke.mindustry.world.Tile;
|
import io.anuke.mindustry.world.Tile;
|
||||||
import io.anuke.mindustry.world.meta.BlockFlag;
|
import io.anuke.mindustry.world.meta.BlockFlag;
|
||||||
@@ -21,66 +18,43 @@ import io.anuke.ucore.function.Predicate;
|
|||||||
import io.anuke.ucore.util.EnumSet;
|
import io.anuke.ucore.util.EnumSet;
|
||||||
import io.anuke.ucore.util.Geometry;
|
import io.anuke.ucore.util.Geometry;
|
||||||
import io.anuke.ucore.util.Mathf;
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
import io.anuke.ucore.util.ThreadArray;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
//TODO consider using quadtrees for finding specific types of blocks within an area
|
//TODO consider using quadtrees for finding specific types of blocks within an area
|
||||||
//TODO maybe use Arrays instead of ObjectSets?
|
//TODO maybe use Arrays instead of ObjectSets?
|
||||||
|
|
||||||
/**
|
/**Class used for indexing special target blocks for AI.*/
|
||||||
* Class used for indexing special target blocks for AI.
|
|
||||||
*/
|
|
||||||
public class BlockIndexer{
|
public class BlockIndexer{
|
||||||
/**
|
/**Size of one ore quadrant.*/
|
||||||
* Size of one ore quadrant.
|
|
||||||
*/
|
|
||||||
private final static int oreQuadrantSize = 20;
|
private final static int oreQuadrantSize = 20;
|
||||||
/**
|
/**Size of one structure quadrant.*/
|
||||||
* Size of one structure quadrant.
|
|
||||||
*/
|
|
||||||
private final static int structQuadrantSize = 12;
|
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(Items.copper, Items.coal, Items.lead, Items.thorium, Items.titanium);
|
private final ObjectSet<Item> scanOres = ObjectSet.with(Items.copper, Items.coal, Items.lead, Items.thorium, Items.titanium);
|
||||||
private final ObjectSet<Item> itemSet = new ObjectSet<>();
|
private final ObjectSet<Item> itemSet = new ObjectSet<>();
|
||||||
/**
|
/**Stores all ore quadtrants on the map.*/
|
||||||
* Stores all ore quadtrants on the map.
|
|
||||||
*/
|
|
||||||
private ObjectMap<Item, ObjectSet<Tile>> ores;
|
private ObjectMap<Item, ObjectSet<Tile>> ores;
|
||||||
/**
|
/**Tags all quadrants.*/
|
||||||
* Tags all quadrants.
|
|
||||||
*/
|
|
||||||
private Bits[] structQuadrants;
|
private Bits[] structQuadrants;
|
||||||
|
|
||||||
/**
|
/**Maps teams to a map of flagged tiles by type.*/
|
||||||
* Maps teams to a map of flagged tiles by type.
|
private ObjectSet<Tile>[][] flagMap = new ObjectSet[Team.all.length][BlockFlag.all.length];
|
||||||
*/
|
/**Maps tile positions to their last known tile index data.*/
|
||||||
private ObjectMap<BlockFlag, ObjectSet<Tile>> enemyMap = new ObjectMap<>();
|
|
||||||
/**
|
|
||||||
* Maps teams to a map of flagged tiles by type.
|
|
||||||
*/
|
|
||||||
private ObjectMap<BlockFlag, ObjectSet<Tile>> allyMap = new ObjectMap<>();
|
|
||||||
/**
|
|
||||||
* Empty map for invalid teams.
|
|
||||||
*/
|
|
||||||
private ObjectMap<BlockFlag, ObjectSet<Tile>> emptyMap = new ObjectMap<>();
|
|
||||||
/**
|
|
||||||
* Maps tile positions to their last known tile index data.
|
|
||||||
*/
|
|
||||||
private IntMap<TileIndex> typeMap = new IntMap<>();
|
private IntMap<TileIndex> typeMap = new IntMap<>();
|
||||||
/**
|
/**Empty set used for returning.*/
|
||||||
* Empty array used for returning.
|
private ObjectSet<Tile> emptySet = new ObjectSet<>();
|
||||||
*/
|
/**Array used for returning and reusing.*/
|
||||||
private ObjectSet<Tile> emptyArray = new ObjectSet<>();
|
private Array<Tile> returnArray = new ThreadArray<>();
|
||||||
|
|
||||||
public BlockIndexer(){
|
public BlockIndexer(){
|
||||||
Events.on(TileChangeEvent.class, tile -> {
|
Events.on(TileChangeEvent.class, tile -> {
|
||||||
if(typeMap.get(tile.packedPosition()) != null){
|
if(typeMap.get(tile.packedPosition()) != null){
|
||||||
TileIndex index = typeMap.get(tile.packedPosition());
|
TileIndex index = typeMap.get(tile.packedPosition());
|
||||||
for(BlockFlag flag : index.flags){
|
for(BlockFlag flag : index.flags){
|
||||||
getMap(index.team).get(flag).remove(tile);
|
getFlagged(index.team)[flag.ordinal()].remove(tile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
process(tile);
|
process(tile);
|
||||||
@@ -88,8 +62,12 @@ public class BlockIndexer{
|
|||||||
});
|
});
|
||||||
|
|
||||||
Events.on(WorldLoadEvent.class, () -> {
|
Events.on(WorldLoadEvent.class, () -> {
|
||||||
enemyMap.clear();
|
flagMap = new ObjectSet[Team.all.length][BlockFlag.all.length];
|
||||||
allyMap.clear();
|
for(int i = 0; i < flagMap.length; i++){
|
||||||
|
for(int j = 0; j < BlockFlag.all.length; j++){
|
||||||
|
flagMap[i][j] = new ObjectSet<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
typeMap.clear();
|
typeMap.clear();
|
||||||
ores = null;
|
ores = null;
|
||||||
|
|
||||||
@@ -115,18 +93,26 @@ public class BlockIndexer{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private ObjectSet<Tile>[] getFlagged(Team team){
|
||||||
* Get all allied blocks with a flag.
|
return flagMap[team.ordinal()];
|
||||||
*/
|
|
||||||
public ObjectSet<Tile> getAllied(Team team, BlockFlag type){
|
|
||||||
return state.teams.has(team) ? (state.teams.get(team).ally ? allyMap : enemyMap).get(type, emptyArray) : emptyArray;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**Get all allied blocks with a flag.*/
|
||||||
* Get all enemy blocks with a flag.
|
public ObjectSet<Tile> getAllied(Team team, BlockFlag type){
|
||||||
*/
|
return flagMap[team.ordinal()][type.ordinal()];
|
||||||
public ObjectSet<Tile> getEnemy(Team team, BlockFlag type){
|
}
|
||||||
return (!state.teams.get(team).ally ? allyMap : enemyMap).get(type, emptyArray);
|
|
||||||
|
/**Get all enemy blocks with a flag.*/
|
||||||
|
public Array<Tile> getEnemy(Team team, BlockFlag type){
|
||||||
|
returnArray.clear();
|
||||||
|
for(Team enemy : state.teams.enemiesOf(team)){
|
||||||
|
if(state.teams.isActive(enemy)){
|
||||||
|
for(Tile tile : getFlagged(enemy)[type.ordinal()]){
|
||||||
|
returnArray.add(tile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TileEntity findTile(Team team, float x, float y, float range, Predicate<Tile> pred){
|
public TileEntity findTile(Team team, float x, float y, float range, Predicate<Tile> pred){
|
||||||
@@ -166,7 +152,7 @@ public class BlockIndexer{
|
|||||||
* 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){
|
||||||
return ores.get(item, emptyArray);
|
return ores.get(item, emptySet);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -192,19 +178,15 @@ public class BlockIndexer{
|
|||||||
private void process(Tile tile){
|
private void process(Tile tile){
|
||||||
if(tile.block().flags != null &&
|
if(tile.block().flags != null &&
|
||||||
tile.getTeam() != Team.none){
|
tile.getTeam() != Team.none){
|
||||||
ObjectMap<BlockFlag, ObjectSet<Tile>> map = getMap(tile.getTeam());
|
ObjectSet<Tile>[] map = getFlagged(tile.getTeam());
|
||||||
|
|
||||||
for(BlockFlag flag : tile.block().flags){
|
for(BlockFlag flag : tile.block().flags){
|
||||||
|
|
||||||
ObjectSet<Tile> arr = map.get(flag);
|
ObjectSet<Tile> arr = map[flag.ordinal()];
|
||||||
if(arr == null){
|
|
||||||
arr = new ObjectSet<>();
|
|
||||||
map.put(flag, arr);
|
|
||||||
}
|
|
||||||
|
|
||||||
arr.add(tile);
|
arr.add(tile);
|
||||||
|
|
||||||
map.put(flag, arr);
|
map[flag.ordinal()] = arr;
|
||||||
}
|
}
|
||||||
typeMap.put(tile.packedPosition(), new TileIndex(tile.block().flags, tile.getTeam()));
|
typeMap.put(tile.packedPosition(), new TileIndex(tile.block().flags, tile.getTeam()));
|
||||||
}
|
}
|
||||||
@@ -247,7 +229,8 @@ public class BlockIndexer{
|
|||||||
int quadrantY = tile.y / structQuadrantSize;
|
int quadrantY = tile.y / structQuadrantSize;
|
||||||
int index = quadrantX + quadrantY * quadWidth();
|
int index = quadrantX + quadrantY * quadWidth();
|
||||||
|
|
||||||
for(TeamData data : state.teams.getTeams()){
|
for(Team team : Team.all){
|
||||||
|
TeamData data = state.teams.get(team);
|
||||||
|
|
||||||
//fast-set this quadrant to 'occupied' if the tile just placed is already of this team
|
//fast-set this quadrant to 'occupied' if the tile just placed is already of this team
|
||||||
if(tile.getTeam() == data.team && tile.entity != null){
|
if(tile.getTeam() == data.team && tile.entity != null){
|
||||||
@@ -284,11 +267,6 @@ public class BlockIndexer{
|
|||||||
return Mathf.ceil(world.height() / (float) structQuadrantSize);
|
return Mathf.ceil(world.height() / (float) structQuadrantSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ObjectMap<BlockFlag, ObjectSet<Tile>> getMap(Team team){
|
|
||||||
if(!state.teams.has(team)) return emptyMap;
|
|
||||||
return state.teams.get(team).ally ? allyMap : enemyMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void scanOres(){
|
private void scanOres(){
|
||||||
ores = new ObjectMap<>();
|
ores = new ObjectMap<>();
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
package io.anuke.mindustry.ai;
|
package io.anuke.mindustry.ai;
|
||||||
|
|
||||||
import com.badlogic.gdx.math.GridPoint2;
|
import com.badlogic.gdx.math.GridPoint2;
|
||||||
|
import com.badlogic.gdx.utils.Array;
|
||||||
import com.badlogic.gdx.utils.IntArray;
|
import com.badlogic.gdx.utils.IntArray;
|
||||||
import com.badlogic.gdx.utils.ObjectSet;
|
|
||||||
import com.badlogic.gdx.utils.ObjectSet.ObjectSetIterator;
|
|
||||||
import com.badlogic.gdx.utils.Queue;
|
import com.badlogic.gdx.utils.Queue;
|
||||||
import com.badlogic.gdx.utils.TimeUtils;
|
import com.badlogic.gdx.utils.TimeUtils;
|
||||||
import io.anuke.mindustry.game.EventType.TileChangeEvent;
|
import io.anuke.mindustry.game.EventType.TileChangeEvent;
|
||||||
import io.anuke.mindustry.game.EventType.WorldLoadEvent;
|
import io.anuke.mindustry.game.EventType.WorldLoadEvent;
|
||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
import io.anuke.mindustry.game.TeamInfo.TeamData;
|
import io.anuke.mindustry.game.Teams.TeamData;
|
||||||
import io.anuke.mindustry.net.Net;
|
import io.anuke.mindustry.net.Net;
|
||||||
import io.anuke.mindustry.world.Tile;
|
import io.anuke.mindustry.world.Tile;
|
||||||
import io.anuke.mindustry.world.meta.BlockFlag;
|
import io.anuke.mindustry.world.meta.BlockFlag;
|
||||||
@@ -30,8 +29,9 @@ public class Pathfinder{
|
|||||||
Events.on(TileChangeEvent.class, tile -> {
|
Events.on(TileChangeEvent.class, tile -> {
|
||||||
if(Net.client()) return;
|
if(Net.client()) return;
|
||||||
|
|
||||||
for(TeamData data : state.teams.getTeams()){
|
for(Team team : Team.all){
|
||||||
if(data.team != tile.getTeam() && paths[data.team.ordinal()].weights[tile.x][tile.y] >= Float.MAX_VALUE){
|
TeamData data = state.teams.get(team);
|
||||||
|
if(state.teams.isActive(team) && data.team != tile.getTeam() && paths[data.team.ordinal()].weights[tile.x][tile.y] >= Float.MAX_VALUE){
|
||||||
update(tile, data.team);
|
update(tile, data.team);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -43,10 +43,10 @@ public class Pathfinder{
|
|||||||
public void update(){
|
public void update(){
|
||||||
if(Net.client()) return;
|
if(Net.client()) return;
|
||||||
|
|
||||||
ObjectSetIterator<TeamData> iterator = new ObjectSetIterator<>(state.teams.getTeams());
|
for(Team team : Team.all){
|
||||||
|
if(state.teams.isActive(team)){
|
||||||
for(TeamData team : iterator){
|
updateFrontier(team, maxUpdate);
|
||||||
updateFrontier(team.team, maxUpdate);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ public class Pathfinder{
|
|||||||
|
|
||||||
path.lastSearchTime = TimeUtils.millis();
|
path.lastSearchTime = TimeUtils.millis();
|
||||||
|
|
||||||
ObjectSet<Tile> set = world.indexer().getEnemy(team, BlockFlag.target);
|
Array<Tile> set = world.indexer().getEnemy(team, BlockFlag.target);
|
||||||
for(Tile other : set){
|
for(Tile other : set){
|
||||||
path.weights[other.x][other.y] = 0;
|
path.weights[other.x][other.y] = 0;
|
||||||
path.searches[other.x][other.y] = path.search;
|
path.searches[other.x][other.y] = path.search;
|
||||||
@@ -173,11 +173,13 @@ public class Pathfinder{
|
|||||||
paths = new PathData[Team.all.length];
|
paths = new PathData[Team.all.length];
|
||||||
blocked.clear();
|
blocked.clear();
|
||||||
|
|
||||||
for(TeamData data : state.teams.getTeams()){
|
for(Team team : Team.all){
|
||||||
PathData path = new PathData();
|
PathData path = new PathData();
|
||||||
paths[data.team.ordinal()] = path;
|
paths[team.ordinal()] = path;
|
||||||
|
|
||||||
createFor(data.team);
|
if(state.teams.isActive(team)){
|
||||||
|
createFor(team);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state.spawner.checkAllQuadrants();
|
state.spawner.checkAllQuadrants();
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import io.anuke.mindustry.ai.WaveSpawner;
|
|||||||
import io.anuke.mindustry.game.Difficulty;
|
import io.anuke.mindustry.game.Difficulty;
|
||||||
import io.anuke.mindustry.game.EventType.StateChangeEvent;
|
import io.anuke.mindustry.game.EventType.StateChangeEvent;
|
||||||
import io.anuke.mindustry.game.GameMode;
|
import io.anuke.mindustry.game.GameMode;
|
||||||
import io.anuke.mindustry.game.TeamInfo;
|
import io.anuke.mindustry.game.Teams;
|
||||||
import io.anuke.mindustry.net.Net;
|
import io.anuke.mindustry.net.Net;
|
||||||
import io.anuke.ucore.core.Events;
|
import io.anuke.ucore.core.Events;
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ public class GameState{
|
|||||||
public Difficulty difficulty = Difficulty.normal;
|
public Difficulty difficulty = Difficulty.normal;
|
||||||
public boolean friendlyFire;
|
public boolean friendlyFire;
|
||||||
public WaveSpawner spawner = new WaveSpawner();
|
public WaveSpawner spawner = new WaveSpawner();
|
||||||
public TeamInfo teams = new TeamInfo();
|
public Teams teams = new Teams();
|
||||||
private State state = State.menu;
|
private State state = State.menu;
|
||||||
|
|
||||||
public void set(State astate){
|
public void set(State astate){
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ import io.anuke.mindustry.game.EventType.PlayEvent;
|
|||||||
import io.anuke.mindustry.game.EventType.ResetEvent;
|
import io.anuke.mindustry.game.EventType.ResetEvent;
|
||||||
import io.anuke.mindustry.game.EventType.WaveEvent;
|
import io.anuke.mindustry.game.EventType.WaveEvent;
|
||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
import io.anuke.mindustry.game.TeamInfo;
|
import io.anuke.mindustry.game.Teams;
|
||||||
import io.anuke.mindustry.game.TeamInfo.TeamData;
|
|
||||||
import io.anuke.mindustry.net.Net;
|
import io.anuke.mindustry.net.Net;
|
||||||
import io.anuke.mindustry.type.Item;
|
import io.anuke.mindustry.type.Item;
|
||||||
import io.anuke.mindustry.type.ItemStack;
|
import io.anuke.mindustry.type.ItemStack;
|
||||||
@@ -50,26 +49,25 @@ public class Logic extends Module{
|
|||||||
state.set(State.playing);
|
state.set(State.playing);
|
||||||
state.wavetime = wavespace * state.difficulty.timeScaling * 2;
|
state.wavetime = wavespace * state.difficulty.timeScaling * 2;
|
||||||
|
|
||||||
for(TeamData team : state.teams.getTeams(true)){
|
for(Tile tile : state.teams.get(defaultTeam).cores){
|
||||||
for(Tile tile : team.cores){
|
if(debug){
|
||||||
if(debug){
|
for(Item item : Item.all()){
|
||||||
for(Item item : Item.all()){
|
if(item.type == ItemType.material){
|
||||||
if(item.type == ItemType.material){
|
tile.entity.items.set(item, 1000);
|
||||||
tile.entity.items.set(item, 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(world.getSector() != null){
|
|
||||||
Array<ItemStack> items = world.getSector().startingItems;
|
|
||||||
for(ItemStack stack : items){
|
|
||||||
tile.entity.items.add(stack.item, stack.amount);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(world.getSector() != null){
|
||||||
|
Array<ItemStack> items = world.getSector().startingItems;
|
||||||
|
for(ItemStack stack : items){
|
||||||
|
tile.entity.items.add(stack.item, stack.amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Events.fire(PlayEvent.class);
|
Events.fire(PlayEvent.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,9 +75,7 @@ public class Logic extends Module{
|
|||||||
state.wave = 1;
|
state.wave = 1;
|
||||||
state.wavetime = wavespace * state.difficulty.timeScaling;
|
state.wavetime = wavespace * state.difficulty.timeScaling;
|
||||||
state.gameOver = false;
|
state.gameOver = false;
|
||||||
state.teams = new TeamInfo();
|
state.teams = new Teams();
|
||||||
state.teams.add(Team.blue, true);
|
|
||||||
state.teams.add(Team.red, false);
|
|
||||||
|
|
||||||
Timers.clear();
|
Timers.clear();
|
||||||
Entities.clear();
|
Entities.clear();
|
||||||
@@ -96,11 +92,12 @@ public class Logic extends Module{
|
|||||||
Events.fire(WaveEvent.class);
|
Events.fire(WaveEvent.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//for gameOver to trigger, there must not be no cores remaining at all; obviously this never triggers in PvP
|
||||||
private void checkGameOver(){
|
private void checkGameOver(){
|
||||||
boolean gameOver = true;
|
boolean gameOver = true;
|
||||||
|
|
||||||
for(TeamData data : state.teams.getTeams(true)){
|
for(Team team : Team.all){
|
||||||
if(data.cores.size > 0){
|
if(state.teams.get(team).cores.size > 0){
|
||||||
gameOver = false;
|
gameOver = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import io.anuke.mindustry.core.GameState.State;
|
|||||||
import io.anuke.mindustry.entities.Player;
|
import io.anuke.mindustry.entities.Player;
|
||||||
import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest;
|
import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest;
|
||||||
import io.anuke.mindustry.entities.traits.SyncTrait;
|
import io.anuke.mindustry.entities.traits.SyncTrait;
|
||||||
|
import io.anuke.mindustry.game.Team;
|
||||||
import io.anuke.mindustry.game.Version;
|
import io.anuke.mindustry.game.Version;
|
||||||
import io.anuke.mindustry.gen.Call;
|
import io.anuke.mindustry.gen.Call;
|
||||||
import io.anuke.mindustry.gen.RemoteReadServer;
|
import io.anuke.mindustry.gen.RemoteReadServer;
|
||||||
@@ -31,6 +32,7 @@ import io.anuke.ucore.io.delta.ByteMatcherHash;
|
|||||||
import io.anuke.ucore.io.delta.DEZEncoder;
|
import io.anuke.ucore.io.delta.DEZEncoder;
|
||||||
import io.anuke.ucore.modules.Module;
|
import io.anuke.ucore.modules.Module;
|
||||||
import io.anuke.ucore.util.Log;
|
import io.anuke.ucore.util.Log;
|
||||||
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
@@ -166,6 +168,24 @@ public class NetServer extends Module{
|
|||||||
player.setNet(player.x, player.y);
|
player.setNet(player.x, player.y);
|
||||||
player.color.set(packet.color);
|
player.color.set(packet.color);
|
||||||
player.color.a = 1f;
|
player.color.a = 1f;
|
||||||
|
|
||||||
|
if(state.mode.isPvp){
|
||||||
|
//find team with minimum amount of players and auto-assign player to that.
|
||||||
|
Team min = Mathf.findMin(Team.all, team -> {
|
||||||
|
if(state.teams.isActive(team)){
|
||||||
|
int count = 0;
|
||||||
|
for(Player other : playerGroup.all()){
|
||||||
|
if(other.getTeam() == team){
|
||||||
|
count ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
return Integer.MAX_VALUE;
|
||||||
|
});
|
||||||
|
player.setTeam(min);
|
||||||
|
}
|
||||||
|
|
||||||
connections.put(id, player);
|
connections.put(id, player);
|
||||||
|
|
||||||
trace.playerid = player.id;
|
trace.playerid = player.id;
|
||||||
|
|||||||
@@ -244,6 +244,10 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
|||||||
return playerGroup;
|
return playerGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setTeam(Team team){
|
||||||
|
this.team = team;
|
||||||
|
}
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
//region draw methods
|
//region draw methods
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import com.badlogic.gdx.math.Vector2;
|
|||||||
import io.anuke.mindustry.content.blocks.Blocks;
|
import io.anuke.mindustry.content.blocks.Blocks;
|
||||||
import io.anuke.mindustry.entities.traits.*;
|
import io.anuke.mindustry.entities.traits.*;
|
||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
import io.anuke.mindustry.game.TeamInfo.TeamData;
|
import io.anuke.mindustry.game.Teams.TeamData;
|
||||||
import io.anuke.mindustry.net.Interpolator;
|
import io.anuke.mindustry.net.Interpolator;
|
||||||
import io.anuke.mindustry.net.Net;
|
import io.anuke.mindustry.net.Net;
|
||||||
import io.anuke.mindustry.type.StatusEffect;
|
import io.anuke.mindustry.type.StatusEffect;
|
||||||
@@ -179,17 +179,13 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
|||||||
}
|
}
|
||||||
|
|
||||||
public TileEntity getClosestCore(){
|
public TileEntity getClosestCore(){
|
||||||
if(state.teams.has(team)){
|
TeamData data = state.teams.get(team);
|
||||||
TeamData data = state.teams.get(team);
|
|
||||||
|
|
||||||
Tile tile = Geometry.findClosest(x, y, data.cores);
|
Tile tile = Geometry.findClosest(x, y, data.cores);
|
||||||
if(tile == null){
|
if(tile == null){
|
||||||
return null;
|
|
||||||
}else{
|
|
||||||
return tile.entity;
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
return null;
|
return null;
|
||||||
|
}else{
|
||||||
|
return tile.entity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package io.anuke.mindustry.entities;
|
|||||||
|
|
||||||
import com.badlogic.gdx.math.Rectangle;
|
import com.badlogic.gdx.math.Rectangle;
|
||||||
import com.badlogic.gdx.math.Vector2;
|
import com.badlogic.gdx.math.Vector2;
|
||||||
import com.badlogic.gdx.utils.ObjectSet;
|
|
||||||
import io.anuke.mindustry.entities.traits.TargetTrait;
|
import io.anuke.mindustry.entities.traits.TargetTrait;
|
||||||
import io.anuke.mindustry.entities.units.BaseUnit;
|
import io.anuke.mindustry.entities.units.BaseUnit;
|
||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
@@ -12,6 +11,7 @@ import io.anuke.ucore.entities.EntityGroup;
|
|||||||
import io.anuke.ucore.entities.EntityPhysics;
|
import io.anuke.ucore.entities.EntityPhysics;
|
||||||
import io.anuke.ucore.function.Consumer;
|
import io.anuke.ucore.function.Consumer;
|
||||||
import io.anuke.ucore.function.Predicate;
|
import io.anuke.ucore.function.Predicate;
|
||||||
|
import io.anuke.ucore.util.EnumSet;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
@@ -106,13 +106,7 @@ public class Units{
|
|||||||
* Returns the neareset ally tile in a range.
|
* Returns the neareset ally tile in a range.
|
||||||
*/
|
*/
|
||||||
public static TileEntity findAllyTile(Team team, float x, float y, float range, Predicate<Tile> pred){
|
public static TileEntity findAllyTile(Team team, float x, float y, float range, Predicate<Tile> pred){
|
||||||
for(Team enemy : state.teams.alliesOf(team)){
|
return world.indexer().findTile(team, x, y, range, pred);
|
||||||
TileEntity entity = world.indexer().findTile(enemy, x, y, range, pred);
|
|
||||||
if(entity != null){
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -271,7 +265,7 @@ public class Units{
|
|||||||
* Iterates over all units that are enemies of this team.
|
* Iterates over all units that are enemies of this team.
|
||||||
*/
|
*/
|
||||||
public static void getNearbyEnemies(Team team, Rectangle rect, Consumer<Unit> cons){
|
public static void getNearbyEnemies(Team team, Rectangle rect, Consumer<Unit> cons){
|
||||||
ObjectSet<Team> targets = state.teams.enemiesOf(team);
|
EnumSet<Team> targets = state.teams.enemiesOf(team);
|
||||||
|
|
||||||
for(Team other : targets){
|
for(Team other : targets){
|
||||||
EntityGroup<BaseUnit> group = unitGroups[other.ordinal()];
|
EntityGroup<BaseUnit> group = unitGroups[other.ordinal()];
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package io.anuke.mindustry.entities.units;
|
package io.anuke.mindustry.entities.units;
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||||
import com.badlogic.gdx.utils.ObjectSet;
|
|
||||||
import io.anuke.annotations.Annotations.Loc;
|
import io.anuke.annotations.Annotations.Loc;
|
||||||
import io.anuke.annotations.Annotations.Remote;
|
import io.anuke.annotations.Annotations.Remote;
|
||||||
import io.anuke.mindustry.Vars;
|
import io.anuke.mindustry.Vars;
|
||||||
@@ -15,7 +14,6 @@ import io.anuke.mindustry.entities.traits.ShooterTrait;
|
|||||||
import io.anuke.mindustry.entities.traits.SpawnerTrait;
|
import io.anuke.mindustry.entities.traits.SpawnerTrait;
|
||||||
import io.anuke.mindustry.entities.traits.TargetTrait;
|
import io.anuke.mindustry.entities.traits.TargetTrait;
|
||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
import io.anuke.mindustry.game.TeamInfo.TeamData;
|
|
||||||
import io.anuke.mindustry.gen.Call;
|
import io.anuke.mindustry.gen.Call;
|
||||||
import io.anuke.mindustry.graphics.Palette;
|
import io.anuke.mindustry.graphics.Palette;
|
||||||
import io.anuke.mindustry.net.Net;
|
import io.anuke.mindustry.net.Net;
|
||||||
@@ -188,16 +186,14 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public TileEntity getClosestEnemyCore(){
|
public TileEntity getClosestEnemyCore(){
|
||||||
if(Vars.state.teams.has(team)){
|
|
||||||
ObjectSet<TeamData> datas = Vars.state.teams.enemyDataOf(team);
|
|
||||||
|
|
||||||
for(TeamData data : datas){
|
for(Team enemy : Vars.state.teams.enemiesOf(team)){
|
||||||
Tile tile = Geometry.findClosest(x, y, data.cores);
|
Tile tile = Geometry.findClosest(x, y, Vars.state.teams.get(enemy).cores);
|
||||||
if(tile != null){
|
if(tile != null){
|
||||||
return tile.entity;
|
return tile.entity;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -241,8 +241,18 @@ public abstract class GroundUnit extends BaseUnit{
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void moveAwayFromCore(){
|
protected void moveAwayFromCore(){
|
||||||
|
Team enemy = null;
|
||||||
|
for(Team team : Vars.state.teams.enemiesOf(team)){
|
||||||
|
if(Vars.state.teams.isActive(team)){
|
||||||
|
enemy = team;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(enemy == null) return;
|
||||||
|
|
||||||
Tile tile = world.tileWorld(x, y);
|
Tile tile = world.tileWorld(x, y);
|
||||||
Tile targetTile = world.pathfinder().getTargetTile(Vars.state.teams.enemiesOf(team).first(), tile);
|
Tile targetTile = world.pathfinder().getTargetTile(enemy, tile);
|
||||||
TileEntity core = getClosestCore();
|
TileEntity core = getClosestCore();
|
||||||
|
|
||||||
if(tile == targetTile || core == null || distanceTo(core) < 90f) return;
|
if(tile == targetTile || core == null || distanceTo(core) < 90f) return;
|
||||||
|
|||||||
@@ -14,11 +14,15 @@ public enum GameMode{
|
|||||||
noWaves{{
|
noWaves{{
|
||||||
disableWaves = true;
|
disableWaves = true;
|
||||||
hidden = true;
|
hidden = true;
|
||||||
|
autoSpawn = true;
|
||||||
|
}},
|
||||||
|
pvp{{
|
||||||
|
disableWaves = true;
|
||||||
|
isPvp = true;
|
||||||
|
hidden = true;
|
||||||
}};
|
}};
|
||||||
public boolean infiniteResources;
|
|
||||||
public boolean disableWaveTimer;
|
public boolean infiniteResources, disableWaveTimer, disableWaves, hidden, autoSpawn, isPvp;
|
||||||
public boolean disableWaves;
|
|
||||||
public boolean hidden;
|
|
||||||
|
|
||||||
public String description(){
|
public String description(){
|
||||||
return Bundles.get("mode." + name() + ".description");
|
return Bundles.get("mode." + name() + ".description");
|
||||||
|
|||||||
@@ -1,143 +0,0 @@
|
|||||||
package io.anuke.mindustry.game;
|
|
||||||
|
|
||||||
import com.badlogic.gdx.utils.Array;
|
|
||||||
import com.badlogic.gdx.utils.ObjectMap;
|
|
||||||
import com.badlogic.gdx.utils.ObjectSet;
|
|
||||||
import io.anuke.mindustry.world.Tile;
|
|
||||||
import io.anuke.ucore.util.ThreadArray;
|
|
||||||
import io.anuke.ucore.util.ThreadSet;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class for various team-based utilities.
|
|
||||||
*/
|
|
||||||
public class TeamInfo{
|
|
||||||
private ObjectMap<Team, TeamData> map = new ObjectMap<>();
|
|
||||||
private ThreadSet<Team> allies = new ThreadSet<>(),
|
|
||||||
enemies = new ThreadSet<>();
|
|
||||||
private ThreadSet<TeamData> allyData = new ThreadSet<>(),
|
|
||||||
enemyData = new ThreadSet<>();
|
|
||||||
private ThreadSet<TeamData> allTeamData = new ThreadSet<>();
|
|
||||||
private ThreadSet<Team> allTeams = new ThreadSet<>();
|
|
||||||
private int allyBits = 0;
|
|
||||||
private int enemyBits = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns all teams on a side.
|
|
||||||
*/
|
|
||||||
public ObjectSet<TeamData> getTeams(boolean ally){
|
|
||||||
return ally ? allyData : enemyData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns all team data.
|
|
||||||
*/
|
|
||||||
public ObjectSet<TeamData> getTeams(){
|
|
||||||
return allTeamData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register a team.
|
|
||||||
*
|
|
||||||
* @param team The team type enum.
|
|
||||||
* @param ally Whether this team is an ally with the player or an enemy with the player.
|
|
||||||
* In PvP situations with dedicated servers, the sides can be arbitrary.
|
|
||||||
*/
|
|
||||||
public void add(Team team, boolean ally){
|
|
||||||
if(has(team)) throw new RuntimeException("Can't define team information twice!");
|
|
||||||
|
|
||||||
TeamData data = new TeamData(team, ally);
|
|
||||||
|
|
||||||
if(ally){
|
|
||||||
allies.add(team);
|
|
||||||
allyData.add(data);
|
|
||||||
allyBits |= (1 << team.ordinal());
|
|
||||||
}else{
|
|
||||||
enemies.add(team);
|
|
||||||
enemyData.add(data);
|
|
||||||
enemyBits |= (1 << team.ordinal());
|
|
||||||
}
|
|
||||||
|
|
||||||
allTeamData.add(data);
|
|
||||||
allTeams.add(team);
|
|
||||||
|
|
||||||
map.put(team, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns team data by type. Call {@link #has(Team)} first to make sure it's active!
|
|
||||||
*/
|
|
||||||
public TeamData get(Team team){
|
|
||||||
if(!has(team)) throw new RuntimeException("This team is not active! Check has() before calling get().");
|
|
||||||
return map.get(team);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether the specified team is active, e.g. whether it is participating in the game.
|
|
||||||
*/
|
|
||||||
public boolean has(Team team){
|
|
||||||
return map.containsKey(team);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a set of all teams that are enemies of this team.
|
|
||||||
* For teams not active, an empty set is returned.
|
|
||||||
*/
|
|
||||||
public ObjectSet<Team> enemiesOf(Team team){
|
|
||||||
boolean ally = allies.contains(team);
|
|
||||||
boolean enemy = enemies.contains(team);
|
|
||||||
|
|
||||||
//this team isn't even in the game, so target everything!
|
|
||||||
if(!ally && !enemy) return allTeams;
|
|
||||||
|
|
||||||
return ally ? enemies : allies;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a set of all teams that are allies of this team.
|
|
||||||
* For teams not active, an empty set is returned.
|
|
||||||
*/
|
|
||||||
public ObjectSet<Team> alliesOf(Team team){
|
|
||||||
boolean ally = allies.contains(team);
|
|
||||||
boolean enemy = enemies.contains(team);
|
|
||||||
|
|
||||||
//this team isn't even in the game, so target everything!
|
|
||||||
if(!ally && !enemy) return allTeams;
|
|
||||||
|
|
||||||
return !ally ? enemies : allies;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a set of all teams that are enemies of this team.
|
|
||||||
* For teams not active, an empty set is returned.
|
|
||||||
*/
|
|
||||||
public ObjectSet<TeamData> enemyDataOf(Team team){
|
|
||||||
boolean ally = allies.contains(team);
|
|
||||||
boolean enemy = enemies.contains(team);
|
|
||||||
|
|
||||||
//this team isn't even in the game, so target everything!
|
|
||||||
if(!ally && !enemy) return allTeamData;
|
|
||||||
|
|
||||||
return ally ? enemyData : allyData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether or not these two teams are enemies.
|
|
||||||
*/
|
|
||||||
public boolean areEnemies(Team team, Team other){
|
|
||||||
if(team == other) return false; //fast fail to be more efficient
|
|
||||||
boolean ally = (allyBits & (1 << team.ordinal())) != 0;
|
|
||||||
boolean enemy = (enemyBits & (1 << other.ordinal())) != 0;
|
|
||||||
return (ally == enemy) || !ally; //if it's not in the game, target everything.
|
|
||||||
}
|
|
||||||
|
|
||||||
public class TeamData{
|
|
||||||
public final Array<Tile> cores = new ThreadArray<>();
|
|
||||||
public final Team team;
|
|
||||||
public final boolean ally;
|
|
||||||
|
|
||||||
public TeamData(Team team, boolean ally){
|
|
||||||
this.team = team;
|
|
||||||
this.ally = ally;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
66
core/src/io/anuke/mindustry/game/Teams.java
Normal file
66
core/src/io/anuke/mindustry/game/Teams.java
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
package io.anuke.mindustry.game;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.utils.Array;
|
||||||
|
import io.anuke.mindustry.Vars;
|
||||||
|
import io.anuke.mindustry.world.Tile;
|
||||||
|
import io.anuke.ucore.util.EnumSet;
|
||||||
|
import io.anuke.ucore.util.ThreadArray;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for various team-based utilities.
|
||||||
|
*/
|
||||||
|
public class Teams{
|
||||||
|
private TeamData[] map = new TeamData[Team.all.length];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a team.
|
||||||
|
*
|
||||||
|
* @param team The team type enum.
|
||||||
|
* @param enemies The array of enemies of this team. Any team not in this array is considered neutral.
|
||||||
|
*/
|
||||||
|
public void add(Team team, Team... enemies){
|
||||||
|
if(map[team.ordinal()] != null) throw new RuntimeException("Can't define team information twice!");
|
||||||
|
|
||||||
|
map[team.ordinal()] = new TeamData(team, EnumSet.of(enemies));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**Returns team data by type.*/
|
||||||
|
public TeamData get(Team team){
|
||||||
|
if(map[team.ordinal()] == null){
|
||||||
|
//By default, a non-defined team will be enemies of everything.
|
||||||
|
Team[] others = new Team[Team.all.length-1];
|
||||||
|
for(int i = 0, j = 0; i < Team.all.length; i++){
|
||||||
|
if(Team.all[i] != team) others[j++] = Team.all[i];
|
||||||
|
}
|
||||||
|
add(team, others);
|
||||||
|
}
|
||||||
|
return map[team.ordinal()];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**Returns whether a team is active, e.g. whether it has any cores remaining.*/
|
||||||
|
public boolean isActive(Team team){
|
||||||
|
//the enemy wave team is always active
|
||||||
|
return (!Vars.state.mode.disableWaves && team == Vars.waveTeam) || get(team).cores.size > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**Returns a set of all teams that are enemies of this team.*/
|
||||||
|
public EnumSet<Team> enemiesOf(Team team){
|
||||||
|
return get(team).enemies;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**Returns whether {@param other} is an enemy of {@param #team}.*/
|
||||||
|
public boolean areEnemies(Team team, Team other){
|
||||||
|
return enemiesOf(team).contains(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TeamData{
|
||||||
|
public final Array<Tile> cores = new ThreadArray<>();
|
||||||
|
public final EnumSet<Team> enemies;
|
||||||
|
public final Team team;
|
||||||
|
|
||||||
|
public TeamData(Team team, EnumSet<Team> enemies){
|
||||||
|
this.team = team;
|
||||||
|
this.enemies = enemies;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@ import com.badlogic.gdx.utils.Array;
|
|||||||
import io.anuke.mindustry.content.blocks.Blocks;
|
import io.anuke.mindustry.content.blocks.Blocks;
|
||||||
import io.anuke.mindustry.entities.Player;
|
import io.anuke.mindustry.entities.Player;
|
||||||
import io.anuke.mindustry.entities.TileEntity;
|
import io.anuke.mindustry.entities.TileEntity;
|
||||||
import io.anuke.mindustry.game.TeamInfo.TeamData;
|
import io.anuke.mindustry.game.Team;
|
||||||
import io.anuke.mindustry.input.InputHandler;
|
import io.anuke.mindustry.input.InputHandler;
|
||||||
import io.anuke.mindustry.world.Block;
|
import io.anuke.mindustry.world.Block;
|
||||||
import io.anuke.mindustry.world.Tile;
|
import io.anuke.mindustry.world.Tile;
|
||||||
@@ -63,13 +63,13 @@ public class OverlayRenderer{
|
|||||||
Lines.stroke(buildFadeTime*2f);
|
Lines.stroke(buildFadeTime*2f);
|
||||||
|
|
||||||
if(buildFadeTime > 0.005f){
|
if(buildFadeTime > 0.005f){
|
||||||
for(TeamData data : state.teams.enemyDataOf(player.getTeam())){
|
for(Team enemy : state.teams.enemiesOf(player.getTeam())){
|
||||||
for(Tile core : data.cores){
|
for(Tile core : state.teams.get(enemy).cores){
|
||||||
float dst = Vector2.dst(player.x, player.y, core.drawx(), core.drawy());
|
float dst = Vector2.dst(player.x, player.y, core.drawx(), core.drawy());
|
||||||
if(dst < enemyCoreBuildRange * 1.5f){
|
if(dst < enemyCoreBuildRange * 1.5f){
|
||||||
Draw.color(Color.DARK_GRAY);
|
Draw.color(Color.DARK_GRAY);
|
||||||
Lines.poly(core.drawx(), core.drawy() - 2, 200, enemyCoreBuildRange);
|
Lines.poly(core.drawx(), core.drawy() - 2, 200, enemyCoreBuildRange);
|
||||||
Draw.color(Palette.accent, data.team.color, 0.5f + Mathf.absin(Timers.time(), 10f, 0.5f));
|
Draw.color(Palette.accent, enemy.color, 0.5f + Mathf.absin(Timers.time(), 10f, 0.5f));
|
||||||
Lines.poly(core.drawx(), core.drawy(), 200, enemyCoreBuildRange);
|
Lines.poly(core.drawx(), core.drawy(), 200, enemyCoreBuildRange);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,8 +117,7 @@ public class Save16 extends SaveFileVersion{
|
|||||||
|
|
||||||
tile.entity.read(stream);
|
tile.entity.read(stream);
|
||||||
|
|
||||||
if(tile.block() == StorageBlocks.core &&
|
if(tile.block() == StorageBlocks.core){
|
||||||
state.teams.has(t)){
|
|
||||||
state.teams.get(t).cores.add(tile);
|
state.teams.get(t).cores.add(tile);
|
||||||
}
|
}
|
||||||
}else if(wallid == 0){
|
}else if(wallid == 0){
|
||||||
|
|||||||
@@ -84,8 +84,7 @@ public class WorldGenerator{
|
|||||||
|
|
||||||
Team team = tile.getTeam();
|
Team team = tile.getTeam();
|
||||||
|
|
||||||
if(tile.block() == StorageBlocks.core &&
|
if(tile.block() == StorageBlocks.core){
|
||||||
state.teams.has(team)){
|
|
||||||
state.teams.get(team).cores.add(tile);
|
state.teams.get(team).cores.add(tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,8 +39,12 @@ public class BattleMission implements Mission{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isComplete(){
|
public boolean isComplete(){
|
||||||
//TODO check all enemy teams, not just the first
|
for(Team team : Vars.state.teams.enemiesOf(Vars.defaultTeam)){
|
||||||
return Vars.state.teams.getTeams(false).first().cores.size == 0;
|
if(Vars.state.teams.isActive(team)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ public class ResourceMission implements Mission{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isComplete(){
|
public boolean isComplete(){
|
||||||
return Vars.state.teams.getTeams(true).first().cores.first().entity.items.has(item, amount);
|
return Vars.state.teams.get(Vars.defaultTeam).cores.first().entity.items.has(item, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import io.anuke.mindustry.content.blocks.Blocks;
|
|||||||
import io.anuke.mindustry.entities.Player;
|
import io.anuke.mindustry.entities.Player;
|
||||||
import io.anuke.mindustry.game.GameMode;
|
import io.anuke.mindustry.game.GameMode;
|
||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
import io.anuke.mindustry.game.TeamInfo;
|
import io.anuke.mindustry.game.Teams;
|
||||||
import io.anuke.mindustry.game.TeamInfo.TeamData;
|
import io.anuke.mindustry.game.Teams.TeamData;
|
||||||
|
import io.anuke.mindustry.game.Version;
|
||||||
import io.anuke.mindustry.maps.Map;
|
import io.anuke.mindustry.maps.Map;
|
||||||
import io.anuke.mindustry.maps.MapMeta;
|
import io.anuke.mindustry.maps.MapMeta;
|
||||||
import io.anuke.mindustry.game.Version;
|
|
||||||
import io.anuke.mindustry.world.Tile;
|
import io.anuke.mindustry.world.Tile;
|
||||||
import io.anuke.mindustry.world.blocks.BlockPart;
|
import io.anuke.mindustry.world.blocks.BlockPart;
|
||||||
import io.anuke.ucore.core.Core;
|
import io.anuke.ucore.core.Core;
|
||||||
@@ -119,11 +119,16 @@ public class NetworkIO{
|
|||||||
}
|
}
|
||||||
|
|
||||||
//write team data
|
//write team data
|
||||||
stream.writeByte(state.teams.getTeams().size);
|
for(Team team : Team.all){
|
||||||
for(TeamData data : state.teams.getTeams()){
|
TeamData data = state.teams.get(team);
|
||||||
stream.writeByte(data.team.ordinal());
|
stream.writeByte(data.team.ordinal());
|
||||||
stream.writeBoolean(data.ally);
|
|
||||||
stream.writeShort(data.cores.size);
|
stream.writeByte(data.enemies.size());
|
||||||
|
for(Team enemy : data.enemies){
|
||||||
|
stream.writeByte(enemy.ordinal());
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.writeByte(data.cores.size);
|
||||||
for(Tile tile : data.cores){
|
for(Tile tile : data.cores){
|
||||||
stream.writeInt(tile.packedPosition());
|
stream.writeInt(tile.packedPosition());
|
||||||
}
|
}
|
||||||
@@ -253,14 +258,21 @@ public class NetworkIO{
|
|||||||
}
|
}
|
||||||
|
|
||||||
player.reset();
|
player.reset();
|
||||||
state.teams = new TeamInfo();
|
state.teams = new Teams();
|
||||||
|
|
||||||
byte teams = stream.readByte();
|
byte teams = stream.readByte();
|
||||||
for(int i = 0; i < teams; i++){
|
for(int i = 0; i < teams; i++){
|
||||||
Team team = Team.all[stream.readByte()];
|
Team team = Team.all[stream.readByte()];
|
||||||
boolean ally = stream.readBoolean();
|
|
||||||
short cores = stream.readShort();
|
byte enemies = stream.readByte();
|
||||||
state.teams.add(team, ally);
|
Team[] enemyArr = new Team[enemies];
|
||||||
|
for(int j = 0; j < enemies; j++){
|
||||||
|
enemyArr[j] = Team.all[stream.readByte()];
|
||||||
|
}
|
||||||
|
|
||||||
|
state.teams.add(team, enemyArr);
|
||||||
|
|
||||||
|
byte cores = stream.readByte();
|
||||||
|
|
||||||
for(int j = 0; j < cores; j++){
|
for(int j = 0; j < cores; j++){
|
||||||
state.teams.get(team).cores.add(world.tile(stream.readInt()));
|
state.teams.get(team).cores.add(world.tile(stream.readInt()));
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import io.anuke.mindustry.content.blocks.Blocks;
|
|||||||
import io.anuke.mindustry.entities.Units;
|
import io.anuke.mindustry.entities.Units;
|
||||||
import io.anuke.mindustry.game.EventType.BlockBuildEvent;
|
import io.anuke.mindustry.game.EventType.BlockBuildEvent;
|
||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
import io.anuke.mindustry.game.TeamInfo.TeamData;
|
|
||||||
import io.anuke.mindustry.type.Recipe;
|
import io.anuke.mindustry.type.Recipe;
|
||||||
import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity;
|
import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity;
|
||||||
import io.anuke.ucore.core.Events;
|
import io.anuke.ucore.core.Events;
|
||||||
@@ -138,8 +137,8 @@ public class Build{
|
|||||||
}
|
}
|
||||||
|
|
||||||
//check for enemy cores
|
//check for enemy cores
|
||||||
for(TeamData data : state.teams.enemyDataOf(team)){
|
for(Team enemy : state.teams.enemiesOf(team)){
|
||||||
for(Tile core : data.cores){
|
for(Tile core : state.teams.get(enemy).cores){
|
||||||
if(Vector2.dst(x*tilesize + type.offset(), y*tilesize + type.offset(), core.drawx(), core.drawy()) < enemyCoreBuildRange + type.size*tilesize/2f){
|
if(Vector2.dst(x*tilesize + type.offset(), y*tilesize + type.offset(), core.drawx(), core.drawy()) < enemyCoreBuildRange + type.size*tilesize/2f){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -176,9 +176,7 @@ public class CoreBlock extends StorageBlock{
|
|||||||
//TODO more dramatic effects
|
//TODO more dramatic effects
|
||||||
super.onDestroyed(tile);
|
super.onDestroyed(tile);
|
||||||
|
|
||||||
if(state.teams.has(tile.getTeam())){
|
state.teams.get(tile.getTeam()).cores.removeValue(tile, true);
|
||||||
state.teams.get(tile.getTeam()).cores.removeValue(tile, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import io.anuke.mindustry.content.fx.BlockFx;
|
|||||||
import io.anuke.mindustry.entities.TileEntity;
|
import io.anuke.mindustry.entities.TileEntity;
|
||||||
import io.anuke.mindustry.entities.units.BaseUnit;
|
import io.anuke.mindustry.entities.units.BaseUnit;
|
||||||
import io.anuke.mindustry.entities.units.UnitType;
|
import io.anuke.mindustry.entities.units.UnitType;
|
||||||
import io.anuke.mindustry.game.Team;
|
|
||||||
import io.anuke.mindustry.gen.Call;
|
import io.anuke.mindustry.gen.Call;
|
||||||
import io.anuke.mindustry.graphics.Palette;
|
import io.anuke.mindustry.graphics.Palette;
|
||||||
import io.anuke.mindustry.graphics.Shaders;
|
import io.anuke.mindustry.graphics.Shaders;
|
||||||
@@ -36,6 +35,9 @@ import java.io.DataInputStream;
|
|||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static io.anuke.mindustry.Vars.state;
|
||||||
|
import static io.anuke.mindustry.Vars.waveTeam;
|
||||||
|
|
||||||
public class UnitPad extends Block{
|
public class UnitPad extends Block{
|
||||||
protected float gracePeriodMultiplier = 23f;
|
protected float gracePeriodMultiplier = 23f;
|
||||||
protected float speedupTime = 60f * 60f * 20;
|
protected float speedupTime = 60f * 60f * 20;
|
||||||
@@ -142,7 +144,7 @@ public class UnitPad extends Block{
|
|||||||
|
|
||||||
entity.time += Timers.delta() * entity.speedScl;
|
entity.time += Timers.delta() * entity.speedScl;
|
||||||
|
|
||||||
boolean isEnemy = tile.getTeam() == Team.red;
|
boolean isEnemy = tile.getTeam() == waveTeam && state.mode.autoSpawn;
|
||||||
|
|
||||||
if(isEnemy){
|
if(isEnemy){
|
||||||
entity.warmup += Timers.delta();
|
entity.warmup += Timers.delta();
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ public enum BlockFlag{
|
|||||||
/**Special flag for command center blocks.*/
|
/**Special flag for command center blocks.*/
|
||||||
comandCenter(Float.MAX_VALUE);
|
comandCenter(Float.MAX_VALUE);
|
||||||
|
|
||||||
|
public final static BlockFlag[] all = values();
|
||||||
|
|
||||||
public final float cost;
|
public final float cost;
|
||||||
|
|
||||||
BlockFlag(float cost){
|
BlockFlag(float cost){
|
||||||
|
|||||||
Reference in New Issue
Block a user