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

This commit is contained in:
Anuken
2019-08-03 19:38:26 -04:00
109 changed files with 1971 additions and 1718 deletions

View File

@@ -42,9 +42,9 @@ public class Vars{
/** maximum distance between mine and core that supports automatic transferring */
public static final float mineTransferRange = 220f;
/** team of the player by default */
public static final Team defaultTeam = Team.blue;
public static final Team defaultTeam = Team.sharded;
/** team of the enemy in waves/sectors */
public static final Team waveTeam = Team.red;
public static final Team waveTeam = Team.crux;
/** whether to enable editing of units in the editor */
public static final boolean enableUnitEditing = false;
/** max chat message length */

View File

@@ -219,7 +219,7 @@ public class BlockIndexer{
}
private void process(Tile tile){
if(tile.block().flags.size() > 0 && tile.getTeam() != Team.none){
if(tile.block().flags.size() > 0 && tile.getTeam() != Team.derelict){
ObjectSet<Tile>[] map = getFlagged(tile.getTeam());
for(BlockFlag flag : tile.block().flags){

File diff suppressed because it is too large Load Diff

View File

@@ -115,7 +115,7 @@ public class Bullets implements ContentList{
lifetime = 70f;
bulletWidth = bulletHeight = 14f;
collidesTiles = false;
ammoMultiplier = 2f;
ammoMultiplier = 4f;
splashDamageRadius = 45f;
splashDamage = 50f;
backColor = Pal.missileYellowBack;
@@ -137,7 +137,7 @@ public class Bullets implements ContentList{
flakLead = new FlakBulletType(4.2f, 3){{
lifetime = 60f;
ammoMultiplier = 3f;
ammoMultiplier = 4f;
shootEffect = Fx.shootSmall;
bulletWidth = 6f;
bulletHeight = 8f;
@@ -148,7 +148,7 @@ public class Bullets implements ContentList{
flakScrap = new FlakBulletType(4f, 3){{
lifetime = 60f;
ammoMultiplier = 3f;
ammoMultiplier = 5f;
shootEffect = Fx.shootSmall;
reloadMultiplier = 0.5f;
bulletWidth = 6f;
@@ -171,7 +171,7 @@ public class Bullets implements ContentList{
flakExplosive = new FlakBulletType(4f, 5){{
//default bullet type, no changes
shootEffect = Fx.shootBig;
ammoMultiplier = 2f;
ammoMultiplier = 4f;
}};
flakSurge = new FlakBulletType(4f, 7){{
@@ -188,7 +188,7 @@ public class Bullets implements ContentList{
drag = -0.01f;
splashDamageRadius = 30f;
splashDamage = 30f;
ammoMultiplier = 2f;
ammoMultiplier = 4f;
lifetime = 150f;
hitEffect = Fx.blastExplosion;
despawnEffect = Fx.blastExplosion;
@@ -286,14 +286,14 @@ public class Bullets implements ContentList{
lifetime = 60f;
shootEffect = Fx.shootSmall;
smokeEffect = Fx.shootSmallSmoke;
ammoMultiplier = 1;
ammoMultiplier = 2;
}};
standardDense = new BasicBulletType(3.5f, 18, "bullet"){{
bulletWidth = 9f;
bulletHeight = 12f;
reloadMultiplier = 0.6f;
ammoMultiplier = 2;
ammoMultiplier = 4;
lifetime = 60f;
}};
@@ -302,7 +302,7 @@ public class Bullets implements ContentList{
bulletHeight = 13f;
shootEffect = Fx.shootBig;
smokeEffect = Fx.shootBigSmoke;
ammoMultiplier = 2;
ammoMultiplier = 4;
lifetime = 60f;
}};
@@ -311,7 +311,7 @@ public class Bullets implements ContentList{
bulletHeight = 9f;
homingPower = 5f;
reloadMultiplier = 1.4f;
ammoMultiplier = 3;
ammoMultiplier = 5;
lifetime = 60f;
}};

View File

@@ -11,7 +11,7 @@ import io.anuke.mindustry.entities.effect.GroundEffectEntity.GroundEffect;
import io.anuke.mindustry.entities.type.BaseUnit;
import io.anuke.mindustry.game.ContentList;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.graphics.Shapes;
import io.anuke.mindustry.graphics.Drawf;
import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.type.Item.Icon;
@@ -672,16 +672,16 @@ public class Fx implements ContentList{
shootSmall = new Effect(8, e -> {
Draw.color(Pal.lighterOrange, Pal.lightOrange, e.fin());
float w = 1f + 5 * e.fout();
Shapes.tri(e.x, e.y, w, 15f * e.fout(), e.rotation);
Shapes.tri(e.x, e.y, w, 3f * e.fout(), e.rotation + 180f);
Drawf.tri(e.x, e.y, w, 15f * e.fout(), e.rotation);
Drawf.tri(e.x, e.y, w, 3f * e.fout(), e.rotation + 180f);
Draw.reset();
});
shootHeal = new Effect(8, e -> {
Draw.color(Pal.heal);
float w = 1f + 5 * e.fout();
Shapes.tri(e.x, e.y, w, 17f * e.fout(), e.rotation);
Shapes.tri(e.x, e.y, w, 4f * e.fout(), e.rotation + 180f);
Drawf.tri(e.x, e.y, w, 17f * e.fout(), e.rotation);
Drawf.tri(e.x, e.y, w, 4f * e.fout(), e.rotation + 180f);
Draw.reset();
});
@@ -698,16 +698,16 @@ public class Fx implements ContentList{
shootBig = new Effect(9, e -> {
Draw.color(Pal.lighterOrange, Pal.lightOrange, e.fin());
float w = 1.2f + 7 * e.fout();
Shapes.tri(e.x, e.y, w, 25f * e.fout(), e.rotation);
Shapes.tri(e.x, e.y, w, 4f * e.fout(), e.rotation + 180f);
Drawf.tri(e.x, e.y, w, 25f * e.fout(), e.rotation);
Drawf.tri(e.x, e.y, w, 4f * e.fout(), e.rotation + 180f);
Draw.reset();
});
shootBig2 = new Effect(10, e -> {
Draw.color(Pal.lightOrange, Color.GRAY, e.fin());
float w = 1.2f + 8 * e.fout();
Shapes.tri(e.x, e.y, w, 29f * e.fout(), e.rotation);
Shapes.tri(e.x, e.y, w, 5f * e.fout(), e.rotation + 180f);
Drawf.tri(e.x, e.y, w, 29f * e.fout(), e.rotation);
Drawf.tri(e.x, e.y, w, 5f * e.fout(), e.rotation + 180f);
Draw.reset();
});
@@ -829,7 +829,7 @@ public class Fx implements ContentList{
Draw.color(Pal.lancerLaser);
for(int i : Mathf.signs){
Shapes.tri(e.x, e.y, 4f * e.fout(), 29f, e.rotation + 90f * i);
Drawf.tri(e.x, e.y, 4f * e.fout(), 29f, e.rotation + 90f * i);
}
Draw.reset();
@@ -867,7 +867,7 @@ public class Fx implements ContentList{
Draw.color(Pal.lancerLaser);
Angles.randLenVectors(e.id, 2, 1f + 20f * e.fout(), e.rotation, 120f, (x, y) -> {
Shapes.tri(e.x + x, e.y + y, e.fslope() * 3f + 1, e.fslope() * 3f + 1, Mathf.angle(x, y));
Drawf.tri(e.x + x, e.y + y, e.fslope() * 3f + 1, e.fslope() * 3f + 1, Mathf.angle(x, y));
});
Draw.reset();

View File

@@ -32,6 +32,7 @@ public class Mechs implements ContentList{
mineSpeed = 1.5f;
mass = 1.2f;
speed = 0.5f;
itemCapacity = 40;
boostSpeed = 0.95f;
buildPower = 1.2f;
engineColor = Color.valueOf("ffd37f");
@@ -151,7 +152,7 @@ public class Mechs implements ContentList{
{
drillPower = 2;
mineSpeed = 1.5f;
itemCapacity = 50;
itemCapacity = 80;
speed = 0.36f;
boostSpeed = 0.6f;
mass = 4f;

View File

@@ -294,7 +294,7 @@ public class TechTree implements ContentList{
private TechNode node(Block block, Runnable children){
ItemStack[] requirements = new ItemStack[block.buildRequirements.length];
for(int i = 0; i < requirements.length; i++){
requirements[i] = new ItemStack(block.buildRequirements[i].item, block.buildRequirements[i].amount * 5);
requirements[i] = new ItemStack(block.buildRequirements[i].item, 30 + block.buildRequirements[i].amount * 5);
}
return new TechNode(block, requirements, children);

View File

@@ -12,7 +12,7 @@ import io.anuke.mindustry.world.Block;
public class Zones implements ContentList{
public static Zone
groundZero, desertWastes,
craters, frozenForest, ruinousShores, stainedMountains, tarFields,
craters, frozenForest, ruinousShores, stainedMountains, tarFields, fungalPass,
saltFlats, overgrowth, impact0078, crags,
desolateRift, nuclearComplex;
@@ -20,8 +20,8 @@ public class Zones implements ContentList{
public void load(){
groundZero = new Zone("groundZero", new MapGenerator("groundZero", 1)){{
baseLaunchCost = ItemStack.with(Items.copper, -100);
startingItems = ItemStack.list(Items.copper, 100);
baseLaunchCost = ItemStack.with(Items.copper, -60);
startingItems = ItemStack.list(Items.copper, 60);
alwaysUnlocked = true;
conditionWave = 5;
launchPeriod = 5;
@@ -29,7 +29,7 @@ public class Zones implements ContentList{
}};
desertWastes = new Zone("desertWastes", new DesertWastesGenerator(260, 260)){{
startingItems = ItemStack.list(Items.copper, 200);
startingItems = ItemStack.list(Items.copper, 120);
conditionWave = 20;
launchPeriod = 10;
loadout = Loadouts.advancedShard;
@@ -78,8 +78,7 @@ public class Zones implements ContentList{
}};
saltFlats = new Zone("saltFlats", new MapGenerator("saltFlats")){{
baseLaunchCost = ItemStack.with(Items.copper, -100);
startingItems = ItemStack.list(Items.copper, 100);
startingItems = ItemStack.list(Items.copper, 200, Items.silicon, 100, Items.lead, 200);
alwaysUnlocked = true;
conditionWave = 5;
launchPeriod = 5;
@@ -93,35 +92,25 @@ public class Zones implements ContentList{
.decor(new Decoration(Blocks.snow, Blocks.sporeCluster, 0.02))){{
loadout = Loadouts.basicFoundation;
baseLaunchCost = ItemStack.with();
startingItems = ItemStack.list(Items.copper, 400);
startingItems = ItemStack.list(Items.copper, 250);
conditionWave = 10;
blockRequirements = new Block[]{Blocks.junction, Blocks.router};
zoneRequirements = ZoneRequirement.with(groundZero, 10);
resources = new Item[]{Items.copper, Items.lead, Items.coal};
}};
craters = new Zone("craters", new MapGenerator("craters", 1).dist(0).decor(new Decoration(Blocks.snow, Blocks.sporeCluster, 0.004))){{
startingItems = ItemStack.list(Items.copper, 200);
craters = new Zone("craters", new MapGenerator("craters", 1).decor(new Decoration(Blocks.snow, Blocks.sporeCluster, 0.004))){{
startingItems = ItemStack.list(Items.copper, 100);
conditionWave = 10;
zoneRequirements = ZoneRequirement.with(frozenForest, 10);
blockRequirements = new Block[]{Blocks.mender, Blocks.combustionGenerator};
resources = new Item[]{Items.copper, Items.lead, Items.coal, Items.sand, Items.scrap};
}};
overgrowth = new Zone("overgrowth", new MapGenerator("overgrowth")){{
startingItems = ItemStack.list(Items.copper, 3000, Items.lead, 2000, Items.silicon, 1000, Items.metaglass, 500);
conditionWave = 12;
launchPeriod = 4;
loadout = Loadouts.basicNucleus;
zoneRequirements = ZoneRequirement.with(craters, 40);
blockRequirements = new Block[]{Blocks.cultivator, Blocks.sporePress};
resources = new Item[]{Items.copper, Items.lead, Items.coal, Items.titanium, Items.sand, Items.thorium, Items.scrap};
}};
ruinousShores = new Zone("ruinousShores", new MapGenerator("ruinousShores", 1).dist(3f, true)){{
ruinousShores = new Zone("ruinousShores", new MapGenerator("ruinousShores", 1)){{
loadout = Loadouts.basicFoundation;
baseLaunchCost = ItemStack.with();
startingItems = ItemStack.list(Items.copper, 400);
startingItems = ItemStack.list(Items.copper, 140, Items.lead, 50);
conditionWave = 20;
launchPeriod = 20;
zoneRequirements = ZoneRequirement.with(desertWastes, 20, craters, 15);
@@ -130,10 +119,9 @@ public class Zones implements ContentList{
}};
stainedMountains = new Zone("stainedMountains", new MapGenerator("stainedMountains", 2)
.dist(0f, false)
.decor(new Decoration(Blocks.shale, Blocks.shaleBoulder, 0.02))){{
loadout = Loadouts.basicFoundation;
startingItems = ItemStack.list(Items.copper, 400, Items.lead, 100);
startingItems = ItemStack.list(Items.copper, 200, Items.lead, 50);
conditionWave = 10;
launchPeriod = 10;
zoneRequirements = ZoneRequirement.with(frozenForest, 15);
@@ -141,11 +129,27 @@ public class Zones implements ContentList{
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};
resources = new Item[]{Items.copper, Items.lead, Items.coal, Items.titanium, Items.sand};
}};
overgrowth = new Zone("overgrowth", new MapGenerator("overgrowth")){{
startingItems = ItemStack.list(Items.copper, 1500, Items.lead, 1000, Items.silicon, 500, Items.metaglass, 250);
conditionWave = 12;
launchPeriod = 4;
loadout = Loadouts.basicNucleus;
zoneRequirements = ZoneRequirement.with(craters, 40, fungalPass, 10);
blockRequirements = new Block[]{Blocks.cultivator, Blocks.sporePress, Blocks.titanFactory, Blocks.wraithFactory};
resources = new Item[]{Items.copper, Items.lead, Items.coal, Items.titanium, Items.sand, Items.thorium, Items.scrap};
}};
tarFields = new Zone("tarFields", new MapGenerator("tarFields")
.dist(0f, false)
.decor(new Decoration(Blocks.shale, Blocks.shaleBoulder, 0.02))){{
loadout = Loadouts.basicFoundation;
startingItems = ItemStack.list(Items.copper, 500, Items.lead, 200);
startingItems = ItemStack.list(Items.copper, 250, Items.lead, 100);
conditionWave = 15;
launchPeriod = 10;
zoneRequirements = ZoneRequirement.with(ruinousShores, 20);
@@ -153,10 +157,10 @@ public class Zones implements ContentList{
resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.titanium, Items.sand};
}};
desolateRift = new Zone("desolateRift", new MapGenerator("desolateRift").dist(2f)){{
desolateRift = new Zone("desolateRift", new MapGenerator("desolateRift")){{
loadout = Loadouts.basicNucleus;
baseLaunchCost = ItemStack.with();
startingItems = ItemStack.list(Items.copper, 2000, Items.lead, 2000, Items.graphite, 500, Items.titanium, 500, Items.silicon, 500);
startingItems = ItemStack.list(Items.copper, 1000, Items.lead, 1000, Items.graphite, 250, Items.titanium, 250, Items.silicon, 250);
conditionWave = 3;
launchPeriod = 2;
zoneRequirements = ZoneRequirement.with(tarFields, 20);
@@ -180,10 +184,10 @@ public class Zones implements ContentList{
.decor(new Decoration(Blocks.snow, Blocks.sporeCluster, 0.01))){{
loadout = Loadouts.basicNucleus;
baseLaunchCost = ItemStack.with();
startingItems = ItemStack.list(Items.copper, 2500, Items.lead, 3000, Items.silicon, 800, Items.metaglass, 400);
startingItems = ItemStack.list(Items.copper, 1250, Items.lead, 1500, Items.silicon, 400, Items.metaglass, 250);
conditionWave = 30;
launchPeriod = 15;
zoneRequirements = ZoneRequirement.with(stainedMountains, 20);
zoneRequirements = ZoneRequirement.with(fungalPass, 8);
blockRequirements = new Block[]{Blocks.thermalGenerator, Blocks.laserDrill};
resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.titanium, Items.thorium, Items.sand};
}};

View File

@@ -132,16 +132,27 @@ public class UI implements ApplicationListener{
void generateFonts(Skin skin){
generator = new FreeTypeFontGenerator(Core.files.internal("fonts/font.ttf"));
FreeTypeFontParameter param = new FreeTypeFontParameter();
param.size = (int)(9 * 2 * Math.max(Unit.dp.scl(1f), 0.5f));
param.shadowColor = Color.DARK_GRAY;
param.shadowOffsetY = 2;
param.incremental = true;
skin.add("default-font", generator.generateFont(param));
skin.add("default-font-chat", generator.generateFont(param));
skin.getFont("default-font").getData().markupEnabled = true;
skin.getFont("default-font").setOwnsTexture(false);
FreeTypeFontParameter param = new FreeTypeFontParameter(){{
size = (int)(9 * 2 * Math.max(Unit.dp.scl(1f), 0.5f));
shadowColor = Color.DARK_GRAY;
shadowOffsetY = 2;
incremental = true;
}};
FreeTypeFontParameter outlined = new FreeTypeFontParameter(){{
size = param.size;
borderColor = Color.DARK_GRAY;
borderWidth = 2f;
spaceX -= borderWidth;
incremental = true;
}};
skin.add("outline", generator.generateFont(outlined));
skin.add("default", generator.generateFont(param));
skin.add("chat", generator.generateFont(param));
skin.getFont("default").getData().markupEnabled = true;
skin.getFont("default").setOwnsTexture(false);
}
@Override

View File

@@ -115,7 +115,7 @@ public class EditorTile extends Tile{
return;
}
super.setTeam(Team.none);
super.setTeam(Team.derelict);
}
@Override

View File

@@ -32,7 +32,7 @@ public class MapEditor{
public int brushSize = 1;
public int rotation;
public Block drawBlock = Blocks.stone;
public Team drawTeam = Team.blue;
public Team drawTeam = Team.sharded;
public StringMap getTags(){
return tags;
@@ -175,7 +175,6 @@ public class MapEditor{
world.setBlock(tile(x, y), drawBlock, drawTeam);
}else{
boolean isFloor = drawBlock.isFloor() && drawBlock != Blocks.air;
Consumer<Tile> drawer = tile -> {

View File

@@ -335,7 +335,12 @@ public class MapEditorDialog extends Dialog implements Disposable{
@Override
public Dialog show(){
return super.show(Core.scene, Actions.sequence());
return super.show(Core.scene, Actions.sequence(Actions.alpha(1f)));
}
@Override
public void hide(){
super.hide(Actions.sequence(Actions.alpha(0f)));
}
@Override
@@ -360,6 +365,10 @@ public class MapEditorDialog extends Dialog implements Disposable{
return view;
}
public MapGenerateDialog getGenerateDialog(){
return generateDialog;
}
public void resetSaved(){
saved = false;
}
@@ -533,6 +542,11 @@ public class MapEditorDialog extends Dialog implements Disposable{
mid.table("underline", t -> {
Slider slider = new Slider(0, MapEditor.brushSizes.length - 1, 1, false);
slider.moved(f -> editor.brushSize = MapEditor.brushSizes[(int)(float)f]);
for(int j = 0; j < MapEditor.brushSizes.length; j++){
if(MapEditor.brushSizes[j] == editor.brushSize){
slider.setValue(j);
}
}
t.top();
t.add("$editor.brush");

View File

@@ -11,7 +11,6 @@ import io.anuke.arc.scene.ui.*;
import io.anuke.arc.scene.ui.layout.*;
import io.anuke.arc.util.*;
import io.anuke.arc.util.async.*;
import io.anuke.mindustry.content.*;
import io.anuke.mindustry.game.*;
import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.io.*;
@@ -28,8 +27,8 @@ import static io.anuke.mindustry.Vars.*;
public class MapGenerateDialog extends FloatingDialog{
private final Supplier<GenerateFilter>[] filterTypes = new Supplier[]{
NoiseFilter::new, ScatterFilter::new, TerrainFilter::new, DistortFilter::new,
RiverNoiseFilter::new, OreFilter::new, MedianFilter::new, BlendFilter::new,
MirrorFilter::new, ClearFilter::new
RiverNoiseFilter::new, OreFilter::new, OreMedianFilter::new, MedianFilter::new,
BlendFilter::new, MirrorFilter::new, ClearFilter::new
};
private final MapEditor editor;
private final boolean applied;
@@ -150,16 +149,6 @@ public class MapGenerateDialog extends FloatingDialog{
editor.clearOp();
}
public void addDefaultOres(Array<GenerateFilter> filters){
int index = 0;
for(Block block : new Block[]{Blocks.oreCopper, Blocks.oreLead, Blocks.oreCoal, Blocks.oreTitanium, Blocks.oreThorium}){
OreFilter filter = new OreFilter();
filter.threshold += index ++ * 0.019f;
filter.ore = block;
filters.add(filter);
}
}
void setup(){
if(pixmap != null){
pixmap.dispose();
@@ -315,7 +304,7 @@ public class MapGenerateDialog extends FloatingDialog{
}
selection.cont.addButton("$filter.defaultores", () -> {
addDefaultOres(filters);
world.maps.addDefaultOres(filters);
rebuildFilters();
update();
selection.hide();
@@ -394,10 +383,10 @@ public class MapGenerateDialog extends FloatingDialog{
//get result from buffer1 if there's filters left, otherwise get from editor directly
if(filters.isEmpty()){
Tile tile = editor.tile(px * scaling, py * scaling);
color = MapIO.colorFor(tile.floor(), tile.block(), tile.overlay(), Team.none);
color = MapIO.colorFor(tile.floor(), tile.block(), tile.overlay(), Team.derelict);
}else{
GenTile tile = buffer1[px][py];
color = MapIO.colorFor(content.block(tile.floor), content.block(tile.block), content.block(tile.ore), Team.none);
color = MapIO.colorFor(content.block(tile.floor), content.block(tile.block), content.block(tile.ore), Team.derelict);
}
pixmap.drawPixel(px, pixmap.getHeight() - 1 - py, color);
}

View File

@@ -240,10 +240,6 @@ public class MapView extends Element implements GestureListener{
editor.renderer().draw(centerx - sclwidth / 2, centery - sclheight / 2, sclwidth, sclheight);
Draw.reset();
if(!ScissorStack.pushScissors(rect.set(x, y, width, height))){
return;
}
if(grid){
Draw.color(Color.GRAY);
image.setBounds(centerx - sclwidth / 2, centery - sclheight / 2, sclwidth, sclheight);
@@ -303,7 +299,6 @@ public class MapView extends Element implements GestureListener{
Draw.reset();
ScissorStack.popScissors();
ScissorStack.popScissors();
}
private boolean active(){

View File

@@ -35,7 +35,7 @@ public class Damage{
public static void dynamicExplosion(float x, float y, float flammability, float explosiveness, float power, float radius, Color color){
for(int i = 0; i < Mathf.clamp(power / 20, 0, 6); i++){
int branches = 5 + Mathf.clamp((int)(power / 30), 1, 20);
Time.run(i * 2f + Mathf.random(4f), () -> Lightning.create(Team.none, Pal.power, 3,
Time.run(i * 2f + Mathf.random(4f), () -> Lightning.create(Team.derelict, Pal.power, 3,
x, y, Mathf.random(360f), branches + Mathf.range(2)));
}

View File

@@ -79,7 +79,7 @@ public class Units{
/** Returns the neareset enemy tile in a range. */
public static TileEntity findEnemyTile(Team team, float x, float y, float range, Predicate<Tile> pred){
if(team == Team.none) return null;
if(team == Team.derelict) return null;
for(Team enemy : state.teams.enemiesOf(team)){
TileEntity entity = world.indexer.findTile(enemy, x, y, range, pred);
@@ -102,7 +102,7 @@ public class Units{
/** Returns the closest target enemy. First, units are checked, then tile entities. */
public static TargetTrait closestTarget(Team team, float x, float y, float range, Predicate<Unit> unitPred, Predicate<Tile> tilePred){
if(team == Team.none) return null;
if(team == Team.derelict) return null;
Unit unit = closestEnemy(team, x, y, range, unitPred);
if(unit != null){
@@ -114,7 +114,7 @@ public class Units{
/** Returns the closest enemy of this team. Filter by predicate. */
public static Unit closestEnemy(Team team, float x, float y, float range, Predicate<Unit> predicate){
if(team == Team.none) return null;
if(team == Team.derelict) return null;
result = null;
cdist = 0f;

View File

@@ -83,7 +83,7 @@ public class Bullet extends SolidEntity implements DamageTrait, ScaleTrait, Pool
/** Internal use only. */
@Remote(called = Loc.server, unreliable = true)
public static void createBullet(BulletType type, float x, float y, float angle){
create(type, null, Team.none, x, y, angle);
create(type, null, Team.derelict, x, y, angle);
}
/** ok */

View File

@@ -31,7 +31,7 @@ public abstract class BulletType extends Content{
/** Extra inaccuracy when firing. */
public float inaccuracy = 0f;
/** How many bullets get created per ammo item/liquid. */
public float ammoMultiplier = 1f;
public float ammoMultiplier = 2f;
/** Multiplied by turret reload speed to get final shoot speed. */
public float reloadMultiplier = 1f;
/** Recoil from shooter entities. */

View File

@@ -90,7 +90,7 @@ public interface MinerTrait extends Entity{
Draw.color(Color.LIGHT_GRAY, Color.WHITE, 1f - flashScl + Mathf.absin(Time.time(), 0.5f, flashScl));
Shapes.laser(Core.atlas.find("minelaser"), Core.atlas.find("minelaser-end"), px, py, ex, ey, 0.75f);
Drawf.laser(Core.atlas.find("minelaser"), Core.atlas.find("minelaser-end"), px, py, ex, ey, 0.75f);
if(unit instanceof Player && ((Player)unit).isLocal){
Lines.stroke(1f, Pal.accent);

View File

@@ -1,30 +1,23 @@
package io.anuke.mindustry.entities.type;
import io.anuke.annotations.Annotations.*;
import io.anuke.arc.Core;
import io.anuke.arc.graphics.g2d.Draw;
import io.anuke.arc.graphics.g2d.TextureRegion;
import io.anuke.arc.math.Angles;
import io.anuke.arc.math.Mathf;
import io.anuke.arc.math.geom.Geometry;
import io.anuke.arc.math.geom.Rectangle;
import io.anuke.arc.util.Interval;
import io.anuke.arc.util.Time;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.content.StatusEffects;
import io.anuke.mindustry.entities.EntityGroup;
import io.anuke.mindustry.entities.Units;
import io.anuke.mindustry.entities.traits.ShooterTrait;
import io.anuke.mindustry.entities.traits.TargetTrait;
import io.anuke.arc.*;
import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.math.*;
import io.anuke.arc.math.geom.*;
import io.anuke.arc.util.*;
import io.anuke.mindustry.*;
import io.anuke.mindustry.content.*;
import io.anuke.mindustry.entities.*;
import io.anuke.mindustry.entities.traits.*;
import io.anuke.mindustry.entities.units.*;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.game.TypeID;
import io.anuke.mindustry.gen.Call;
import io.anuke.mindustry.game.*;
import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.type.*;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.units.UnitFactory.UnitFactoryEntity;
import io.anuke.mindustry.world.meta.BlockFlag;
import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.blocks.units.UnitFactory.*;
import io.anuke.mindustry.world.meta.*;
import java.io.*;
@@ -168,22 +161,6 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
return null;
}
protected void drawItems(){
float backTrns = 4f;
if(item.amount > 0){
int stored = Mathf.clamp(item.amount / 6, 1, 8);
for(int i = 0; i < stored; i++){
float angT = i == 0 ? 0 : Mathf.randomSeedRange(i + 2, 60f);
float lenT = i == 0 ? 0 : Mathf.randomSeedRange(i + 3, 1f) - 1f;
Draw.rect(item.item.icon(Item.Icon.large),
x + Angles.trnsx(rotation + 180f + angT, backTrns + lenT),
y + Angles.trnsy(rotation + 180f + angT, backTrns + lenT),
itemSize, itemSize, rotation);
}
}
}
public boolean isBoss(){
return hasEffect(StatusEffects.boss);
}

View File

@@ -115,7 +115,6 @@ public abstract class FlyingUnit extends BaseUnit{
Draw.rect(type.region, x, y, rotation - 90);
drawWeapons();
drawItems();
Draw.mixcol();
}

View File

@@ -145,8 +145,6 @@ public abstract class GroundUnit extends BaseUnit{
y + Angles.trnsy(tra, getWeapon().width * i, trY), w, type.weapon.region.getHeight() * Draw.scl, rotation - 90);
}
drawItems();
Draw.mixcol();
}

View File

@@ -65,7 +65,7 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
public String lastText;
public float textFadeTime;
private float walktime;
private float walktime, itemtime;
private Queue<BuildRequest> placeQueue = new Queue<>();
private Tile mining;
private Vector2 movement = new Vector2();
@@ -338,21 +338,6 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
rotation - 90);
}
float backTrns = 4f;
if(item.amount > 0){
ItemStack stack = item;
int stored = Mathf.clamp(stack.amount / 6, 1, 8);
for(int i = 0; i < stored; i++){
float angT = i == 0 ? 0 : Mathf.randomSeedRange(i + 1, 60f);
float lenT = i == 0 ? 0 : Mathf.randomSeedRange(i + 2, 1f) - 1f;
Draw.rect(stack.item.icon(Item.Icon.large),
x + Angles.trnsx(rotation + 180f + angT, backTrns + lenT),
y + Angles.trnsy(rotation + 180f + angT, backTrns + lenT),
itemSize, itemSize, rotation);
}
}
Draw.reset();
}
@@ -360,7 +345,8 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
public void drawStats(){
Draw.color(Color.BLACK, team.color, healthf() + Mathf.absin(Time.time(), healthf() * 5f, 1f - healthf()));
Draw.rect(getPowerCellRegion(), x + Angles.trnsx(rotation, mech.cellTrnsY, 0f), y + Angles.trnsy(rotation, mech.cellTrnsY, 0f), rotation - 90);
Draw.color();
Draw.reset();
drawBackItems(itemtime, isLocal);
}
@Override
@@ -386,7 +372,7 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
}
public void drawName(){
BitmapFont font = Core.scene.skin.getFont("default-font");
BitmapFont font = Core.scene.skin.getFont("default");
GlyphLayout layout = Pools.obtain(GlyphLayout.class, GlyphLayout::new);
final float nameHeight = 11;
final float textHeight = 15;
@@ -478,8 +464,7 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
for(int i = 0; i < 4; i++){
Point2 p = Geometry.d8edge[i];
float offset = -Math.max(request.block.size - 1, 0) / 2f * tilesize;
if(i % 2 == 0)
Draw.rect("block-select", request.x * tilesize + request.block.offset() + offset * p.x, request.y * tilesize + request.block.offset() + offset * p.y, i * 90);
Draw.rect("block-select", request.x * tilesize + request.block.offset() + offset * p.x, request.y * tilesize + request.block.offset() + offset * p.y, i * 90);
}
Draw.color();
@@ -498,6 +483,7 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
public void update(){
hitTime -= Time.delta();
textFadeTime -= Time.delta() / (60 * 5);
itemtime = Mathf.lerpDelta(itemtime, Mathf.num(item.amount > 0), 0.1f);
if(Float.isNaN(x) || Float.isNaN(y)){
velocity.set(0f, 0f);
@@ -729,10 +715,10 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
if(target == null){
isShooting = false;
if(Core.settings.getBool("autotarget")){
target = Units.closestTarget(team, x, y, getWeapon().bullet.range(), u -> u.getTeam() != Team.none, u -> u.getTeam() != Team.none);
target = Units.closestTarget(team, x, y, getWeapon().bullet.range(), u -> u.getTeam() != Team.derelict, u -> u.getTeam() != Team.derelict);
if(mech.canHeal && target == null){
target = Geometry.findClosest(x, y, world.indexer.getDamaged(Team.blue));
target = Geometry.findClosest(x, y, world.indexer.getDamaged(Team.sharded));
if(target != null && dst(target) > getWeapon().bullet.range()){
target = null;
}else if(target != null){
@@ -785,7 +771,7 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
public void resetNoAdd(){
status.clear();
team = Team.blue;
team = Team.sharded;
item.amount = 0;
placeQueue.clear();
dead = true;

View File

@@ -1,33 +1,28 @@
package io.anuke.mindustry.entities.type;
import io.anuke.annotations.Annotations.Nullable;
import io.anuke.arc.Core;
import io.anuke.arc.Events;
import io.anuke.arc.graphics.Color;
import io.anuke.arc.graphics.g2d.Draw;
import io.anuke.arc.graphics.g2d.TextureRegion;
import io.anuke.arc.math.Mathf;
import io.anuke.arc.math.geom.Geometry;
import io.anuke.arc.math.geom.Vector2;
import io.anuke.annotations.Annotations.*;
import io.anuke.arc.*;
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.util.*;
import io.anuke.mindustry.content.Blocks;
import io.anuke.mindustry.content.Fx;
import io.anuke.mindustry.content.*;
import io.anuke.mindustry.entities.*;
import io.anuke.mindustry.entities.effect.ScorchDecal;
import io.anuke.mindustry.entities.impl.DestructibleEntity;
import io.anuke.mindustry.entities.effect.*;
import io.anuke.mindustry.entities.impl.*;
import io.anuke.mindustry.entities.traits.*;
import io.anuke.mindustry.entities.units.Statuses;
import io.anuke.mindustry.game.EventType.UnitDestroyEvent;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.game.Teams.TeamData;
import io.anuke.mindustry.entities.units.*;
import io.anuke.mindustry.game.EventType.*;
import io.anuke.mindustry.game.*;
import io.anuke.mindustry.game.Teams.*;
import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.net.Interpolator;
import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.net.*;
import io.anuke.mindustry.type.*;
import io.anuke.mindustry.world.Pos;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.Floor;
import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.blocks.*;
import java.io.*;
@@ -50,7 +45,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
protected final Statuses status = new Statuses();
protected final ItemStack item = new ItemStack(content.item(0), 0);
protected Team team = Team.blue;
protected Team team = Team.sharded;
protected float drownTime, hitTime;
@Override
@@ -379,6 +374,40 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
Draw.color(Color.BLACK, team.color, healthf() + Mathf.absin(Time.time(), Math.max(healthf() * 5f, 1f), 1f - healthf()));
Draw.rect(getPowerCellRegion(), x, y, rotation - 90);
Draw.color();
drawBackItems(item.amount > 0 ? 1f : 0f, false);
}
public void drawBackItems(float itemtime, boolean number){
//draw back items
if(itemtime > 0.01f && item.item != null){
float backTrns = 5f;
float size = (itemSize + Mathf.absin(Time.time(), 5f, 1f)) * itemtime;
Draw.mixcol(Pal.accent, Mathf.absin(Time.time(), 5f, 0.5f));
Draw.rect(item.item.icon(Item.Icon.large),
x + Angles.trnsx(rotation + 180f, backTrns),
y + Angles.trnsy(rotation + 180f, backTrns),
size, size, rotation);
Draw.mixcol();
Lines.stroke(1f, Pal.accent);
Lines.circle(
x + Angles.trnsx(rotation + 180f, backTrns),
y + Angles.trnsy(rotation + 180f, backTrns),
(3f + Mathf.absin(Time.time(), 5f, 1f)) * itemtime);
if(number){
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
);
}
}
Draw.reset();
}
public TextureRegion getPowerCellRegion(){

View File

@@ -24,6 +24,7 @@ public enum Gamemode{
rules.unitDrops = true;
rules.waves = false;
rules.attackMode = true;
rules.waves = true;
}, map -> map.teams.contains(waveTeam.ordinal())),
pvp(rules -> {
rules.pvp = true;

View File

@@ -1,6 +1,7 @@
package io.anuke.mindustry.game;
import io.anuke.annotations.Annotations.*;
import io.anuke.arc.*;
import io.anuke.arc.audio.*;
import io.anuke.arc.math.*;
import io.anuke.arc.util.*;
@@ -9,24 +10,29 @@ import io.anuke.arc.util.*;
public class MusicControl{
private static final float finTime = 80f, foutTime = 80f;
private @Nullable Music current;
private float fade;
public void play(@Nullable Music music){
if(current != null){
current.setVolume(fade * Core.settings.getInt("musicvol") / 100f);
}
if(current == null && music != null){
current = music;
current.setLooping(true);
current.setVolume(0f);
current.setVolume(fade = 0f);
current.play();
}else if(current == music && music != null){
current.setVolume(Mathf.clamp(current.getVolume() + Time.delta()/finTime));
fade = Mathf.clamp(fade + Time.delta()/finTime);
}else if(current != null){
current.setVolume(Mathf.clamp(current.getVolume() - Time.delta()/foutTime));
fade = Mathf.clamp(fade - Time.delta()/foutTime);
if(current.getVolume() <= 0.01f){
if(fade <= 0.01f){
current.stop();
current = null;
if(music != null){
current = music;
current.setVolume(0f);
current.setVolume(fade = 0f);
current.setLooping(true);
current.play();
}

View File

@@ -68,7 +68,7 @@ public class Rules{
/** Whether the tutorial is enabled. False by default.*/
public boolean tutorial = false;
/** Starting items put in cores */
public Array<ItemStack> loadout = Array.with(ItemStack.with(Items.copper, 200));
public Array<ItemStack> loadout = Array.with(ItemStack.with(Items.copper, 100));
/** Copies this ruleset exactly. Not very efficient at all, do not use often. */
public Rules copy(){

View File

@@ -2,14 +2,15 @@ package io.anuke.mindustry.game;
import io.anuke.arc.Core;
import io.anuke.arc.graphics.Color;
import io.anuke.mindustry.graphics.*;
public enum Team{
none(Color.valueOf("4d4e58")),
blue(Color.valueOf("4169e1")),
red(Color.valueOf("e84737")),
green(Color.valueOf("1dc645")),
purple(Color.valueOf("ba5bd9")),
orange(Color.valueOf("e8c66a"));
derelict(Color.valueOf("4d4e58")),
sharded(Pal.accent),
crux(Color.valueOf("e82d2d")),
green(Color.valueOf("4dd98b")),
purple(Color.valueOf("9a4bdf")),
blue(Color.ROYAL.cpy());
public final static Team[] all = values();
public final Color color;

View File

@@ -1,11 +1,46 @@
package io.anuke.mindustry.graphics;
import io.anuke.arc.Core;
import io.anuke.arc.*;
import io.anuke.arc.graphics.*;
import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.math.Mathf;
import io.anuke.arc.util.Tmp;
import io.anuke.arc.math.*;
import io.anuke.arc.util.*;
public class Shapes{
public class Drawf{
public static void dashCircle(float x, float y, float rad, Color color){
Lines.stroke(3f, Pal.gray);
Lines.dashCircle(x, y, rad);
Lines.stroke(1f, color);
Lines.dashCircle(x, y, rad);
Draw.reset();
}
public static void circles(float x, float y, float rad){
circles(x, y, rad, Pal.accent);
}
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.stroke(1f, color);
Lines.poly(x, y, vertices, rad);
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;
Tmp.v1.set(x2, y2).sub(x, y).limit(length);
float vx = Tmp.v1.x + x, vy = Tmp.v1.y + y;
Draw.color(Pal.gray);
Fill.poly(vx, vy, 3, radius + space, angle);
Draw.color(Pal.accent);
Fill.poly(vx, vy, 3, radius, angle);
Draw.color();
}
public static void laser(TextureRegion line, TextureRegion edge, float x, float y, float x2, float y2, float scale){
laser(line, edge, x, y, x2, y2, Mathf.angle(x2 - x, y2 - y), scale);

View File

@@ -105,7 +105,7 @@ public class OverlayRenderer{
Draw.reset();
//draw selected block bars and info
//draw selected block
if(input.block == null && !Core.scene.hasMouse()){
Vector2 vec = Core.input.mouseWorld(input.getMouseX(), input.getMouseY());
Tile tile = world.ltileWorld(vec.x, vec.y);
@@ -115,6 +115,7 @@ public class OverlayRenderer{
}
}
//draw selection overlay when dropping item
if(input.isDroppingItem()){
Vector2 v = Core.input.mouseWorld(input.getMouseX(), input.getMouseY());
float size = 8;
@@ -125,9 +126,12 @@ public class OverlayRenderer{
Tile tile = world.ltileWorld(v.x, v.y);
if(tile != null && tile.interactable(player.getTeam()) && tile.block().acceptStack(player.item().item, player.item().amount, tile, player) > 0){
Draw.color(Pal.place);
Lines.square(tile.drawx(), tile.drawy(), tile.block().size * tilesize / 2f + 1 + Mathf.absin(Time.time(), 5f, 1f));
Draw.color();
Lines.stroke(3f, Pal.gray);
Lines.square(tile.drawx(), tile.drawy(), tile.block().size * tilesize / 2f + 3 + Mathf.absin(Time.time(), 5f, 1f));
Lines.stroke(1f, Pal.place);
Lines.square(tile.drawx(), tile.drawy(), tile.block().size * tilesize / 2f + 2 + Mathf.absin(Time.time(), 5f, 1f));
Draw.reset();
}
}
}

View File

@@ -1,22 +1,19 @@
package io.anuke.mindustry.input;
import io.anuke.arc.Core;
import io.anuke.arc.Graphics.Cursor;
import io.anuke.arc.Graphics.Cursor.SystemCursor;
import io.anuke.arc.graphics.g2d.Draw;
import io.anuke.arc.graphics.g2d.Lines;
import io.anuke.arc.math.Mathf;
import io.anuke.arc.math.geom.Geometry;
import io.anuke.arc.math.geom.Point2;
import io.anuke.arc.scene.ui.TextField;
import io.anuke.mindustry.content.Blocks;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.input.PlaceUtils.NormalizeDrawResult;
import io.anuke.mindustry.input.PlaceUtils.NormalizeResult;
import io.anuke.arc.*;
import io.anuke.arc.Graphics.*;
import io.anuke.arc.Graphics.Cursor.*;
import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.math.*;
import io.anuke.arc.math.geom.*;
import io.anuke.arc.scene.ui.*;
import io.anuke.arc.util.*;
import io.anuke.mindustry.content.*;
import io.anuke.mindustry.core.GameState.*;
import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.input.PlaceUtils.*;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.*;
import static io.anuke.arc.Core.scene;
import static io.anuke.mindustry.Vars.*;
@@ -41,6 +38,7 @@ public class DesktopInput extends InputHandler{
block.getPlaceDraw(placeDraw, rotation, prevX, prevY, prevRotation);
Draw.color();
Draw.mixcol(Pal.accent, 0.12f + Mathf.absin(Time.time(), 8f, 0.35f));
Draw.rect(placeDraw.region, x * tilesize + block.offset(), y * tilesize + block.offset(),
placeDraw.region.getWidth() * selectScale * Draw.scl * placeDraw.scalex,
placeDraw.region.getHeight() * selectScale * Draw.scl * placeDraw.scaley,
@@ -54,6 +52,7 @@ public class DesktopInput extends InputHandler{
Draw.rect("block-select", x * tilesize + block.offset() + offset * p.x, y * tilesize + block.offset() + offset * p.y, i * 90);
}
Draw.color();
Draw.mixcol();
}else{
Draw.color(Pal.removeBack);
Lines.square(x * tilesize + block.offset(), y * tilesize + block.offset() - 1, block.size * tilesize / 2f - 1);

View File

@@ -215,13 +215,13 @@ public class MobileInput extends InputHandler implements GestureListener{
float offset = request.block.offset();
TextureRegion region = placeDraw.region;
Draw.mixcol(Pal.accent, Mathf.clamp((1f - request.scale) / 0.5f));
Draw.mixcol(Pal.accent, Mathf.clamp((1f - request.scale) / 0.5f + 0.12f + Mathf.absin(Time.time(), 8f, 0.35f)));
Draw.tint(Color.WHITE, Pal.breakInvalid, request.redness);
Draw.rect(region, tile.worldx() + offset, tile.worldy() + offset,
region.getWidth() * request.scale * Draw.scl * placeDraw.scalex,
region.getHeight() * request.scale * Draw.scl * placeDraw.scaley,
request.block.rotate ? placeDraw.rotation * 90 : 0);
region.getWidth() * request.scale * Draw.scl * placeDraw.scalex,
region.getHeight() * request.scale * Draw.scl * placeDraw.scaley,
request.block.rotate ? placeDraw.rotation * 90 : 0);
Draw.mixcol(Pal.accent, 1f);
for(int i = 0; i < 4; i++){

View File

@@ -217,14 +217,14 @@ public class LegacyMapIO{
if(Structs.inBounds(worldx, worldy, pixmap.getWidth(), pixmap.getHeight())){
Tile write = tiles[worldx][worldy];
write.setBlock(BlockPart.get(dx - 1, dy - 1));
write.setTeam(Team.blue);
write.setTeam(Team.sharded);
}
}
}
//actual core parts
tile.setBlock(Blocks.coreShard);
tile.setTeam(Team.blue);
tile.setTeam(Team.sharded);
}
}
}

View File

@@ -112,9 +112,9 @@ public class MapIO{
@Override
public Tile create(int x, int y, int floorID, int overlayID, int wallID){
if(overlayID != 0){
floors.drawPixel(x, floors.getHeight() - 1 - y, colorFor(Blocks.air, Blocks.air, content.block(overlayID), Team.none));
floors.drawPixel(x, floors.getHeight() - 1 - y, colorFor(Blocks.air, Blocks.air, content.block(overlayID), Team.derelict));
}else{
floors.drawPixel(x, floors.getHeight() - 1 - y, colorFor(content.block(floorID), Blocks.air, Blocks.air, Team.none));
floors.drawPixel(x, floors.getHeight() - 1 - y, colorFor(content.block(floorID), Blocks.air, Blocks.air, Team.derelict));
}
if(content.block(overlayID) == Blocks.spawn){
map.spawns ++;

View File

@@ -210,13 +210,7 @@ public class Maps implements Disposable{
}}
);
int index = 0;
for(Block block : new Block[]{Blocks.oreCopper, Blocks.oreLead, Blocks.oreCoal, Blocks.oreTitanium, Blocks.oreThorium}){
OreFilter filter = new OreFilter();
filter.threshold += index ++ * 0.019f;
filter.ore = block;
filters.add(filter);
}
addDefaultOres(filters);
return filters;
}else{
@@ -224,6 +218,17 @@ public class Maps implements Disposable{
}
}
public void addDefaultOres(Array<GenerateFilter> filters){
int index = 0;
for(Block block : new Block[]{Blocks.oreCopper, Blocks.oreLead, Blocks.oreCoal, Blocks.oreTitanium, Blocks.oreThorium}){
OreFilter filter = new OreFilter();
filter.threshold += index ++ * 0.019f;
filter.scl += index/2f;
filter.ore = block;
filters.add(filter);
}
}
public String writeWaves(Array<SpawnGroup> groups){
if(groups == null){
return "[]";

View File

@@ -8,7 +8,7 @@ import static io.anuke.mindustry.maps.filters.FilterOption.BlockOption;
import static io.anuke.mindustry.maps.filters.FilterOption.oresOnly;
public class OreFilter extends GenerateFilter{
public float scl = 40, threshold = 0.75f, octaves = 2f, falloff = 0.4f;
public float scl = 23, threshold = 0.811f, octaves = 2f, falloff = 0.3f;
public Block ore = Blocks.oreCopper;
{

View File

@@ -0,0 +1,57 @@
package io.anuke.mindustry.maps.filters;
import io.anuke.arc.collection.*;
import io.anuke.arc.math.*;
import io.anuke.mindustry.*;
import io.anuke.mindustry.content.*;
import io.anuke.mindustry.maps.filters.FilterOption.*;
import io.anuke.mindustry.world.*;
public class OreMedianFilter extends GenerateFilter{
public float radius = 2;
public float percentile = 0.5f;
private IntArray blocks = new IntArray();
{
buffered = true;
options(
new SliderOption("radius", () -> radius, f -> radius = f, 1f, 12f),
new SliderOption("percentile", () -> percentile, f -> percentile = f, 0f, 1f)
);
}
@Override
public void apply(){
if(in.ore == Blocks.spawn) return;
int cx = (in.x / 2) * 2;
int cy = (in.y / 2) * 2;
if(in.ore != Blocks.air){
if(!(in.tile(cx + 1, cy).overlay() == in.ore && in.tile(cx, cy).overlay() == in.ore && in.tile(cx + 1, cy + 1).overlay() == in.ore && in.tile(cx, cy + 1).overlay() == in.ore &&
!in.tile(cx + 1, cy).block().isStatic() && !in.tile(cx, cy).block().isStatic() && !in.tile(cx + 1, cy + 1).block().isStatic() && !in.tile(cx, cy + 1).block().isStatic())){
in.ore = Blocks.air;
}
}
int rad = (int)radius;
blocks.clear();
for(int x = -rad; x <= rad; x++){
for(int y = -rad; y <= rad; y++){
if(Mathf.dst2(x, y) > rad*rad) continue;
Tile tile = in.tile(in.x + x, in.y + y);
if(tile.overlay() != Blocks.spawn)
blocks.add(tile.overlay().id);
}
}
blocks.sort();
int index = Math.min((int)(blocks.size * percentile), blocks.size - 1);
int overlay = blocks.get(index);
in.ore = Vars.content.block(overlay);
}
}

View File

@@ -4,7 +4,6 @@ import io.anuke.arc.collection.*;
import io.anuke.arc.math.*;
import io.anuke.arc.math.geom.*;
import io.anuke.arc.util.*;
import io.anuke.arc.util.noise.*;
import io.anuke.mindustry.content.*;
import io.anuke.mindustry.io.*;
import io.anuke.mindustry.maps.*;
@@ -19,8 +18,6 @@ public class MapGenerator extends Generator{
private Map map;
private String mapName;
private Array<Decoration> decorations = Array.with(new Decoration(Blocks.stone, Blocks.rock, 0.003f));
/** How much the landscape is randomly distorted. */
public float distortion = 3;
/**
* The amount of final enemy spawns used. -1 to use everything in the map.
* This amount of enemy spawns is selected randomly from the map.
@@ -43,17 +40,6 @@ public class MapGenerator extends Generator{
return this;
}
public MapGenerator dist(float distortion){
this.distortion = distortion;
return this;
}
public MapGenerator dist(float distortion, boolean floor){
this.distortion = distortion;
this.distortFloor = floor;
return this;
}
{
decor(new Decoration(Blocks.snow, Blocks.snowrock, 0.01), new Decoration(Blocks.ignarock, Blocks.pebbles, 0.03f));
}
@@ -100,28 +86,9 @@ public class MapGenerator extends Generator{
}
}
Simplex simplex = new Simplex(Mathf.random(99999));
for(int x = 0; x < width; x++){
for(int y = 0; y < height; y++){
final double scl = 10;
Tile tile = tiles[x][y];
int newX = Mathf.clamp((int)(simplex.octaveNoise2D(1, 1, 1.0 / scl, x, y) * distortion + x), 0, width - 1);
int newY = Mathf.clamp((int)(simplex.octaveNoise2D(1, 1, 1.0 / scl, x + 9999, y + 9999) * distortion + y), 0, height - 1);
if(((tile.block() instanceof StaticWall
&& tiles[newX][newY].block() instanceof StaticWall)
|| (tile.block() == Blocks.air && !tiles[newX][newY].block().synthetic())
|| (tiles[newX][newY].block() == Blocks.air && tile.block() instanceof StaticWall))){
tile.setBlock(tiles[newX][newY].block());
}
if(distortFloor){
tile.setFloor(tiles[newX][newY].floor());
if(tiles[newX][newY].overlay() != Blocks.spawn && tile.overlay() != Blocks.spawn){
tile.setOverlay(tiles[newX][newY].overlay());
}
}
for(Decoration decor : decorations){
if(x > 0 && y > 0 && (tiles[x - 1][y].block() == decor.wall || tiles[x][y - 1].block() == decor.wall)){

View File

@@ -23,6 +23,14 @@ public class ItemStack implements Comparable<ItemStack>{
return other != null && other.item == item && other.amount == amount;
}
public static ItemStack[] mult(ItemStack[] stacks, int amount){
ItemStack[] copy = new ItemStack[stacks.length];
for(int i = 0; i < copy.length; i++){
copy[i] = new ItemStack(stacks[i].item, stacks[i].amount * amount);
}
return copy;
}
public static ItemStack[] with(Object... items){
ItemStack[] stacks = new ItemStack[items.length / 2];
for(int i = 0; i < items.length; i += 2){

View File

@@ -3,6 +3,7 @@ package io.anuke.mindustry.type;
import io.anuke.arc.*;
import io.anuke.arc.collection.*;
import io.anuke.arc.function.*;
import io.anuke.arc.graphics.*;
import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.scene.ui.layout.*;
import io.anuke.arc.util.*;
@@ -27,6 +28,7 @@ public class Zone extends UnlockableContent{
public int configureWave = 15;
public int launchPeriod = 10;
public Loadout loadout = Loadouts.basicShard;
public Texture preview;
protected ItemStack[] baseLaunchCost = {};
protected Array<ItemStack> startingItems = new Array<>();
@@ -152,6 +154,13 @@ public class Zone extends UnlockableContent{
}
}
@Override
public void load(){
if(Core.files.internal("zones/" + name + ".png").exists()){
preview = new Texture(Core.files.internal("zones/" + name + ".png"));
}
}
@Override
public boolean alwaysUnlocked(){
return alwaysUnlocked;

View File

@@ -71,7 +71,7 @@ public class Bar extends Element{
Draw.color();
BitmapFont font = Core.scene.skin.getFont("default-font");
BitmapFont font = Core.scene.skin.getFont("default");
GlyphLayout lay = Pools.obtain(GlyphLayout.class, GlyphLayout::new);
lay.setText(font, name);

View File

@@ -17,6 +17,13 @@ public class ItemImage extends Stack{
add(t);
}
public ItemImage(TextureRegion region){
Table t = new Table().left().bottom();
add(new Image(region));
add(t);
}
public ItemImage(ItemStack stack){
add(new Image(stack.item.icon(Icon.large)));

View File

@@ -70,7 +70,7 @@ public class CustomRulesDialog extends FloatingDialog{
() -> rules.loadout,
() -> {
rules.loadout.clear();
rules.loadout.add(new ItemStack(Items.copper, 200));
rules.loadout.add(new ItemStack(Items.copper, 100));
},
() -> {}, () -> {},
item -> item.type == ItemType.material

View File

@@ -10,6 +10,7 @@ import io.anuke.arc.math.geom.*;
import io.anuke.arc.scene.*;
import io.anuke.arc.scene.ui.*;
import io.anuke.arc.scene.ui.layout.*;
import io.anuke.arc.scene.utils.*;
import io.anuke.arc.util.*;
import io.anuke.mindustry.content.*;
import io.anuke.mindustry.core.GameState.*;
@@ -24,7 +25,7 @@ import io.anuke.mindustry.ui.TreeLayout.*;
import static io.anuke.mindustry.Vars.*;
public class DeployDialog extends FloatingDialog{
private final float nodeSize = Unit.dp.scl(210f);
private final float nodeSize = Unit.dp.scl(230f);
private ObjectSet<ZoneNode> nodes = new ObjectSet<>();
private ZoneInfoDialog info = new ZoneInfoDialog();
private Rectangle bounds = new Rectangle();
@@ -35,7 +36,8 @@ public class DeployDialog extends FloatingDialog{
ZoneNode root = new ZoneNode(Zones.groundZero, null);
TreeLayout layout = new TreeLayout();
layout.gapBetweenLevels = layout.gapBetweenNodes = Unit.dp.scl(50f);
layout.gapBetweenLevels = layout.gapBetweenNodes = Unit.dp.scl(60f);
layout.gapBetweenNodes = Unit.dp.scl(120f);
layout.layout(root);
bounds.set(layout.getBounds());
bounds.y += nodeSize*0.4f;
@@ -78,10 +80,18 @@ public class DeployDialog extends FloatingDialog{
}}.setScaling(Scaling.fit));
if(control.saves.getZoneSlot() != null){
float size = 230f;
stack.add(new Table(t -> {
SaveSlot slot = control.saves.getZoneSlot();
TextButton button = t.addButton(Core.bundle.format("resume", slot.getZone().localizedName()), () -> {
Stack sub = new Stack();
if(control.saves.getZoneSlot().getZone() != null){
sub.add(new Table(f -> f.margin(4f).add(new Image(control.saves.getZoneSlot().getZone().preview).setScaling(Scaling.fit)).color(Color.DARK_GRAY).grow()));
}
TextButton button = Elements.newButton(Core.bundle.format("resume", slot.getZone().localizedName()), "square", () -> {
hide();
ui.loadAnd(() -> {
@@ -95,7 +105,11 @@ public class DeployDialog extends FloatingDialog{
show();
}
});
}).size(230f).get();
});
sub.add(button);
t.add(sub).size(size);
String color = "[lightgray]";
@@ -149,13 +163,12 @@ public class DeployDialog extends FloatingDialog{
drawDefaultBackground(x, y);
}
void buildButton(Zone zone, TextButton button){
void buildButton(Zone zone, Button button){
button.setDisabled(() -> hidden(zone));
button.clicked(() -> info.show(zone));
if(zone.unlocked()){
button.addImage("icon-terrain").size(iconsize).padRight(3);
button.labelWrap(zone.localizedName()).width(140).growX();
button.labelWrap(zone.localizedName()).style("outline").width(140).growX().get().setAlignment(Align.center);
}else{
button.addImage("icon-locked");
button.row();
@@ -170,14 +183,26 @@ public class DeployDialog extends FloatingDialog{
{
for(ZoneNode node : nodes){
TextButton button = new TextButton("", "node");
button.setSize(node.width, node.height);
button.update(() -> {
button.setPosition(node.x + panX + width / 2f, node.y + panY + height / 2f, Align.center);
});
button.clearChildren();
Stack stack = new Stack();
Tmp.v1.set(node.width, node.height);
if(node.zone.preview != null){
Tmp.v1.set(Scaling.fit.apply(node.zone.preview.getWidth(), node.zone.preview.getHeight(), node.width, node.height));
}
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.update(() -> stack.setPosition(node.x + panX + width / 2f, node.y + panY + height / 2f, Align.center));
Button button = new Button("square");
buildButton(node.zone, button);
addChild(button);
stack.add(button);
addChild(stack);
}
dragged((x, y) -> {
@@ -206,7 +231,7 @@ public class DeployDialog extends FloatingDialog{
for(ZoneNode node : nodes){
for(ZoneNode child : node.allChildren){
Lines.stroke(Unit.dp.scl(3f), node.zone.locked() || child.zone.locked() ? Pal.gray : Pal.accent);
Lines.stroke(Unit.dp.scl(4f), node.zone.locked() || child.zone.locked() ? Pal.gray : Pal.gray);
Lines.line(node.x + offsetX, node.y + offsetY, child.x + offsetX, child.y + offsetY);
}
}
@@ -225,7 +250,7 @@ public class DeployDialog extends FloatingDialog{
this.zone = zone;
this.parent = parent;
this.width = this.height = nodeSize;
this.height /= 2f;
//this.height /= 2f;
nodes.add(this);
arr.selectFrom(content.zones(), other -> other.zoneRequirements.length > 0 && other.zoneRequirements[0].zone == zone);

View File

@@ -190,7 +190,7 @@ public class FileChooser extends FloatingDialog{
GlyphLayout layout = Pools.obtain(GlyphLayout.class, GlyphLayout::new);
layout.setText(Core.scene.skin.getFont("default-font"), navigation.getText());
layout.setText(Core.scene.skin.getFont("default"), navigation.getText());
if(layout.width < navigation.getWidth()){
navigation.setCursorPosition(0);

View File

@@ -75,7 +75,15 @@ public class MapsDialog extends FloatingDialog{
map = world.maps.makeLegacyMap(file);
}
String name = map.tags.get("name");
//when you attempt to import a save, it will have no name, so generate one
String name = map.tags.getOr("name", () -> {
String result = "unknown";
int number = 0;
while(world.maps.byName(result + number++) != null);
return result + number;
});
//this will never actually get called, but it remains just in case
if(name == null){
ui.showError("$editor.errorname");
return;

View File

@@ -1,22 +1,22 @@
package io.anuke.mindustry.ui.dialogs;
import io.anuke.arc.Core;
import io.anuke.arc.collection.ObjectMap;
import io.anuke.arc.files.FileHandle;
import io.anuke.arc.function.Consumer;
import io.anuke.arc.input.KeyCode;
import io.anuke.arc.scene.Element;
import io.anuke.arc.scene.event.InputEvent;
import io.anuke.arc.scene.event.InputListener;
import io.anuke.arc.*;
import io.anuke.arc.collection.*;
import io.anuke.arc.files.*;
import io.anuke.arc.function.*;
import io.anuke.arc.input.*;
import io.anuke.arc.scene.*;
import io.anuke.arc.scene.event.*;
import io.anuke.arc.scene.ui.*;
import io.anuke.arc.scene.ui.SettingsDialog.SettingsTable.Setting;
import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.arc.scene.ui.SettingsDialog.SettingsTable.*;
import io.anuke.arc.scene.ui.layout.*;
import io.anuke.arc.util.*;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.core.Platform;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.core.GameState.*;
import io.anuke.mindustry.core.*;
import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.net.Net;
import static io.anuke.arc.Core.bundle;
import static io.anuke.mindustry.Vars.*;
public class SettingsMenuDialog extends SettingsDialog{
@@ -127,9 +127,8 @@ public class SettingsMenuDialog extends SettingsDialog{
}
void addSettings(){
//TODO add when sound works again
//sound.volumePrefs();
sound.add("[LIGHT_GRAY]there is no sound implemented in v4 yet");
sound.sliderPref("musicvol", bundle.get("setting.musicvol.name", "Music Volume"), 100, 0, 100, 1, i -> i + "%");
sound.sliderPref("sfxvol", bundle.get("setting.sfxvol.name", "SFX Volume"), 100, 0, 100, 1, i -> i + "%");
game.screenshakePref();
if(mobile){

View File

@@ -50,7 +50,7 @@ public class ChatFragment extends Table{
super();
setFillParent(true);
font = scene.skin.getFont("default-font");
font = scene.skin.getFont("default");
visible(() -> {
if(!Net.active() && messages.size > 0){
@@ -106,7 +106,7 @@ public class ChatFragment extends Table{
chatfield = new TextField("", new TextField.TextFieldStyle(scene.skin.get(TextField.TextFieldStyle.class)));
chatfield.setFilter((field, c) -> field.getText().length() < Vars.maxTextLength);
chatfield.getStyle().background = null;
chatfield.getStyle().font = scene.skin.getFont("default-font-chat");
chatfield.getStyle().font = scene.skin.getFont("chat");
chatfield.getStyle().fontColor = Color.WHITE;
chatfield.setStyle(chatfield.getStyle());

View File

@@ -1,6 +1,7 @@
package io.anuke.mindustry.ui.fragments;
import io.anuke.arc.scene.Group;
import io.anuke.arc.scene.actions.*;
import io.anuke.arc.scene.event.Touchable;
import io.anuke.arc.scene.ui.Label;
import io.anuke.arc.scene.ui.TextButton;
@@ -42,13 +43,16 @@ public class LoadingFragment extends Fragment{
}
public void show(String text){
table.touchable(Touchable.enabled);
table.<Label>find("namelabel").setText(text);
table.visible(true);
table.getColor().a = 1f;
table.toFront();
}
public void hide(){
table.visible(false);
button.visible(false);
table.toFront();
table.touchable(Touchable.disabled);
table.actions(Actions.fadeOut(1f), Actions.visible(false));
}
}

View File

@@ -12,6 +12,7 @@ import io.anuke.arc.graphics.*;
import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.graphics.g2d.TextureAtlas.*;
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.arc.util.pooling.*;
@@ -27,6 +28,7 @@ import io.anuke.mindustry.input.InputHandler.*;
import io.anuke.mindustry.type.*;
import io.anuke.mindustry.ui.*;
import io.anuke.mindustry.world.blocks.*;
import io.anuke.mindustry.world.blocks.power.*;
import io.anuke.mindustry.world.consumers.*;
import io.anuke.mindustry.world.meta.*;
@@ -141,6 +143,10 @@ public class Block extends BlockStorage{
return buildVisibility != invisible;
}
public boolean isStatic(){
return cacheLayer == CacheLayer.walls;
}
public void onProximityRemoved(Tile tile){
if(tile.entity.power != null){
tile.block().powerGraphRemoved(tile);
@@ -228,7 +234,7 @@ public class Block extends BlockStorage{
if(renderer.pixelator.enabled()) return;
Color color = valid ? Pal.accent : Pal.remove;
BitmapFont font = Core.scene.skin.getFont("default-font");
BitmapFont font = Core.scene.skin.getFont("outline");
GlyphLayout layout = Pools.obtain(GlyphLayout.class, GlyphLayout::new);
boolean ints = font.usesIntegerPositions();
font.setUseIntegerPositions(false);
@@ -236,10 +242,13 @@ public class Block extends BlockStorage{
layout.setText(font, text);
font.setColor(color);
float dx = x * tilesize + offset(), dy = y * tilesize + offset() + size * tilesize / 2f + 2;
float dx = x * tilesize + offset(), dy = y * tilesize + offset() + size * tilesize / 2f + 3;
font.draw(text, dx, dy + layout.height + 1, Align.center);
dy -= 1f;
Lines.stroke(2f, Color.DARK_GRAY);
Lines.line(dx - layout.width / 2f - 2f, dy, dx + layout.width / 2f + 1.5f, dy);
Lines.stroke(1f, color);
Lines.line(dx - layout.width / 2f - 2f, dy, dx + layout.width / 2f + 2f, dy);
Lines.line(dx - layout.width / 2f - 2f, dy, dx + layout.width / 2f + 1.5f, dy);
font.setUseIntegerPositions(ints);
font.setColor(Color.WHITE);
@@ -259,7 +268,27 @@ public class Block extends BlockStorage{
}
/** Called after the block is placed by this client. */
@CallSuper
public void playerPlaced(Tile tile){
if((consumesPower && !outputsPower) || (!consumesPower && outputsPower)){
int range = 10;
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)){
tempTiles.add(other);
}
});
tempTiles.sort(Structs.comparingFloat(t -> t.dst2(tile)));
if(!tempTiles.isEmpty()){
Call.linkPowerNodes(null, tempTiles.first(), tile);
}
}
if(outputsPower && !consumesPower){
PowerNode.lastPlaced = tile.pos();
}
}
public void removed(Tile tile){

View File

@@ -299,7 +299,7 @@ public class Tile implements Position, TargetTrait{
}
public boolean interactable(Team team){
return getTeam() == Team.none || team == getTeam();
return getTeam() == Team.derelict || team == getTeam();
}
public Item drop(){

View File

@@ -67,7 +67,7 @@ public class DeflectorWall extends Wall{
}
bullet.updateVelocity();
bullet.resetOwner(entity, Team.none);
bullet.resetOwner(entity, Team.derelict);
bullet.scaleTime(1f);
bullet.supress();

View File

@@ -9,7 +9,7 @@ import io.anuke.arc.util.*;
import io.anuke.mindustry.content.Fx;
import io.anuke.mindustry.entities.Effects;
import io.anuke.mindustry.entities.type.TileEntity;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.meta.*;
@@ -101,9 +101,7 @@ public class MendProjector extends Block{
@Override
public void drawPlace(int x, int y, int rotation, boolean valid){
Draw.color(Pal.accent);
Lines.dashCircle(x * tilesize, y * tilesize, range);
Draw.color();
Drawf.dashCircle(x * tilesize, y * tilesize, range, Pal.accent);
}
@Override
@@ -111,9 +109,7 @@ public class MendProjector extends Block{
MendEntity entity = tile.entity();
float realRange = range + entity.phaseHeat * phaseRangeBoost;
Draw.color(color);
Lines.dashCircle(tile.drawx(), tile.drawy(), realRange);
Draw.color();
Drawf.dashCircle(tile.drawx(), tile.drawy(), realRange, color);
}
@Override

View File

@@ -7,7 +7,7 @@ import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.math.Mathf;
import io.anuke.arc.util.Time;
import io.anuke.mindustry.entities.type.TileEntity;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.meta.*;
@@ -52,9 +52,7 @@ public class OverdriveProjector extends Block{
@Override
public void drawPlace(int x, int y, int rotation, boolean valid){
Draw.color(Pal.accent);
Lines.dashCircle(x * tilesize + offset(), y * tilesize + offset(), range);
Draw.color();
Drawf.dashCircle(x * tilesize + offset(), y * tilesize + offset(), range, Pal.accent);
}
@Override
@@ -114,9 +112,7 @@ public class OverdriveProjector extends Block{
OverdriveEntity entity = tile.entity();
float realRange = range + entity.phaseHeat * phaseRangeBoost;
Draw.color(color);
Lines.dashCircle(tile.drawx(), tile.drawy(), realRange);
Draw.color();
Drawf.dashCircle(tile.drawx(), tile.drawy(), realRange, color);
}
@Override
@@ -128,9 +124,7 @@ public class OverdriveProjector extends Block{
Draw.color(color, phase, entity.phaseHeat);
Draw.alpha(entity.heat * Mathf.absin(Time.time(), 10f, 1f) * 0.5f);
//Draw.blend(Blending.additive);
Draw.rect(topRegion, tile.drawx(), tile.drawy());
//Draw.blend();
Draw.alpha(1f);
Lines.stroke((2f * f + 0.2f) * entity.heat);
Lines.square(tile.drawx(), tile.drawy(), (1f - f) * 8f);

View File

@@ -16,6 +16,8 @@ import io.anuke.mindustry.world.meta.values.*;
import java.io.*;
import static io.anuke.mindustry.Vars.*;
public class ItemTurret extends CooledTurret{
protected int maxAmmo = 30;
protected ObjectMap<Item, BulletType> ammo = new ObjectMap<>();
@@ -37,6 +39,15 @@ public class ItemTurret extends CooledTurret{
stats.remove(BlockStat.itemCapacity);
stats.add(BlockStat.ammo, new AmmoListValue<>(ammo));
consumes.add(new ConsumeItemFilter(i -> ammo.containsKey(i)){
@Override
public void build(Tile tile, Table table){
MultiReqImage image = new MultiReqImage();
content.items().each(i -> filter.test(i) && (!world.isZone() || data.isUnlocked(i)), item -> image.add(new ReqImage(new ItemImage(item.icon(Item.Icon.large)),
() -> tile.entity != null && !((ItemTurretEntity)tile.entity).ammo.isEmpty() && ((ItemEntry)tile.<ItemTurretEntity>entity().ammo.peek()).item == item)));
table.add(image).size(8 * 4);
}
@Override
public boolean valid(TileEntity entity){
//valid when there's any ammo in the turret

View File

@@ -7,7 +7,6 @@ import io.anuke.mindustry.entities.effect.*;
import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.type.*;
import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.blocks.defense.turrets.ItemTurret.*;
import io.anuke.mindustry.world.consumers.*;
import io.anuke.mindustry.world.meta.*;
import io.anuke.mindustry.world.meta.values.*;

View File

@@ -18,8 +18,7 @@ import io.anuke.mindustry.entities.bullet.Bullet;
import io.anuke.mindustry.entities.bullet.BulletType;
import io.anuke.mindustry.entities.traits.TargetTrait;
import io.anuke.mindustry.entities.type.TileEntity;
import io.anuke.mindustry.graphics.Layer;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.meta.*;
@@ -130,16 +129,12 @@ public abstract class Turret extends Block{
@Override
public void drawSelect(Tile tile){
Draw.color(tile.getTeam().color);
Lines.dashCircle(tile.drawx(), tile.drawy(), range);
Draw.reset();
Drawf.dashCircle(tile.drawx(), tile.drawy(), range, tile.getTeam().color);
}
@Override
public void drawPlace(int x, int y, int rotation, boolean valid){
Lines.stroke(1f, Pal.placing);
Lines.dashCircle(x * tilesize + offset(), y * tilesize + offset(), range);
Draw.color();
Drawf.dashCircle(x * tilesize + offset(), y * tilesize + offset(), range, Pal.placing);
}
@Override

View File

@@ -1,28 +1,22 @@
package io.anuke.mindustry.world.blocks.distribution;
import io.anuke.annotations.Annotations.Loc;
import io.anuke.annotations.Annotations.Remote;
import io.anuke.arc.Core;
import io.anuke.arc.collection.OrderedSet;
import io.anuke.annotations.Annotations.*;
import io.anuke.arc.*;
import io.anuke.arc.collection.*;
import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.math.Angles;
import io.anuke.arc.math.Mathf;
import io.anuke.arc.util.Time;
import io.anuke.arc.util.pooling.Pool.Poolable;
import io.anuke.arc.util.pooling.Pools;
import io.anuke.mindustry.content.Bullets;
import io.anuke.mindustry.content.Fx;
import io.anuke.mindustry.entities.Effects;
import io.anuke.mindustry.entities.Effects.Effect;
import io.anuke.mindustry.entities.bullet.Bullet;
import io.anuke.mindustry.entities.type.Player;
import io.anuke.mindustry.entities.type.TileEntity;
import io.anuke.mindustry.gen.Call;
import io.anuke.mindustry.graphics.Layer;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile;
import io.anuke.arc.math.*;
import io.anuke.arc.util.*;
import io.anuke.arc.util.pooling.Pool.*;
import io.anuke.arc.util.pooling.*;
import io.anuke.mindustry.content.*;
import io.anuke.mindustry.entities.*;
import io.anuke.mindustry.entities.Effects.*;
import io.anuke.mindustry.entities.bullet.*;
import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.type.*;
import io.anuke.mindustry.world.*;
import java.io.*;
@@ -167,9 +161,7 @@ public class MassDriver extends Block{
@Override
public void drawPlace(int x, int y, int rotation, boolean valid){
Draw.color(Pal.accent);
Lines.dashCircle(x * tilesize, y*tilesize, range);
Draw.color();
Drawf.dashCircle(x * tilesize, y*tilesize, range, Pal.accent);
}
@Override
@@ -178,21 +170,17 @@ public class MassDriver extends Block{
Draw.color(Pal.accent);
Lines.stroke(1f);
Lines.poly(tile.drawx(), tile.drawy(), 20, (tile.block().size / 2f + 1) * tilesize + sin);
Drawf.circles(tile.drawx(), tile.drawy(), (tile.block().size / 2f + 1) * tilesize + sin - 2f, Pal.accent);
MassDriverEntity entity = tile.entity();
if(linkValid(tile)){
Tile target = world.tile(entity.link);
Draw.color(Pal.place);
Lines.poly(target.drawx(), target.drawy(), 20, (target.block().size / 2f + 1) * tilesize + sin);
Draw.reset();
Drawf.circles(target.drawx(), target.drawy(), (target.block().size / 2f + 1) * tilesize + sin - 2f, Pal.place);
Drawf.arrow(tile.drawx(), tile.drawy(), target.drawx(), target.drawy(), size * tilesize + sin, 4f + sin);
}
Draw.color(Pal.accent);
Lines.dashCircle(tile.drawx(), tile.drawy(), range);
Draw.color();
Drawf.dashCircle(tile.drawx(), tile.drawy(), range, Pal.accent);
}
@Override

View File

@@ -30,7 +30,7 @@ public class NuclearReactor extends PowerGenerator{
protected Color coolColor = new Color(1, 1, 1, 0f);
protected Color hotColor = Color.valueOf("ff9575a3");
protected int itemDuration = 120; //time to consume 1 fuel
protected float itemDuration = 120; //time to consume 1 fuel
protected float heating = 0.01f; //heating per frame * fullness
protected float smokeThreshold = 0.3f; //threshold at which block starts smoking
protected int explosionRadius = 40;

View File

@@ -1,31 +1,25 @@
package io.anuke.mindustry.world.blocks.power;
import io.anuke.annotations.Annotations.Loc;
import io.anuke.annotations.Annotations.Remote;
import io.anuke.arc.Core;
import io.anuke.arc.graphics.Color;
import io.anuke.annotations.Annotations.*;
import io.anuke.arc.*;
import io.anuke.arc.graphics.*;
import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.math.Angles;
import io.anuke.arc.math.Mathf;
import io.anuke.arc.math.geom.Intersector;
import io.anuke.arc.math.geom.Vector2;
import io.anuke.arc.math.*;
import io.anuke.arc.math.geom.*;
import io.anuke.arc.util.*;
import io.anuke.mindustry.entities.type.Player;
import io.anuke.mindustry.entities.type.TileEntity;
import io.anuke.mindustry.gen.Call;
import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.ui.Bar;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.PowerBlock;
import io.anuke.mindustry.world.meta.BlockStat;
import io.anuke.mindustry.world.meta.StatUnit;
import io.anuke.mindustry.ui.*;
import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.blocks.*;
import io.anuke.mindustry.world.meta.*;
import static io.anuke.mindustry.Vars.tilesize;
import static io.anuke.mindustry.Vars.world;
import static io.anuke.mindustry.Vars.*;
public class PowerNode extends PowerBlock{
//last distribution block placed
private static int lastPlaced = -1;
public static int lastPlaced = -1;
protected Vector2 t1 = new Vector2(), t2 = new Vector2();
protected TextureRegion laser, laserEnd;
@@ -106,17 +100,20 @@ public class PowerNode extends PowerBlock{
@Override
public void playerPlaced(Tile tile){
Tile before = world.tile(lastPlaced);
if(linkValid(tile, before) && before.block() instanceof PowerNode){
for(Tile near : before.entity.proximity()){
if(near == tile){
lastPlaced = tile.pos();
return;
}
}
if(linkValid(tile, before) && !before.entity.proximity().contains(tile)){
Call.linkPowerNodes(null, tile, before);
}
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);
}
});
lastPlaced = tile.pos();
super.playerPlaced(tile);
}
@Override
@@ -170,7 +167,9 @@ public class PowerNode extends PowerBlock{
Lines.circle(tile.drawx(), tile.drawy(),
tile.block().size * tilesize / 2f + 1f + Mathf.absin(Time.time(), 4f, 1f));
Lines.poly(tile.drawx(), tile.drawy(), 50, laserRange * tilesize);
Drawf.circles(tile.drawx(), tile.drawy(), laserRange * tilesize);
Lines.stroke(1.5f);
for(int x = (int)(tile.x - laserRange - 1); x <= tile.x + laserRange + 1; x++){
for(int y = (int)(tile.y - laserRange - 1); y <= tile.y + laserRange + 1; y++){
@@ -199,7 +198,7 @@ public class PowerNode extends PowerBlock{
public void drawPlace(int x, int y, int rotation, boolean valid){
Lines.stroke(1f);
Draw.color(Pal.placing);
Lines.poly(x * tilesize + offset(), y * tilesize + offset(), 50, laserRange * tilesize);
Drawf.circles(x * tilesize + offset(), y * tilesize + offset(), laserRange * tilesize);
Draw.reset();
}
@@ -223,11 +222,11 @@ public class PowerNode extends PowerBlock{
return tile.entity.power.links.contains(other.pos());
}
protected boolean linkValid(Tile tile, Tile link){
public boolean linkValid(Tile tile, Tile link){
return linkValid(tile, link, true);
}
protected boolean linkValid(Tile tile, Tile link, boolean checkMaxNodes){
public boolean linkValid(Tile tile, Tile link, boolean checkMaxNodes){
if(tile == link || link == 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))){
@@ -257,7 +256,7 @@ public class PowerNode extends PowerBlock{
y2 += t2.y;
Draw.color(Pal.powerLight, Color.WHITE, Mathf.absin(Time.time(), 8f, 0.3f) + 0.2f);
Shapes.laser(laser, laserEnd, x1, y1, x2, y2, 0.6f);
Drawf.laser(laser, laserEnd, x1, y1, x2, y2, 0.6f);
Draw.color();
}

View File

@@ -1,28 +1,22 @@
package io.anuke.mindustry.world.blocks.production;
import io.anuke.arc.Core;
import io.anuke.arc.collection.Array;
import io.anuke.arc.collection.ObjectIntMap;
import io.anuke.arc.graphics.Blending;
import io.anuke.arc.graphics.Color;
import io.anuke.arc.*;
import io.anuke.arc.collection.*;
import io.anuke.arc.graphics.*;
import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.math.Mathf;
import io.anuke.arc.util.Strings;
import io.anuke.arc.util.Time;
import io.anuke.mindustry.content.Fx;
import io.anuke.mindustry.entities.Effects;
import io.anuke.mindustry.entities.Effects.Effect;
import io.anuke.mindustry.entities.type.TileEntity;
import io.anuke.mindustry.graphics.Layer;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.type.ItemType;
import io.anuke.mindustry.ui.Bar;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile;
import io.anuke.arc.math.*;
import io.anuke.arc.util.*;
import io.anuke.mindustry.content.*;
import io.anuke.mindustry.entities.*;
import io.anuke.mindustry.entities.Effects.*;
import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.type.*;
import io.anuke.mindustry.ui.*;
import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.meta.*;
import static io.anuke.mindustry.Vars.content;
import static io.anuke.mindustry.Vars.*;
public class Drill extends Block{
protected final static float hardnessDrillMultiplier = 50f;
@@ -39,6 +33,10 @@ public class Drill extends Block{
/** Speed at which the drill speeds up. */
protected float warmupSpeed = 0.02f;
//return variables for countOre
protected Item returnItem;
protected int returnCount;
/** Whether to draw the item this drill is mining. */
protected boolean drawMineItem = false;
/** Effect played when an item is produced. This is colored. */
@@ -115,7 +113,7 @@ public class Drill extends Block{
if(entity.dominantItem != null && drawMineItem){
Draw.color(entity.dominantItem.color);
Fill.square(tile.drawx(), tile.drawy(), 1f);
Draw.rect("drill-top", tile.drawx(), tile.drawy(), 1f);
Draw.color();
}
}
@@ -130,6 +128,43 @@ public class Drill extends Block{
return tile.entity.items.total() < itemCapacity;
}
@Override
public void drawPlace(int x, int y, int rotation, boolean valid){
Tile tile = world.tile(x, y);
if(tile == null) return;
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;
Draw.mixcol(Color.DARK_GRAY, 1f);
Draw.rect(returnItem.icon(Item.Icon.large), dx, dy - 1);
Draw.reset();
Draw.rect(returnItem.icon(Item.Icon.large), dx, dy);
}else{
Tile to = tile.getLinkedTilesAs(this, tempTiles).find(t -> t.drop() != null && t.drop().hardness > tier);
Item item = to == null ? null : to.drop();
if(item != null){
drawPlaceText(Core.bundle.get("bar.drilltierreq"), x, y, valid);
}
}
}
@Override
public void drawSelect(Tile tile){
DrillEntity entity = tile.entity();
if(entity.dominantItem != null){
float dx = tile.drawx() - size * tilesize/2f, dy = tile.drawy() + size * tilesize/2f;
Draw.mixcol(Color.DARK_GRAY, 1f);
Draw.rect(entity.dominantItem.icon(Item.Icon.large), dx, dy);
Draw.reset();
Draw.rect(entity.dominantItem.icon(Item.Icon.medium), dx, dy);
}
}
@Override
public void setStats(){
super.setStats();
@@ -158,40 +193,50 @@ public class Drill extends Block{
stats.add(BlockStat.boostEffect, liquidBoostIntensity, StatUnit.timesSpeed);
}
void countOre(Tile tile){
returnItem = null;
returnCount = 0;
oreCount.clear();
itemArray.clear();
for(Tile other : tile.getLinkedTilesAs(this, tempTiles)){
if(isValid(other)){
oreCount.getAndIncrement(getDrop(other), 0, 1);
}
}
for(Item item : oreCount.keys()){
itemArray.add(item);
}
itemArray.sort((item1, item2) -> {
int type = Boolean.compare(item1 != Items.sand, item2 != Items.sand);
if(type != 0) return type;
int amounts = Integer.compare(oreCount.get(item1, 0), oreCount.get(item2, 0));
if(amounts != 0) return amounts;
return Integer.compare(item1.id, item2.id);
});
if(itemArray.size == 0){
return;
}
returnItem = itemArray.peek();
returnCount = oreCount.get(itemArray.peek(), 0);
}
@Override
public void update(Tile tile){
DrillEntity entity = tile.entity();
if(entity.dominantItem == null){
oreCount.clear();
itemArray.clear();
for(Tile other : tile.getLinkedTiles(tempTiles)){
if(isValid(other)){
oreCount.getAndIncrement(getDrop(other), 0, 1);
}
}
for(Item item : oreCount.keys()){
itemArray.add(item);
}
itemArray.sort((item1, item2) -> {
int type = Boolean.compare(item1.type == ItemType.material, item2.type == ItemType.material);
if(type != 0) return type;
return Integer.compare(item1.id, item2.id);
});
if(itemArray.size == 0){
return;
}
entity.dominantItem = itemArray.peek();
entity.dominantItems = oreCount.get(itemArray.peek(), 0);
countOre(tile);
if(returnItem == null) return;
entity.dominantItem = returnItem;
entity.dominantItems = returnCount;
}
float totalHardness = entity.dominantItems * entity.dominantItem.hardness;
if(entity.timer.get(timerDump, dumpTime)){
tryDump(tile, entity.dominantItem);
}
@@ -210,7 +255,7 @@ public class Drill extends Block{
speed *= entity.power.satisfaction; // Drill slower when not at full power
}
entity.lastDrillSpeed = (speed * entity.dominantItems * entity.warmup) / (drillTime + hardnessDrillMultiplier * Math.max(totalHardness, 1f) / entity.dominantItems);
entity.lastDrillSpeed = (speed * entity.dominantItems * entity.warmup) / (drillTime + hardnessDrillMultiplier * entity.dominantItem.hardness);
entity.warmup = Mathf.lerpDelta(entity.warmup, speed, warmupSpeed);
entity.progress += entity.delta()
* entity.dominantItems * speed * entity.warmup;
@@ -223,8 +268,7 @@ public class Drill extends Block{
return;
}
if(entity.dominantItems > 0 && entity.progress >= drillTime + hardnessDrillMultiplier * Math.max(totalHardness, 1f) / entity.dominantItems
&& tile.entity.items.total() < itemCapacity){
if(entity.dominantItems > 0 && entity.progress >= drillTime + hardnessDrillMultiplier * entity.dominantItem.hardness && tile.entity.items.total() < itemCapacity){
offloadNear(tile, entity.dominantItem);

View File

@@ -15,14 +15,14 @@ import io.anuke.mindustry.gen.Call;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.graphics.Shaders;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.type.ItemType;
import io.anuke.mindustry.type.*;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.meta.BlockFlag;
import static io.anuke.mindustry.Vars.*;
public class CoreBlock extends StorageBlock{
protected Mech mech = Mechs.starter;
public CoreBlock(String name){
super(name);
@@ -40,10 +40,10 @@ public class CoreBlock extends StorageBlock{
CoreEntity entity = tile.entity();
Effects.effect(Fx.spawn, entity);
entity.progress = 0;
entity.currentUnit = player;
entity.currentUnit.onRespawn(tile);
entity.currentUnit.applyImpulse(0, 8f);
entity.currentUnit = null;
entity.spawnPlayer = player;
entity.spawnPlayer.onRespawn(tile);
entity.spawnPlayer.applyImpulse(0, 8f);
entity.spawnPlayer = null;
}
@Override
@@ -94,8 +94,8 @@ public class CoreBlock extends StorageBlock{
Draw.reset();
}
if(entity.currentUnit != null){
Unit player = entity.currentUnit;
if(entity.spawnPlayer != null){
Unit player = entity.spawnPlayer;
TextureRegion region = player.getIconRegion();
@@ -129,19 +129,19 @@ public class CoreBlock extends StorageBlock{
public void update(Tile tile){
CoreEntity entity = tile.entity();
if(entity.currentUnit != null){
if(!entity.currentUnit.isDead() || !entity.currentUnit.isAdded()){
entity.currentUnit = null;
if(entity.spawnPlayer != null){
if(!entity.spawnPlayer.isDead() || !entity.spawnPlayer.isAdded()){
entity.spawnPlayer = null;
return;
}
entity.currentUnit.set(tile.drawx(), tile.drawy());
entity.spawnPlayer.set(tile.drawx(), tile.drawy());
entity.heat = Mathf.lerpDelta(entity.heat, 1f, 0.1f);
entity.time += entity.delta();
entity.progress += 1f / state.rules.respawnTime * entity.delta();
if(entity.progress >= 1f){
Call.onUnitRespawn(tile, entity.currentUnit);
Call.onUnitRespawn(tile, entity.spawnPlayer);
}
}else{
entity.heat = Mathf.lerpDelta(entity.heat, 0f, 0.1f);
@@ -154,17 +154,17 @@ public class CoreBlock extends StorageBlock{
}
public class CoreEntity extends TileEntity implements SpawnerTrait{
public Player currentUnit;
public Player spawnPlayer;
float progress;
float time;
float heat;
@Override
public void updateSpawning(Player player){
if(!netServer.isWaitingForPlayers() && currentUnit == null){
currentUnit = player;
if(!netServer.isWaitingForPlayers() && spawnPlayer == null){
spawnPlayer = player;
progress = 0f;
player.mech = Mechs.starter;
player.mech = mech;
player.beginRespawning(this);
}
}

View File

@@ -55,9 +55,7 @@ public class RepairPoint extends Block{
@Override
public void drawSelect(Tile tile){
Draw.color(Pal.accent);
Lines.dashCircle(tile.drawx(), tile.drawy(), repairRadius);
Draw.color();
Drawf.dashCircle(tile.drawx(), tile.drawy(), repairRadius, Pal.accent);
}
@Override
@@ -82,7 +80,7 @@ public class RepairPoint extends Block{
float len = 5f;
Draw.color(Color.valueOf("e8ffd7"));
Shapes.laser(laser, laserEnd,
Drawf.laser(laser, laserEnd,
tile.drawx() + Angles.trnsx(ang, len), tile.drawy() + Angles.trnsy(ang, len),
entity.target.x, entity.target.y, entity.strength);
Draw.color();