Balancing

This commit is contained in:
Anuken
2019-01-17 13:03:06 -05:00
parent 47605583d1
commit ccc20a9716
23 changed files with 333 additions and 553 deletions

View File

@@ -182,8 +182,6 @@ public class Pathfinder{
createFor(team); createFor(team);
} }
} }
world.spawner.checkAllQuadrants();
} }
class PathData{ class PathData{

View File

@@ -2,32 +2,18 @@ package io.anuke.mindustry.ai;
import io.anuke.arc.Events; import io.anuke.arc.Events;
import io.anuke.arc.collection.Array; import io.anuke.arc.collection.Array;
import io.anuke.arc.collection.GridBits; import io.anuke.arc.math.Angles;
import io.anuke.arc.math.Mathf; import io.anuke.arc.math.Mathf;
import io.anuke.arc.util.Structs;
import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.content.Blocks;
import io.anuke.mindustry.entities.units.BaseUnit; import io.anuke.mindustry.entities.units.BaseUnit;
import io.anuke.mindustry.entities.units.Squad; import io.anuke.mindustry.entities.units.Squad;
import io.anuke.mindustry.game.EventType.WorldLoadEvent; import io.anuke.mindustry.game.EventType.WorldLoadEvent;
import io.anuke.mindustry.game.SpawnGroup; import io.anuke.mindustry.game.SpawnGroup;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.game.Waves;
import io.anuke.mindustry.world.Tile;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.*;
public class WaveSpawner{ public class WaveSpawner{
private static final int quadsize = 6;
private GridBits quadrants;
private Array<SpawnGroup> groups; private Array<SpawnGroup> groups;
private boolean dynamicSpawn;
private Array<FlyerSpawn> flySpawns = new Array<>(); private Array<FlyerSpawn> flySpawns = new Array<>();
private Array<GroundSpawn> groundSpawns = new Array<>(); private Array<GroundSpawn> groundSpawns = new Array<>();
@@ -35,273 +21,76 @@ public class WaveSpawner{
Events.on(WorldLoadEvent.class, e -> reset()); Events.on(WorldLoadEvent.class, e -> reset());
} }
public void write(DataOutput output) throws IOException{
output.writeShort(flySpawns.size);
for(FlyerSpawn spawn : flySpawns){
output.writeFloat(spawn.angle);
}
output.writeShort(groundSpawns.size);
for(GroundSpawn spawn : groundSpawns){
output.writeShort((short) spawn.x);
output.writeShort((short) spawn.y);
}
}
public void read(DataInput input) throws IOException{
short flya = input.readShort();
for(int i = 0; i < flya; i++){
FlyerSpawn spawn = new FlyerSpawn();
spawn.angle = input.readFloat();
flySpawns.add(spawn);
}
short grounda = input.readShort();
for(int i = 0; i < grounda; i++){
GroundSpawn spawn = new GroundSpawn();
spawn.x = input.readShort();
spawn.y = input.readShort();
groundSpawns.add(spawn);
}
}
public void spawnEnemies(){ public void spawnEnemies(){
int flyGroups = 0;
int groundGroups = 0;
//count total subgroups spawned by flying/group types
for(SpawnGroup group : groups){
int amount = group.getGroupsSpawned(state.wave);
if(group.type.isFlying){
flyGroups += amount;
}else if(dynamicSpawn){
groundGroups += amount;
}
}
int addGround = groundGroups - groundSpawns.size, addFly = flyGroups - flySpawns.size;
//add extra groups if the total exceeds it
if(dynamicSpawn){
for(int i = 0; i < addGround; i++){
GroundSpawn spawn = new GroundSpawn();
findLocation(spawn);
groundSpawns.add(spawn);
}
}
for(int i = 0; i < addFly; i++){
FlyerSpawn spawn = new FlyerSpawn();
findLocation(spawn);
flySpawns.add(spawn);
}
//store index of last used fly/ground spawn locations
int flyCount = 0, groundCount = 0;
for(SpawnGroup group : groups){ for(SpawnGroup group : groups){
int groups = group.getGroupsSpawned(state.wave);
int spawned = group.getUnitsSpawned(state.wave); int spawned = group.getUnitsSpawned(state.wave);
for(int i = 0; i < groups; i++){ float spawnX, spawnY;
Squad squad = new Squad(); float spread;
float spawnX, spawnY;
float spread;
if(!group.type.isFlying && groundCount >= groundSpawns.size) continue;
if(group.type.isFlying){
FlyerSpawn spawn = flySpawns.get(flyCount);
if(group.type.isFlying){
for(FlyerSpawn spawn : flySpawns){
Squad squad = new Squad();
float margin = 40f; //how far away from the edge flying units spawn float margin = 40f; //how far away from the edge flying units spawn
spawnX = world.width() * tilesize / 2f + sqrwavex(spawn.angle) * (world.width() / 2f * tilesize + margin); float trns = (world.width() + world.height()) * tilesize;
spawnY = world.height() * tilesize / 2f + sqrwavey(spawn.angle) * (world.height() / 2f * tilesize + margin); spawnX = Mathf.clamp(world.width() * tilesize / 2f + Angles.trnsx(spawn.angle, trns), -margin, world.width() * tilesize + margin);
spawnY = Mathf.clamp(world.height() * tilesize / 2f + Angles.trnsy(spawn.angle, trns), -margin, world.height() * tilesize + margin);
spread = margin / 1.5f; spread = margin / 1.5f;
flyCount++; for(int i = 0; i < spawned; i++){
}else{ //make sure it works for non-dynamic spawns BaseUnit unit = group.createUnit(waveTeam);
GroundSpawn spawn = groundSpawns.get(groundCount); unit.setWave();
unit.setSquad(squad);
if(dynamicSpawn){ unit.set(spawnX + Mathf.range(spread), spawnY + Mathf.range(spread));
checkQuadrant(spawn.x, spawn.y); unit.add();
if(!getQuad(spawn.x, spawn.y)){
findLocation(spawn);
}
} }
spawnX = spawn.x * quadsize * tilesize + quadsize * tilesize / 2f;
spawnY = spawn.y * quadsize * tilesize + quadsize * tilesize / 2f;
spread = quadsize * tilesize / 3f;
groundCount++;
} }
}else{
for(GroundSpawn spawn : groundSpawns){
Squad squad = new Squad();
spawnX = spawn.x * tilesize;
spawnY = spawn.y * tilesize;
spread = tilesize;
for(int j = 0; j < spawned; j++){ for(int i = 0; i < spawned; i++){
BaseUnit unit = group.createUnit(Team.red); BaseUnit unit = group.createUnit(waveTeam);
unit.setWave(); unit.setWave();
unit.setSquad(squad); unit.setSquad(squad);
unit.set(spawnX + Mathf.range(spread), spawnY + Mathf.range(spread)); unit.set(spawnX + Mathf.range(spread), spawnY + Mathf.range(spread));
unit.add(); unit.add();
} }
}
}
}
public void checkAllQuadrants(){
for(int x = 0; x < quadWidth(); x++){
for(int y = 0; y < quadHeight(); y++){
checkQuadrant(x, y);
}
}
}
private void checkQuadrant(int quadx, int quady){
setQuad(quadx, quady, true);
outer:
for(int x = quadx * quadsize; x < world.width() && x < (quadx + 1) * quadsize; x++){
for(int y = quady * quadsize; y < world.height() && y < (quady + 1) * quadsize; y++){
Tile tile = world.tile(x, y);
if(tile == null || tile.solid() || tile.getTeam() == defaultTeam || world.pathfinder.getValueforTeam(Team.red, x, y) == Float.MAX_VALUE || tile.floor().isLiquid){
setQuad(quadx, quady, false);
break outer;
} }
} }
} }
} }
private void reset(){ private void reset(){
dynamicSpawn = false;
flySpawns.clear(); flySpawns.clear();
groundSpawns.clear(); groundSpawns.clear();
quadrants = new GridBits(quadWidth(), quadHeight()); groups = state.rules.spawns;
groups = Waves.getSpawns();
dynamicSpawn = true;
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++){
if(world.tile(x, y).block() == Blocks.spawn){ if(world.tile(x, y).block() == Blocks.spawn){
dynamicSpawn = false;
GroundSpawn spawn = new GroundSpawn(); GroundSpawn spawn = new GroundSpawn();
spawn.x = x/quadsize; spawn.x = x;
spawn.y = y/quadsize; spawn.y = y;
groundSpawns.add(spawn); groundSpawns.add(spawn);
FlyerSpawn fspawn = new FlyerSpawn();
fspawn.angle = Angles.angle(world.width()/2f, world.height()/2f, x, y);
flySpawns.add(fspawn);
} }
} }
} }
} }
private boolean getQuad(int quadx, int quady){
return quadrants.get(quadx, quady);
}
private void setQuad(int quadx, int quady, boolean valid){
if(quadrants == null){
quadrants = new GridBits(quadWidth(), quadHeight());
}
if(!Structs.inBounds(quadx, quady, quadWidth(), quadHeight())){
return;
}
quadrants.set(quadx, quady, valid);
}
//TODO instead of randomly scattering locations around the map, find spawns close to each other
private void findLocation(GroundSpawn spawn){
spawn.x = Mathf.random(quadWidth()-1);
spawn.y = Mathf.random(quadHeight()-1);
int shellWidth = quadWidth() * 2 + quadHeight() * 2 * 6;
shellWidth = Math.min(quadWidth() * quadHeight() / 4, shellWidth);
traverseSpiral(quadWidth(), quadHeight(), Mathf.random(shellWidth), (x, y) -> {
if(getQuad(x, y)){
spawn.x = x;
spawn.y = y;
return true;
}
return false;
});
}
//TODO instead of randomly scattering locations around the map, find spawns close to each other
private void findLocation(FlyerSpawn spawn){
spawn.angle = Mathf.random(360f);
}
private int quadWidth(){
return Mathf.ceil(world.width() / (float) quadsize);
}
private int quadHeight(){
return Mathf.ceil(world.height() / (float) quadsize);
}
private class FlyerSpawn{ private class FlyerSpawn{
//square angle
float angle; float angle;
} }
private class GroundSpawn{ private class GroundSpawn{
//quadrant spawn coordinates
int x, y; int x, y;
} }
//utility methods
float sqrwavex(float degrees){
degrees = Mathf.mod(degrees, 360f);
if(degrees < 45){
return 1;
}else if(degrees < 135){
return 1f - (degrees - 45f) / 90f;
}else if(degrees < 225){
return -1f;
}else if(degrees < 315){
return (degrees - 225) / 90f;
}else{
return 1f;
}
}
float sqrwavey(float degrees){
return sqrwavex(degrees + 90f);
}
void traverseSpiral(int width, int height, int offset, SpiralTraverser con){
int directionIdx = 0;
int curRow = 0, curCol = 0;
for(int i = 0; i < height * width; i++){
if(i >= offset && con.accept(curCol, curRow)) break;
int same = 1, row = curRow, col = curCol;
if(row > height - 1 - row){
row = height - 1 - row;
same = 0;
}
if(col >= width - 1 - col){
col = width - 1 - col;
same = 0;
}
row -= same;
if(row == col){
directionIdx = (directionIdx + 1) % 4;
}
curRow += directions[directionIdx][0];
curCol += directions[directionIdx][1];
}
}
interface SpiralTraverser{
boolean accept(int x, int y);
}
private static int[][] directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
} }

