From ccc20a9716d52ba2d80f86ff640dea40a9e8403a Mon Sep 17 00:00:00 2001 From: Anuken Date: Thu, 17 Jan 2019 13:03:06 -0500 Subject: [PATCH] Balancing --- .../src/io/anuke/mindustry/ai/Pathfinder.java | 2 - .../io/anuke/mindustry/ai/WaveSpawner.java | 281 +++--------------- .../io/anuke/mindustry/content/Blocks.java | 22 +- .../src/io/anuke/mindustry/content/Zones.java | 32 ++ core/src/io/anuke/mindustry/core/World.java | 20 +- .../io/anuke/mindustry/entities/Player.java | 6 + .../src/io/anuke/mindustry/entities/Unit.java | 2 + .../io/anuke/mindustry/game/GlobalData.java | 6 +- core/src/io/anuke/mindustry/game/Rules.java | 3 + core/src/io/anuke/mindustry/game/Saves.java | 15 +- .../io/anuke/mindustry/game/SpawnGroup.java | 75 ++--- core/src/io/anuke/mindustry/game/Waves.java | 279 +++++++++-------- .../io/anuke/mindustry/graphics/Palette.java | 2 +- core/src/io/anuke/mindustry/io/SaveIO.java | 29 +- .../anuke/mindustry/io/versions/Save16.java | 10 +- .../mindustry/ui/dialogs/DeployDialog.java | 12 +- .../mindustry/ui/dialogs/LoadDialog.java | 3 +- core/src/io/anuke/mindustry/world/Block.java | 2 - .../mindustry/world/blocks/BlockPart.java | 1 - .../world/blocks/defense/turrets/Turret.java | 9 - .../world/blocks/distribution/MassDriver.java | 7 - .../world/blocks/storage/CoreBlock.java | 62 +--- .../world/blocks/storage/LaunchPad.java | 6 +- 23 files changed, 333 insertions(+), 553 deletions(-) diff --git a/core/src/io/anuke/mindustry/ai/Pathfinder.java b/core/src/io/anuke/mindustry/ai/Pathfinder.java index dc44315bb1..2f27133d89 100644 --- a/core/src/io/anuke/mindustry/ai/Pathfinder.java +++ b/core/src/io/anuke/mindustry/ai/Pathfinder.java @@ -182,8 +182,6 @@ public class Pathfinder{ createFor(team); } } - - world.spawner.checkAllQuadrants(); } class PathData{ diff --git a/core/src/io/anuke/mindustry/ai/WaveSpawner.java b/core/src/io/anuke/mindustry/ai/WaveSpawner.java index 969a9befaa..ec098dcf8d 100644 --- a/core/src/io/anuke/mindustry/ai/WaveSpawner.java +++ b/core/src/io/anuke/mindustry/ai/WaveSpawner.java @@ -2,32 +2,18 @@ package io.anuke.mindustry.ai; import io.anuke.arc.Events; 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.util.Structs; import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.entities.units.BaseUnit; import io.anuke.mindustry.entities.units.Squad; import io.anuke.mindustry.game.EventType.WorldLoadEvent; 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.*; public class WaveSpawner{ - private static final int quadsize = 6; - - private GridBits quadrants; - private Array groups; - private boolean dynamicSpawn; - private Array flySpawns = new Array<>(); private Array groundSpawns = new Array<>(); @@ -35,273 +21,76 @@ public class WaveSpawner{ 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(){ - 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){ - int groups = group.getGroupsSpawned(state.wave); int spawned = group.getUnitsSpawned(state.wave); - for(int i = 0; i < groups; i++){ - Squad squad = new Squad(); - float spawnX, spawnY; - float spread; - - if(!group.type.isFlying && groundCount >= groundSpawns.size) continue; - - if(group.type.isFlying){ - FlyerSpawn spawn = flySpawns.get(flyCount); + float spawnX, spawnY; + float spread; + if(group.type.isFlying){ + for(FlyerSpawn spawn : flySpawns){ + Squad squad = new Squad(); 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); - spawnY = world.height() * tilesize / 2f + sqrwavey(spawn.angle) * (world.height() / 2f * tilesize + margin); + float trns = (world.width() + world.height()) * tilesize; + 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; - flyCount++; - }else{ //make sure it works for non-dynamic spawns - GroundSpawn spawn = groundSpawns.get(groundCount); - - if(dynamicSpawn){ - checkQuadrant(spawn.x, spawn.y); - if(!getQuad(spawn.x, spawn.y)){ - findLocation(spawn); - } + for(int i = 0; i < spawned; i++){ + BaseUnit unit = group.createUnit(waveTeam); + unit.setWave(); + unit.setSquad(squad); + unit.set(spawnX + Mathf.range(spread), spawnY + Mathf.range(spread)); + unit.add(); } - - 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++){ - BaseUnit unit = group.createUnit(Team.red); - unit.setWave(); - unit.setSquad(squad); - unit.set(spawnX + Mathf.range(spread), spawnY + Mathf.range(spread)); - 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; + for(int i = 0; i < spawned; i++){ + BaseUnit unit = group.createUnit(waveTeam); + unit.setWave(); + unit.setSquad(squad); + unit.set(spawnX + Mathf.range(spread), spawnY + Mathf.range(spread)); + unit.add(); + } } } } } private void reset(){ - dynamicSpawn = false; flySpawns.clear(); groundSpawns.clear(); - quadrants = new GridBits(quadWidth(), quadHeight()); - groups = Waves.getSpawns(); - - dynamicSpawn = true; + groups = state.rules.spawns; for(int x = 0; x < world.width(); x++){ for(int y = 0; y < world.height(); y++){ if(world.tile(x, y).block() == Blocks.spawn){ - dynamicSpawn = false; GroundSpawn spawn = new GroundSpawn(); - spawn.x = x/quadsize; - spawn.y = y/quadsize; + spawn.x = x; + spawn.y = y; 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{ - //square angle float angle; } private class GroundSpawn{ - //quadrant spawn coordinates 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}}; } diff --git a/core/src/io/anuke/mindustry/content/Blocks.java b/core/src/io/anuke/mindustry/content/Blocks.java index 0db67048f0..eecebea3b9 100644 --- a/core/src/io/anuke/mindustry/content/Blocks.java +++ b/core/src/io/anuke/mindustry/content/Blocks.java @@ -2,9 +2,6 @@ package io.anuke.mindustry.content; import io.anuke.arc.graphics.Color; 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.graphics.CacheLayer; 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.SortedUnloader; 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; @@ -630,20 +630,20 @@ public class Blocks implements ContentList{ mechanicalDrill = new Drill("mechanical-drill"){{ tier = 2; - drillTime = 300; + drillTime = 600; size = 2; drawMineItem = true; }}; pneumaticDrill = new Drill("pneumatic-drill"){{ tier = 3; - drillTime = 240; + drillTime = 480; size = 2; drawMineItem = true; }}; laserDrill = new Drill("laser-drill"){{ - drillTime = 140; + drillTime = 280; size = 2; hasPower = true; tier = 4; @@ -654,7 +654,7 @@ public class Blocks implements ContentList{ }}; blastDrill = new Drill("blast-drill"){{ - drillTime = 60; + drillTime = 120; size = 3; drawRim = true; hasPower = true; @@ -670,7 +670,7 @@ public class Blocks implements ContentList{ plasmaDrill = new Drill("plasma-drill"){{ heatColor = Color.valueOf("ff461b"); - drillTime = 50; + drillTime = 100; size = 4; hasLiquids = true; hasPower = true; @@ -726,6 +726,9 @@ public class Blocks implements ContentList{ core = new CoreBlock("core"){{ health = 1100; itemCapacity = 2000; + launchThreshold = 1000; + launchTime = 60f * 10; + launchChunkSize = 100; }}; vault = new Vault("vault"){{ @@ -746,6 +749,7 @@ public class Blocks implements ContentList{ size = 3; itemCapacity = 100; launchTime = 60f * 6; + hasPower = true; consumes.power(0.1f); }}; diff --git a/core/src/io/anuke/mindustry/content/Zones.java b/core/src/io/anuke/mindustry/content/Zones.java index c5c27b18a3..8c5c48e251 100644 --- a/core/src/io/anuke/mindustry/content/Zones.java +++ b/core/src/io/anuke/mindustry/content/Zones.java @@ -1,7 +1,9 @@ package io.anuke.mindustry.content; +import io.anuke.arc.collection.Array; import io.anuke.mindustry.game.ContentList; import io.anuke.mindustry.game.Rules; +import io.anuke.mindustry.game.SpawnGroup; import io.anuke.mindustry.maps.generators.MapGenerator; import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.type.Zone; @@ -20,6 +22,36 @@ public class Zones implements ContentList{ waves = true; waveTimer = true; 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; + }} + ); }}; }}; } diff --git a/core/src/io/anuke/mindustry/core/World.java b/core/src/io/anuke/mindustry/core/World.java index 5a05b2a4b9..8145191ac4 100644 --- a/core/src/io/anuke/mindustry/core/World.java +++ b/core/src/io/anuke/mindustry/core/World.java @@ -182,6 +182,8 @@ public class World implements ApplicationListener{ } } + addDarkness(tiles); + EntityQuery.resizeTree(0, 0, tiles.length * tilesize, tiles[0].length * tilesize); generating = false; @@ -411,11 +413,7 @@ public class World implements ApplicationListener{ prepareTiles(tiles); } - /**'Prepares' a tile array by:
- * - setting up multiblocks
- * - updating occlusion
- * Usually used before placing structures on a tile array.*/ - public void prepareTiles(Tile[][] tiles){ + public void addDarkness(Tile[][] tiles){ byte[][] dark = 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 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:
+ * - setting up multiblocks
+ * - updating occlusion
+ * Usually used before placing structures on a tile array.*/ + public void prepareTiles(Tile[][] tiles){ //find multiblocks IntArray multiblocks = new IntArray(); diff --git a/core/src/io/anuke/mindustry/entities/Player.java b/core/src/io/anuke/mindustry/entities/Player.java index c2e4ea6a52..98a1371692 100644 --- a/core/src/io/anuke/mindustry/entities/Player.java +++ b/core/src/io/anuke/mindustry/entities/Player.java @@ -109,6 +109,12 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra rectangle.setSize(mech.hitsize * 2f / 3f).setCenter(x, y); } + @Override + public void onRespawn(Tile tile){ + boostHeat = 1f; + achievedFlight = true; + } + @Override public float drag(){ return mech.drag; diff --git a/core/src/io/anuke/mindustry/entities/Unit.java b/core/src/io/anuke/mindustry/entities/Unit.java index 207c5f7087..efb067caec 100644 --- a/core/src/io/anuke/mindustry/entities/Unit.java +++ b/core/src/io/anuke/mindustry/entities/Unit.java @@ -217,6 +217,8 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ return tile == null ? (Floor) Blocks.air : tile.floor(); } + public void onRespawn(Tile tile){} + @Override public boolean isValid(){ return !isDead() && isAdded(); diff --git a/core/src/io/anuke/mindustry/game/GlobalData.java b/core/src/io/anuke/mindustry/game/GlobalData.java index cf852bb072..91be265eaf 100644 --- a/core/src/io/anuke/mindustry/game/GlobalData.java +++ b/core/src/io/anuke/mindustry/game/GlobalData.java @@ -7,11 +7,14 @@ import io.anuke.arc.collection.ObjectMap; import io.anuke.arc.collection.ObjectSet; import io.anuke.mindustry.Vars; import io.anuke.mindustry.content.Items; +import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.game.EventType.UnlockEvent; import io.anuke.mindustry.type.ContentType; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.ItemStack; +import static io.anuke.mindustry.Vars.*; + /**Stores player unlocks. Clientside only.*/ public class GlobalData{ private ObjectMap> unlocked = new ObjectMap<>(); @@ -49,8 +52,7 @@ public class GlobalData{ /** Returns whether or not this piece of content is unlocked yet.*/ public boolean isUnlocked(UnlockableContent content){ - //return true; - return content.alwaysUnlocked() || unlocked.getOr(content.getContentType(), ObjectSet::new).contains(content.getContentName()); + return (!state.is(State.menu) && !world.isZone()) || content.alwaysUnlocked() || unlocked.getOr(content.getContentType(), ObjectSet::new).contains(content.getContentName()); } /** diff --git a/core/src/io/anuke/mindustry/game/Rules.java b/core/src/io/anuke/mindustry/game/Rules.java index 7111d14237..16a8b52845 100644 --- a/core/src/io/anuke/mindustry/game/Rules.java +++ b/core/src/io/anuke/mindustry/game/Rules.java @@ -1,6 +1,7 @@ package io.anuke.mindustry.game; import io.anuke.annotations.Annotations.Serialize; +import io.anuke.arc.collection.Array; /**Defines current rules on how the game should function. * Does not store game state, just configuration.*/ @@ -26,4 +27,6 @@ public class Rules{ public float waveSpacing = 60 * 60; /**Zone ID, -1 for invalid zone.*/ public byte zone = -1; + /**Spawn layout. Since only zones modify this, it should be assigned on save load.*/ + public transient Array spawns = Waves.getDefaultSpawns(); } diff --git a/core/src/io/anuke/mindustry/game/Saves.java b/core/src/io/anuke/mindustry/game/Saves.java index bcb9c4151b..5555684cef 100644 --- a/core/src/io/anuke/mindustry/game/Saves.java +++ b/core/src/io/anuke/mindustry/game/Saves.java @@ -11,6 +11,7 @@ import io.anuke.arc.util.Time; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.game.EventType.StateChangeEvent; import io.anuke.mindustry.io.SaveIO; +import io.anuke.mindustry.io.SaveIO.SaveException; import io.anuke.mindustry.io.SaveMeta; import io.anuke.mindustry.maps.Map; import io.anuke.mindustry.type.ContentType; @@ -170,11 +171,15 @@ public class Saves{ this.index = index; } - public void load(){ - SaveIO.loadFromSlot(index); - meta = SaveIO.getData(index); - current = this; - totalPlaytime = meta.timePlayed; + public void load() throws SaveException{ + try{ + SaveIO.loadFromSlot(index); + meta = SaveIO.getData(index); + current = this; + totalPlaytime = meta.timePlayed; + }catch(Exception e){ + throw new SaveException(e); + } } public void save(){ diff --git a/core/src/io/anuke/mindustry/game/SpawnGroup.java b/core/src/io/anuke/mindustry/game/SpawnGroup.java index 98640d4616..13f9c9d1d0 100644 --- a/core/src/io/anuke/mindustry/game/SpawnGroup.java +++ b/core/src/io/anuke/mindustry/game/SpawnGroup.java @@ -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. */ public class SpawnGroup{ - /** - * The unit type spawned - */ + /**The unit type spawned*/ public final UnitType type; - /** - * When this spawn should end - */ + /**When this spawn should end*/ protected int end = Integer.MAX_VALUE; - /** - * When this spawn should start - */ + /**When this spawn should start*/ 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; - /** - * Maximum amount of units that spawn - */ + /**Maximum amount of units that spawn*/ 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; - /** - * 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 - */ + /**Amount of enemies spawned initially, with no scaling*/ protected int unitAmount = 1; - /** - * 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. - */ + /**Weapon used by the spawned unit. Null to disable. Only applicable to ground units.*/ 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; - /** - * Items this unit spawns with. Null to disable. - */ + /**Items this unit spawns with. Null to disable.*/ protected ItemStack items; public SpawnGroup(UnitType type){ @@ -78,17 +50,6 @@ public class SpawnGroup{ 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. * This method does not add() the unit. @@ -110,4 +71,20 @@ public class SpawnGroup{ 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 + + '}'; + } } diff --git a/core/src/io/anuke/mindustry/game/Waves.java b/core/src/io/anuke/mindustry/game/Waves.java index d05a2f9aa3..48d6baf44c 100644 --- a/core/src/io/anuke/mindustry/game/Waves.java +++ b/core/src/io/anuke/mindustry/game/Waves.java @@ -8,176 +8,171 @@ import io.anuke.mindustry.content.Weapons; import io.anuke.mindustry.type.ItemStack; public class Waves{ + private static Array spawns = Array.with( + new SpawnGroup(UnitTypes.dagger){{ + end = 8; + unitScaling = 3; + }}, - public static Array getSpawns(){ - return Array.with( - new SpawnGroup(UnitTypes.dagger){{ - end = 8; - unitScaling = 3; - }}, + new SpawnGroup(UnitTypes.wraith){{ + begin = 12; + end = 14; + }}, - new SpawnGroup(UnitTypes.wraith){{ - begin = 12; - end = 14; - }}, + new SpawnGroup(UnitTypes.dagger){{ + begin = 11; + unitScaling = 2; + spacing = 2; + max = 4; + }}, - new SpawnGroup(UnitTypes.dagger){{ - begin = 11; - unitScaling = 2; - spacing = 2; - max = 4; - }}, + new SpawnGroup(UnitTypes.titan){{ + begin = 9; + spacing = 3; + unitScaling = 2; - new SpawnGroup(UnitTypes.titan){{ - begin = 9; - spacing = 3; - unitScaling = 2; + end = 30; + }}, - end = 30; - }}, + new SpawnGroup(UnitTypes.dagger){{ + begin = 10; + unitScaling = 2; + unitAmount = 1; + spacing = 2; + end = 30; + }}, - new SpawnGroup(UnitTypes.dagger){{ - begin = 10; - unitScaling = 2; - unitAmount = 1; - spacing = 2; - end = 30; - }}, + new SpawnGroup(UnitTypes.titan){{ + begin = 28; + spacing = 3; + unitScaling = 2; + weapon = Weapons.flamethrower; + end = 40; + }}, - new SpawnGroup(UnitTypes.titan){{ - begin = 28; - spacing = 3; - unitScaling = 2; - weapon = Weapons.flamethrower; - end = 40; - }}, + new SpawnGroup(UnitTypes.titan){{ + begin = 45; + spacing = 3; + unitScaling = 2; + weapon = Weapons.flamethrower; + effect = StatusEffects.overdrive; + }}, - new SpawnGroup(UnitTypes.titan){{ - begin = 45; - spacing = 3; - unitScaling = 2; - weapon = Weapons.flamethrower; - effect = StatusEffects.overdrive; - }}, + new SpawnGroup(UnitTypes.titan){{ + begin = 120; + spacing = 2; + unitScaling = 3; + unitAmount = 5; + weapon = Weapons.flakgun; + effect = StatusEffects.overdrive; + }}, - new SpawnGroup(UnitTypes.titan){{ - begin = 120; - spacing = 2; - unitScaling = 3; - unitAmount = 5; - weapon = Weapons.flakgun; - effect = StatusEffects.overdrive; - }}, + new SpawnGroup(UnitTypes.wraith){{ + begin = 16; + unitScaling = 2; + spacing = 2; - new SpawnGroup(UnitTypes.wraith){{ - begin = 16; - unitScaling = 2; - spacing = 2; + end = 39; + max = 7; + }}, - end = 39; - max = 7; - }}, + new SpawnGroup(UnitTypes.dagger){{ + begin = 82; + spacing = 3; + unitAmount = 4; + unitScaling = 3; + effect = StatusEffects.overdrive; + }}, - new SpawnGroup(UnitTypes.dagger){{ - begin = 82; - spacing = 3; - unitAmount = 4; - groupAmount = 2; - unitScaling = 3; - effect = StatusEffects.overdrive; - }}, + new SpawnGroup(UnitTypes.dagger){{ + begin = 41; + spacing = 5; + unitAmount = 1; + unitScaling = 3; + effect = StatusEffects.shielded; + max = 10; + }}, - new SpawnGroup(UnitTypes.dagger){{ - begin = 41; - spacing = 5; - unitAmount = 1; - unitScaling = 3; - effect = StatusEffects.shielded; - max = 10; - }}, + new SpawnGroup(UnitTypes.fortress){{ + begin = 40; + spacing = 5; + unitAmount = 2; + unitScaling = 3; + max = 10; + }}, - new SpawnGroup(UnitTypes.fortress){{ - begin = 40; - spacing = 5; - unitAmount = 2; - unitScaling = 3; - max = 10; - }}, + new SpawnGroup(UnitTypes.dagger){{ + begin = 35; + spacing = 3; + unitAmount = 4; + effect = StatusEffects.overdrive; + items = new ItemStack(Items.blastCompound, 60); + end = 60; + }}, - new SpawnGroup(UnitTypes.dagger){{ - begin = 35; - spacing = 3; - unitAmount = 4; - groupAmount = 2; - effect = StatusEffects.overdrive; - items = new ItemStack(Items.blastCompound, 60); - end = 60; - }}, + new SpawnGroup(UnitTypes.dagger){{ + begin = 42; + spacing = 3; + unitAmount = 4; + effect = StatusEffects.overdrive; + items = new ItemStack(Items.pyratite, 100); + end = 130; + }}, - new SpawnGroup(UnitTypes.dagger){{ - begin = 42; - spacing = 3; - unitAmount = 4; - groupAmount = 2; - effect = StatusEffects.overdrive; - items = new ItemStack(Items.pyratite, 100); - end = 130; - }}, + new SpawnGroup(UnitTypes.ghoul){{ + begin = 40; + unitAmount = 2; + spacing = 2; + unitScaling = 3; + max = 8; + }}, - new SpawnGroup(UnitTypes.ghoul){{ - begin = 40; - unitAmount = 2; - spacing = 2; - unitScaling = 3; - max = 8; - }}, + new SpawnGroup(UnitTypes.wraith){{ + begin = 50; + unitAmount = 4; + unitScaling = 3; + spacing = 5; + effect = StatusEffects.overdrive; + max = 8; + }}, - new SpawnGroup(UnitTypes.wraith){{ - begin = 50; - unitAmount = 4; - unitScaling = 3; - spacing = 5; - groupAmount = 2; - effect = StatusEffects.overdrive; - max = 8; - }}, + new SpawnGroup(UnitTypes.revenant){{ + begin = 50; + unitAmount = 4; + unitScaling = 3; + spacing = 5; + max = 8; + }}, - new SpawnGroup(UnitTypes.revenant){{ - begin = 50; - unitAmount = 4; - unitScaling = 3; - spacing = 5; - groupAmount = 2; - max = 8; - }}, + new SpawnGroup(UnitTypes.ghoul){{ + begin = 53; + unitAmount = 2; + unitScaling = 3; + spacing = 4; + max = 8; + end = 74; + }}, - new SpawnGroup(UnitTypes.ghoul){{ - begin = 53; - unitAmount = 2; - unitScaling = 3; - spacing = 4; - max = 8; - end = 74; - }}, + new SpawnGroup(UnitTypes.ghoul){{ + begin = 53; + unitAmount = 2; + unitScaling = 3; + spacing = 4; + max = 8; + end = 74; + }} + ); - new SpawnGroup(UnitTypes.ghoul){{ - begin = 53; - unitAmount = 2; - unitScaling = 3; - spacing = 4; - max = 8; - end = 74; - }} - ); + public static Array getDefaultSpawns(){ + return spawns; } public static void testWaves(int from, int to){ - Array spawns = getSpawns(); for(int i = from; i <= to; i++){ System.out.print(i + ": "); int total = 0; for(SpawnGroup spawn : spawns){ - int a = spawn.getUnitsSpawned(i) * spawn.getGroupsSpawned(i); + int a = spawn.getUnitsSpawned(i); total += a; if(a > 0){ diff --git a/core/src/io/anuke/mindustry/graphics/Palette.java b/core/src/io/anuke/mindustry/graphics/Palette.java index 0ffcf551be..a3bc3a534b 100644 --- a/core/src/io/anuke/mindustry/graphics/Palette.java +++ b/core/src/io/anuke/mindustry/graphics/Palette.java @@ -54,7 +54,7 @@ public class Palette{ range = Color.valueOf("f4ba6e"), power = Color.valueOf("fbad67"), powerLight = Color.valueOf("fbd367"), - placing = Color.valueOf("616161"), + placing = accent, lightTrail = Color.valueOf("ffe2a9"), diff --git a/core/src/io/anuke/mindustry/io/SaveIO.java b/core/src/io/anuke/mindustry/io/SaveIO.java index 2248d056c4..10846a4268 100644 --- a/core/src/io/anuke/mindustry/io/SaveIO.java +++ b/core/src/io/anuke/mindustry/io/SaveIO.java @@ -43,7 +43,7 @@ public class SaveIO{ } } - public static void loadFromSlot(int slot){ + public static void loadFromSlot(int slot) throws SaveException{ 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 and load; if any exception at all occurs load(new InflaterInputStream(file.read())); - }catch(RuntimeException e){ + }catch(SaveException e){ e.printStackTrace(); FileHandle backup = file.sibling(file.name() + "-backup." + file.extension()); if(backup.exists()){ load(new InflaterInputStream(backup.read())); }else{ - throw new RuntimeException(e); + throw new SaveException(e.getCause()); } } } - public static void load(InputStream is){ - logic.reset(); - - DataInputStream stream; - - try{ - stream = new DataInputStream(is); + public static void load(InputStream is) throws SaveException{ + try(DataInputStream stream = new DataInputStream(is)){ + logic.reset(); int version = stream.readInt(); SaveFileVersion ver = versions.get(version); ver.read(stream); - - stream.close(); }catch(Exception e){ content.setTemporaryMapper(null); - throw new RuntimeException(e); + throw new SaveException(e); } } public static SaveFileVersion getVersion(){ return versionArray.peek(); } + + public static class SaveException extends RuntimeException{ + public SaveException(Throwable throwable){ + super(throwable); + } + } } diff --git a/core/src/io/anuke/mindustry/io/versions/Save16.java b/core/src/io/anuke/mindustry/io/versions/Save16.java index afc9b633c9..5eb83a7fb9 100644 --- a/core/src/io/anuke/mindustry/io/versions/Save16.java +++ b/core/src/io/anuke/mindustry/io/versions/Save16.java @@ -5,6 +5,8 @@ import io.anuke.mindustry.game.Version; import io.anuke.mindustry.gen.Serialization; import io.anuke.mindustry.io.SaveFileVersion; 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.DataOutputStream; @@ -26,6 +28,10 @@ public class Save16 extends SaveFileVersion{ //general state state.rules = Serialization.readRules(stream); + //load zone spawn patterns if applicable + if(content.getByID(ContentType.zone, state.rules.zone) != null){ + state.rules.spawns = content.getByID(ContentType.zone, state.rules.zone).rules.get().spawns; + } String mapname = stream.readUTF(); Map map = world.maps.getByName(mapname); if(map == null) map = new Map("unknown", 1, 1); @@ -39,8 +45,6 @@ public class Save16 extends SaveFileVersion{ content.setTemporaryMapper(readContentHeader(stream)); - world.spawner.read(stream); - readEntities(stream); readMap(stream); @@ -63,8 +67,6 @@ public class Save16 extends SaveFileVersion{ writeContentHeader(stream); - world.spawner.write(stream); //spawnes - //--ENTITIES-- writeEntities(stream); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/DeployDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/DeployDialog.java index c7f4911616..84c00df328 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/DeployDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/DeployDialog.java @@ -5,6 +5,7 @@ import io.anuke.arc.collection.ObjectIntMap; import io.anuke.arc.scene.ui.layout.Table; import io.anuke.mindustry.Vars; 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.ItemStack; 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()), () -> { hide(); ui.loadAnd(() -> { - control.saves.getZoneSlot().load(); - state.set(State.playing); + try{ + 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); } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/LoadDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/LoadDialog.java index 00e3e7227c..1bfccbc6df 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/LoadDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/LoadDialog.java @@ -14,6 +14,7 @@ import io.anuke.arc.scene.ui.TextButton; import io.anuke.arc.scene.ui.layout.Table; import io.anuke.arc.util.Log; import io.anuke.arc.util.Strings; +import io.anuke.mindustry.io.SaveIO.SaveException; import java.io.IOException; @@ -173,7 +174,7 @@ public class LoadDialog extends FloatingDialog{ try{ slot.load(); state.set(State.playing); - }catch(Exception e){ + }catch(SaveException e){ Log.err(e); state.set(State.menu); logic.reset(); diff --git a/core/src/io/anuke/mindustry/world/Block.java b/core/src/io/anuke/mindustry/world/Block.java index 444995ffaa..b555aaab98 100644 --- a/core/src/io/anuke/mindustry/world/Block.java +++ b/core/src/io/anuke/mindustry/world/Block.java @@ -92,8 +92,6 @@ public class Block extends BaseBlock { public boolean consumesTap; /** The color of this block when displayed on the minimap or map preview. */ 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.*/ public boolean turretIcon = false; /**Whether units target this block.*/ diff --git a/core/src/io/anuke/mindustry/world/blocks/BlockPart.java b/core/src/io/anuke/mindustry/world/blocks/BlockPart.java index 476829489e..20c7e20778 100644 --- a/core/src/io/anuke/mindustry/world/blocks/BlockPart.java +++ b/core/src/io/anuke/mindustry/world/blocks/BlockPart.java @@ -16,7 +16,6 @@ public class BlockPart extends Block{ super("blockpart"); solid = false; hasPower = hasItems = hasLiquids = true; - viewRange = -1; } @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/Turret.java b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/Turret.java index 6a07a00846..62a0c8fb98 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/Turret.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/Turret.java @@ -92,11 +92,6 @@ public abstract class Turret extends Block{ return false; } - @Override - public void init(){ - super.init(); - viewRange = range; - } @Override public void load(){ @@ -110,10 +105,6 @@ public abstract class Turret extends Block{ @Override public void 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.inaccuracy, (int) inaccuracy, StatUnit.degrees); diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/MassDriver.java b/core/src/io/anuke/mindustry/world/blocks/distribution/MassDriver.java index e890f4bfd4..b75b74a5a5 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/MassDriver.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/MassDriver.java @@ -130,13 +130,6 @@ public class MassDriver extends Block{ stats.add(BlockStat.powerShot, consumes.get(ConsumePower.class).powerCapacity * powerPercentageUsed, StatUnit.powerUnits); } - @Override - public void init(){ - super.init(); - - viewRange = range; - } - @Override public void update(Tile tile){ MassDriverEntity entity = tile.entity(); diff --git a/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java b/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java index d91b70b777..a62b7e30f3 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java @@ -14,36 +14,29 @@ import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.Unit; -import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.traits.SpawnerTrait; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.graphics.Shaders; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.ItemType; import io.anuke.mindustry.world.Tile; 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.*; -public class CoreBlock extends StorageBlock{ - protected TextureRegion openRegion; +public class CoreBlock extends LaunchPad{ protected TextureRegion topRegion; + protected int launchThreshold; + protected int launchChunkSize; public CoreBlock(String name){ super(name); - solid = false; - solidifes = true; + solid = true; update = true; - size = 3; hasItems = true; - viewRange = 200f; + size = 3; flags = EnumSet.of(BlockFlag.resupplyPoint, BlockFlag.target); } @@ -53,11 +46,12 @@ public class CoreBlock extends StorageBlock{ CoreEntity entity = tile.entity(); Effects.effect(Fx.spawn, entity); - entity.solid = false; entity.progress = 0; + entity.currentUnit.onRespawn(tile); entity.currentUnit = player; entity.currentUnit.heal(); entity.currentUnit.rotation = 90f; + entity.currentUnit.applyImpulse(0, 8f); entity.currentUnit.setNet(tile.drawx(), tile.drawy()); entity.currentUnit.add(); 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 public int getMaximumAccepted(Tile tile, Item item){ return itemCapacity * state.teams.get(tile.getTeam()).cores.size; @@ -118,7 +100,6 @@ public class CoreBlock extends StorageBlock{ public void load(){ super.load(); - openRegion = Core.atlas.find(name + "-open"); topRegion = Core.atlas.find(name + "-top"); } @@ -126,7 +107,7 @@ public class CoreBlock extends StorageBlock{ public void draw(Tile tile){ 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.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 public void handleItem(Item item, Tile tile, 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){ CoreEntity entity = tile.entity(); - if(!entity.solid && !Units.anyEntities(tile)){ - Call.setCoreSolid(tile, true); + for(Item item : Vars.content.items()){ + 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){ @@ -200,7 +179,6 @@ public class CoreBlock extends StorageBlock{ public class CoreEntity extends TileEntity implements SpawnerTrait{ public Unit currentUnit; - boolean solid = true; float progress; float time; float heat; @@ -218,15 +196,5 @@ public class CoreBlock extends StorageBlock{ public float getSpawnProgress(){ return progress; } - - @Override - public void write(DataOutput stream) throws IOException{ - stream.writeBoolean(solid); - } - - @Override - public void read(DataInput stream) throws IOException{ - solid = stream.readBoolean(); - } } } diff --git a/core/src/io/anuke/mindustry/world/blocks/storage/LaunchPad.java b/core/src/io/anuke/mindustry/world/blocks/storage/LaunchPad.java index 65e67d7b94..5647974149 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/LaunchPad.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/LaunchPad.java @@ -6,12 +6,11 @@ import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.ItemType; -import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; import static io.anuke.mindustry.Vars.data; -public class LaunchPad extends Block{ +public class LaunchPad extends StorageBlock{ protected final int timerLaunch = timers++; /**Time inbetween launches.*/ protected float launchTime; @@ -19,14 +18,13 @@ public class LaunchPad extends Block{ public LaunchPad(String name){ super(name); update = true; - hasPower = true; hasItems = true; solid = true; } @Override 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