Merge branch 'master' of https://github.com/Anuken/Mindustry into tutorial

This commit is contained in:
Anuken
2019-08-08 11:26:29 -04:00
100 changed files with 1116 additions and 1013 deletions

View File

@@ -12,6 +12,7 @@ import io.anuke.mindustry.game.*;
import io.anuke.mindustry.game.Teams.*;
import io.anuke.mindustry.type.*;
import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.blocks.*;
import io.anuke.mindustry.world.meta.*;
import static io.anuke.mindustry.Vars.*;
@@ -118,7 +119,7 @@ public class BlockIndexer{
ObjectSet<Tile> set = damagedTiles[team.ordinal()];
for(Tile tile : set){
if(tile.entity == null || tile.entity.getTeam() != team || !tile.entity.damaged()){
if((tile.entity == null || tile.entity.getTeam() != team || !tile.entity.damaged()) && !(tile.block() instanceof BuildBlock)){
returnArray.add(tile);
}
}

View File

@@ -1613,13 +1613,13 @@ public class Blocks implements ContentList{
}};
spiritFactory = new UnitFactory("spirit-factory"){{
requirements(Category.units, ItemStack.with(Items.metaglass, 35, Items.lead, 55, Items.silicon, 45));
requirements(Category.units, ItemStack.with(Items.metaglass, 45, Items.lead, 55, Items.silicon, 45));
type = UnitTypes.spirit;
produceTime = 2850;
produceTime = 3500;
size = 2;
maxSpawn = 2;
consumes.power(0.80f);
consumes.items(new ItemStack(Items.silicon, 10), new ItemStack(Items.lead, 15));
consumes.items(new ItemStack(Items.silicon, 15), new ItemStack(Items.lead, 15));
}};
phantomFactory = new UnitFactory("phantom-factory"){{
@@ -1673,9 +1673,9 @@ public class Blocks implements ContentList{
type = UnitTypes.crawler;
produceTime = 250;
size = 2;
maxSpawn = 6;
maxSpawn = 8;
consumes.power(0.4f);
consumes.items(new ItemStack(Items.coal, 6));
consumes.items(new ItemStack(Items.coal, 5));
}};
titanFactory = new UnitFactory("titan-factory"){{
@@ -1699,7 +1699,8 @@ public class Blocks implements ContentList{
repairPoint = new RepairPoint("repair-point"){{
requirements(Category.units, ItemStack.with(Items.lead, 15, Items.copper, 15, Items.silicon, 15));
repairSpeed = 0.3f;
repairSpeed = 0.5f;
repairRadius = 65f;
powerUse = 1f;
}};

View File

@@ -1,19 +1,16 @@
package io.anuke.mindustry.content;
import io.anuke.arc.graphics.Color;
import io.anuke.arc.graphics.*;
import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.math.Mathf;
import io.anuke.arc.util.Time;
import io.anuke.arc.util.Tmp;
import io.anuke.mindustry.entities.Damage;
import io.anuke.mindustry.entities.Effects;
import io.anuke.arc.math.*;
import io.anuke.arc.util.*;
import io.anuke.mindustry.entities.*;
import io.anuke.mindustry.entities.bullet.*;
import io.anuke.mindustry.entities.effect.*;
import io.anuke.mindustry.entities.type.Unit;
import io.anuke.mindustry.game.ContentList;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.BuildBlock;
import io.anuke.mindustry.game.*;
import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.blocks.*;
import static io.anuke.mindustry.Vars.world;
@@ -43,7 +40,7 @@ public class Bullets implements ContentList{
fireball, basicFlame, pyraFlame, driverBolt, healBullet, frag, eruptorShot,
//bombs
bombExplosive, bombIncendiary, bombOil, explode;
bombExplosive, bombIncendiary, bombOil;
@Override
public void load(){
@@ -470,6 +467,11 @@ public class Bullets implements ContentList{
status = StatusEffects.burning;
}
@Override
public float range(){
return 50f;
}
@Override
public void draw(Bullet b){
}
@@ -698,23 +700,5 @@ public class Bullets implements ContentList{
}
}
};
explode = new BombBulletType(2f, 3f, "clear"){
{
hitEffect = Fx.pulverize;
lifetime = 30f;
speed = 1f;
splashDamageRadius = 50f;
splashDamage = 28f;
}
@Override
public void init(Bullet b){
if(b.getOwner() instanceof Unit){
((Unit)b.getOwner()).kill();
}
b.time(b.lifetime());
}
};
}
}

View File

@@ -160,14 +160,14 @@ public class Fx implements ContentList{
healWave = new Effect(22, e -> {
Draw.color(Pal.heal);
Lines.stroke(e.fout() * 2f);
Lines.poly(e.x, e.y, 30, 4f + e.finpow() * 60f);
Lines.circle(e.x, e.y, 4f + e.finpow() * 60f);
Draw.color();
});
heal = new Effect(11, e -> {
Draw.color(Pal.heal);
Lines.stroke(e.fout() * 2f);
Lines.poly(e.x, e.y, 24, 2f + e.finpow() * 7f);
Lines.circle(e.x, e.y, 2f + e.finpow() * 7f);
Draw.color();
});
@@ -568,21 +568,21 @@ public class Fx implements ContentList{
nuclearShockwave = new Effect(10f, 200f, e -> {
Draw.color(Color.WHITE, Color.LIGHT_GRAY, e.fin());
Lines.stroke(e.fout() * 3f + 0.2f);
Lines.poly(e.x, e.y, 40, e.fin() * 140f);
Lines.circle(e.x, e.y, e.fin() * 140f);
Draw.reset();
});
impactShockwave = new Effect(13f, 300f, e -> {
Draw.color(Pal.lighterOrange, Color.LIGHT_GRAY, e.fin());
Lines.stroke(e.fout() * 4f + 0.2f);
Lines.poly(e.x, e.y, 60, e.fin() * 200f);
Lines.circle(e.x, e.y, e.fin() * 200f);
Draw.reset();
});
spawnShockwave = new Effect(20f, 400f, e -> {
Draw.color(Color.WHITE, Color.LIGHT_GRAY, e.fin());
Lines.stroke(e.fout() * 3f + 0.5f);
Lines.poly(e.x, e.y, 40, e.fin() * (e.rotation + 50f));
Lines.circle(e.x, e.y, e.fin() * (e.rotation + 50f));
Draw.reset();
});
@@ -614,7 +614,7 @@ public class Fx implements ContentList{
e.scaled(5 + intensity * 2, i -> {
Lines.stroke(3.1f * i.fout());
Lines.poly(e.x, e.y, (int)(20 * intensity), (3f + i.fin() * 14f) * intensity);
Lines.circle(e.x, e.y, (3f + i.fin() * 14f) * intensity);
});
Draw.color(Color.GRAY);
@@ -1157,21 +1157,21 @@ public class Fx implements ContentList{
launch = new Effect(28, e -> {
Draw.color(Pal.command);
Lines.stroke(e.fout() * 2f);
Lines.poly(e.x, e.y, 40, 4f + e.finpow() * 120f);
Lines.circle(e.x, e.y, 4f + e.finpow() * 120f);
Draw.color();
});
healWaveMend = new Effect(40, e -> {
Draw.color(e.color);
Lines.stroke(e.fout() * 2f);
Lines.poly(e.x, e.y, 30, e.finpow() * e.rotation);
Lines.circle(e.x, e.y, e.finpow() * e.rotation);
Draw.color();
});
overdriveWave = new Effect(50, e -> {
Draw.color(e.color);
Lines.stroke(e.fout() * 1f);
Lines.poly(e.x, e.y, 30, e.finpow() * e.rotation);
Lines.circle(e.x, e.y, e.finpow() * e.rotation);
Draw.color();
});

View File

@@ -1,10 +1,11 @@
package io.anuke.mindustry.content;
import io.anuke.arc.collection.ObjectSet;
import io.anuke.arc.collection.*;
import io.anuke.mindustry.entities.bullet.*;
import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.entities.type.base.*;
import io.anuke.mindustry.game.ContentList;
import io.anuke.mindustry.type.UnitType;
import io.anuke.mindustry.type.Weapon;
import io.anuke.mindustry.game.*;
import io.anuke.mindustry.type.*;
public class UnitTypes implements ContentList{
public static UnitType
@@ -90,31 +91,49 @@ public class UnitTypes implements ContentList{
}};
crawler = new UnitType("crawler", Crawler.class, Crawler::new){{
maxVelocity = 1.25f;
speed = 0.28f;
maxVelocity = 1.27f;
speed = 0.285f;
drag = 0.4f;
hitsize = 8f;
mass = 1.75f;
health = 100;
health = 120;
weapon = new Weapon("bomber"){{
reload = 12f;
ejectEffect = Fx.none;
bullet = Bullets.explode;
bullet = new BombBulletType(2f, 3f, "clear"){
{
hitEffect = Fx.pulverize;
lifetime = 30f;
speed = 1.1f;
splashDamageRadius = 55f;
splashDamage = 30f;
}
@Override
public void init(Bullet b){
if(b.getOwner() instanceof Unit){
((Unit)b.getOwner()).kill();
}
b.time(b.lifetime());
}
};
}};
}};
titan = new UnitType("titan", Titan.class, Titan::new){{
maxVelocity = 0.8f;
speed = 0.18f;
speed = 0.22f;
drag = 0.4f;
mass = 3.5f;
hitsize = 9f;
range = 10f;
rotatespeed = 0.1f;
health = 440;
health = 460;
immunities.add(StatusEffects.burning);
weapon = new Weapon("flamethrower"){{
length = 1f;
reload = 14f;
range = 30f;
roundrobin = true;
recoil = 1f;
ejectEffect = Fx.none;

View File

@@ -78,14 +78,13 @@ public class Zones implements ContentList{
}};
saltFlats = new Zone("saltFlats", new MapGenerator("saltFlats")){{
startingItems = ItemStack.list(Items.copper, 200, Items.silicon, 100, Items.lead, 200);
alwaysUnlocked = true;
conditionWave = 5;
launchPeriod = 5;
startingItems = ItemStack.list(Items.copper, 200, Items.silicon, 200, Items.lead, 200);
loadout = Loadouts.basicFoundation;
conditionWave = 10;
launchPeriod = 5;
zoneRequirements = ZoneRequirement.with(desertWastes, 60);
blockRequirements = new Block[]{Blocks.daggerFactory, Blocks.draugFactory};
resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.sand};
blockRequirements = new Block[]{Blocks.daggerFactory, Blocks.draugFactory, Blocks.door, Blocks.waterExtractor};
resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.sand, Items.titanium};
}};
frozenForest = new Zone("frozenForest", new MapGenerator("frozenForest", 1)
@@ -114,7 +113,7 @@ public class Zones implements ContentList{
conditionWave = 20;
launchPeriod = 20;
zoneRequirements = ZoneRequirement.with(desertWastes, 20, craters, 15);
blockRequirements = new Block[]{Blocks.graphitePress, Blocks.combustionGenerator, Blocks.kiln};
blockRequirements = new Block[]{Blocks.graphitePress, Blocks.combustionGenerator, Blocks.kiln, Blocks.mechanicalPump};
resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.sand};
}};
@@ -125,14 +124,14 @@ public class Zones implements ContentList{
conditionWave = 10;
launchPeriod = 10;
zoneRequirements = ZoneRequirement.with(frozenForest, 15);
blockRequirements = new Block[]{Blocks.pneumaticDrill};
blockRequirements = new Block[]{Blocks.pneumaticDrill, Blocks.powerNode, Blocks.turbineGenerator};
resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.titanium, Items.sand};
}};
fungalPass = new Zone("fungalPass", new MapGenerator("fungalPass")){{
startingItems = ItemStack.list(Items.copper, 250, Items.lead, 250, Items.metaglass, 100, Items.graphite, 100);
zoneRequirements = ZoneRequirement.with(stainedMountains, 15);
blockRequirements = new Block[]{Blocks.daggerFactory, Blocks.crawlerFactory, Blocks.door};
blockRequirements = new Block[]{Blocks.daggerFactory, Blocks.crawlerFactory, Blocks.door, Blocks.siliconSmelter};
resources = new Item[]{Items.copper, Items.lead, Items.coal, Items.titanium, Items.sand};
}};
@@ -153,7 +152,7 @@ public class Zones implements ContentList{
conditionWave = 15;
launchPeriod = 10;
zoneRequirements = ZoneRequirement.with(ruinousShores, 20);
blockRequirements = new Block[]{Blocks.coalCentrifuge};
blockRequirements = new Block[]{Blocks.coalCentrifuge, Blocks.conduit, Blocks.wave};
resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.titanium, Items.sand};
}};
@@ -164,7 +163,7 @@ public class Zones implements ContentList{
conditionWave = 3;
launchPeriod = 2;
zoneRequirements = ZoneRequirement.with(tarFields, 20);
blockRequirements = new Block[]{Blocks.thermalGenerator};
blockRequirements = new Block[]{Blocks.thermalGenerator, Blocks.thoriumReactor};
resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.titanium, Items.sand, Items.thorium};
}};

View File

@@ -5,7 +5,7 @@ import io.anuke.arc.graphics.*;
import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.input.*;
import io.anuke.arc.scene.ui.*;
import io.anuke.arc.scene.ui.layout.Unit;
import io.anuke.arc.scene.ui.layout.UnitScl;
import io.anuke.arc.util.*;
import io.anuke.mindustry.content.*;
import io.anuke.mindustry.core.GameState.*;
@@ -48,7 +48,7 @@ public class Control implements ApplicationListener{
tutorial = new Tutorial();
music = new MusicControl();
Unit.dp.product = settings.getInt("uiscale", 100) / 100f;
UnitScl.dp.setProduct(settings.getInt("uiscale", 100) / 100f);
Core.input.setCatch(KeyCode.BACK, true);
@@ -211,6 +211,7 @@ public class Control implements ApplicationListener{
public void playZone(Zone zone){
ui.loadAnd(() -> {
logic.reset();
Net.reset();
world.loadGenerator(zone.generator);
zone.rules.accept(state.rules);
state.rules.zone = zone;
@@ -308,7 +309,7 @@ public class Control implements ApplicationListener{
if(state.is(State.menu)){
if(ui.deploy.isShown()){
music.silence(); //TODO deploy music
music.play(Musics.launch);
}else if(ui.editor.isShown()){
music.play(Musics.editor);
}else{

View File

@@ -45,6 +45,8 @@ public class NetClient implements ApplicationListener{
private boolean connecting = false;
/** If true, no message will be shown on disconnect. */
private boolean quiet = false;
/** Whether to supress disconnect events completely.*/
private boolean quietReset = false;
/** Counter for data timeout. */
private float timeoutTime = 0f;
/** Last sent client snapshot ID. */
@@ -94,8 +96,10 @@ public class NetClient implements ApplicationListener{
});
Net.handleClient(Disconnect.class, packet -> {
state.set(State.menu);
if(quietReset) return;
connecting = false;
state.set(State.menu);
logic.reset();
Platform.instance.updateRPC();
@@ -325,11 +329,11 @@ public class NetClient implements ApplicationListener{
private void finishConnecting(){
state.set(State.playing);
connecting = false;
ui.loadfrag.hide();
ui.join.hide();
Net.setClientLoaded(true);
Core.app.post(Call::connectConfirm);
Time.runTask(40f, Platform.instance::updateRPC);
Core.app.post(() -> ui.loadfrag.hide());
}
private void reset(){
@@ -337,6 +341,7 @@ public class NetClient implements ApplicationListener{
removed.clear();
timeoutTime = 0f;
connecting = true;
quietReset = false;
quiet = false;
lastSent = 0;
@@ -348,11 +353,18 @@ public class NetClient implements ApplicationListener{
connecting = true;
}
/** Disconnects, resetting state to the menu. */
public void disconnectQuietly(){
quiet = true;
Net.disconnect();
}
/** Disconnects, causing no further changes or reset.*/
public void disconnectNoReset(){
quiet = quietReset = true;
Net.disconnect();
}
/** When set, any disconnects will be ignored and no dialogs will be shown. */
public void setQuiet(){
quiet = true;

View File

@@ -10,6 +10,7 @@ import io.anuke.arc.graphics.glutils.FrameBuffer;
import io.anuke.arc.math.Mathf;
import io.anuke.arc.math.geom.Rectangle;
import io.anuke.arc.math.geom.Vector2;
import io.anuke.arc.scene.ui.layout.*;
import io.anuke.arc.util.*;
import io.anuke.arc.util.pooling.Pools;
import io.anuke.mindustry.content.Fx;
@@ -37,7 +38,7 @@ public class Renderer implements ApplicationListener{
public FrameBuffer shieldBuffer = new FrameBuffer(2, 2);
private Bloom bloom;
private Color clearColor;
private float targetscale = io.anuke.arc.scene.ui.layout.Unit.dp.scl(4);
private float targetscale = UnitScl.dp.scl(4);
private float camerascale = targetscale;
private Rectangle rect = new Rectangle(), rect2 = new Rectangle();
private float shakeIntensity, shaketime;
@@ -47,7 +48,6 @@ public class Renderer implements ApplicationListener{
if(settings.getBool("bloom")){
setupBloom();
}
Lines.setCircleVertices(20);
Shaders.init();
Effects.setScreenShakeProvider((intensity, duration) -> {
@@ -357,7 +357,7 @@ public class Renderer implements ApplicationListener{
}
public void clampScale(){
float s = io.anuke.arc.scene.ui.layout.Unit.dp.scl(1f);
float s = UnitScl.dp.scl(1f);
targetscale = Mathf.clamp(targetscale, s * 1.5f, Math.round(s * 6));
}

View File

@@ -31,9 +31,6 @@ import static io.anuke.arc.scene.actions.Actions.*;
import static io.anuke.mindustry.Vars.*;
public class UI implements ApplicationListener{
private static final int cursorScaling = 1, outlineThickness = 3;
private static final Color outlineColor = Color.valueOf("444444");
private FreeTypeFontGenerator generator;
public MenuFragment menufrag;
@@ -99,9 +96,9 @@ public class UI implements ApplicationListener{
/** Called from a static context to make the cursor appear immediately upon startup.*/
public static void loadSystemCursors(){
SystemCursor.arrow.set(Core.graphics.newCursor("cursor", cursorScaling, outlineColor, outlineThickness));
SystemCursor.hand.set(Core.graphics.newCursor("hand", cursorScaling, outlineColor, outlineThickness));
SystemCursor.ibeam.set(Core.graphics.newCursor("ibeam", cursorScaling, outlineColor, outlineThickness));
SystemCursor.arrow.set(Core.graphics.newCursor("cursor"));
SystemCursor.hand.set(Core.graphics.newCursor("hand"));
SystemCursor.ibeam.set(Core.graphics.newCursor("ibeam"));
Core.graphics.restoreCursor();
}
@@ -126,15 +123,15 @@ public class UI implements ApplicationListener{
}
void loadExtraCursors(){
drillCursor = Core.graphics.newCursor("drill", cursorScaling, outlineColor, outlineThickness);
unloadCursor = Core.graphics.newCursor("unload", cursorScaling, outlineColor, outlineThickness);
drillCursor = Core.graphics.newCursor("drill");
unloadCursor = Core.graphics.newCursor("unload");
}
void generateFonts(Skin skin){
generator = new FreeTypeFontGenerator(Core.files.internal("fonts/font.ttf"));
FreeTypeFontParameter param = new FreeTypeFontParameter(){{
size = (int)(9 * 2 * Math.max(Unit.dp.scl(1f), 0.5f));
size = (int)(UnitScl.dp.scl(18f));
shadowColor = Color.DARK_GRAY;
shadowOffsetY = 2;
incremental = true;
@@ -143,7 +140,7 @@ public class UI implements ApplicationListener{
FreeTypeFontParameter outlined = new FreeTypeFontParameter(){{
size = param.size;
borderColor = Color.DARK_GRAY;
borderWidth = 2f;
borderWidth = UnitScl.dp.scl(2f);
spaceX -= borderWidth;
incremental = true;
}};

View File

@@ -1,40 +1,34 @@
package io.anuke.mindustry.editor;
import io.anuke.arc.Core;
import io.anuke.arc.collection.Array;
import io.anuke.arc.collection.StringMap;
import io.anuke.arc.files.FileHandle;
import io.anuke.arc.function.Consumer;
import io.anuke.arc.graphics.Color;
import io.anuke.arc.graphics.Pixmap;
import io.anuke.arc.graphics.g2d.TextureRegion;
import io.anuke.arc.input.KeyCode;
import io.anuke.arc.math.Mathf;
import io.anuke.arc.math.geom.Vector2;
import io.anuke.arc.scene.actions.Actions;
import io.anuke.arc.scene.event.Touchable;
import io.anuke.arc.scene.style.TextureRegionDrawable;
import io.anuke.arc.*;
import io.anuke.arc.collection.*;
import io.anuke.arc.files.*;
import io.anuke.arc.function.*;
import io.anuke.arc.graphics.*;
import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.input.*;
import io.anuke.arc.math.*;
import io.anuke.arc.math.geom.*;
import io.anuke.arc.scene.actions.*;
import io.anuke.arc.scene.event.*;
import io.anuke.arc.scene.style.*;
import io.anuke.arc.scene.ui.*;
import io.anuke.arc.scene.ui.TextButton.TextButtonStyle;
import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.arc.scene.ui.layout.Unit;
import io.anuke.arc.scene.ui.TextButton.*;
import io.anuke.arc.scene.ui.layout.*;
import io.anuke.arc.util.*;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.*;
import io.anuke.mindustry.content.*;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.core.Platform;
import io.anuke.mindustry.core.GameState.*;
import io.anuke.mindustry.core.*;
import io.anuke.mindustry.game.*;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.io.JsonIO;
import io.anuke.mindustry.io.MapIO;
import io.anuke.mindustry.maps.Map;
import io.anuke.mindustry.ui.dialogs.FileChooser;
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Block.Icon;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.io.*;
import io.anuke.mindustry.maps.*;
import io.anuke.mindustry.ui.dialogs.*;
import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.Block.*;
import io.anuke.mindustry.world.blocks.*;
import io.anuke.mindustry.world.blocks.storage.CoreBlock;
import io.anuke.mindustry.world.blocks.storage.*;
import static io.anuke.mindustry.Vars.*;
@@ -378,10 +372,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
}
public void build(){
float amount = 10f, baseSize = 60f;
float size = mobile ? (int)(Math.min(Core.graphics.getHeight(), Core.graphics.getWidth()) / amount / Unit.dp.scl(1f)) :
Math.min(Core.graphics.getHeight() / amount, baseSize);
float size = 60f;
clearChildren();
table(cont -> {

View File

@@ -216,7 +216,7 @@ public class MapGenerateDialog extends FloatingDialog{
}
void rebuildFilters(){
int cols = Math.max((int)(Math.max(filterTable.getParent().getWidth(), Core.graphics.getWidth()/2f * 0.9f) / Unit.dp.scl(290f)), 1);
int cols = Math.max((int)(Math.max(filterTable.getParent().getWidth(), Core.graphics.getWidth()/2f * 0.9f) / UnitScl.dp.scl(290f)), 1);
filterTable.clearChildren();
filterTable.top().left();
int i = 0;

View File

@@ -11,7 +11,7 @@ import io.anuke.arc.math.geom.*;
import io.anuke.arc.scene.Element;
import io.anuke.arc.scene.event.*;
import io.anuke.arc.scene.ui.TextField;
import io.anuke.arc.scene.ui.layout.Unit;
import io.anuke.arc.scene.ui.layout.UnitScl;
import io.anuke.arc.util.*;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.input.Binding;
@@ -258,7 +258,7 @@ public class MapView extends Element implements GestureListener{
float scaling = zoom * Math.min(width, height) / editor.width();
Draw.color(Pal.accent);
Lines.stroke(Unit.dp.scl(2f));
Lines.stroke(UnitScl.dp.scl(2f));
if((!editor.drawBlock.isMultiblock() || tool == EditorTool.eraser) && tool != EditorTool.fill){
if(tool == EditorTool.line && drawing){
@@ -294,7 +294,7 @@ public class MapView extends Element implements GestureListener{
}
Draw.color(Pal.accent);
Lines.stroke(Unit.dp.scl(3f));
Lines.stroke(UnitScl.dp.scl(3f));
Lines.rect(x, y, width, height);
Draw.reset();
@@ -320,7 +320,7 @@ public class MapView extends Element implements GestureListener{
public boolean zoom(float initialDistance, float distance){
if(!active()) return false;
float nzoom = distance - initialDistance;
zoom += nzoom / 10000f / Unit.dp.scl(1f) * zoom;
zoom += nzoom / 10000f / UnitScl.dp.scl(1f) * zoom;
clampZoom();
return false;
}

View File

@@ -17,7 +17,7 @@ public abstract class Decal extends TimedEntity implements BelowLiquidTrait, Dra
@Override
public float lifetime(){
return 8200f;
return 3600;
}
@Override

View File

@@ -25,6 +25,11 @@ public class RubbleDecal extends Decal{
decal.add();
}
@Override
public float lifetime(){
return 8200f;
}
@Override
public void drawDecal(){
if(!Core.atlas.isFound(region)){

View File

@@ -34,7 +34,7 @@ public class ScorchDecal extends Decal{
@Override
public void drawDecal(){
for(int i = 0; i < 5; i++){
for(int i = 0; i < 3; i++){
TextureRegion region = regions[Mathf.randomSeed(id - i, 0, scorches - 1)];
float rotation = Mathf.randomSeed(id + i, 0, 360);
float space = 1.5f + Mathf.randomSeed(id + i + 1, 0, 20) / 10f;

View File

@@ -9,6 +9,7 @@ import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.math.Angles;
import io.anuke.arc.math.Mathf;
import io.anuke.arc.math.geom.*;
import io.anuke.arc.scene.ui.layout.*;
import io.anuke.arc.util.*;
import io.anuke.arc.util.pooling.Pools;
import io.anuke.mindustry.Vars;
@@ -27,7 +28,7 @@ import io.anuke.mindustry.net.NetConnection;
import io.anuke.mindustry.type.*;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.Floor;
import io.anuke.mindustry.world.blocks.*;
import java.io.*;
@@ -379,7 +380,7 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
boolean ints = font.usesIntegerPositions();
font.setUseIntegerPositions(false);
font.getData().setScale(0.25f / io.anuke.arc.scene.ui.layout.Unit.dp.scl(1f));
font.getData().setScale(0.25f / UnitScl.dp.scl(1f));
layout.setText(font, name);
Draw.color(0f, 0f, 0f, 0.3f);
Fill.rect(x, y + nameHeight - layout.height / 2, layout.width + 2, layout.height + 3);
@@ -420,7 +421,7 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
public void drawBuildRequests(){
BuildRequest last = null;
for(BuildRequest request : buildQueue()){
if(request.progress > 0.01f || (buildRequest() == request && (dst(request.x * tilesize, request.y * tilesize) <= placeDistance || state.isEditor()))) continue;
if(request.progress > 0.01f || (buildRequest() == request && request.initialized && (dst(request.x * tilesize, request.y * tilesize) <= placeDistance || state.isEditor()))) continue;
if(request.breaking){
Block block = world.ltile(request.x, request.y).block();
@@ -638,7 +639,8 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
}
protected void updateTouch(){
if(Units.invalidateTarget(target, this) && !(target instanceof TileEntity && ((TileEntity)target).damaged() && target.isValid() && target.getTeam() == team && mech.canHeal && dst(target) < getWeapon().bullet.range())){
if(Units.invalidateTarget(target, this) &&
!(target instanceof TileEntity && ((TileEntity)target).damaged() && target.isValid() && target.getTeam() == team && mech.canHeal && dst(target) < getWeapon().bullet.range() && !(((TileEntity)target).block instanceof BuildBlock))){
target = null;
}

View File

@@ -6,6 +6,7 @@ import io.anuke.arc.graphics.*;
import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.math.*;
import io.anuke.arc.math.geom.*;
import io.anuke.arc.scene.ui.layout.*;
import io.anuke.arc.util.*;
import io.anuke.mindustry.content.*;
import io.anuke.mindustry.entities.*;
@@ -402,7 +403,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
Core.scene.skin.getFont("outline").draw(item.amount + "",
x + Angles.trnsx(rotation + 180f, backTrns),
y + Angles.trnsy(rotation + 180f, backTrns) - 3,
Pal.accent, 0.25f * itemtime, false, Align.center
Pal.accent, 0.25f * itemtime / UnitScl.dp.scl(1f), false, Align.center
);
}
}

View File

@@ -30,11 +30,11 @@ public enum Gamemode{
rules.pvp = true;
rules.enemyCoreBuildRadius = 600f;
rules.respawnTime = 60 * 10;
rules.buildCostMultiplier = 0.5f;
rules.buildSpeedMultiplier = 2f;
rules.buildCostMultiplier = 1f;
rules.buildSpeedMultiplier = 1f;
rules.playerDamageMultiplier = 0.33f;
rules.playerHealthMultiplier = 0.5f;
rules.unitBuildSpeedMultiplier = 3f;
rules.unitBuildSpeedMultiplier = 2f;
rules.unitHealthMultiplier = 3f;
rules.attackMode = true;
}, map -> map.teams.size > 1),

View File

@@ -8,7 +8,7 @@ import io.anuke.arc.util.*;
/** Controls playback of multiple music tracks.*/
public class MusicControl{
private static final float finTime = 80f, foutTime = 80f;
private static final float finTime = 120f, foutTime = 120f;
private @Nullable Music current;
private float fade;

View File

@@ -21,14 +21,34 @@ public class Drawf{
}
public static void circles(float x, float y, float rad, Color color){
int vertices = (int)(rad * 2);
Lines.stroke(3f, Pal.gray);
Lines.poly(x, y, vertices, rad);
Lines.circle(x, y, rad);
Lines.stroke(1f, color);
Lines.poly(x, y, vertices, rad);
Lines.circle(x, y, rad);
Draw.reset();
}
public static void square(float x, float y, float radius, Color color){
Lines.stroke(3f, Pal.gray);
Lines.square(x, y, radius + 1f, 45);
Lines.stroke(1f, color);
Lines.square(x, y, radius + 1f, 45);
Draw.reset();
}
public static void square(float x, float y, float radius){
square(x, y, radius, Pal.accent);
}
/*
public static void square(float x, float y, float radius){
Lines.stroke(1f, Pal.gray);
Lines.square(x, y - 1f, radius + 1f, 45);
Lines.stroke(1f, Pal.accent);
Lines.square(x, y, radius + 1f, 45);
Draw.reset();
}*/
public static void arrow(float x, float y, float x2, float y2, float length, float radius){
float angle = Angles.angle(x, y, x2, y2);
float space = 2f;

View File

@@ -8,7 +8,7 @@ import io.anuke.arc.graphics.Color;
import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.graphics.glutils.FrameBuffer;
import io.anuke.arc.math.*;
import io.anuke.arc.scene.ui.layout.Unit;
import io.anuke.arc.scene.ui.layout.UnitScl;
import io.anuke.arc.util.*;
import io.anuke.arc.util.noise.RidgedPerlin;
import io.anuke.arc.util.noise.Simplex;
@@ -220,7 +220,7 @@ public class MenuRenderer implements Disposable{
public void render(){
time += Time.delta();
float scaling = Math.max(Unit.dp.scl(4f), Math.max(Core.graphics.getWidth() / ((width - 1f) * tilesize), Core.graphics.getHeight() / ((height - 1f) * tilesize)));
float scaling = Math.max(UnitScl.dp.scl(4f), Math.max(Core.graphics.getWidth() / ((width - 1f) * tilesize), Core.graphics.getHeight() / ((height - 1f) * tilesize)));
camera.position.set(width * tilesize / 2f, height * tilesize / 2f);
camera.resize(Core.graphics.getWidth() / scaling,
Core.graphics.getHeight() / scaling);

View File

@@ -7,6 +7,7 @@ import io.anuke.arc.graphics.Pixmap.*;
import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.math.*;
import io.anuke.arc.math.geom.*;
import io.anuke.arc.scene.ui.layout.*;
import io.anuke.arc.util.*;
import io.anuke.mindustry.entities.*;
import io.anuke.mindustry.entities.type.*;
@@ -77,7 +78,7 @@ public class MinimapRenderer implements Disposable{
for(Unit unit : units){
float rx = (unit.x - rect.x) / rect.width * w, ry = (unit.y - rect.y) / rect.width * h;
Draw.color(unit.getTeam().color);
Fill.rect(x + rx, y + ry, io.anuke.arc.scene.ui.layout.Unit.dp.scl(baseSize / 2f), io.anuke.arc.scene.ui.layout.Unit.dp.scl(baseSize / 2f));
Fill.rect(x + rx, y + ry, UnitScl.dp.scl(baseSize / 2f), UnitScl.dp.scl(baseSize / 2f));
}
Draw.color();

View File

@@ -85,9 +85,9 @@ public class OverlayRenderer{
float dst = Mathf.dst(player.x, player.y, core.drawx(), core.drawy());
if(dst < state.rules.enemyCoreBuildRadius * 1.5f){
Draw.color(Color.DARK_GRAY);
Lines.poly(core.drawx(), core.drawy() - 2, 200, state.rules.enemyCoreBuildRadius);
Lines.circle(core.drawx(), core.drawy() - 2, state.rules.enemyCoreBuildRadius);
Draw.color(Pal.accent, enemy.color, 0.5f + Mathf.absin(Time.time(), 10f, 0.5f));
Lines.poly(core.drawx(), core.drawy(), 200, state.rules.enemyCoreBuildRadius);
Lines.circle(core.drawx(), core.drawy(), state.rules.enemyCoreBuildRadius);
}
}
}

View File

@@ -24,6 +24,8 @@ public class Pal{
lightFlame = Color.valueOf("ffdd55"),
darkFlame = Color.valueOf("db401c"),
power2 = Color.valueOf("ff9f6c"),
lightPyraFlame = Color.valueOf("ffb855"),
darkPyraFlame = Color.valueOf("db661c"),

View File

@@ -4,7 +4,7 @@ import io.anuke.arc.Core;
import io.anuke.arc.graphics.Color;
import io.anuke.arc.graphics.g2d.TextureRegion;
import io.anuke.arc.graphics.glutils.Shader;
import io.anuke.arc.scene.ui.layout.Unit;
import io.anuke.arc.scene.ui.layout.UnitScl;
import io.anuke.arc.util.Time;
public class Shaders{
@@ -41,7 +41,7 @@ public class Shaders{
setUniformf("u_resolution", Core.graphics.getWidth(), Core.graphics.getHeight());
setUniformi("u_time", (int)(time += Core.graphics.getDeltaTime() * 60f));
setUniformf("u_uv", Core.atlas.white().getU(), Core.atlas.white().getV());
setUniformf("u_scl", Unit.dp.scl(1f));
setUniformf("u_scl", UnitScl.dp.scl(1f));
setUniformf("u_uv2", Core.atlas.white().getU2(), Core.atlas.white().getV2());
}
}
@@ -117,8 +117,8 @@ public class Shaders{
@Override
public void apply(){
setUniformf("u_dp", Unit.dp.scl(1f));
setUniformf("u_time", Time.time() / Unit.dp.scl(1f));
setUniformf("u_dp", UnitScl.dp.scl(1f));
setUniformf("u_time", Time.time() / UnitScl.dp.scl(1f));
setUniformf("u_offset",
Core.camera.position.x - Core.camera.width / 2,
Core.camera.position.y - Core.camera.height / 2);

View File

@@ -16,7 +16,7 @@ public enum Binding implements KeyBind{
diagonal_placement(KeyCode.CONTROL_LEFT),
pick(KeyCode.MOUSE_MIDDLE),
dash(KeyCode.SHIFT_LEFT),
gridMode(KeyCode.GRAVE),
gridMode(KeyCode.BACKTICK),
gridModeShift(KeyCode.ALT_LEFT),
zoom_hold(KeyCode.CONTROL_LEFT, "view"),
zoom(new Axis(KeyCode.SCROLL)),

View File

@@ -13,7 +13,7 @@ import io.anuke.arc.math.Mathf;
import io.anuke.arc.math.geom.*;
import io.anuke.arc.scene.actions.Actions;
import io.anuke.arc.scene.event.Touchable;
import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.arc.scene.ui.layout.*;
import io.anuke.arc.util.*;
import io.anuke.mindustry.content.Blocks;
import io.anuke.mindustry.content.Fx;
@@ -38,7 +38,7 @@ public class MobileInput extends InputHandler implements GestureListener{
private static final float maxPanSpeed = 1.3f;
private static Rectangle r1 = new Rectangle(), r2 = new Rectangle();
/** Distance to edge of screen to start panning. */
private final float edgePan = io.anuke.arc.scene.ui.layout.Unit.dp.scl(60f);
private final float edgePan = UnitScl.dp.scl(60f);
//gesture data
private Vector2 vector = new Vector2();
@@ -155,7 +155,6 @@ public class MobileInput extends InputHandler implements GestureListener{
return req;
}
}else{
r1.setSize(other.block().size * tilesize);
r1.setCenter(other.worldx() + other.block().offset(), other.worldy() + other.block().offset());
@@ -248,7 +247,7 @@ public class MobileInput extends InputHandler implements GestureListener{
/** Draws a placement icon for a specific block. */
void drawPlace(int x, int y, Block block, int rotation, int prevX, int prevY, int prevRotation){
if(validPlace(x, y, block, rotation)){
if(validPlace(x, y, block, rotation) && !checkOverlapPlacement(x, y, block)){
block.getPlaceDraw(placeDraw, rotation, prevX, prevY, prevRotation);
Draw.color();
@@ -509,7 +508,7 @@ public class MobileInput extends InputHandler implements GestureListener{
if(mode == placing && isPlacing()){
iterateLine(lineStartX, lineStartY, tileX, tileY, l -> {
Tile tile = world.tile(l.x, l.y);
if(tile != null && hasRequest(tile)){
if(tile != null && checkOverlapPlacement(tile.x, tile.y, block)){
return;
}
@@ -765,7 +764,7 @@ public class MobileInput extends InputHandler implements GestureListener{
if(lastDistance == -1) lastDistance = initialDistance;
float amount = (Mathf.sign(distance > lastDistance) * 0.04f) * Time.delta();
renderer.scaleCamera(io.anuke.arc.scene.ui.layout.Unit.dp.scl(amount));
renderer.scaleCamera(UnitScl.dp.scl(amount));
lastDistance = distance;
return true;
}

View File

@@ -24,8 +24,8 @@ public class MirrorFilter extends GenerateFilter{
v1.trns(angle - 90, 1f);
v2.set(v1).scl(-1f);
v1.add(in.width/2f, in.height/2f);
v2.add(in.width/2f, in.height/2f);
v1.add(in.width/2f - 0.5f, in.height/2f - 0.5f);
v2.add(in.width/2f - 0.5f, in.height/2f - 0.5f);
v3.set(in.x, in.y);
@@ -57,7 +57,7 @@ public class MirrorFilter extends GenerateFilter{
clamper.accept(Tmp.v1.trns(angle - 90, size).add(image.getWidth()/2f + image.getX(), image.getHeight()/2f + image.getY()));
clamper.accept(Tmp.v2.set(Tmp.v1).sub(image.getWidth()/2f + image.getX(), image.getHeight()/2f + image.getY()).rotate(180f).add(image.getWidth()/2f + image.getX(), image.getHeight()/2f + image.getY()));
Lines.stroke(Unit.dp.scl(3f), Pal.accent);
Lines.stroke(UnitScl.dp.scl(3f), Pal.accent);
Lines.line(Tmp.v1.x, Tmp.v1.y, Tmp.v2.x, Tmp.v2.y);
Draw.reset();
}

View File

@@ -39,8 +39,8 @@ public abstract class BasicGenerator extends RandomGenerator{
int offsetX = x - 4, offsetY = y + 23;
for(int i = ores.size - 1; i >= 0; i--){
Block entry = ores.get(i);
if(Math.abs(0.5f - sim.octaveNoise2D(2, 0.7, 1f / (50 + i * 2), offsetX, offsetY + i*999)) > 0.23f &&
Math.abs(0.5f - sim2.octaveNoise2D(1, 1, 1f / (40 + i * 4), offsetX, offsetY - i*999)) > 0.32f){
if(Math.abs(0.5f - sim.octaveNoise2D(2, 0.7, 1f / (40 + i * 2), offsetX, offsetY + i*999)) > 0.26f &&
Math.abs(0.5f - sim2.octaveNoise2D(1, 1, 1f / (30 + i * 4), offsetX, offsetY - i*999)) > 0.37f){
ore = entry;
break;
}

View File

@@ -132,6 +132,11 @@ public class Net{
active = false;
}
public static void reset(){
closeServer();
netClient.disconnectNoReset();
}
public static void disconnect(){
clientProvider.disconnect();
server = false;

View File

@@ -59,6 +59,26 @@ public class Zone extends UnlockableContent{
return metCondition() && wave % launchPeriod == 0;
}
public boolean canUnlock(){
if(data.isUnlocked(this)){
return true;
}
for(ZoneRequirement other : zoneRequirements){
if(other.zone.bestWave() < other.wave){
return false;
}
}
for(Block other : blockRequirements){
if(!data.isUnlocked(other)){
return false;
}
}
return true;
}
public ItemStack[] getLaunchCost(){
if(launchCost == null){
updateLaunchCost();

View File

@@ -3,7 +3,7 @@ package io.anuke.mindustry.ui;
import io.anuke.arc.graphics.Texture;
import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.scene.ui.Image;
import io.anuke.arc.scene.ui.layout.Unit;
import io.anuke.arc.scene.ui.layout.UnitScl;
import io.anuke.mindustry.graphics.Pal;
public class BorderImage extends Image{
@@ -36,7 +36,7 @@ public class BorderImage extends Image{
Draw.color(Pal.gray);
Draw.alpha(parentAlpha);
Lines.stroke(Unit.dp.scl(thickness));
Lines.stroke(UnitScl.dp.scl(thickness));
Lines.rect(x + imageX, y + imageY, imageWidth * scaleX, imageHeight * scaleY);
Draw.reset();
}

View File

@@ -18,12 +18,12 @@ public class Minimap extends Table{
add(new Element(){
{
setSize(Unit.dp.scl(140f));
setSize(UnitScl.dp.scl(140f));
}
@Override
public void act(float delta){
setPosition(Unit.dp.scl(margin), Unit.dp.scl(margin));
setPosition(UnitScl.dp.scl(margin), UnitScl.dp.scl(margin));
super.act(delta);
}
@@ -52,7 +52,7 @@ public class Minimap extends Table{
addListener(new ClickListener(){
{
tapSquareSize = Unit.dp.scl(11f);
tapSquareSize = UnitScl.dp.scl(11f);
}
@Override

View File

@@ -5,7 +5,7 @@ import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.scene.Element;
import io.anuke.arc.scene.ui.Image;
import io.anuke.arc.scene.ui.layout.Stack;
import io.anuke.arc.scene.ui.layout.Unit;
import io.anuke.arc.scene.ui.layout.UnitScl;
import io.anuke.mindustry.graphics.Pal;
public class ReqImage extends Stack{
@@ -21,7 +21,7 @@ public class ReqImage extends Stack{
@Override
public void draw(){
Lines.stroke(Unit.dp.scl(2f), Pal.removeBack);
Lines.stroke(UnitScl.dp.scl(2f), Pal.removeBack);
Lines.line(x, y - 2f + height, x + width, y - 2f);
Draw.color(Pal.remove);
Lines.line(x, y + height, x + width, y);

View File

@@ -37,7 +37,7 @@ public class CustomGameDialog extends FloatingDialog{
ScrollPane pane = new ScrollPane(maps);
pane.setFadeScrollBars(false);
int maxwidth = Mathf.clamp((int)(Core.graphics.getWidth() / Unit.dp.scl(200)), 1, 8);
int maxwidth = Mathf.clamp((int)(Core.graphics.getWidth() / UnitScl.dp.scl(200)), 1, 8);
float images = 146f;
int i = 0;

View File

@@ -3,6 +3,7 @@ package io.anuke.mindustry.ui.dialogs;
import io.anuke.arc.*;
import io.anuke.arc.collection.*;
import io.anuke.arc.collection.ObjectSet.*;
import io.anuke.arc.function.*;
import io.anuke.arc.graphics.*;
import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.math.*;
@@ -14,9 +15,11 @@ import io.anuke.arc.scene.utils.*;
import io.anuke.arc.util.*;
import io.anuke.mindustry.content.*;
import io.anuke.mindustry.core.GameState.*;
import io.anuke.mindustry.game.EventType.*;
import io.anuke.mindustry.game.Saves.*;
import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.io.SaveIO.*;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.type.*;
import io.anuke.mindustry.type.Zone.*;
import io.anuke.mindustry.ui.*;
@@ -25,19 +28,22 @@ import io.anuke.mindustry.ui.TreeLayout.*;
import static io.anuke.mindustry.Vars.*;
public class DeployDialog extends FloatingDialog{
private final float nodeSize = Unit.dp.scl(230f);
private final float nodeSize = UnitScl.dp.scl(230f);
private ObjectSet<ZoneNode> nodes = new ObjectSet<>();
private ZoneInfoDialog info = new ZoneInfoDialog();
private Rectangle bounds = new Rectangle();
private Texture nomap = new Texture("zones/nomap.png");
public DeployDialog(){
super("", "fulldialog");
Events.on(DisposeEvent.class, e -> nomap.dispose());
ZoneNode root = new ZoneNode(Zones.groundZero, null);
TreeLayout layout = new TreeLayout();
layout.gapBetweenLevels = layout.gapBetweenNodes = Unit.dp.scl(60f);
layout.gapBetweenNodes = Unit.dp.scl(120f);
layout.gapBetweenLevels = layout.gapBetweenNodes = UnitScl.dp.scl(60f);
layout.gapBetweenNodes = UnitScl.dp.scl(120f);
layout.layout(root);
bounds.set(layout.getBounds());
bounds.y += nodeSize*0.4f;
@@ -95,6 +101,8 @@ public class DeployDialog extends FloatingDialog{
hide();
ui.loadAnd(() -> {
logic.reset();
Net.reset();
try{
control.saves.getZoneSlot().load();
state.set(State.playing);
@@ -167,12 +175,13 @@ public class DeployDialog extends FloatingDialog{
button.setDisabled(() -> hidden(zone));
button.clicked(() -> info.show(zone));
if(zone.unlocked()){
if(zone.unlocked() && !hidden(zone)){
button.labelWrap(zone.localizedName()).style("outline").width(140).growX().get().setAlignment(Align.center);
}else{
button.addImage("icon-locked");
Consumer<Element> flasher = zone.canUnlock() && !hidden(zone) ? e -> e.update(() -> e.getColor().set(Color.WHITE).lerp(Pal.accent, Mathf.absin(3f, 1f))) : e -> {};
flasher.accept(button.addImage("icon-locked").get());
button.row();
button.add("$locked");
flasher.accept(button.add("$locked").get());
}
}
@@ -190,13 +199,7 @@ public class DeployDialog extends FloatingDialog{
}
stack.setSize(Tmp.v1.x, Tmp.v1.y);
if(node.zone.unlocked() && node.zone.preview != null){
stack.add(new Table(t -> t.margin(4f).add(new Image(node.zone.preview)
.setScaling(Scaling.stretch)).color(Color.DARK_GRAY).grow()));
}else{
stack.add(new Table(t -> t.margin(4f).add(new Image("whiteui", Color.BLACK).setScaling(Scaling.stretch)).grow()));
}
stack.add(new Table(t -> t.margin(4f).add(new Image(node.zone.preview != null ? node.zone.preview : nomap).setScaling(Scaling.stretch)).color(node.zone.unlocked() ? Color.DARK_GRAY : Color.fromGray(0.2f)).grow()));
stack.update(() -> stack.setPosition(node.x + panX + width / 2f, node.y + panY + height / 2f, Align.center));
Button button = new Button("square");
@@ -231,7 +234,8 @@ public class DeployDialog extends FloatingDialog{
for(ZoneNode node : nodes){
for(ZoneNode child : node.allChildren){
Lines.stroke(Unit.dp.scl(4f), node.zone.locked() || child.zone.locked() ? Pal.gray : Pal.gray);
Lines.stroke(UnitScl.dp.scl(4f), node.zone.locked() || child.zone.locked() ? Pal.gray : Pal.gray);
Draw.alpha(parentAlpha);
Lines.line(node.x + offsetX, node.y + offsetY, child.x + offsetX, child.y + offsetY);
}
}

View File

@@ -9,7 +9,7 @@ import io.anuke.arc.graphics.g2d.GlyphLayout;
import io.anuke.arc.scene.event.Touchable;
import io.anuke.arc.scene.ui.*;
import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.arc.scene.ui.layout.Unit;
import io.anuke.arc.scene.ui.layout.UnitScl;
import io.anuke.arc.util.*;
import io.anuke.arc.util.pooling.Pools;
import io.anuke.mindustry.core.Platform;
@@ -151,7 +151,7 @@ public class FileChooser extends FloatingDialog{
content.add(icontable).expandX().fillX();
content.row();
content.center().add(pane).width(Core.graphics.isPortrait() ? Core.graphics.getWidth() / Unit.dp.scl(1) : Core.graphics.getWidth() / Unit.dp.scl(2)).colspan(3).grow();
content.center().add(pane).width(Core.graphics.isPortrait() ? Core.graphics.getWidth() / UnitScl.dp.scl(1) : Core.graphics.getWidth() / UnitScl.dp.scl(2)).colspan(3).grow();
content.row();
if(!open){

View File

@@ -310,6 +310,7 @@ public class JoinDialog extends FloatingDialog{
Time.runTask(2f, () -> {
logic.reset();
Net.reset();
Vars.netClient.beginConnecting();
Net.connect(ip, port, () -> {
hide();

View File

@@ -1,20 +1,20 @@
package io.anuke.mindustry.ui.dialogs;
import io.anuke.arc.Core;
import io.anuke.arc.collection.Array;
import io.anuke.arc.files.FileHandle;
import io.anuke.arc.scene.ui.ScrollPane;
import io.anuke.arc.scene.ui.TextButton;
import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.arc.*;
import io.anuke.arc.collection.*;
import io.anuke.arc.files.*;
import io.anuke.arc.scene.ui.*;
import io.anuke.arc.scene.ui.layout.*;
import io.anuke.arc.util.*;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.core.Platform;
import io.anuke.mindustry.game.Saves.SaveSlot;
import io.anuke.mindustry.io.SaveIO;
import io.anuke.mindustry.io.SaveIO.SaveException;
import io.anuke.mindustry.*;
import io.anuke.mindustry.core.GameState.*;
import io.anuke.mindustry.core.*;
import io.anuke.mindustry.game.Saves.*;
import io.anuke.mindustry.io.*;
import io.anuke.mindustry.io.SaveIO.*;
import io.anuke.mindustry.net.Net;
import java.io.IOException;
import java.io.*;
import static io.anuke.mindustry.Vars.*;
@@ -137,7 +137,6 @@ public class LoadDialog extends FloatingDialog{
for(SaveSlot slot : control.saves.getSaveSlots()) if(!slot.isHidden()) valids = true;
if(!valids){
slots.row();
slots.addButton("$save.none", () -> {
}).disabled(true).fillX().margin(20f).minWidth(340f).height(80f).pad(4f);
@@ -170,6 +169,7 @@ public class LoadDialog extends FloatingDialog{
ui.loadAnd(() -> {
try{
Net.reset();
slot.load();
state.set(State.playing);
}catch(SaveException e){
@@ -184,7 +184,6 @@ public class LoadDialog extends FloatingDialog{
public void modifyButton(TextButton button, SaveSlot slot){
button.clicked(() -> {
if(!button.childrenPressed()){
int build = slot.getBuild();
runLoadSave(slot);
}
});

View File

@@ -117,7 +117,7 @@ public class MapsDialog extends FloatingDialog{
ScrollPane pane = new ScrollPane(maps);
pane.setFadeScrollBars(false);
int maxwidth = Mathf.clamp((int)(Core.graphics.getWidth() / Unit.dp.scl(230)), 1, 8);
int maxwidth = Mathf.clamp((int)(Core.graphics.getWidth() / UnitScl.dp.scl(230)), 1, 8);
float mapsize = 200f;
int i = 0;
@@ -176,7 +176,7 @@ public class MapsDialog extends FloatingDialog{
t.row();
t.add("$editor.author").padRight(10).color(Color.GRAY);
t.row();
t.add(map.author()).growX().wrap().padTop(2);
t.add(map.custom && map.author().isEmpty() ? "Anuke" : map.author()).growX().wrap().padTop(2);
t.row();
t.add("$editor.description").padRight(10).color(Color.GRAY).top();
t.row();

View File

@@ -6,7 +6,7 @@ import io.anuke.arc.graphics.g2d.Draw;
import io.anuke.arc.input.KeyCode;
import io.anuke.arc.scene.event.InputEvent;
import io.anuke.arc.scene.event.InputListener;
import io.anuke.arc.scene.ui.layout.Unit;
import io.anuke.arc.scene.ui.layout.UnitScl;
import static io.anuke.mindustry.Vars.*;
@@ -24,12 +24,13 @@ public class MinimapDialog extends FloatingDialog{
void setup(){
cont.clear();
float size = Math.min(Core.graphics.getWidth(), Core.graphics.getHeight()) / Unit.dp.scl(1f) / 1.3f;
float size = Math.min(Core.graphics.getWidth(), Core.graphics.getHeight()) / UnitScl.dp.scl(1f) / 1.3f;
cont.table("pane", t -> {
t.addRect((x, y, width, height) -> {
if(renderer.minimap.getRegion() == null) return;
Draw.color(Color.WHITE);
Draw.alpha(parentAlpha);
Draw.rect(renderer.minimap.getRegion(), x + width / 2f, y + height / 2f, width, height);
if(renderer.minimap.getTexture() != null){

View File

@@ -13,6 +13,7 @@ import io.anuke.arc.scene.ui.layout.*;
import io.anuke.arc.util.*;
import io.anuke.mindustry.core.GameState.*;
import io.anuke.mindustry.core.*;
import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.net.Net;
@@ -32,6 +33,7 @@ public class SettingsMenuDialog extends SettingsDialog{
setStyle(Core.scene.skin.get("dialog", WindowStyle.class));
hidden(() -> {
Sounds.back.play();
if(!state.is(State.menu)){
if(!wasPaused || Net.active())
state.set(State.playing);

View File

@@ -24,7 +24,7 @@ import io.anuke.mindustry.world.Block.*;
import static io.anuke.mindustry.Vars.*;
public class TechTreeDialog extends FloatingDialog{
private final float nodeSize = Unit.dp.scl(60f);
private final float nodeSize = UnitScl.dp.scl(60f);
private ObjectSet<TechTreeNode> nodes = new ObjectSet<>();
private TechTreeNode root = new TechTreeNode(TechTree.root, null);
private Rectangle bounds = new Rectangle();
@@ -59,8 +59,8 @@ public class TechTreeDialog extends FloatingDialog{
void treeLayout(){
TreeLayout layout = new TreeLayout();
layout.gapBetweenLevels = Unit.dp.scl(60f);
layout.gapBetweenNodes = Unit.dp.scl(40f);
layout.gapBetweenLevels = UnitScl.dp.scl(60f);
layout.gapBetweenNodes = UnitScl.dp.scl(40f);
LayoutNode node = new LayoutNode(root, null);
layout.layout(node);
bounds.set(layout.getBounds());
@@ -318,7 +318,7 @@ public class TechTreeDialog extends FloatingDialog{
for(TechTreeNode child : node.children){
if(!child.visible) continue;
Lines.stroke(Unit.dp.scl(4f), locked(node.node) || locked(child.node) ? Pal.gray : Pal.accent);
Lines.stroke(UnitScl.dp.scl(4f), locked(node.node) || locked(child.node) ? Pal.gray : Pal.accent);
Draw.alpha(parentAlpha);
Lines.line(node.x + offsetX, node.y + offsetY, child.x + offsetX, child.y + offsetY);
}

View File

@@ -151,29 +151,9 @@ public class ZoneInfoDialog extends FloatingDialog{
hide();
control.playZone(zone);
}
}).minWidth(150f).margin(13f).padTop(5).disabled(b -> zone.locked() ? !canUnlock(zone) : !data.hasItems(zone.getLaunchCost())).uniformY().get();
}).minWidth(150f).margin(13f).padTop(5).disabled(b -> zone.locked() ? !zone.canUnlock() : !data.hasItems(zone.getLaunchCost())).uniformY().get();
button.row();
button.add(iteminfo);
}
private boolean canUnlock(Zone zone){
if(data.isUnlocked(zone)){
return true;
}
for(ZoneRequirement other : zone.zoneRequirements){
if(other.zone.bestWave() < other.wave){
return false;
}
}
for(Block other : zone.blockRequirements){
if(!data.isUnlocked(other)){
return false;
}
}
return true;
}
}

View File

@@ -11,7 +11,7 @@ import io.anuke.arc.scene.ui.Label;
import io.anuke.arc.scene.ui.Label.LabelStyle;
import io.anuke.arc.scene.ui.TextField;
import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.arc.scene.ui.layout.Unit;
import io.anuke.arc.scene.ui.layout.UnitScl;
import io.anuke.arc.util.Align;
import io.anuke.arc.util.Time;
import io.anuke.mindustry.Vars;
@@ -33,9 +33,9 @@ public class ChatFragment extends Table{
private Label fieldlabel = new Label(">");
private BitmapFont font;
private GlyphLayout layout = new GlyphLayout();
private float offsetx = Unit.dp.scl(4), offsety = Unit.dp.scl(4), fontoffsetx = Unit.dp.scl(2), chatspace = Unit.dp.scl(50);
private float offsetx = UnitScl.dp.scl(4), offsety = UnitScl.dp.scl(4), fontoffsetx = UnitScl.dp.scl(2), chatspace = UnitScl.dp.scl(50);
private Color shadowColor = new Color(0, 0, 0, 0.4f);
private float textspacing = Unit.dp.scl(10);
private float textspacing = UnitScl.dp.scl(10);
private Array<String> history = new Array<>();
private int historyPos = 0;
private int scrollPos = 0;
@@ -123,7 +123,7 @@ public class ChatFragment extends Table{
@Override
public void draw(){
float opacity = Core.settings.getInt("chatopacity") / 100f;
float textWidth = Math.min(Core.graphics.getWidth()/1.5f, Unit.dp.scl(700f));
float textWidth = Math.min(Core.graphics.getWidth()/1.5f, UnitScl.dp.scl(700f));
Draw.color(shadowColor);
@@ -158,7 +158,7 @@ public class ChatFragment extends Table{
font.getCache().setAlphas(opacity);
}
Fill.crect(offsetx, theight - layout.height - 2, textWidth + Unit.dp.scl(4f), layout.height + textspacing);
Fill.crect(offsetx, theight - layout.height - 2, textWidth + UnitScl.dp.scl(4f), layout.height + textspacing);
Draw.color(shadowColor);
Draw.alpha(opacity * shadowColor.a);

View File

@@ -5,7 +5,6 @@ import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.math.*;
import io.anuke.arc.scene.*;
import io.anuke.arc.scene.event.*;
import io.anuke.arc.util.*;
/** Fades in a black overlay.*/
public class FadeInFragment extends Fragment{
@@ -30,7 +29,7 @@ public class FadeInFragment extends Fragment{
@Override
public void act(float delta){
super.act(delta);
time += Time.delta() / duration;
time += 1f / duration;
if(time > 1){
remove();
}

View File

@@ -1,42 +1,34 @@
package io.anuke.mindustry.ui.fragments;
import io.anuke.annotations.Annotations.Loc;
import io.anuke.annotations.Annotations.Remote;
import io.anuke.arc.Core;
import io.anuke.arc.Events;
import io.anuke.arc.collection.Array;
import io.anuke.arc.graphics.Color;
import io.anuke.arc.graphics.g2d.Draw;
import io.anuke.arc.graphics.g2d.Lines;
import io.anuke.arc.input.KeyCode;
import io.anuke.arc.math.Interpolation;
import io.anuke.arc.math.Mathf;
import io.anuke.arc.math.geom.Vector2;
import io.anuke.arc.scene.Element;
import io.anuke.arc.scene.Group;
import io.anuke.arc.scene.actions.Actions;
import io.anuke.arc.scene.event.Touchable;
import io.anuke.arc.scene.style.TextureRegionDrawable;
import io.anuke.annotations.Annotations.*;
import io.anuke.arc.*;
import io.anuke.arc.collection.*;
import io.anuke.arc.graphics.*;
import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.input.*;
import io.anuke.arc.math.*;
import io.anuke.arc.math.geom.*;
import io.anuke.arc.scene.*;
import io.anuke.arc.scene.actions.*;
import io.anuke.arc.scene.event.*;
import io.anuke.arc.scene.style.*;
import io.anuke.arc.scene.ui.*;
import io.anuke.arc.scene.ui.layout.UnitScl;
import io.anuke.arc.scene.ui.layout.*;
import io.anuke.arc.scene.utils.Elements;
import io.anuke.arc.util.*;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.entities.Units;
import io.anuke.mindustry.entities.type.BaseUnit;
import io.anuke.mindustry.entities.type.Player;
import io.anuke.mindustry.game.EventType.StateChangeEvent;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.game.UnlockableContent;
import io.anuke.mindustry.gen.Call;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.input.Binding;
import io.anuke.mindustry.core.GameState.*;
import io.anuke.mindustry.entities.*;
import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.game.EventType.*;
import io.anuke.mindustry.game.*;
import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.input.*;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.net.Packets.AdminAction;
import io.anuke.mindustry.type.ContentType;
import io.anuke.mindustry.type.UnitType;
import io.anuke.mindustry.net.Packets.*;
import io.anuke.mindustry.type.*;
import io.anuke.mindustry.ui.*;
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
import io.anuke.mindustry.ui.dialogs.*;
import static io.anuke.mindustry.Vars.*;
@@ -110,7 +102,7 @@ public class HudFragment extends Fragment{
select.addImage("whiteui").color(Pal.gray).width(4f).fillY();
float size = Unit.dp.scl(dsize);
float size = UnitScl.dp.scl(dsize);
Array<Element> children = new Array<>(select.getChildren());
//now, you may be wondering, why is this necessary? the answer is, I don't know, but it fixes layout issues somehow
@@ -122,7 +114,7 @@ public class HudFragment extends Fragment{
if(fi < 4){
elem.setSize(size);
}else{
elem.setSize(Unit.dp.scl(4f), size);
elem.setSize(UnitScl.dp.scl(4f), size);
}
elem.setPosition(fi * size, Core.graphics.getHeight(), Align.topLeft);
return true;
@@ -144,21 +136,14 @@ public class HudFragment extends Fragment{
});
Table wavesMain, editorMain;
boolean[] prev = {false};
cont.stack(wavesMain = new Table(), editorMain = new Table()).height(wavesMain.getPrefHeight()).update(s -> {
((Table)s.getParent()).getCell(s).height((wavesMain.isVisible() ? wavesMain.getPrefHeight() : editorMain.getPrefHeight()) / Unit.dp.scl(1f));
if(prev[0] != wavesMain.isVisible()){
s.getParent().pack();
prev[0] = wavesMain.isVisible();
}
});
cont.stack(wavesMain = new Table(), editorMain = new Table()).height(wavesMain.getPrefHeight());
{
wavesMain.visible(() -> shown && !state.isEditor());
wavesMain.left();
wavesMain.top().left();
Stack stack = new Stack();
TextButton waves = new TextButton("", "wave");
Button waves = new Button("wave");
Table btable = new Table().margin(0);
stack.add(waves);
@@ -253,7 +238,7 @@ public class HudFragment extends Fragment{
//fps display
cont.table(info -> {
info.top().left().margin(4).visible(() -> Core.settings.getBool("fps"));
info.update(() -> info.setTranslation(state.rules.waves || state.isEditor() ? 0f : -Unit.dp.scl(dsize * 4 + 3), 0));
info.update(() -> info.setTranslation(state.rules.waves || state.isEditor() ? 0f : -UnitScl.dp.scl(dsize * 4 + 3), 0));
IntFormat fps = new IntFormat("fps");
IntFormat ping = new IntFormat("ping");
@@ -327,59 +312,6 @@ public class HudFragment extends Fragment{
.update(label -> label.getColor().set(Color.ORANGE).lerp(Color.SCARLET, Mathf.absin(Time.time(), 2f, 1f)))).touchable(Touchable.disabled);
});
//launch button
parent.fill(t -> {
t.top().right();
TextButton[] testb = {null};
TextButton button = Elements.newButton("$launch", () -> {
FloatingDialog dialog = new FloatingDialog("$launch");
dialog.update(() -> {
if(!testb[0].isVisible()){
dialog.hide();
}
});
dialog.cont.add("$launch.confirm").width(500f).wrap().pad(4f).get().setAlignment(Align.center, Align.center);
dialog.buttons.defaults().size(200f, 54f).pad(2f);
dialog.setFillParent(false);
dialog.buttons.addButton("$cancel", dialog::hide);
dialog.buttons.addButton("$ok", () -> {
dialog.hide();
Call.launchZone();
});
dialog.keyDown(KeyCode.ESCAPE, dialog::hide);
dialog.keyDown(KeyCode.BACK, dialog::hide);
dialog.show();
});
testb[0] = button;
button.getStyle().disabledFontColor = Color.WHITE;
button.margin(16f);
button.visible(() ->
world.isZone() &&
world.getZone().metCondition() &&
!Net.client() &&
state.wave % world.getZone().launchPeriod == 0 && !world.spawner.isSpawning());
button.update(() -> {
if(world.getZone() == null){
button.setText("");
return;
}
button.setText(state.enemies() > 0 ? Core.bundle.format("launch.unable", state.enemies()) : Core.bundle.get("launch") + "\n" +
Core.bundle.format("launch.next", state.wave + world.getZone().launchPeriod));
button.getLabel().setColor(Tmp.c1.set(Color.WHITE).lerp(state.enemies() > 0 ? Color.WHITE : Color.SCARLET,
Mathf.absin(Time.time(), 2f, 1f)));
});
button.setDisabled(() -> state.enemies() > 0);
button.getLabelCell().left().get().setAlignment(Align.left, Align.left);
t.add(button).size(250f, 80f);
});
//paused table
parent.fill(t -> {
t.top().visible(() -> state.isPaused());
@@ -542,6 +474,37 @@ public class HudFragment extends Fragment{
Core.scene.add(image);
}
private void showLaunchConfirm(){
FloatingDialog dialog = new FloatingDialog("$launch");
dialog.update(() -> {
if(!inLaunchWave()){
dialog.hide();
}
});
dialog.cont.add("$launch.confirm").width(500f).wrap().pad(4f).get().setAlignment(Align.center, Align.center);
dialog.buttons.defaults().size(200f, 54f).pad(2f);
dialog.setFillParent(false);
dialog.buttons.addButton("$cancel", dialog::hide);
dialog.buttons.addButton("$ok", () -> {
dialog.hide();
Call.launchZone();
});
dialog.keyDown(KeyCode.ESCAPE, dialog::hide);
dialog.keyDown(KeyCode.BACK, dialog::hide);
dialog.show();
}
private boolean inLaunchWave(){
return world.isZone() &&
world.getZone().metCondition() &&
!Net.client() &&
state.wave % world.getZone().launchPeriod == 0 && !world.spawner.isSpawning();
}
private boolean canLaunch(){
return inLaunchWave() && state.enemies() <= 0;
}
private void toggleMenus(){
if(flip != null){
flip.getStyle().imageUp = Core.scene.skin.getDrawable(shown ? "icon-arrow-down" : "icon-arrow-up");
@@ -553,7 +516,7 @@ public class HudFragment extends Fragment{
}
}
private void addWaveTable(TextButton table){
private void addWaveTable(Button table){
StringBuilder ibuild = new StringBuilder();
IntFormat wavef = new IntFormat("wave");
@@ -586,6 +549,22 @@ public class HudFragment extends Fragment{
builder.append(wavef.get(state.wave));
builder.append("\n");
if(inLaunchWave()){
builder.append("[#");
Tmp.c1.set(Color.WHITE).lerp(state.enemies() > 0 ? Color.WHITE : Color.SCARLET, Mathf.absin(Time.time(), 2f, 1f)).toString(builder);
builder.append("]");
if(!canLaunch()){
builder.append(Core.bundle.get("launch.unable2"));
}else{
builder.append(Core.bundle.get("launch"));
builder.append("\n");
builder.append(Core.bundle.format("launch.next", state.wave + world.getZone().launchPeriod));
builder.append("\n");
}
builder.append("[]\n");
}
if(state.enemies() > 0){
if(state.enemies() == 1){
builder.append(enemyf.get(state.enemies()));
@@ -604,8 +583,13 @@ public class HudFragment extends Fragment{
return builder;
}).growX().pad(8f);
table.setDisabled(true);
table.setDisabled(() -> !canLaunch());
table.visible(() -> state.rules.waves);
table.clicked(() -> {
if(canLaunch()){
showLaunchConfirm();
}
});
}
private void addPlayButton(Table table){
@@ -616,7 +600,6 @@ public class HudFragment extends Fragment{
state.wavetime = 0f;
}
}).growY().fillX().right().width(40f)
.visible(() -> state.rules.waves && ((Net.server() || player.isAdmin) || !Net.active()) && state.enemies() == 0
&& !world.spawner.isSpawning());
.visible(() -> state.rules.waves && ((Net.server() || player.isAdmin) || !Net.active()) && state.enemies() == 0 && !world.spawner.isSpawning() && !inLaunchWave());
}
}

View File

@@ -43,6 +43,7 @@ public class LoadingFragment extends Fragment{
}
public void show(String text){
table.clearActions();
table.touchable(Touchable.enabled);
table.<Label>find("namelabel").setText(text);
table.visible(true);
@@ -51,6 +52,7 @@ public class LoadingFragment extends Fragment{
}
public void hide(){
table.clearActions();
table.toFront();
table.touchable(Touchable.disabled);
table.actions(Actions.fadeOut(1f), Actions.visible(false));

View File

@@ -73,12 +73,12 @@ public class MenuFragment extends Fragment{
String versionText = "[#ffffffba]" + ((Version.build == -1) ? "[#fc8140aa]custom build" : Version.modifier + " build " + Version.build);
parent.fill((x, y, w, h) -> {
float logoscl = (int)Unit.dp.scl(1);
float logow = Math.min(logo.getWidth() * logoscl, Core.graphics.getWidth() - Unit.dp.scl(20));
float logoscl = UnitScl.dp.scl(1);
float logow = Math.min(logo.getWidth() * logoscl, Core.graphics.getWidth() - UnitScl.dp.scl(20));
float logoh = logow * (float)logo.getHeight() / logo.getWidth();
float fx = (int)(Core.graphics.getWidth() / 2f);
float fy = (int)(Core.graphics.getHeight() - 6 - logoh) + logoh / 2 - (Core.graphics.isPortrait() ? Unit.dp.scl(30f) : 0f);
float fy = (int)(Core.graphics.getHeight() - 6 - logoh) + logoh / 2 - (Core.graphics.isPortrait() ? UnitScl.dp.scl(30f) : 0f);
Draw.color();
Draw.rect(Draw.wrap(logo), fx, fy, logow, logoh);
@@ -210,7 +210,7 @@ public class MenuFragment extends Fragment{
submenu.clearChildren();
fadeInMenu();
//correctly offset the button
submenu.add().height((Core.graphics.getHeight() - out[0].getY(Align.topLeft)) / Unit.dp.scl(1f));
submenu.add().height((Core.graphics.getHeight() - out[0].getY(Align.topLeft)) / UnitScl.dp.scl(1f));
submenu.row();
buttons(submenu, b.submenu);
}else{

View File

@@ -7,7 +7,7 @@ import io.anuke.arc.scene.Group;
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.scene.ui.layout.UnitScl;
import io.anuke.arc.util.Interval;
import io.anuke.arc.util.Scaling;
import io.anuke.mindustry.core.GameState.State;
@@ -84,7 +84,7 @@ public class PlayerListFragment extends Fragment{
super.draw();
Draw.color(Pal.gray);
Draw.alpha(parentAlpha);
Lines.stroke(Unit.dp.scl(4f));
Lines.stroke(UnitScl.dp.scl(4f));
Lines.rect(x, y, width, height);
Draw.reset();
}

View File

@@ -230,17 +230,19 @@ public class Block extends BlockStorage{
public void drawPlace(int x, int y, int rotation, boolean valid){
}
protected void drawPlaceText(String text, int x, int y, boolean valid){
if(renderer.pixelator.enabled()) return;
protected float drawPlaceText(String text, int x, int y, boolean valid){
if(renderer.pixelator.enabled()) return 0;
Color color = valid ? Pal.accent : Pal.remove;
BitmapFont font = Core.scene.skin.getFont("outline");
GlyphLayout layout = Pools.obtain(GlyphLayout.class, GlyphLayout::new);
boolean ints = font.usesIntegerPositions();
font.setUseIntegerPositions(false);
font.getData().setScale(1f / 4f);
font.getData().setScale(1f / 4f / UnitScl.dp.scl(1f));
layout.setText(font, text);
float width = layout.width;
font.setColor(color);
float dx = x * tilesize + offset(), dy = y * tilesize + offset() + size * tilesize / 2f + 3;
font.draw(text, dx, dy + layout.height + 1, Align.center);
@@ -255,6 +257,7 @@ public class Block extends BlockStorage{
font.getData().setScale(1f);
Draw.reset();
Pools.free(layout);
return width;
}
public void draw(Tile tile){
@@ -276,7 +279,8 @@ public class Block extends BlockStorage{
tempTiles.clear();
Geometry.circle(tile.x, tile.y, range, (x, y) -> {
Tile other = world.ltile(x, y);
if(other != null && other.block instanceof PowerNode && ((PowerNode)other.block).linkValid(other, tile)){
if(other != null && other.block instanceof PowerNode && ((PowerNode)other.block).linkValid(other, tile) && !other.entity.proximity().contains(tile) &&
!(outputsPower && tile.entity.proximity().contains(p -> p.entity != null && p.entity.power != null && p.entity.power.graph == other.entity.power.graph))){
tempTiles.add(other);
}
});

View File

@@ -220,7 +220,7 @@ public class Tile implements Position, TargetTrait{
}
public boolean isEnemyCheat(){
return getTeam() == waveTeam && !state.rules.pvp;
return getTeam() == waveTeam && state.rules.enemyCheat;
}
public boolean isLinked(){

View File

@@ -70,7 +70,7 @@ public class MendProjector extends Block{
entity.phaseHeat = Mathf.lerpDelta(entity.phaseHeat, Mathf.num(entity.cons.optionalValid()), 0.1f);
if(entity.cons.optionalValid() && entity.timer.get(timerUse, useTime)){
if(entity.cons.optionalValid() && entity.timer.get(timerUse, useTime) && entity.power.satisfaction > 0){
entity.cons.trigger();
}
@@ -78,12 +78,12 @@ public class MendProjector extends Block{
float realRange = range + entity.phaseHeat * phaseRangeBoost;
entity.charge = 0f;
int tileRange = (int)(realRange / tilesize);
int tileRange = (int)(realRange / tilesize + 1);
healed.clear();
for(int x = -tileRange + tile.x; x <= tileRange + tile.x; x++){
for(int y = -tileRange + tile.y; y <= tileRange + tile.y; y++){
if(Mathf.dst(x, y, tile.x, tile.y) > tileRange) continue;
if(!Mathf.within(x * tilesize, y * tilesize, tile.drawx(), tile.drawy(), realRange)) continue;
Tile other = world.ltile(x, y);

View File

@@ -74,7 +74,7 @@ public class OverdriveProjector extends Block{
entity.phaseHeat = Mathf.lerpDelta(entity.phaseHeat, Mathf.num(entity.cons.optionalValid()), 0.1f);
if(entity.timer.get(timerUse, useTime)){
if(entity.timer.get(timerUse, useTime) && entity.power.satisfaction > 0){
entity.cons.trigger();
}
@@ -84,12 +84,12 @@ public class OverdriveProjector extends Block{
entity.charge = 0f;
int tileRange = (int)(realRange / tilesize);
int tileRange = (int)(realRange / tilesize + 1);
healed.clear();
for(int x = -tileRange + tile.x; x <= tileRange + tile.x; x++){
for(int y = -tileRange + tile.y; y <= tileRange + tile.y; y++){
if(Mathf.dst(x, y, tile.x, tile.y) > tileRange) continue;
if(!Mathf.within(x * tilesize, y * tilesize, tile.drawx(), tile.drawy(), realRange)) continue;
Tile other = world.ltile(x, y);

View File

@@ -20,6 +20,7 @@ public class PowerGraph{
private final ObjectSet<Tile> all = new ObjectSet<>();
private final WindowedMean powerBalance = new WindowedMean(60);
private float lastPowerProduced, lastPowerNeeded;
private long lastFrameUpdated = -1;
private final int graphID;
@@ -37,6 +38,23 @@ public class PowerGraph{
return powerBalance.getMean();
}
public float getLastPowerNeeded(){
return lastPowerNeeded;
}
public float getLastPowerProduced(){
return lastPowerProduced;
}
public float getSatisfaction(){
if(Mathf.isZero(lastPowerProduced)){
return 0f;
}else if(Mathf.isZero(lastPowerNeeded)){
return 1f;
}
return Mathf.clamp(lastPowerProduced / lastPowerNeeded);
}
public float getPowerProduced(){
float powerProduced = 0f;
for(Tile producer : producers){
@@ -164,6 +182,9 @@ public class PowerGraph{
float powerNeeded = getPowerNeeded();
float powerProduced = getPowerProduced();
lastPowerNeeded = powerNeeded;
lastPowerProduced = powerProduced;
powerBalance.addValue((powerProduced - powerNeeded) / Time.delta());
if(consumers.size == 0 && producers.size == 0 && batteries.size == 0){
@@ -188,6 +209,7 @@ public class PowerGraph{
}
public void add(Tile tile){
if(tile.entity == null || tile.entity.power == null) return;
tile.entity.power.graph = this;
all.add(tile);

View File

@@ -2,6 +2,7 @@ package io.anuke.mindustry.world.blocks.power;
import io.anuke.annotations.Annotations.*;
import io.anuke.arc.*;
import io.anuke.arc.function.*;
import io.anuke.arc.graphics.*;
import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.math.*;
@@ -105,13 +106,20 @@ public class PowerNode extends PowerBlock{
Call.linkPowerNodes(null, tile, before);
}
Predicate<Tile> valid = other -> other != null && other != tile && ((!other.block().outputsPower && other.block().consumesPower) || (other.block().outputsPower && !other.block().consumesPower)) && linkValid(tile, other)
&& !other.entity.proximity().contains(tile) && other.entity.power.graph != tile.entity.power.graph;
tempTiles.clear();
Geometry.circle(tile.x, tile.y, (int)(laserRange + 1), (x, y) -> {
Tile other = world.ltile(x, y);
if(other != null && other != tile && ((!other.block().outputsPower && other.block().consumesPower) || (other.block().outputsPower && !other.block().consumesPower)) && linkValid(tile, other)){
Call.linkPowerNodes(null, tile, other);
if(valid.test(other)){
tempTiles.add(other);
}
});
tempTiles.sort(Structs.comparingFloat(t -> t.dst2(tile)));
tempTiles.each(valid, other -> Call.linkPowerNodes(null, tile, other));
lastPlaced = tile.pos();
super.playerPlaced(tile);
}
@@ -153,13 +161,12 @@ public class PowerNode extends PowerBlock{
Lines.stroke(1f);
Draw.color(Pal.accent);
Lines.poly(tile.drawx(), tile.drawy(), 50, laserRange * tilesize);
Drawf.circles(tile.drawx(), tile.drawy(), laserRange * tilesize);
Draw.reset();
}
@Override
public void drawConfigure(Tile tile){
TileEntity entity = tile.entity();
Draw.color(Pal.accent);
@@ -177,15 +184,9 @@ public class PowerNode extends PowerBlock{
if(link != tile && linkValid(tile, link, false)){
boolean linked = linked(tile, link);
Draw.color(linked ? Pal.place : Pal.breakInvalid);
Lines.circle(link.drawx(), link.drawy(),
link.block().size * tilesize / 2f + 1f + (linked ? 0f : Mathf.absin(Time.time(), 4f, 1f)));
if((entity.power.links.size >= maxNodes || (link.block() instanceof PowerNode && link.entity.power.links.size >= ((PowerNode)link.block()).maxNodes)) && !linked){
Draw.color(Pal.breakInvalid);
Lines.lineAngleCenter(link.drawx(), link.drawy(), 45, link.block().size * Mathf.sqrt2 * tilesize * 0.9f);
Draw.color();
if(linked){
Drawf.square(link.drawx(), link.drawy(), link.block().size * tilesize / 2f + 1f, Pal.place);
}
}
}
@@ -196,9 +197,24 @@ public class PowerNode extends PowerBlock{
@Override
public void drawPlace(int x, int y, int rotation, boolean valid){
Tile tile = world.tile(x, y);
if(tile == null) return;
Lines.stroke(1f);
Draw.color(Pal.placing);
Drawf.circles(x * tilesize + offset(), y * tilesize + offset(), laserRange * tilesize);
for(int cx = (int)(x - laserRange - 1); cx <= x + laserRange + 1; cx++){
for(int cy = (int)(y - laserRange - 1); cy <= y + laserRange + 1; cy++){
Tile link = world.ltile(cx, cy);
if(link != null && !(link.x == x && link.y == y) && link.block().hasPower && overlaps(x * tilesize + offset(), y *tilesize + offset(), link, laserRange * tilesize)){
Drawf.square(link.drawx(), link.drawy(), link.block().size * tilesize / 2f + 2f, link.pos() == lastPlaced ? Pal.place : Pal.accent);
}
}
}
Draw.reset();
}
@@ -227,7 +243,7 @@ public class PowerNode extends PowerBlock{
}
public boolean linkValid(Tile tile, Tile link, boolean checkMaxNodes){
if(tile == link || link == null || !link.block().hasPower || tile.getTeam() != link.getTeam()) return false;
if(tile == link || link == null || link.entity == null || tile.entity == null || !link.block().hasPower || tile.getTeam() != link.getTeam()) return false;
if(overlaps(tile, link, laserRange * tilesize) || (link.block() instanceof PowerNode && overlaps(link, tile, link.<PowerNode>cblock().laserRange * tilesize))){
if(checkMaxNodes && link.block() instanceof PowerNode){
@@ -238,8 +254,12 @@ public class PowerNode extends PowerBlock{
return false;
}
protected boolean overlaps(float srcx, float srcy, Tile other, float range){
return Intersector.overlaps(Tmp.cr1.set(srcx, srcy, range), other.getHitbox(Tmp.r1));
}
protected boolean overlaps(Tile src, Tile other, float range){
return Intersector.overlaps(Tmp.cr1.set(src.drawx(), src.drawy(), range), other.getHitbox(Tmp.r1));
return overlaps(src.drawx(), src.drawy(), other, range);
}
protected void drawLaser(Tile tile, Tile target){
@@ -255,8 +275,10 @@ public class PowerNode extends PowerBlock{
x2 += t2.x;
y2 += t2.y;
Draw.color(Pal.powerLight, Color.WHITE, Mathf.absin(Time.time(), 8f, 0.3f) + 0.2f);
Drawf.laser(laser, laserEnd, x1, y1, x2, y2, 0.6f);
float fract = 1f-tile.entity.power.graph.getSatisfaction();
Draw.color(Color.WHITE, Pal.powerLight, fract*0.86f + Mathf.absin(3f, 0.1f));
Drawf.laser(laser, laserEnd, x1, y1, x2, y2, 0.4f);
Draw.color();
}

View File

@@ -136,9 +136,8 @@ public class Drill extends Block{
countOre(tile);
if(returnItem != null){
drawPlaceText(Core.bundle.formatFloat("bar.drillspeed", 60f / (drillTime + hardnessDrillMultiplier * returnItem.hardness) * returnCount, 2), x, y, valid);
float dx = x * tilesize + offset() - 31f, dy = y * tilesize + offset() + size * tilesize / 2f + 5;
float width = drawPlaceText(Core.bundle.formatFloat("bar.drillspeed", 60f / (drillTime + hardnessDrillMultiplier * returnItem.hardness) * returnCount, 2), x, y, valid);
float dx = x * tilesize + offset() - width/2f - 4f, dy = y * tilesize + offset() + size * tilesize / 2f + 5;
Draw.mixcol(Color.DARK_GRAY, 1f);
Draw.rect(returnItem.icon(Item.Icon.large), dx, dy - 1);
Draw.reset();