View File

@@ -2,9 +2,6 @@ package io.anuke.mindustry.content;
import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.Color;
import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.Draw;
import io.anuke.arc.graphics.g2d.Lines;
import io.anuke.arc.math.Mathf;
import io.anuke.arc.util.Time;
import io.anuke.mindustry.game.ContentList; import io.anuke.mindustry.game.ContentList;
import io.anuke.mindustry.graphics.CacheLayer; import io.anuke.mindustry.graphics.CacheLayer;
import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Item;
@@ -22,7 +19,10 @@ import io.anuke.mindustry.world.blocks.storage.CoreBlock;
import io.anuke.mindustry.world.blocks.storage.LaunchPad; import io.anuke.mindustry.world.blocks.storage.LaunchPad;
import io.anuke.mindustry.world.blocks.storage.SortedUnloader; import io.anuke.mindustry.world.blocks.storage.SortedUnloader;
import io.anuke.mindustry.world.blocks.storage.Vault; import io.anuke.mindustry.world.blocks.storage.Vault;
import io.anuke.mindustry.world.blocks.units.*; import io.anuke.mindustry.world.blocks.units.MechPad;
import io.anuke.mindustry.world.blocks.units.Reconstructor;
import io.anuke.mindustry.world.blocks.units.RepairPoint;
import io.anuke.mindustry.world.blocks.units.UnitFactory;
import static io.anuke.mindustry.Vars.content; import static io.anuke.mindustry.Vars.content;
@@ -630,20 +630,20 @@ public class Blocks implements ContentList{
mechanicalDrill = new Drill("mechanical-drill"){{ mechanicalDrill = new Drill("mechanical-drill"){{
tier = 2; tier = 2;
drillTime = 300; drillTime = 600;
size = 2; size = 2;
drawMineItem = true; drawMineItem = true;
}}; }};
pneumaticDrill = new Drill("pneumatic-drill"){{ pneumaticDrill = new Drill("pneumatic-drill"){{
tier = 3; tier = 3;
drillTime = 240; drillTime = 480;
size = 2; size = 2;
drawMineItem = true; drawMineItem = true;
}}; }};
laserDrill = new Drill("laser-drill"){{ laserDrill = new Drill("laser-drill"){{
drillTime = 140; drillTime = 280;
size = 2; size = 2;
hasPower = true; hasPower = true;
tier = 4; tier = 4;
@@ -654,7 +654,7 @@ public class Blocks implements ContentList{
}}; }};
blastDrill = new Drill("blast-drill"){{ blastDrill = new Drill("blast-drill"){{
drillTime = 60; drillTime = 120;
size = 3; size = 3;
drawRim = true; drawRim = true;
hasPower = true; hasPower = true;
@@ -670,7 +670,7 @@ public class Blocks implements ContentList{
plasmaDrill = new Drill("plasma-drill"){{ plasmaDrill = new Drill("plasma-drill"){{
heatColor = Color.valueOf("ff461b"); heatColor = Color.valueOf("ff461b");
drillTime = 50; drillTime = 100;
size = 4; size = 4;
hasLiquids = true; hasLiquids = true;
hasPower = true; hasPower = true;
@@ -726,6 +726,9 @@ public class Blocks implements ContentList{
core = new CoreBlock("core"){{ core = new CoreBlock("core"){{
health = 1100; health = 1100;
itemCapacity = 2000; itemCapacity = 2000;
launchThreshold = 1000;
launchTime = 60f * 10;
launchChunkSize = 100;
}}; }};
vault = new Vault("vault"){{ vault = new Vault("vault"){{
@@ -746,6 +749,7 @@ public class Blocks implements ContentList{
size = 3; size = 3;
itemCapacity = 100; itemCapacity = 100;
launchTime = 60f * 6; launchTime = 60f * 6;
hasPower = true;
consumes.power(0.1f); consumes.power(0.1f);
}}; }};

View File

@@ -1,7 +1,9 @@
package io.anuke.mindustry.content; package io.anuke.mindustry.content;
import io.anuke.arc.collection.Array;
import io.anuke.mindustry.game.ContentList; import io.anuke.mindustry.game.ContentList;
import io.anuke.mindustry.game.Rules; import io.anuke.mindustry.game.Rules;
import io.anuke.mindustry.game.SpawnGroup;
import io.anuke.mindustry.maps.generators.MapGenerator; import io.anuke.mindustry.maps.generators.MapGenerator;
import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.type.ItemStack;
import io.anuke.mindustry.type.Zone; import io.anuke.mindustry.type.Zone;
@@ -20,6 +22,36 @@ public class Zones implements ContentList{
waves = true; waves = true;
waveTimer = true; waveTimer = true;
waveSpacing = 60 * 60; waveSpacing = 60 * 60;
spawns = Array.with(
new SpawnGroup(UnitTypes.dagger){{
unitScaling = 2;
}},
new SpawnGroup(UnitTypes.dagger){{
begin = 5;
unitScaling = 2;
}},
new SpawnGroup(UnitTypes.dagger){{
begin = 10;
unitScaling = 1;
}},
new SpawnGroup(UnitTypes.dagger){{
begin = 15;
unitScaling = 1;
}},
new SpawnGroup(UnitTypes.dagger){{
begin = 20;
unitScaling = 1;
}},
new SpawnGroup(UnitTypes.dagger){{
begin = 25;
unitScaling = 1;
}}
);
}}; }};
}}; }};
} }

View File

@@ -182,6 +182,8 @@ public class World implements ApplicationListener{
} }
} }
addDarkness(tiles);
EntityQuery.resizeTree(0, 0, tiles.length * tilesize, tiles[0].length * tilesize); EntityQuery.resizeTree(0, 0, tiles.length * tilesize, tiles[0].length * tilesize);
generating = false; generating = false;
@@ -411,11 +413,7 @@ public class World implements ApplicationListener{
prepareTiles(tiles); prepareTiles(tiles);
} }
/**'Prepares' a tile array by:<br> public void addDarkness(Tile[][] tiles){
* - setting up multiblocks<br>
* - updating occlusion<br>
* Usually used before placing structures on a tile array.*/
public void prepareTiles(Tile[][] tiles){
byte[][] dark = new byte[tiles.length][tiles[0].length]; byte[][] dark = new byte[tiles.length][tiles[0].length];
byte[][] writeBuffer = new byte[tiles.length][tiles[0].length]; byte[][] writeBuffer = new byte[tiles.length][tiles[0].length];
@@ -454,9 +452,19 @@ public class World implements ApplicationListener{
for(int x = 0; x < tiles.length; x++){ for(int x = 0; x < tiles.length; x++){
for(int y = 0; y < tiles[0].length; y++){ for(int y = 0; y < tiles[0].length; y++){
tiles[x][y].setRotation(dark[x][y]); Tile tile = tiles[x][y];
if(tile.block().solid && !tile.block().update){
tiles[x][y].setRotation(dark[x][y]);
}
} }
} }
}
/**'Prepares' a tile array by:<br>
* - setting up multiblocks<br>
* - updating occlusion<br>
* Usually used before placing structures on a tile array.*/
public void prepareTiles(Tile[][] tiles){
//find multiblocks //find multiblocks
IntArray multiblocks = new IntArray(); IntArray multiblocks = new IntArray();

View File

@@ -109,6 +109,12 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
rectangle.setSize(mech.hitsize * 2f / 3f).setCenter(x, y); rectangle.setSize(mech.hitsize * 2f / 3f).setCenter(x, y);
} }
@Override
public void onRespawn(Tile tile){
boostHeat = 1f;
achievedFlight = true;
}
@Override @Override
public float drag(){ public float drag(){
return mech.drag; return mech.drag;

View File

@@ -217,6 +217,8 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
return tile == null ? (Floor) Blocks.air : tile.floor(); return tile == null ? (Floor) Blocks.air : tile.floor();
} }
public void onRespawn(Tile tile){}
@Override @Override
public boolean isValid(){ public boolean isValid(){
return !isDead() && isAdded(); return !isDead() && isAdded();

View File

@@ -7,11 +7,14 @@ import io.anuke.arc.collection.ObjectMap;
import io.anuke.arc.collection.ObjectSet; import io.anuke.arc.collection.ObjectSet;
import io.anuke.mindustry.Vars; import io.anuke.mindustry.Vars;
import io.anuke.mindustry.content.Items; import io.anuke.mindustry.content.Items;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.game.EventType.UnlockEvent; import io.anuke.mindustry.game.EventType.UnlockEvent;
import io.anuke.mindustry.type.ContentType; import io.anuke.mindustry.type.ContentType;
import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.type.ItemStack;
import static io.anuke.mindustry.Vars.*;
/**Stores player unlocks. Clientside only.*/ /**Stores player unlocks. Clientside only.*/
public class GlobalData{ public class GlobalData{
private ObjectMap<ContentType, ObjectSet<String>> unlocked = new ObjectMap<>(); private ObjectMap<ContentType, ObjectSet<String>> unlocked = new ObjectMap<>();
@@ -49,8 +52,7 @@ public class GlobalData{
/** Returns whether or not this piece of content is unlocked yet.*/ /** Returns whether or not this piece of content is unlocked yet.*/
public boolean isUnlocked(UnlockableContent content){ public boolean isUnlocked(UnlockableContent content){
//return true; return (!state.is(State.menu) && !world.isZone()) || content.alwaysUnlocked() || unlocked.getOr(content.getContentType(), ObjectSet::new).contains(content.getContentName());
return content.alwaysUnlocked() || unlocked.getOr(content.getContentType(), ObjectSet::new).contains(content.getContentName());
} }
/** /**

View File

@@ -1,6 +1,7 @@
package io.anuke.mindustry.game; package io.anuke.mindustry.game;
import io.anuke.annotations.Annotations.Serialize; import io.anuke.annotations.Annotations.Serialize;
import io.anuke.arc.collection.Array;
/**Defines current rules on how the game should function. /**Defines current rules on how the game should function.
* Does not store game state, just configuration.*/ * Does not store game state, just configuration.*/
@@ -26,4 +27,6 @@ public class Rules{
public float waveSpacing = 60 * 60; public float waveSpacing = 60 * 60;
/**Zone ID, -1 for invalid zone.*/ /**Zone ID, -1 for invalid zone.*/
public byte zone = -1; public byte zone = -1;
/**Spawn layout. Since only zones modify this, it should be assigned on save load.*/
public transient Array<SpawnGroup> spawns = Waves.getDefaultSpawns();
} }

View File

@@ -11,6 +11,7 @@ import io.anuke.arc.util.Time;
import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.game.EventType.StateChangeEvent; import io.anuke.mindustry.game.EventType.StateChangeEvent;
import io.anuke.mindustry.io.SaveIO; import io.anuke.mindustry.io.SaveIO;
import io.anuke.mindustry.io.SaveIO.SaveException;
import io.anuke.mindustry.io.SaveMeta; import io.anuke.mindustry.io.SaveMeta;
import io.anuke.mindustry.maps.Map; import io.anuke.mindustry.maps.Map;
import io.anuke.mindustry.type.ContentType; import io.anuke.mindustry.type.ContentType;
@@ -170,11 +171,15 @@ public class Saves{
this.index = index; this.index = index;
} }
public void load(){ public void load() throws SaveException{
SaveIO.loadFromSlot(index); try{
meta = SaveIO.getData(index); SaveIO.loadFromSlot(index);
current = this; meta = SaveIO.getData(index);
totalPlaytime = meta.timePlayed; current = this;
totalPlaytime = meta.timePlayed;
}catch(Exception e){
throw new SaveException(e);
}
} }
public void save(){ public void save(){

View File

@@ -13,53 +13,25 @@ import io.anuke.mindustry.type.Weapon;
* Each spawn group can have multiple sub-groups spawned in different areas of the map. * Each spawn group can have multiple sub-groups spawned in different areas of the map.
*/ */
public class SpawnGroup{ public class SpawnGroup{
/** /**The unit type spawned*/
* The unit type spawned
*/
public final UnitType type; public final UnitType type;
/** /**When this spawn should end*/
* When this spawn should end
*/
protected int end = Integer.MAX_VALUE; protected int end = Integer.MAX_VALUE;
/** /**When this spawn should start*/
* When this spawn should start
*/
protected int begin; protected int begin;
/** /**The spacing, in waves, of spawns. For example, 2 = spawns every other wave*/
* The spacing, in waves, of spawns. For example, 2 = spawns every other wave
*/
protected int spacing = 1; protected int spacing = 1;
/** /**Maximum amount of units that spawn*/
* Maximum amount of units that spawn
*/
protected int max = 60; protected int max = 60;
/** /**How many waves need to pass before the amount of units spawned increases by 1*/
* How many waves need to pass before the amount of units spawned increases by 1
*/
protected float unitScaling = 9999f; protected float unitScaling = 9999f;
/** /**Amount of enemies spawned initially, with no scaling*/
* How many waves need to pass before the amount of instances of this group increases by 1
*/
protected float groupScaling = 9999f;
/**
* Amount of enemies spawned initially, with no scaling
*/
protected int unitAmount = 1; protected int unitAmount = 1;
/** /**Weapon used by the spawned unit. Null to disable. Only applicable to ground units.*/
* Amount of enemies spawned initially, with no scaling
*/
protected int groupAmount = 1;
/**
* Weapon used by the spawned unit. Null to disable. Only applicable to ground units.
*/
protected Weapon weapon; protected Weapon weapon;
/** /**Status effect applied to the spawned unit. Null to disable.*/
* Status effect applied to the spawned unit. Null to disable.
*/
protected StatusEffect effect; protected StatusEffect effect;
/** /**Items this unit spawns with. Null to disable.*/
* Items this unit spawns with. Null to disable.
*/
protected ItemStack items; protected ItemStack items;
public SpawnGroup(UnitType type){ public SpawnGroup(UnitType type){
@@ -78,17 +50,6 @@ public class SpawnGroup{
return Math.min(unitAmount - 1 + Math.max((int) ((wave / spacing) / scaling), 1), max); return Math.min(unitAmount - 1 + Math.max((int) ((wave / spacing) / scaling), 1), max);
} }
/**
* Returns the amount of different unit groups at a specific wave.
*/
public int getGroupsSpawned(int wave){
if(wave < begin || wave > end || (wave - begin) % spacing != 0){
return 0;
}
return Math.min(groupAmount - 1 + Math.max((int) ((wave / spacing) / groupScaling), 1), max);
}
/** /**
* Creates a unit, and assigns correct values based on this group's data. * Creates a unit, and assigns correct values based on this group's data.
* This method does not add() the unit. * This method does not add() the unit.
@@ -110,4 +71,20 @@ public class SpawnGroup{
return unit; return unit;
} }
@Override
public String toString(){
return "SpawnGroup{" +
"type=" + type +
", end=" + end +
", begin=" + begin +
", spacing=" + spacing +
", max=" + max +
", unitScaling=" + unitScaling +
", unitAmount=" + unitAmount +
", weapon=" + weapon +
", effect=" + effect +
", items=" + items +
'}';
}
} }

View File

@@ -8,176 +8,171 @@ import io.anuke.mindustry.content.Weapons;
import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.type.ItemStack;
public class Waves{ public class Waves{
private static Array<SpawnGroup> spawns = Array.with(
new SpawnGroup(UnitTypes.dagger){{
end = 8;
unitScaling = 3;
}},
public static Array<SpawnGroup> getSpawns(){ new SpawnGroup(UnitTypes.wraith){{
return Array.with( begin = 12;
new SpawnGroup(UnitTypes.dagger){{ end = 14;
end = 8; }},
unitScaling = 3;
}},
new SpawnGroup(UnitTypes.wraith){{ new SpawnGroup(UnitTypes.dagger){{
begin = 12; begin = 11;
end = 14; unitScaling = 2;
}}, spacing = 2;
max = 4;
}},
new SpawnGroup(UnitTypes.dagger){{ new SpawnGroup(UnitTypes.titan){{
begin = 11; begin = 9;
unitScaling = 2; spacing = 3;
spacing = 2; unitScaling = 2;
max = 4;
}},
new SpawnGroup(UnitTypes.titan){{ end = 30;
begin = 9; }},
spacing = 3;
unitScaling = 2;
end = 30; new SpawnGroup(UnitTypes.dagger){{
}}, begin = 10;
unitScaling = 2;
unitAmount = 1;
spacing = 2;
end = 30;
}},
new SpawnGroup(UnitTypes.dagger){{ new SpawnGroup(UnitTypes.titan){{
begin = 10; begin = 28;
unitScaling = 2; spacing = 3;
unitAmount = 1; unitScaling = 2;
spacing = 2; weapon = Weapons.flamethrower;
end = 30; end = 40;
}}, }},
new SpawnGroup(UnitTypes.titan){{ new SpawnGroup(UnitTypes.titan){{
begin = 28; begin = 45;
spacing = 3; spacing = 3;
unitScaling = 2; unitScaling = 2;
weapon = Weapons.flamethrower; weapon = Weapons.flamethrower;
end = 40; effect = StatusEffects.overdrive;
}}, }},
new SpawnGroup(UnitTypes.titan){{ new SpawnGroup(UnitTypes.titan){{
begin = 45; begin = 120;
spacing = 3; spacing = 2;
unitScaling = 2; unitScaling = 3;
weapon = Weapons.flamethrower; unitAmount = 5;
effect = StatusEffects.overdrive; weapon = Weapons.flakgun;
}}, effect = StatusEffects.overdrive;
}},
new SpawnGroup(UnitTypes.titan){{ new SpawnGroup(UnitTypes.wraith){{
begin = 120; begin = 16;
spacing = 2; unitScaling = 2;
unitScaling = 3; spacing = 2;
unitAmount = 5;
weapon = Weapons.flakgun;
effect = StatusEffects.overdrive;
}},
new SpawnGroup(UnitTypes.wraith){{ end = 39;
begin = 16; max = 7;
unitScaling = 2; }},
spacing = 2;
end = 39; new SpawnGroup(UnitTypes.dagger){{
max = 7; begin = 82;
}}, spacing = 3;
unitAmount = 4;
unitScaling = 3;
effect = StatusEffects.overdrive;
}},
new SpawnGroup(UnitTypes.dagger){{ new SpawnGroup(UnitTypes.dagger){{
begin = 82; begin = 41;
spacing = 3; spacing = 5;
unitAmount = 4; unitAmount = 1;
groupAmount = 2; unitScaling = 3;
unitScaling = 3; effect = StatusEffects.shielded;
effect = StatusEffects.overdrive; max = 10;
}}, }},
new SpawnGroup(UnitTypes.dagger){{ new SpawnGroup(UnitTypes.fortress){{
begin = 41; begin = 40;
spacing = 5; spacing = 5;
unitAmount = 1; unitAmount = 2;
unitScaling = 3; unitScaling = 3;
effect = StatusEffects.shielded; max = 10;
max = 10; }},
}},
new SpawnGroup(UnitTypes.fortress){{ new SpawnGroup(UnitTypes.dagger){{
begin = 40; begin = 35;
spacing = 5; spacing = 3;
unitAmount = 2; unitAmount = 4;
unitScaling = 3; effect = StatusEffects.overdrive;
max = 10; items = new ItemStack(Items.blastCompound, 60);
}}, end = 60;
}},
new SpawnGroup(UnitTypes.dagger){{ new SpawnGroup(UnitTypes.dagger){{
begin = 35; begin = 42;
spacing = 3; spacing = 3;
unitAmount = 4; unitAmount = 4;
groupAmount = 2; effect = StatusEffects.overdrive;
effect = StatusEffects.overdrive; items = new ItemStack(Items.pyratite, 100);
items = new ItemStack(Items.blastCompound, 60); end = 130;
end = 60; }},
}},
new SpawnGroup(UnitTypes.dagger){{ new SpawnGroup(UnitTypes.ghoul){{
begin = 42; begin = 40;
spacing = 3; unitAmount = 2;
unitAmount = 4; spacing = 2;
groupAmount = 2; unitScaling = 3;
effect = StatusEffects.overdrive; max = 8;
items = new ItemStack(Items.pyratite, 100); }},
end = 130;
}},
new SpawnGroup(UnitTypes.ghoul){{ new SpawnGroup(UnitTypes.wraith){{
begin = 40; begin = 50;
unitAmount = 2; unitAmount = 4;
spacing = 2; unitScaling = 3;
unitScaling = 3; spacing = 5;
max = 8; effect = StatusEffects.overdrive;
}}, max = 8;
}},
new SpawnGroup(UnitTypes.wraith){{ new SpawnGroup(UnitTypes.revenant){{
begin = 50; begin = 50;
unitAmount = 4; unitAmount = 4;
unitScaling = 3; unitScaling = 3;
spacing = 5; spacing = 5;
groupAmount = 2; max = 8;
effect = StatusEffects.overdrive; }},
max = 8;
}},
new SpawnGroup(UnitTypes.revenant){{ new SpawnGroup(UnitTypes.ghoul){{
begin = 50; begin = 53;
unitAmount = 4; unitAmount = 2;
unitScaling = 3; unitScaling = 3;
spacing = 5; spacing = 4;
groupAmount = 2; max = 8;
max = 8; end = 74;
}}, }},
new SpawnGroup(UnitTypes.ghoul){{ new SpawnGroup(UnitTypes.ghoul){{
begin = 53; begin = 53;
unitAmount = 2; unitAmount = 2;
unitScaling = 3; unitScaling = 3;
spacing = 4; spacing = 4;
max = 8; max = 8;
end = 74; end = 74;
}}, }}
);
new SpawnGroup(UnitTypes.ghoul){{ public static Array<SpawnGroup> getDefaultSpawns(){
begin = 53; return spawns;
unitAmount = 2;
unitScaling = 3;
spacing = 4;
max = 8;
end = 74;
}}
);
} }
public static void testWaves(int from, int to){ public static void testWaves(int from, int to){
Array<SpawnGroup> spawns = getSpawns();
for(int i = from; i <= to; i++){ for(int i = from; i <= to; i++){
System.out.print(i + ": "); System.out.print(i + ": ");
int total = 0; int total = 0;
for(SpawnGroup spawn : spawns){ for(SpawnGroup spawn : spawns){
int a = spawn.getUnitsSpawned(i) * spawn.getGroupsSpawned(i); int a = spawn.getUnitsSpawned(i);
total += a; total += a;
if(a > 0){ if(a > 0){

View File

@@ -54,7 +54,7 @@ public class Palette{
range = Color.valueOf("f4ba6e"), range = Color.valueOf("f4ba6e"),
power = Color.valueOf("fbad67"), power = Color.valueOf("fbad67"),
powerLight = Color.valueOf("fbd367"), powerLight = Color.valueOf("fbd367"),
placing = Color.valueOf("616161"), placing = accent,
lightTrail = Color.valueOf("ffe2a9"), lightTrail = Color.valueOf("ffe2a9"),

View File

@@ -43,7 +43,7 @@ public class SaveIO{
} }
} }
public static void loadFromSlot(int slot){ public static void loadFromSlot(int slot) throws SaveException{
load(fileFor(slot)); load(fileFor(slot));
} }
@@ -117,40 +117,41 @@ public class SaveIO{
} }
} }
public static void load(FileHandle file){ public static void load(FileHandle file) throws SaveException{
try{ try{
//try and load; if any exception at all occurs
load(new InflaterInputStream(file.read())); load(new InflaterInputStream(file.read()));
}catch(RuntimeException e){ }catch(SaveException e){
e.printStackTrace(); e.printStackTrace();
FileHandle backup = file.sibling(file.name() + "-backup." + file.extension()); FileHandle backup = file.sibling(file.name() + "-backup." + file.extension());
if(backup.exists()){ if(backup.exists()){
load(new InflaterInputStream(backup.read())); load(new InflaterInputStream(backup.read()));
}else{ }else{
throw new RuntimeException(e); throw new SaveException(e.getCause());
} }
} }
} }
public static void load(InputStream is){ public static void load(InputStream is) throws SaveException{
logic.reset(); try(DataInputStream stream = new DataInputStream(is)){
logic.reset();
DataInputStream stream;
try{
stream = new DataInputStream(is);
int version = stream.readInt(); int version = stream.readInt();
SaveFileVersion ver = versions.get(version); SaveFileVersion ver = versions.get(version);
ver.read(stream); ver.read(stream);
stream.close();
}catch(Exception e){ }catch(Exception e){
content.setTemporaryMapper(null); content.setTemporaryMapper(null);
throw new RuntimeException(e); throw new SaveException(e);
} }
} }
public static SaveFileVersion getVersion(){ public static SaveFileVersion getVersion(){
return versionArray.peek(); return versionArray.peek();
} }
public static class SaveException extends RuntimeException{
public SaveException(Throwable throwable){
super(throwable);
}
}
} }

View File

@@ -5,6 +5,8 @@ import io.anuke.mindustry.game.Version;
import io.anuke.mindustry.gen.Serialization; import io.anuke.mindustry.gen.Serialization;
import io.anuke.mindustry.io.SaveFileVersion; import io.anuke.mindustry.io.SaveFileVersion;
import io.anuke.mindustry.maps.Map; import io.anuke.mindustry.maps.Map;
import io.anuke.mindustry.type.ContentType;
import io.anuke.mindustry.type.Zone;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
@@ -26,6 +28,10 @@ public class Save16 extends SaveFileVersion{
//general state //general state
state.rules = Serialization.readRules(stream); state.rules = Serialization.readRules(stream);
//load zone spawn patterns if applicable
if(content.getByID(ContentType.zone, state.rules.zone) != null){
state.rules.spawns = content.<Zone>getByID(ContentType.zone, state.rules.zone).rules.get().spawns;
}
String mapname = stream.readUTF(); String mapname = stream.readUTF();
Map map = world.maps.getByName(mapname); Map map = world.maps.getByName(mapname);
if(map == null) map = new Map("unknown", 1, 1); if(map == null) map = new Map("unknown", 1, 1);
@@ -39,8 +45,6 @@ public class Save16 extends SaveFileVersion{
content.setTemporaryMapper(readContentHeader(stream)); content.setTemporaryMapper(readContentHeader(stream));
world.spawner.read(stream);
readEntities(stream); readEntities(stream);
readMap(stream); readMap(stream);
@@ -63,8 +67,6 @@ public class Save16 extends SaveFileVersion{
writeContentHeader(stream); writeContentHeader(stream);
world.spawner.write(stream); //spawnes
//--ENTITIES-- //--ENTITIES--
writeEntities(stream); writeEntities(stream);

View File

@@ -5,6 +5,7 @@ import io.anuke.arc.collection.ObjectIntMap;
import io.anuke.arc.scene.ui.layout.Table; import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.mindustry.Vars; import io.anuke.mindustry.Vars;
import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.io.SaveIO.SaveException;
import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.type.ItemStack;
import io.anuke.mindustry.type.ItemType; import io.anuke.mindustry.type.ItemType;
@@ -66,8 +67,15 @@ public class DeployDialog extends FloatingDialog{
addButton(Core.bundle.format("resume", control.saves.getZoneSlot().getZone().localizedName()), () -> { addButton(Core.bundle.format("resume", control.saves.getZoneSlot().getZone().localizedName()), () -> {
hide(); hide();
ui.loadAnd(() -> { ui.loadAnd(() -> {
control.saves.getZoneSlot().load(); try{
state.set(State.playing); control.saves.getZoneSlot().load();
state.set(State.playing);
}catch(SaveException e){ //make sure to handle any save load errors!
e.printStackTrace();
if(control.saves.getZoneSlot() != null) control.saves.getZoneSlot().delete();
ui.showInfo("$save.corrupted");
show();
}
}); });
}).size(200f); }).size(200f);
} }

View File

@@ -14,6 +14,7 @@ import io.anuke.arc.scene.ui.TextButton;
import io.anuke.arc.scene.ui.layout.Table; import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.arc.util.Log; import io.anuke.arc.util.Log;
import io.anuke.arc.util.Strings; import io.anuke.arc.util.Strings;
import io.anuke.mindustry.io.SaveIO.SaveException;
import java.io.IOException; import java.io.IOException;
@@ -173,7 +174,7 @@ public class LoadDialog extends FloatingDialog{
try{ try{
slot.load(); slot.load();
state.set(State.playing); state.set(State.playing);
}catch(Exception e){ }catch(SaveException e){
Log.err(e); Log.err(e);
state.set(State.menu); state.set(State.menu);
logic.reset(); logic.reset();

View File

@@ -92,8 +92,6 @@ public class Block extends BaseBlock {
public boolean consumesTap; public boolean consumesTap;
/** The color of this block when displayed on the minimap or map preview. */ /** The color of this block when displayed on the minimap or map preview. */
public Color minimapColor = Color.CLEAR; public Color minimapColor = Color.CLEAR;
/** View range of this block type. Use a value < 0 to disable. */
public float viewRange = 10;
/**Whether the top icon is outlined, like a turret.*/ /**Whether the top icon is outlined, like a turret.*/
public boolean turretIcon = false; public boolean turretIcon = false;
/**Whether units target this block.*/ /**Whether units target this block.*/

View File

@@ -16,7 +16,6 @@ public class BlockPart extends Block{
super("blockpart"); super("blockpart");
solid = false; solid = false;
hasPower = hasItems = hasLiquids = true; hasPower = hasItems = hasLiquids = true;
viewRange = -1;
} }
@Override @Override

View File

@@ -92,11 +92,6 @@ public abstract class Turret extends Block{
return false; return false;
} }
@Override
public void init(){
super.init();
viewRange = range;
}
@Override @Override
public void load(){ public void load(){
@@ -110,10 +105,6 @@ public abstract class Turret extends Block{
@Override @Override
public void setStats(){ public void setStats(){
super.setStats(); super.setStats();
/*
if(ammo != null) stats.add("ammo", ammo);
if(ammo != null) stats.add("ammocapacity", maxAmmo);
if(ammo != null) stats.add("ammoitem", ammoMultiplier);*/
stats.add(BlockStat.shootRange, range, StatUnit.blocks); stats.add(BlockStat.shootRange, range, StatUnit.blocks);
stats.add(BlockStat.inaccuracy, (int) inaccuracy, StatUnit.degrees); stats.add(BlockStat.inaccuracy, (int) inaccuracy, StatUnit.degrees);

View File

@@ -130,13 +130,6 @@ public class MassDriver extends Block{
stats.add(BlockStat.powerShot, consumes.get(ConsumePower.class).powerCapacity * powerPercentageUsed, StatUnit.powerUnits); stats.add(BlockStat.powerShot, consumes.get(ConsumePower.class).powerCapacity * powerPercentageUsed, StatUnit.powerUnits);
} }
@Override
public void init(){
super.init();
viewRange = range;
}
@Override @Override
public void update(Tile tile){ public void update(Tile tile){
MassDriverEntity entity = tile.entity(); MassDriverEntity entity = tile.entity();

View File

@@ -14,36 +14,29 @@ import io.anuke.mindustry.content.Fx;
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.entities.Unit; import io.anuke.mindustry.entities.Unit;
import io.anuke.mindustry.entities.Units;
import io.anuke.mindustry.entities.traits.SpawnerTrait; import io.anuke.mindustry.entities.traits.SpawnerTrait;
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;
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.ItemType;
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;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.*;
public class CoreBlock extends StorageBlock{ public class CoreBlock extends LaunchPad{
protected TextureRegion openRegion;
protected TextureRegion topRegion; protected TextureRegion topRegion;
protected int launchThreshold;
protected int launchChunkSize;
public CoreBlock(String name){ public CoreBlock(String name){
super(name); super(name);
solid = false; solid = true;
solidifes = true;
update = true; update = true;
size = 3;
hasItems = true; hasItems = true;
viewRange = 200f; size = 3;
flags = EnumSet.of(BlockFlag.resupplyPoint, BlockFlag.target); flags = EnumSet.of(BlockFlag.resupplyPoint, BlockFlag.target);
} }
@@ -53,11 +46,12 @@ public class CoreBlock extends StorageBlock{
CoreEntity entity = tile.entity(); CoreEntity entity = tile.entity();
Effects.effect(Fx.spawn, entity); Effects.effect(Fx.spawn, entity);
entity.solid = false;
entity.progress = 0; entity.progress = 0;
entity.currentUnit.onRespawn(tile);
entity.currentUnit = player; entity.currentUnit = player;
entity.currentUnit.heal(); entity.currentUnit.heal();
entity.currentUnit.rotation = 90f; entity.currentUnit.rotation = 90f;
entity.currentUnit.applyImpulse(0, 8f);
entity.currentUnit.setNet(tile.drawx(), tile.drawy()); entity.currentUnit.setNet(tile.drawx(), tile.drawy());
entity.currentUnit.add(); entity.currentUnit.add();
entity.currentUnit = null; entity.currentUnit = null;
@@ -67,18 +61,6 @@ public class CoreBlock extends StorageBlock{
} }
} }
@Remote(called = Loc.server)
public static void setCoreSolid(Tile tile, boolean solid){
if(tile == null) return;
CoreEntity entity = tile.entity();
if(entity != null) entity.solid = solid;
}
@Override
public boolean acceptItem(Item item, Tile tile, Tile source){
return item.type == ItemType.material && super.acceptItem(item, tile, source);
}
@Override @Override
public int getMaximumAccepted(Tile tile, Item item){ public int getMaximumAccepted(Tile tile, Item item){
return itemCapacity * state.teams.get(tile.getTeam()).cores.size; return itemCapacity * state.teams.get(tile.getTeam()).cores.size;
@@ -118,7 +100,6 @@ public class CoreBlock extends StorageBlock{
public void load(){ public void load(){
super.load(); super.load();
openRegion = Core.atlas.find(name + "-open");
topRegion = Core.atlas.find(name + "-top"); topRegion = Core.atlas.find(name + "-top");
} }
@@ -126,7 +107,7 @@ public class CoreBlock extends StorageBlock{
public void draw(Tile tile){ public void draw(Tile tile){
CoreEntity entity = tile.entity(); CoreEntity entity = tile.entity();
Draw.rect(entity.solid ? region : openRegion, tile.drawx(), tile.drawy()); Draw.rect(region, tile.drawx(), tile.drawy());
Draw.alpha(entity.heat); Draw.alpha(entity.heat);
Draw.rect(topRegion, tile.drawx(), tile.drawy()); Draw.rect(topRegion, tile.drawx(), tile.drawy());
@@ -158,13 +139,6 @@ public class CoreBlock extends StorageBlock{
} }
} }
@Override
public boolean isSolidFor(Tile tile){
CoreEntity entity = tile.entity();
return entity.solid;
}
@Override @Override
public void handleItem(Item item, Tile tile, Tile source){ public void handleItem(Item item, Tile tile, Tile source){
if(Net.server() || !Net.active()) super.handleItem(item, tile, source); if(Net.server() || !Net.active()) super.handleItem(item, tile, source);
@@ -174,8 +148,13 @@ public class CoreBlock extends StorageBlock{
public void update(Tile tile){ public void update(Tile tile){
CoreEntity entity = tile.entity(); CoreEntity entity = tile.entity();
if(!entity.solid && !Units.anyEntities(tile)){ for(Item item : Vars.content.items()){
Call.setCoreSolid(tile, true); if(entity.items.get(item) >= launchThreshold + launchChunkSize && entity.timer.get(timerLaunch, launchTime)){
//TODO play animation of some sort
Effects.effect(Fx.dooropenlarge, tile);
data.addItem(item, launchChunkSize);
entity.items.remove(item, launchChunkSize);
}
} }
if(entity.currentUnit != null){ if(entity.currentUnit != null){
@@ -200,7 +179,6 @@ public class CoreBlock extends StorageBlock{
public class CoreEntity extends TileEntity implements SpawnerTrait{ public class CoreEntity extends TileEntity implements SpawnerTrait{
public Unit currentUnit; public Unit currentUnit;
boolean solid = true;
float progress; float progress;
float time; float time;
float heat; float heat;
@@ -218,15 +196,5 @@ public class CoreBlock extends StorageBlock{
public float getSpawnProgress(){ public float getSpawnProgress(){
return progress; return progress;
} }
@Override
public void write(DataOutput stream) throws IOException{
stream.writeBoolean(solid);
}
@Override
public void read(DataInput stream) throws IOException{
solid = stream.readBoolean();
}
} }
} }

View File

@@ -6,12 +6,11 @@ import io.anuke.mindustry.content.Fx;
import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.TileEntity;
import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.type.ItemType; import io.anuke.mindustry.type.ItemType;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import static io.anuke.mindustry.Vars.data; import static io.anuke.mindustry.Vars.data;
public class LaunchPad extends Block{ public class LaunchPad extends StorageBlock{
protected final int timerLaunch = timers++; protected final int timerLaunch = timers++;
/**Time inbetween launches.*/ /**Time inbetween launches.*/
protected float launchTime; protected float launchTime;
@@ -19,14 +18,13 @@ public class LaunchPad extends Block{
public LaunchPad(String name){ public LaunchPad(String name){
super(name); super(name);
update = true; update = true;
hasPower = true;
hasItems = true; hasItems = true;
solid = true; solid = true;
} }
@Override @Override
public boolean acceptItem(Item item, Tile tile, Tile source){ public boolean acceptItem(Item item, Tile tile, Tile source){
return item.type == ItemType.material && tile.entity.items.get(item) < getMaximumAccepted(tile, item); return item.type == ItemType.material && super.acceptItem(item, tile, source);
} }
@Override @Override