Gamemodes removed
@ -12,6 +12,7 @@ import javax.lang.model.util.ElementFilter;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@ -60,14 +61,12 @@ public class SerializeAnnotationProcessor extends AbstractProcessor{
|
||||
.returns(void.class)
|
||||
.addParameter(DataOutput.class, "stream")
|
||||
.addParameter(type, "object")
|
||||
.addAnnotation(Override.class)
|
||||
.addException(IOException.class)
|
||||
.addModifiers(Modifier.PUBLIC);
|
||||
|
||||
MethodSpec.Builder readMethod = MethodSpec.methodBuilder("read")
|
||||
.returns(type)
|
||||
.addParameter(DataInput.class, "stream")
|
||||
.addAnnotation(Override.class)
|
||||
.addException(IOException.class)
|
||||
.addModifiers(Modifier.PUBLIC);
|
||||
|
||||
@ -96,6 +95,17 @@ public class SerializeAnnotationProcessor extends AbstractProcessor{
|
||||
serializer.addMethod(readMethod.build());
|
||||
|
||||
method.addStatement("io.anuke.arc.Core.settings.setSerializer($N, $L)", Utils.elementUtils.getBinaryName(elem).toString().replace('$', '.') + ".class", serializer.build());
|
||||
|
||||
String sname = type.toString().substring(type.toString().lastIndexOf('.') + 1);
|
||||
|
||||
name(writeMethod, "write" + sname);
|
||||
name(readMethod, "read" + sname);
|
||||
|
||||
writeMethod.addModifiers(Modifier.STATIC);
|
||||
readMethod.addModifiers(Modifier.STATIC);
|
||||
|
||||
classBuilder.addMethod(writeMethod.build());
|
||||
classBuilder.addMethod(readMethod.build());
|
||||
}
|
||||
|
||||
classBuilder.addMethod(method.build());
|
||||
@ -109,4 +119,14 @@ public class SerializeAnnotationProcessor extends AbstractProcessor{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
static void name(MethodSpec.Builder builder, String name){
|
||||
try{
|
||||
Field field = builder.getClass().getDeclaredField("name");
|
||||
field.setAccessible(true);
|
||||
field.set(builder, name);
|
||||
}catch(Exception e){
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
BIN
core/assets-raw/sprites/blocks/environment/rocks-medium1.png
Normal file
After Width: | Height: | Size: 257 B |
BIN
core/assets-raw/sprites/blocks/environment/rocks-medium2.png
Normal file
After Width: | Height: | Size: 252 B |
BIN
core/assets-raw/sprites/blocks/environment/rocks-small1.png
Normal file
After Width: | Height: | Size: 263 B |
BIN
core/assets-raw/sprites/blocks/environment/rocks-small2.png
Normal file
After Width: | Height: | Size: 276 B |
BIN
core/assets-raw/sprites/blocks/environment/rocks-small3.png
Normal file
After Width: | Height: | Size: 249 B |
Before Width: | Height: | Size: 335 KiB After Width: | Height: | Size: 338 KiB |
@ -39,12 +39,8 @@ public class Vars{
|
||||
public static final String contributorsURL = "https://api.github.com/repos/Anuken/Mindustry/contributors";
|
||||
/**URL for sending crash reports to*/
|
||||
public static final String crashReportURL = "http://mindustry.us.to/report";
|
||||
/**time between waves in ticks (on normal mode)*/
|
||||
public static final float wavespace = 60 * 60 * 1.5f;
|
||||
/**maximum distance between mine and core that supports automatic transferring*/
|
||||
public static final float mineTransferRange = 220f;
|
||||
/**maximum distance from core that the player can be before it is no longer used for building*/
|
||||
public static final float coreBuildRange = 999999f;
|
||||
/**team of the player by default*/
|
||||
public static final Team defaultTeam = Team.blue;
|
||||
/**team of the enemy in waves/sectors*/
|
||||
|
@ -82,7 +82,7 @@ public class Pathfinder{
|
||||
}
|
||||
|
||||
public float getValueforTeam(Team team, int x, int y){
|
||||
return paths == null || team.ordinal() >= paths.length ? 0 : Structs.inBounds(x, y, paths[team.ordinal()].weights) ? paths[team.ordinal()].weights[x][y] : 0;
|
||||
return paths == null || paths[team.ordinal()].weights == null || team.ordinal() >= paths.length ? 0 : Structs.inBounds(x, y, paths[team.ordinal()].weights) ? paths[team.ordinal()].weights[x][y] : 0;
|
||||
}
|
||||
|
||||
private boolean passable(Tile tile, Team team){
|
||||
|
@ -31,7 +31,7 @@ public class Blocks implements ContentList{
|
||||
|
||||
//environment
|
||||
air, blockpart, spawn, space, metalfloor, deepwater, water, tar, stone, blackstone, dirt, sand, ice, snow,
|
||||
grass, shrub, rock, icerock, blackrock,
|
||||
grass, shrub, rock, icerock, blackrock, rocksSmall, rocksMedium,
|
||||
|
||||
//crafting
|
||||
siliconSmelter, plastaniumCompressor, phaseWeaver, surgeSmelter, pyratiteMixer, blastMixer, cryofluidMixer,
|
||||
@ -209,6 +209,18 @@ public class Blocks implements ContentList{
|
||||
blackrock = new Rock("blackrock"){{
|
||||
variants = 1;
|
||||
}};
|
||||
|
||||
rocksSmall = new Rock("rocks-small"){{
|
||||
variants = 2;
|
||||
breakable = alwaysReplace = false;
|
||||
solid = true;
|
||||
}};
|
||||
|
||||
rocksMedium = new Rock("rocks-medium"){{
|
||||
variants = 2;
|
||||
breakable = alwaysReplace = false;
|
||||
solid = true;
|
||||
}};
|
||||
|
||||
//endregion
|
||||
//region crafting
|
||||
|
@ -1,7 +1,6 @@
|
||||
package io.anuke.mindustry.content;
|
||||
|
||||
import io.anuke.mindustry.game.ContentList;
|
||||
import io.anuke.mindustry.game.GameMode;
|
||||
import io.anuke.mindustry.type.ItemStack;
|
||||
import io.anuke.mindustry.type.Recipe;
|
||||
import io.anuke.mindustry.type.Recipe.RecipeVisibility;
|
||||
@ -13,11 +12,11 @@ public class Recipes implements ContentList{
|
||||
@Override
|
||||
public void load(){
|
||||
//DEBUG
|
||||
new Recipe(distribution, Blocks.itemSource).setMode(GameMode.sandbox).setHidden(true).setAlwaysUnlocked(true);
|
||||
new Recipe(distribution, Blocks.itemVoid).setMode(GameMode.sandbox).setHidden(true).setAlwaysUnlocked(true);
|
||||
new Recipe(liquid, Blocks.liquidSource).setMode(GameMode.sandbox).setHidden(true).setAlwaysUnlocked(true);
|
||||
new Recipe(power, Blocks.powerVoid).setMode(GameMode.sandbox).setHidden(true).setAlwaysUnlocked(true);
|
||||
new Recipe(power, Blocks.powerSource).setMode(GameMode.sandbox).setHidden(true).setAlwaysUnlocked(true);
|
||||
new Recipe(distribution, Blocks.itemSource).setVisible(RecipeVisibility.sandboxOnly).setHidden(true).setAlwaysUnlocked(true);
|
||||
new Recipe(distribution, Blocks.itemVoid).setVisible(RecipeVisibility.sandboxOnly).setHidden(true).setAlwaysUnlocked(true);
|
||||
new Recipe(liquid, Blocks.liquidSource).setVisible(RecipeVisibility.sandboxOnly).setHidden(true).setAlwaysUnlocked(true);
|
||||
new Recipe(power, Blocks.powerVoid).setVisible(RecipeVisibility.sandboxOnly).setHidden(true).setAlwaysUnlocked(true);
|
||||
new Recipe(power, Blocks.powerSource).setVisible(RecipeVisibility.sandboxOnly).setHidden(true).setAlwaysUnlocked(true);
|
||||
|
||||
//DEFENSE
|
||||
|
||||
|
@ -113,18 +113,7 @@ public class Control implements ApplicationListener{
|
||||
saves.resetSave();
|
||||
});
|
||||
|
||||
Events.on(WaveEvent.class, event -> {
|
||||
|
||||
int last = Core.settings.getInt("hiscore" + world.getMap().name, 0);
|
||||
|
||||
if(state.wave > last && !state.mode.infiniteResources && !state.mode.disableWaveTimer){
|
||||
Core.settings.put("hiscore" + world.getMap().name, state.wave);
|
||||
Core.settings.save();
|
||||
hiscore = true;
|
||||
}
|
||||
|
||||
Platform.instance.updateRPC();
|
||||
});
|
||||
//todo high scores for custom maps, as well as other statistics
|
||||
|
||||
Events.on(GameOverEvent.class, event -> {
|
||||
Effects.shake(5, 6, Core.camera.position.x, Core.camera.position.y);
|
||||
@ -134,7 +123,7 @@ public class Control implements ApplicationListener{
|
||||
|
||||
//autohost for pvp sectors
|
||||
Events.on(WorldLoadEvent.class, event -> {
|
||||
if(state.mode.isPvp && !Net.active()){
|
||||
if(state.rules.pvp && !Net.active()){
|
||||
try{
|
||||
Net.host(port);
|
||||
players[0].isAdmin = true;
|
||||
|
@ -1,11 +1,10 @@
|
||||
package io.anuke.mindustry.core;
|
||||
|
||||
import io.anuke.mindustry.game.Difficulty;
|
||||
import io.anuke.arc.Events;
|
||||
import io.anuke.mindustry.game.EventType.StateChangeEvent;
|
||||
import io.anuke.mindustry.game.GameMode;
|
||||
import io.anuke.mindustry.game.Rules;
|
||||
import io.anuke.mindustry.game.Teams;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
import io.anuke.arc.Events;
|
||||
|
||||
import static io.anuke.mindustry.Vars.unitGroups;
|
||||
import static io.anuke.mindustry.Vars.waveTeam;
|
||||
@ -13,14 +12,12 @@ import static io.anuke.mindustry.Vars.waveTeam;
|
||||
public class GameState{
|
||||
/**Current wave number, can be anything in non-wave modes.*/
|
||||
public int wave = 1;
|
||||
/**Wave countdown in ticks.*/
|
||||
/**Wave time in ticks.*/
|
||||
public float wavetime;
|
||||
/**Whether the game is in game over state.*/
|
||||
public boolean gameOver = false;
|
||||
/**The current game mode.*/
|
||||
public GameMode mode = GameMode.waves;
|
||||
/**The current difficulty for wave modes.*/
|
||||
public Difficulty difficulty = Difficulty.normal;
|
||||
/**The current game rules.*/
|
||||
public Rules rules = new Rules();
|
||||
/**Team data. Gets reset every new game.*/
|
||||
public Teams teams = new Teams();
|
||||
/**Number of enemies in the game; only used clientside in servers.*/
|
||||
|
@ -11,6 +11,7 @@ import io.anuke.arc.util.Time;
|
||||
import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.game.EventType.*;
|
||||
import io.anuke.mindustry.game.Rules;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.game.Teams;
|
||||
import io.anuke.mindustry.game.UnlockableContent;
|
||||
@ -56,16 +57,17 @@ public class Logic implements ApplicationListener{
|
||||
|
||||
public void play(){
|
||||
state.set(State.playing);
|
||||
state.wavetime = wavespace * state.difficulty.timeScaling * 2;
|
||||
state.wavetime = 0;
|
||||
|
||||
Events.fire(new PlayEvent());
|
||||
}
|
||||
|
||||
public void reset(){
|
||||
state.wave = 1;
|
||||
state.wavetime = wavespace * state.difficulty.timeScaling;
|
||||
state.wavetime = 0;
|
||||
state.gameOver = false;
|
||||
state.teams = new Teams();
|
||||
state.rules = new Rules();
|
||||
|
||||
Time.clear();
|
||||
Entities.clear();
|
||||
@ -77,16 +79,16 @@ public class Logic implements ApplicationListener{
|
||||
public void runWave(){
|
||||
world.spawner.spawnEnemies();
|
||||
state.wave++;
|
||||
state.wavetime = wavespace * state.difficulty.timeScaling;
|
||||
state.wavetime = 0;
|
||||
|
||||
Events.fire(new WaveEvent());
|
||||
}
|
||||
|
||||
private void checkGameOver(){
|
||||
if(!state.mode.isPvp && state.teams.get(defaultTeam).cores.size == 0 && !state.gameOver){
|
||||
if(!state.rules.pvp && state.teams.get(defaultTeam).cores.size == 0 && !state.gameOver){
|
||||
state.gameOver = true;
|
||||
Events.fire(new GameOverEvent(waveTeam));
|
||||
}else if(state.mode.isPvp){
|
||||
}else if(state.rules.pvp){
|
||||
Team alive = null;
|
||||
|
||||
for(Team team : Team.all){
|
||||
@ -119,16 +121,17 @@ public class Logic implements ApplicationListener{
|
||||
if(!state.isPaused()){
|
||||
Time.update();
|
||||
|
||||
if(!state.mode.disableWaveTimer && !state.mode.disableWaves && !state.gameOver){
|
||||
state.wavetime -= Time.delta();
|
||||
if(state.rules.waves && state.rules.waveTimer && !state.gameOver){
|
||||
state.wavetime += Time.delta();
|
||||
}
|
||||
|
||||
if(!Net.client() && state.wavetime <= 0 && !state.mode.disableWaves){
|
||||
if(!Net.client() && state.wavetime >= state.rules.waveSpacing && state.rules.waves){
|
||||
runWave();
|
||||
}
|
||||
|
||||
if(!Entities.defaultGroup().isEmpty())
|
||||
throw new RuntimeException("Do not add anything to the default group!");
|
||||
if(!Entities.defaultGroup().isEmpty()){
|
||||
throw new IllegalArgumentException("Do not add anything to the default group!");
|
||||
}
|
||||
|
||||
if(!headless){
|
||||
Entities.update(effectGroup);
|
||||
|
@ -193,7 +193,8 @@ public class NetServer implements ApplicationListener{
|
||||
return;
|
||||
}
|
||||
|
||||
if(state.mode.isPvp){
|
||||
//playing in pvp mode automatically assigns players to teams
|
||||
if(state.rules.pvp){
|
||||
//find team with minimum amount of players and auto-assign player to that.
|
||||
Team min = Structs.findMin(Team.all, team -> {
|
||||
if(state.teams.isActive(team)){
|
||||
@ -382,7 +383,7 @@ public class NetServer implements ApplicationListener{
|
||||
}
|
||||
|
||||
public boolean isWaitingForPlayers(){
|
||||
if(state.mode.isPvp){
|
||||
if(state.rules.pvp){
|
||||
int used = 0;
|
||||
for(Team t : Team.all){
|
||||
if(playerGroup.count(p -> p.getTeam() == t) > 0){
|
||||
|
@ -235,7 +235,7 @@ public class World implements ApplicationListener{
|
||||
if(state.teams.get(players[0].getTeam()).cores.size == 0){
|
||||
ui.showError("$map.nospawn");
|
||||
invalidMap = true;
|
||||
}else if(state.mode.isPvp){
|
||||
}else if(state.rules.pvp){ //pvp maps need two cores to be valid
|
||||
invalidMap = true;
|
||||
for(Team team : Team.all){
|
||||
if(state.teams.get(team).cores.size != 0 && team != players[0].getTeam()){
|
||||
|
@ -12,7 +12,7 @@ public class UnitDrops{
|
||||
|
||||
public static void dropItems(BaseUnit unit){
|
||||
//items only dropped in waves for enemy team
|
||||
if(unit.getTeam() != Vars.waveTeam || Vars.state.mode.disableWaves){
|
||||
if(unit.getTeam() != Vars.waveTeam || !Vars.state.rules.unitDrops){
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2,23 +2,21 @@ package io.anuke.mindustry.game;
|
||||
|
||||
import io.anuke.arc.Core;
|
||||
|
||||
/**Presets for time between waves.
|
||||
* TODO specify correct time*/
|
||||
public enum Difficulty{
|
||||
training(3f, 3f),
|
||||
easy(1.4f, 1.5f),
|
||||
normal(1f, 1f),
|
||||
hard(0.5f, 0.75f),
|
||||
insane(0.25f, 0.5f);
|
||||
easy(1.4f),
|
||||
normal(1f),
|
||||
hard(0.5f),
|
||||
insane(0.25f);
|
||||
|
||||
/**Multiplier of the time between waves.*/
|
||||
public final float timeScaling;
|
||||
/**Multiplier of spawner grace period.*/
|
||||
public final float spawnerScaling;
|
||||
public final float waveTime;
|
||||
|
||||
private String value;
|
||||
|
||||
Difficulty(float timeScaling, float spawnerScaling){
|
||||
this.timeScaling = timeScaling;
|
||||
this.spawnerScaling = spawnerScaling;
|
||||
Difficulty(float waveTime){
|
||||
this.waveTime = waveTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,44 +0,0 @@
|
||||
package io.anuke.mindustry.game;
|
||||
|
||||
import io.anuke.arc.Core;
|
||||
|
||||
public enum GameMode{
|
||||
waves,
|
||||
sandbox{{
|
||||
infiniteResources = true;
|
||||
disableWaveTimer = true;
|
||||
}},
|
||||
freebuild{{
|
||||
disableWaveTimer = true;
|
||||
}},
|
||||
attack{{
|
||||
disableWaves = true;
|
||||
enemyCheat = true;
|
||||
}},
|
||||
victory{{
|
||||
disableWaves = true;
|
||||
hidden = true;
|
||||
enemyCheat = false;
|
||||
showMission = false;
|
||||
}},
|
||||
pvp{{
|
||||
disableWaves = true;
|
||||
isPvp = true;
|
||||
enemyCoreBuildRadius = 600f;
|
||||
respawnTime = 60 * 10;
|
||||
}};
|
||||
|
||||
public boolean infiniteResources, disableWaveTimer, disableWaves, showMission = true, hidden, enemyCheat, isPvp;
|
||||
public float enemyCoreBuildRadius = 400f;
|
||||
public float respawnTime = 60 * 4;
|
||||
|
||||
public String description(){
|
||||
return Core.bundle.get("mode." + name() + ".description");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return Core.bundle.get("mode." + name() + ".name");
|
||||
}
|
||||
|
||||
}
|
46
core/src/io/anuke/mindustry/game/RulePreset.java
Normal file
@ -0,0 +1,46 @@
|
||||
package io.anuke.mindustry.game;
|
||||
|
||||
import io.anuke.arc.Core;
|
||||
import io.anuke.arc.function.Supplier;
|
||||
|
||||
/**Defines preset rule sets..*/
|
||||
public enum RulePreset{
|
||||
survival(() -> new Rules(){{
|
||||
waveTimer = true;
|
||||
waves = true;
|
||||
unitDrops = true;
|
||||
}}),
|
||||
sandbox(() -> new Rules(){{
|
||||
infiniteResources = true;
|
||||
waves = true;
|
||||
waveTimer = false;
|
||||
}}),
|
||||
attack(() -> new Rules(){{
|
||||
enemyCheat = true;
|
||||
unitDrops = true;
|
||||
}}),
|
||||
pvp(() -> new Rules(){{
|
||||
pvp = true;
|
||||
enemyCoreBuildRadius = 600f;
|
||||
respawnTime = 60 * 10;
|
||||
}});
|
||||
|
||||
private final Supplier<Rules> rules;
|
||||
|
||||
RulePreset(Supplier<Rules> rules){
|
||||
this.rules = rules;
|
||||
}
|
||||
|
||||
public Rules get(){
|
||||
return rules.get();
|
||||
}
|
||||
|
||||
public String description(){
|
||||
return Core.bundle.get("mode." + name() + ".description");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return Core.bundle.get("mode." + name() + ".name");
|
||||
}
|
||||
}
|
27
core/src/io/anuke/mindustry/game/Rules.java
Normal file
@ -0,0 +1,27 @@
|
||||
package io.anuke.mindustry.game;
|
||||
|
||||
import io.anuke.annotations.Annotations.Serialize;
|
||||
|
||||
/**Defines current rules on how the game should function.
|
||||
* Does not store game state, just configuration.*/
|
||||
@Serialize
|
||||
public class Rules{
|
||||
/**Whether the player has infinite resources.*/
|
||||
public boolean infiniteResources;
|
||||
/**Whether the waves come automatically on a timer. If not, waves come when the play button is pressed.*/
|
||||
public boolean waveTimer = true;
|
||||
/**Whether waves are spawnable at all.*/
|
||||
public boolean waves;
|
||||
/**Whether the enemy AI has infinite resources in most of their buildings and turrets.*/
|
||||
public boolean enemyCheat;
|
||||
/**Whether the game objective is PvP. Note that this enables automatic hosting.*/
|
||||
public boolean pvp;
|
||||
/**Whether enemy units drop random items on death.*/
|
||||
public boolean unitDrops;
|
||||
/**No-build zone around enemy core radius.*/
|
||||
public float enemyCoreBuildRadius = 400f;
|
||||
/**Player respawn time in ticks.*/
|
||||
public float respawnTime = 60 * 4;
|
||||
/**Time between waves in ticks.*/
|
||||
public float waveSpacing = 60 * 60;
|
||||
}
|
@ -215,10 +215,6 @@ public class Saves{
|
||||
return meta.difficulty;
|
||||
}
|
||||
|
||||
public GameMode getMode(){
|
||||
return meta.mode;
|
||||
}
|
||||
|
||||
public boolean isAutosave(){
|
||||
return Core.settings.getBool("save-" + index + "-autosave", true);
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ public class Teams{
|
||||
/**Returns whether a team is active, e.g. whether it has any cores remaining.*/
|
||||
public boolean isActive(Team team){
|
||||
//the enemy wave team is always active
|
||||
return (!Vars.state.mode.disableWaves && team == Vars.waveTeam) || get(team).cores.size > 0;
|
||||
return (Vars.state.rules.waves && team == Vars.waveTeam) || get(team).cores.size > 0;
|
||||
}
|
||||
|
||||
/**Returns a set of all teams that are enemies of this team.*/
|
||||
|
@ -76,11 +76,11 @@ public class OverlayRenderer{
|
||||
for(Team enemy : state.teams.enemiesOf(player.getTeam())){
|
||||
for(Tile core : state.teams.get(enemy).cores){
|
||||
float dst = Mathf.dst(player.x, player.y, core.drawx(), core.drawy());
|
||||
if(dst < state.mode.enemyCoreBuildRadius * 1.5f){
|
||||
if(dst < state.rules.enemyCoreBuildRadius * 1.5f){
|
||||
Draw.color(Color.DARK_GRAY);
|
||||
Lines.poly(core.drawx(), core.drawy() - 2, 200, state.mode.enemyCoreBuildRadius);
|
||||
Lines.poly(core.drawx(), core.drawy() - 2, 200, state.rules.enemyCoreBuildRadius);
|
||||
Draw.color(Palette.accent, enemy.color, 0.5f + Mathf.absin(Time.time(), 10f, 0.5f));
|
||||
Lines.poly(core.drawx(), core.drawy(), 200, state.mode.enemyCoreBuildRadius);
|
||||
Lines.poly(core.drawx(), core.drawy(), 200, state.rules.enemyCoreBuildRadius);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -330,10 +330,8 @@ public abstract class InputHandler implements InputProcessor{
|
||||
|
||||
public boolean validPlace(int x, int y, Block type, int rotation){
|
||||
for(Tile tile : state.teams.get(player.getTeam()).cores){
|
||||
if(tile.dst(x * tilesize, y * tilesize) < coreBuildRange){
|
||||
return Build.validPlace(player.getTeam(), x, y, type, rotation) &&
|
||||
Mathf.dst(player.x, player.y, x * tilesize, y * tilesize) < Player.placeDistance;
|
||||
}
|
||||
return Build.validPlace(player.getTeam(), x, y, type, rotation) &&
|
||||
Mathf.dst(player.x, player.y, x * tilesize, y * tilesize) < Player.placeDistance;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -1,7 +1,6 @@
|
||||
package io.anuke.mindustry.io;
|
||||
|
||||
import io.anuke.mindustry.game.Difficulty;
|
||||
import io.anuke.mindustry.game.GameMode;
|
||||
import io.anuke.mindustry.maps.Map;
|
||||
|
||||
import static io.anuke.mindustry.Vars.world;
|
||||
@ -11,7 +10,6 @@ public class SaveMeta{
|
||||
public int build;
|
||||
public long timestamp;
|
||||
public long timePlayed;
|
||||
public GameMode mode;
|
||||
public Map map;
|
||||
public int wave;
|
||||
public Difficulty difficulty;
|
||||
@ -21,7 +19,6 @@ public class SaveMeta{
|
||||
this.build = build;
|
||||
this.timestamp = timestamp;
|
||||
this.timePlayed = timePlayed;
|
||||
this.mode = GameMode.values()[mode];
|
||||
this.map = world.maps.getByName(map);
|
||||
this.wave = wave;
|
||||
this.difficulty = difficulty;
|
||||
|
@ -1,9 +1,8 @@
|
||||
package io.anuke.mindustry.io.versions;
|
||||
|
||||
import io.anuke.arc.util.Time;
|
||||
import io.anuke.mindustry.game.Difficulty;
|
||||
import io.anuke.mindustry.game.GameMode;
|
||||
import io.anuke.mindustry.game.Version;
|
||||
import io.anuke.mindustry.gen.Serialization;
|
||||
import io.anuke.mindustry.io.SaveFileVersion;
|
||||
import io.anuke.mindustry.maps.Map;
|
||||
|
||||
@ -26,18 +25,15 @@ public class Save16 extends SaveFileVersion{
|
||||
stream.readInt(); //build
|
||||
|
||||
//general state
|
||||
byte mode = stream.readByte();
|
||||
state.rules = Serialization.readRules(stream);
|
||||
String mapname = stream.readUTF();
|
||||
Map map = world.maps.getByName(mapname);
|
||||
if(map == null) map = new Map("unknown", 1, 1);
|
||||
world.setMap(map);
|
||||
|
||||
int wave = stream.readInt();
|
||||
byte difficulty = stream.readByte();
|
||||
float wavetime = stream.readFloat();
|
||||
|
||||
state.difficulty = Difficulty.values()[difficulty];
|
||||
state.mode = GameMode.values()[mode];
|
||||
state.wave = wave;
|
||||
state.wavetime = wavetime;
|
||||
|
||||
@ -59,11 +55,10 @@ public class Save16 extends SaveFileVersion{
|
||||
stream.writeInt(Version.build); //build
|
||||
|
||||
//--GENERAL STATE--
|
||||
stream.writeByte(state.mode.ordinal()); //gamemode
|
||||
stream.writeUTF(world.getMap().name); //map ID
|
||||
Serialization.writeRules(stream, state.rules);
|
||||
stream.writeUTF(world.getMap().name); //map name
|
||||
|
||||
stream.writeInt(state.wave); //wave
|
||||
stream.writeByte(state.difficulty.ordinal()); //difficulty ordinal
|
||||
stream.writeFloat(state.wavetime); //wave countdown
|
||||
|
||||
writeContentHeader(stream);
|
||||
|
@ -4,6 +4,7 @@ import io.anuke.arc.Core;
|
||||
import io.anuke.arc.collection.IntIntMap;
|
||||
import io.anuke.arc.collection.ObjectMap;
|
||||
|
||||
//todo: specify preferred game rules here; can be overriden
|
||||
public class MapMeta{
|
||||
public final int version;
|
||||
public final ObjectMap<String, String> tags;
|
||||
|
@ -21,6 +21,7 @@ public class BasicGenerator extends RandomGenerator{
|
||||
|
||||
@Override
|
||||
public void generate(Tile[][] tiles){
|
||||
//todo use set seed
|
||||
int seed = Mathf.random(99999999);
|
||||
sim.setSeed(seed);
|
||||
sim2.setSeed(seed + 1);
|
||||
@ -42,5 +43,17 @@ public class BasicGenerator extends RandomGenerator{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//rock outcrops
|
||||
double rocks = sim.octaveNoise2D(3, 0.7, 1f / 70f, x, y);
|
||||
double edgeDist = Math.min(x, Math.min(y, Math.min(Math.abs(x - (width - 1)), Math.abs(y - (height - 1)))));
|
||||
double transition = 8;
|
||||
if(edgeDist < transition){
|
||||
rocks += (transition - edgeDist) / transition / 1.5;
|
||||
}
|
||||
|
||||
if(rocks > 0.64){
|
||||
block = Blocks.rocksSmall;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
package io.anuke.mindustry.net;
|
||||
|
||||
import io.anuke.mindustry.game.GameMode;
|
||||
|
||||
public class Host{
|
||||
public final String name;
|
||||
public final String address;
|
||||
@ -10,9 +8,8 @@ public class Host{
|
||||
public final int players;
|
||||
public final int version;
|
||||
public final String versionType;
|
||||
public final GameMode mode;
|
||||
|
||||
public Host(String name, String address, String mapname, int wave, int players, int version, String versionType, GameMode mode){
|
||||
public Host(String name, String address, String mapname, int wave, int players, int version, String versionType){
|
||||
this.name = name;
|
||||
this.address = address;
|
||||
this.players = players;
|
||||
@ -20,6 +17,5 @@ public class Host{
|
||||
this.wave = wave;
|
||||
this.version = version;
|
||||
this.versionType = versionType;
|
||||
this.mode = mode;
|
||||
}
|
||||
}
|
||||
|
@ -8,11 +8,11 @@ import io.anuke.arc.util.Pack;
|
||||
import io.anuke.arc.util.Time;
|
||||
import io.anuke.mindustry.content.Blocks;
|
||||
import io.anuke.mindustry.entities.Player;
|
||||
import io.anuke.mindustry.game.GameMode;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.game.Teams;
|
||||
import io.anuke.mindustry.game.Teams.TeamData;
|
||||
import io.anuke.mindustry.game.Version;
|
||||
import io.anuke.mindustry.gen.Serialization;
|
||||
import io.anuke.mindustry.maps.Map;
|
||||
import io.anuke.mindustry.maps.MapMeta;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
@ -30,7 +30,7 @@ public class NetworkIO{
|
||||
|
||||
try(DataOutputStream stream = new DataOutputStream(os)){
|
||||
//--GENERAL STATE--
|
||||
stream.writeByte(state.mode.ordinal()); //gamemode
|
||||
Serialization.writeRules(stream, state.rules);
|
||||
stream.writeUTF(world.getMap().name); //map name
|
||||
|
||||
//write tags
|
||||
@ -121,7 +121,7 @@ public class NetworkIO{
|
||||
Time.clear();
|
||||
|
||||
//general state
|
||||
byte mode = stream.readByte();
|
||||
state.rules = Serialization.readRules(stream);
|
||||
String map = stream.readUTF();
|
||||
|
||||
ObjectMap<String, String> tags = new ObjectMap<>();
|
||||
@ -138,7 +138,6 @@ public class NetworkIO{
|
||||
|
||||
state.wave = wave;
|
||||
state.wavetime = wavetime;
|
||||
state.mode = GameMode.values()[mode];
|
||||
|
||||
Entities.clear();
|
||||
int id = stream.readInt();
|
||||
@ -256,7 +255,6 @@ public class NetworkIO{
|
||||
buffer.putInt(Version.build);
|
||||
buffer.put((byte)Version.type.getBytes(StandardCharsets.UTF_8).length);
|
||||
buffer.put(Version.type.getBytes(StandardCharsets.UTF_8));
|
||||
buffer.put((byte)state.mode.ordinal());
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@ -279,8 +277,7 @@ public class NetworkIO{
|
||||
byte[] tb = new byte[tlength];
|
||||
buffer.get(tb);
|
||||
String vertype = new String(tb, StandardCharsets.UTF_8);
|
||||
GameMode mode = GameMode.values()[buffer.get()];
|
||||
|
||||
return new Host(host, hostAddress, map, wave, players, version, vertype, mode);
|
||||
return new Host(host, hostAddress, map, wave, players, version, vertype);
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ import io.anuke.arc.scene.ui.layout.Table;
|
||||
import io.anuke.arc.util.Log;
|
||||
import io.anuke.arc.util.Strings;
|
||||
import io.anuke.mindustry.Vars;
|
||||
import io.anuke.mindustry.game.GameMode;
|
||||
import io.anuke.mindustry.game.UnlockableContent;
|
||||
import io.anuke.mindustry.ui.ContentDisplay;
|
||||
import io.anuke.mindustry.world.Block;
|
||||
@ -31,13 +30,9 @@ public class Recipe extends UnlockableContent{
|
||||
public final float cost;
|
||||
|
||||
public RecipeVisibility visibility = RecipeVisibility.all;
|
||||
//the only gamemode in which the recipe shows up
|
||||
public GameMode mode;
|
||||
public boolean hidden;
|
||||
public boolean alwaysUnlocked;
|
||||
|
||||
private UnlockableContent[] dependencies;
|
||||
|
||||
public Recipe(Category category, Block result, ItemStack... requirements){
|
||||
this.result = result;
|
||||
this.requirements = requirements;
|
||||
@ -59,7 +54,7 @@ public class Recipe extends UnlockableContent{
|
||||
public static Array<Recipe> getByCategory(Category category){
|
||||
returnArray.clear();
|
||||
for(Recipe recipe : content.recipes()){
|
||||
if(recipe.category == category && recipe.visibility.shown() && (recipe.mode == state.mode || recipe.mode == null)){
|
||||
if(recipe.category == category && recipe.visibility.shown()){
|
||||
returnArray.add(recipe);
|
||||
}
|
||||
}
|
||||
@ -75,11 +70,6 @@ public class Recipe extends UnlockableContent{
|
||||
return this;
|
||||
}
|
||||
|
||||
public Recipe setMode(GameMode mode){
|
||||
this.mode = mode;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Recipe setHidden(boolean hidden){
|
||||
this.hidden = hidden;
|
||||
return this;
|
||||
@ -153,7 +143,13 @@ public class Recipe extends UnlockableContent{
|
||||
public enum RecipeVisibility{
|
||||
mobileOnly(true, false),
|
||||
desktopOnly(false, true),
|
||||
all(true, true);
|
||||
all(true, true),
|
||||
sandboxOnly(true, true){
|
||||
@Override
|
||||
public boolean usable(){
|
||||
return state.rules.infiniteResources;
|
||||
}
|
||||
};
|
||||
|
||||
public final boolean mobile, desktop;
|
||||
|
||||
@ -162,8 +158,12 @@ public class Recipe extends UnlockableContent{
|
||||
this.desktop = desktop;
|
||||
}
|
||||
|
||||
public boolean usable(){
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean shown(){
|
||||
return (Vars.mobile && mobile) || (!Vars.mobile && desktop);
|
||||
return usable() && ((Vars.mobile && mobile) || (!Vars.mobile && desktop));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,13 +12,14 @@ import io.anuke.arc.scene.ui.layout.Table;
|
||||
import io.anuke.arc.util.Align;
|
||||
import io.anuke.arc.util.Scaling;
|
||||
import io.anuke.mindustry.game.Difficulty;
|
||||
import io.anuke.mindustry.game.GameMode;
|
||||
import io.anuke.mindustry.game.RulePreset;
|
||||
import io.anuke.mindustry.maps.Map;
|
||||
import io.anuke.mindustry.ui.BorderImage;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
public class CustomGameDialog extends FloatingDialog{
|
||||
Difficulty difficulty = Difficulty.normal;
|
||||
|
||||
public CustomGameDialog(){
|
||||
super("$customgame");
|
||||
@ -46,11 +47,11 @@ public class CustomGameDialog extends FloatingDialog{
|
||||
Table modes = new Table();
|
||||
modes.marginBottom(5);
|
||||
|
||||
for(GameMode mode : GameMode.values()){
|
||||
if(mode.hidden) continue;
|
||||
for(RulePreset mode : RulePreset.values()){
|
||||
|
||||
modes.addButton("$mode." + mode.name() + ".name", "toggle", () -> state.mode = mode)
|
||||
.update(b -> b.setChecked(state.mode == mode)).group(group).size(140f, 54f);
|
||||
//todo fix presets
|
||||
modes.addButton(mode.toString(), "toggle", () -> state.rules = mode.get())/*
|
||||
.update(b -> b.setChecked(state.rules == mode))*/.group(group).size(140f, 54f);
|
||||
if(i++ % 2 == 1) modes.row();
|
||||
}
|
||||
selmode.add(modes);
|
||||
@ -66,20 +67,21 @@ public class CustomGameDialog extends FloatingDialog{
|
||||
Table sdif = new Table();
|
||||
|
||||
sdif.add("$setting.difficulty.name").padRight(15f);
|
||||
|
||||
sdif.defaults().height(s + 4);
|
||||
sdif.addImageButton("icon-arrow-left", 10 * 3, () -> {
|
||||
state.difficulty = (ds[Mathf.mod(state.difficulty.ordinal() - 1, ds.length)]);
|
||||
difficulty = (ds[Mathf.mod(difficulty.ordinal() - 1, ds.length)]);
|
||||
state.wavetime = difficulty.waveTime;
|
||||
}).width(s);
|
||||
|
||||
sdif.addButton("", () -> {})
|
||||
.update(t -> {
|
||||
t.setText(state.difficulty.toString());
|
||||
t.setText(difficulty.toString());
|
||||
t.touchable(Touchable.disabled);
|
||||
}).width(180f);
|
||||
|
||||
sdif.addImageButton("icon-arrow-right", 10 * 3, () -> {
|
||||
state.difficulty = (ds[Mathf.mod(state.difficulty.ordinal() + 1, ds.length)]);
|
||||
difficulty = (ds[Mathf.mod(difficulty.ordinal() + 1, ds.length)]);
|
||||
state.wavetime = difficulty.waveTime;
|
||||
}).width(s);
|
||||
|
||||
cont.add(sdif);
|
||||
@ -141,8 +143,7 @@ public class CustomGameDialog extends FloatingDialog{
|
||||
ScrollPane pane = new ScrollPane(table);
|
||||
pane.setFadeScrollBars(false);
|
||||
table.row();
|
||||
for(GameMode mode : GameMode.values()){
|
||||
if(mode.hidden) continue;
|
||||
for(RulePreset mode : RulePreset.values()){
|
||||
table.labelWrap("[accent]" + mode.toString() + ":[] [lightgray]" + mode.description()).width(400f);
|
||||
table.row();
|
||||
}
|
||||
|
@ -112,9 +112,7 @@ public class LoadDialog extends FloatingDialog{
|
||||
|
||||
button.defaults().padBottom(3);
|
||||
button.row();
|
||||
button.add(Core.bundle.format("save.map", color + (slot.getMap() == null ? "Unknown" : slot.getMap().meta.name())));
|
||||
button.row();
|
||||
button.add(Core.bundle.get("level.mode") + " " + color + slot.getMode());
|
||||
button.add(Core.bundle.format("save.map", color + (slot.getMap() == null ? Core.bundle.get("unknown") : slot.getMap().meta.name())));
|
||||
button.row();
|
||||
button.add(Core.bundle.format("save.wave", color + slot.getWave()));
|
||||
button.row();
|
||||
|
@ -26,7 +26,7 @@ public class RestartDialog extends FloatingDialog{
|
||||
|
||||
buttons.margin(10);
|
||||
|
||||
if(state.mode.isPvp){
|
||||
if(state.rules.pvp){
|
||||
cont.add(Core.bundle.format("gameover.pvp",winner.localized())).pad(6);
|
||||
buttons.addButton("$menu", () -> {
|
||||
hide();
|
||||
|
@ -369,18 +369,18 @@ public class HudFragment extends Fragment{
|
||||
table.touchable(Touchable.enabled);
|
||||
|
||||
table.labelWrap(() ->
|
||||
(state.enemies() > 0 && state.mode.disableWaveTimer ?
|
||||
(state.enemies() > 0 && !state.rules.waveTimer ?
|
||||
wavef.get(state.wave) + "\n" + (state.enemies() == 1 ?
|
||||
enemyf.get(state.enemies()) :
|
||||
enemiesf.get(state.enemies())) :
|
||||
wavef.get(state.wave) + "\n" +
|
||||
(!state.mode.disableWaveTimer ?
|
||||
(state.rules.waveTimer ?
|
||||
Core.bundle.format("wave.waiting", (int)(state.wavetime/60)) :
|
||||
Core.bundle.get("waiting")))
|
||||
).growX().pad(8f);
|
||||
|
||||
table.setDisabled(true);
|
||||
table.visible(() -> !(state.mode.disableWaves || !state.mode.showMission));
|
||||
table.visible(() -> state.rules.waves);
|
||||
}
|
||||
|
||||
private void addPlayButton(Table table){
|
||||
@ -391,11 +391,11 @@ public class HudFragment extends Fragment{
|
||||
state.wavetime = 0f;
|
||||
}
|
||||
}).growY().fillX().right().width(40f).update(l -> {
|
||||
boolean vis = state.mode.disableWaveTimer && ((Net.server() || players[0].isAdmin) || !Net.active());
|
||||
boolean vis = !state.rules.waveTimer && ((Net.server() || players[0].isAdmin) || !Net.active());
|
||||
boolean paused = state.is(State.paused) || !vis;
|
||||
|
||||
l.getStyle().imageUp = Core.scene.skin.getDrawable(vis ? "icon-play" : "clear");
|
||||
l.touchable(!paused ? Touchable.enabled : Touchable.disabled);
|
||||
}).visible(() -> state.mode.disableWaveTimer && ((Net.server() || players[0].isAdmin) || !Net.active()) && unitGroups[Team.red.ordinal()].size() == 0);
|
||||
}).visible(() -> !state.rules.waveTimer && ((Net.server() || players[0].isAdmin) || !Net.active()) && unitGroups[Team.red.ordinal()].size() == 0);
|
||||
}
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ public class PlacementFragment extends Fragment{
|
||||
button.update(() -> { //color unplacable things gray
|
||||
boolean ulock = data.isUnlocked(recipe);
|
||||
TileEntity core = players[0].getClosestCore();
|
||||
Color color = core != null && (core.items.has(recipe.requirements) || state.mode.infiniteResources) ? Color.WHITE : ulock ? Color.GRAY : Color.WHITE;
|
||||
Color color = core != null && (core.items.has(recipe.requirements) || state.rules.infiniteResources) ? Color.WHITE : ulock ? Color.GRAY : Color.WHITE;
|
||||
button.forEach(elem -> elem.setColor(color));
|
||||
button.setChecked(input.recipe == recipe);
|
||||
|
||||
@ -196,7 +196,7 @@ public class PlacementFragment extends Fragment{
|
||||
line.add(stack.item.localizedName()).color(Color.LIGHT_GRAY).padLeft(2).left();
|
||||
line.labelWrap(() -> {
|
||||
TileEntity core = players[0].getClosestCore();
|
||||
if(core == null || state.mode.infiniteResources) return "*/*";
|
||||
if(core == null || state.rules.infiniteResources) return "*/*";
|
||||
|
||||
int amount = core.items.get(stack.item);
|
||||
String color = (amount < stack.amount / 2f ? "[red]" : amount < stack.amount ? "[accent]" : "[white]");
|
||||
|
@ -1,13 +1,6 @@
|
||||
package io.anuke.mindustry.ui.fragments;
|
||||
|
||||
import io.anuke.arc.Core;
|
||||
import io.anuke.arc.util.Interval;
|
||||
import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.gen.Call;
|
||||
import io.anuke.mindustry.graphics.Palette;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
import io.anuke.mindustry.net.NetConnection;
|
||||
import io.anuke.mindustry.net.Packets.AdminAction;
|
||||
import io.anuke.arc.graphics.g2d.Draw;
|
||||
import io.anuke.arc.graphics.g2d.Lines;
|
||||
import io.anuke.arc.scene.Group;
|
||||
@ -15,7 +8,13 @@ import io.anuke.arc.scene.event.Touchable;
|
||||
import io.anuke.arc.scene.ui.Image;
|
||||
import io.anuke.arc.scene.ui.layout.Table;
|
||||
import io.anuke.arc.scene.ui.layout.Unit;
|
||||
import io.anuke.arc.util.Timer;
|
||||
import io.anuke.arc.util.Interval;
|
||||
import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.gen.Call;
|
||||
import io.anuke.mindustry.graphics.Palette;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
import io.anuke.mindustry.net.NetConnection;
|
||||
import io.anuke.mindustry.net.Packets.AdminAction;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
@ -137,7 +136,7 @@ public class PlayerListFragment extends Fragment{
|
||||
|
||||
content.add(button).padBottom(-6).width(350f).maxHeight(h + 14);
|
||||
content.row();
|
||||
content.addImage("blank").height(3f).color(state.mode.isPvp ? player.getTeam().color : Palette.accent).growX();
|
||||
content.addImage("blank").height(3f).color(state.rules.pvp ? player.getTeam().color : Palette.accent).growX();
|
||||
content.row();
|
||||
});
|
||||
|
||||
|
@ -109,7 +109,7 @@ public class Build{
|
||||
public static boolean validPlace(Team team, int x, int y, Block type, int rotation){
|
||||
Recipe recipe = Recipe.getByResult(type);
|
||||
|
||||
if(recipe == null || (recipe.mode != null && recipe.mode != state.mode)){
|
||||
if(recipe == null || (!recipe.visibility.usable())){
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -121,7 +121,7 @@ public class Build{
|
||||
//check for enemy cores
|
||||
for(Team enemy : state.teams.enemiesOf(team)){
|
||||
for(Tile core : state.teams.get(enemy).cores){
|
||||
if(Mathf.dst(x*tilesize + type.offset(), y*tilesize + type.offset(), core.drawx(), core.drawy()) < state.mode.enemyCoreBuildRadius + type.size*tilesize/2f){
|
||||
if(Mathf.dst(x*tilesize + type.offset(), y*tilesize + type.offset(), core.drawx(), core.drawy()) < state.rules.enemyCoreBuildRadius + type.size*tilesize/2f){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -205,7 +205,7 @@ public class Tile implements Position, TargetTrait{
|
||||
}
|
||||
|
||||
public boolean isEnemyCheat(){
|
||||
return getTeam() == waveTeam && !state.mode.isPvp;
|
||||
return getTeam() == waveTeam && !state.rules.pvp;
|
||||
}
|
||||
|
||||
public boolean isLinked(){
|
||||
|
@ -195,7 +195,7 @@ public class BuildBlock extends Block{
|
||||
builderID = builder.getID();
|
||||
}
|
||||
|
||||
if(progress >= 1f || state.mode.infiniteResources){
|
||||
if(progress >= 1f || state.rules.infiniteResources){
|
||||
Call.onConstructFinish(tile, recipe.result, builderID, tile.getRotation(), builder.getTeam());
|
||||
}
|
||||
}
|
||||
@ -226,7 +226,7 @@ public class BuildBlock extends Block{
|
||||
|
||||
progress = Mathf.clamp(progress - amount);
|
||||
|
||||
if(progress <= 0 || state.mode.infiniteResources){
|
||||
if(progress <= 0 || state.rules.infiniteResources){
|
||||
Call.onDeconstructFinish(tile, this.recipe == null ? previous : this.recipe.result);
|
||||
}
|
||||
}
|
||||
|
@ -185,7 +185,7 @@ public class CoreBlock extends StorageBlock{
|
||||
}
|
||||
entity.heat = Mathf.lerpDelta(entity.heat, 1f, 0.1f);
|
||||
entity.time += entity.delta();
|
||||
entity.progress += 1f / state.mode.respawnTime * entity.delta();
|
||||
entity.progress += 1f / state.rules.respawnTime * entity.delta();
|
||||
|
||||
if(entity.progress >= 1f){
|
||||
Call.onUnitRespawn(tile, entity.currentUnit);
|
||||
|
@ -154,8 +154,8 @@ public class UnitFactory extends Block{
|
||||
entity.speedScl = Mathf.lerpDelta(entity.speedScl, 0f, 0.05f);
|
||||
}
|
||||
//check if grace period had passed
|
||||
}else if(entity.warmup > produceTime*gracePeriodMultiplier * Vars.state.difficulty.spawnerScaling){
|
||||
float speedMultiplier = Math.min(0.1f + (entity.warmup - produceTime * gracePeriodMultiplier * Vars.state.difficulty.spawnerScaling) / speedupTime, maxSpeedup);
|
||||
}else if(entity.warmup > produceTime*gracePeriodMultiplier){
|
||||
float speedMultiplier = Math.min(0.1f + (entity.warmup - produceTime * gracePeriodMultiplier) / speedupTime, maxSpeedup);
|
||||
//otherwise, it's an enemy, cheat by not requiring resources
|
||||
entity.buildTime += entity.delta() * speedMultiplier;
|
||||
entity.speedScl = Mathf.lerpDelta(entity.speedScl, 1f, 0.05f);
|
||||
|
@ -77,7 +77,6 @@ public class CrashHandler{
|
||||
ex(() -> value.addChild("build", new JsonValue(Version.build)));
|
||||
ex(() -> value.addChild("net", new JsonValue(fn)));
|
||||
ex(() -> value.addChild("server", new JsonValue(fs)));
|
||||
ex(() -> value.addChild("gamemode", new JsonValue(Vars.state.mode.name())));
|
||||
ex(() -> value.addChild("state", new JsonValue(Vars.state.getState().name())));
|
||||
ex(() -> value.addChild("os", new JsonValue(System.getProperty("os.name"))));
|
||||
ex(() -> value.addChild("trace", new JsonValue(parseException(e))));
|
||||
|
@ -11,7 +11,6 @@ import io.anuke.arc.util.Strings;
|
||||
import io.anuke.arc.util.serialization.Base64Coder;
|
||||
import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.core.Platform;
|
||||
import io.anuke.mindustry.game.GameMode;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
import io.anuke.mindustry.ui.dialogs.FileChooser;
|
||||
|
||||
@ -51,22 +50,18 @@ public class DesktopPlatform extends Platform{
|
||||
DiscordRichPresence presence = new DiscordRichPresence();
|
||||
|
||||
if(!state.is(State.menu)){
|
||||
presence.state = Strings.capitalize(state.mode.name());
|
||||
presence.state = state.rules.waves ? "Survival" : "Attack";
|
||||
if(world.getMap() == null){
|
||||
presence.details = "Unknown Map";
|
||||
}else if(state.mode.disableWaves){
|
||||
}else if(!state.rules.waves){
|
||||
presence.details = Strings.capitalize(world.getMap().name);
|
||||
}else{
|
||||
presence.details = Strings.capitalize(world.getMap().name) + " | Wave " + state.wave;
|
||||
presence.largeImageText = "Wave " + state.wave;
|
||||
}
|
||||
|
||||
if(state.mode != GameMode.attack){
|
||||
presence.state = Strings.capitalize(state.mode.name());
|
||||
}else{
|
||||
presence.state = unitGroups[players[0].getTeam().ordinal()].size() == 1 ? "1 Unit Active" :
|
||||
(unitGroups[players[0].getTeam().ordinal()].size() + " Units Active");
|
||||
}
|
||||
presence.state = unitGroups[players[0].getTeam().ordinal()].size() == 1 ? "1 Unit Active" :
|
||||
(unitGroups[players[0].getTeam().ordinal()].size() + " Units Active");
|
||||
|
||||
if(Net.active()){
|
||||
presence.partyMax = 16;
|
||||
|
@ -48,9 +48,7 @@ public class CrashHandler{
|
||||
ex(() -> value.addChild("versionNumber", new JsonValue(Version.number)));
|
||||
ex(() -> value.addChild("versionModifier", new JsonValue(Version.modifier)));
|
||||
ex(() -> value.addChild("build", new JsonValue(Version.build)));
|
||||
ex(() -> value.addChild("mode", new JsonValue(Vars.state.mode.name())));
|
||||
ex(() -> value.addChild("state", new JsonValue(Vars.state.getState().name())));
|
||||
ex(() -> value.addChild("difficulty", new JsonValue(Vars.state.difficulty.name())));
|
||||
ex(() -> value.addChild("players", new JsonValue(Vars.playerGroup.size())));
|
||||
ex(() -> value.addChild("os", new JsonValue(System.getProperty("os.name"))));
|
||||
ex(() -> value.addChild("trace", new JsonValue(parseException(e))));
|
||||
|
@ -16,8 +16,6 @@ import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.entities.Player;
|
||||
import io.anuke.mindustry.game.Difficulty;
|
||||
import io.anuke.mindustry.game.EventType.GameOverEvent;
|
||||
import io.anuke.mindustry.game.EventType.SectorCompleteEvent;
|
||||
import io.anuke.mindustry.game.GameMode;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.game.Version;
|
||||
import io.anuke.mindustry.gen.Call;
|
||||
@ -139,7 +137,7 @@ public class ServerControl implements ApplicationListener{
|
||||
while(map == previous) map = maps.random();
|
||||
}
|
||||
|
||||
Call.onInfoMessage((state.mode.isPvp
|
||||
Call.onInfoMessage((state.rules.pvp
|
||||
? "[YELLOW]The " + event.winner.name() + " team is victorious![]" : "[SCARLET]Game over![]")
|
||||
+ "\nNext selected map:[accent] "+map.name+"[]"
|
||||
+ (map.meta.author() != null ? " by[accent] " + map.meta.author() + "[]" : "") + "."+
|
||||
@ -188,7 +186,7 @@ public class ServerControl implements ApplicationListener{
|
||||
info("Stopped server.");
|
||||
});
|
||||
|
||||
handler.register("host", "[mapname] [mode]", "Open the server with a specific map.", arg -> {
|
||||
handler.register("host", "[mapname]", "Open the server with a specific map.", arg -> {
|
||||
if(state.is(State.playing)){
|
||||
err("Already hosting. Type 'stop' to stop hosting first.");
|
||||
return;
|
||||
@ -212,18 +210,7 @@ public class ServerControl implements ApplicationListener{
|
||||
|
||||
|
||||
info("Loading map...");
|
||||
|
||||
if(arg.length > 1){
|
||||
GameMode mode;
|
||||
try{
|
||||
mode = GameMode.valueOf(arg[1]);
|
||||
}catch(IllegalArgumentException e){
|
||||
err("No gamemode '{0}' found.", arg[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
state.mode = mode;
|
||||
}
|
||||
err("TODO select gamemode");
|
||||
|
||||
logic.reset();
|
||||
world.loadMap(result);
|
||||
@ -231,7 +218,7 @@ public class ServerControl implements ApplicationListener{
|
||||
|
||||
}else{
|
||||
//TODO
|
||||
info("TODO play generated map");
|
||||
err("TODO play generated map");
|
||||
}
|
||||
|
||||
info("Map loaded.");
|
||||
@ -266,9 +253,9 @@ public class ServerControl implements ApplicationListener{
|
||||
info("Status: &rserver closed");
|
||||
}else{
|
||||
info("Status:");
|
||||
info(" &lyPlaying on map &fi{0}&fb &lb/&ly Wave {1} &lb/&ly {2} &lb/&ly {3}", Strings.capitalize(world.getMap().name), state.wave, Strings.capitalize(state.difficulty.name()), Strings.capitalize(state.mode.name()));
|
||||
info(" &lyPlaying on map &fi{0}&fb &lb/&ly Wave {1} &lb/&ly {2} &lb/&ly {3}", Strings.capitalize(world.getMap().name), state.wave);
|
||||
|
||||
if(state.mode.disableWaveTimer){
|
||||
if(!state.rules.waves){
|
||||
info("&ly {0} enemies.", unitGroups[Team.red.ordinal()].size());
|
||||
}else{
|
||||
info("&ly {0} seconds until next wave.", (int) (state.wavetime / 60));
|
||||
@ -301,7 +288,7 @@ public class ServerControl implements ApplicationListener{
|
||||
|
||||
handler.register("difficulty", "<difficulty>", "Set game difficulty.", arg -> {
|
||||
try{
|
||||
state.difficulty = Difficulty.valueOf(arg[0]);
|
||||
state.rules.waveSpacing = Difficulty.valueOf(arg[0]).waveTime;
|
||||
info("Difficulty set to '{0}'.", arg[0]);
|
||||
}catch(IllegalArgumentException e){
|
||||
err("No difficulty with name '{0}' found.", arg[0]);
|
||||
|
@ -198,7 +198,7 @@ public class ApplicationTests{
|
||||
|
||||
@Test
|
||||
void inventoryDeposit(){
|
||||
depositTest(Blocks.smelter, Items.copper);
|
||||
depositTest(Blocks.surgeSmelter, Items.copper);
|
||||
depositTest(Blocks.vault, Items.copper);
|
||||
depositTest(Blocks.thoriumReactor, Items.thorium);
|
||||
}
|
||||
|