mirror of
https://github.com/Anuken/Mindustry.git
synced 2026-01-21 03:51:41 -08:00
Balancing
This commit is contained in:
parent
47605583d1
commit
ccc20a9716
23 changed files with 333 additions and 553 deletions
|
|
@ -182,8 +182,6 @@ public class Pathfinder{
|
|||
createFor(team);
|
||||
}
|
||||
}
|
||||
|
||||
world.spawner.checkAllQuadrants();
|
||||
}
|
||||
|
||||
class PathData{
|
||||
|
|
|
|||
|
|
@ -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<SpawnGroup> groups;
|
||||
private boolean dynamicSpawn;
|
||||
|
||||
private Array<FlyerSpawn> flySpawns = new Array<>();
|
||||
private Array<GroundSpawn> 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}};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}}
|
||||
);
|
||||
}};
|
||||
}};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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:<br>
|
||||
* - setting up multiblocks<br>
|
||||
* - updating occlusion<br>
|
||||
* 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:<br>
|
||||
* - setting up multiblocks<br>
|
||||
* - updating occlusion<br>
|
||||
* Usually used before placing structures on a tile array.*/
|
||||
public void prepareTiles(Tile[][] tiles){
|
||||
|
||||
//find multiblocks
|
||||
IntArray multiblocks = new IntArray();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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<ContentType, ObjectSet<String>> 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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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<SpawnGroup> spawns = Waves.getDefaultSpawns();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(){
|
||||
|
|
|
|||
|
|
@ -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 +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,176 +8,171 @@ import io.anuke.mindustry.content.Weapons;
|
|||
import io.anuke.mindustry.type.ItemStack;
|
||||
|
||||
public class Waves{
|
||||
private static Array<SpawnGroup> spawns = Array.with(
|
||||
new SpawnGroup(UnitTypes.dagger){{
|
||||
end = 8;
|
||||
unitScaling = 3;
|
||||
}},
|
||||
|
||||
public static Array<SpawnGroup> 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<SpawnGroup> getDefaultSpawns(){
|
||||
return spawns;
|
||||
}
|
||||
|
||||
public static void testWaves(int from, int to){
|
||||
Array<SpawnGroup> 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){
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.<Zone>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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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.*/
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ public class BlockPart extends Block{
|
|||
super("blockpart");
|
||||
solid = false;
|
||||
hasPower = hasItems = hasLiquids = true;
|
||||
viewRange = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue