diff --git a/core/src/io/anuke/mindustry/ai/BlockIndexer.java b/core/src/io/anuke/mindustry/ai/BlockIndexer.java index 6f5e840dcf..892e9db28b 100644 --- a/core/src/io/anuke/mindustry/ai/BlockIndexer.java +++ b/core/src/io/anuke/mindustry/ai/BlockIndexer.java @@ -215,7 +215,7 @@ public class BlockIndexer{ } private void process(Tile tile){ - if(tile.block().flags != null && + if(tile.block().flags.size() > 0 && tile.getTeam() != Team.none){ ObjectSet[] map = getFlagged(tile.getTeam()); diff --git a/core/src/io/anuke/mindustry/ai/Pathfinder.java b/core/src/io/anuke/mindustry/ai/Pathfinder.java index 9a5a66356e..024d83ed4a 100644 --- a/core/src/io/anuke/mindustry/ai/Pathfinder.java +++ b/core/src/io/anuke/mindustry/ai/Pathfinder.java @@ -128,7 +128,7 @@ public class Pathfinder{ for(int y = 0; y < world.height(); y++){ Tile tile = world.tile(x, y); - if(tile.block().flags != null && state.teams.areEnemies(tile.getTeam(), team) + if(state.teams.areEnemies(tile.getTeam(), team) && tile.block().flags.contains(BlockFlag.target)){ path.frontier.addFirst(tile); path.weights[x][y] = 0; diff --git a/core/src/io/anuke/mindustry/content/Blocks.java b/core/src/io/anuke/mindustry/content/Blocks.java index ab1be7272f..ed76b9b9ff 100644 --- a/core/src/io/anuke/mindustry/content/Blocks.java +++ b/core/src/io/anuke/mindustry/content/Blocks.java @@ -23,7 +23,6 @@ import io.anuke.mindustry.world.blocks.storage.LaunchPad; import io.anuke.mindustry.world.blocks.storage.SortedUnloader; import io.anuke.mindustry.world.blocks.storage.Vault; import io.anuke.mindustry.world.blocks.units.MechPad; -import io.anuke.mindustry.world.blocks.units.Reconstructor; import io.anuke.mindustry.world.blocks.units.RepairPoint; import io.anuke.mindustry.world.blocks.units.UnitFactory; @@ -72,7 +71,7 @@ public class Blocks implements ContentList{ //units spiritFactory, phantomFactory, wraithFactory, ghoulFactory, revenantFactory, daggerFactory, titanFactory, - fortressFactory, reconstructor, repairPoint, + fortressFactory, repairPoint, //upgrades alphaPad, deltaPad, tauPad, omegaPad, dartPad, javelinPad, tridentPad, glaivePad; @@ -1344,10 +1343,6 @@ public class Blocks implements ContentList{ repairSpeed = 0.1f; }}; - reconstructor = new Reconstructor("reconstructor"){{ - size = 2; - }}; - //endregion //region upgrades diff --git a/core/src/io/anuke/mindustry/core/Renderer.java b/core/src/io/anuke/mindustry/core/Renderer.java index 9b26d0a006..f8eda41fce 100644 --- a/core/src/io/anuke/mindustry/core/Renderer.java +++ b/core/src/io/anuke/mindustry/core/Renderer.java @@ -71,7 +71,7 @@ public class Renderer implements ApplicationListener{ if(!(effect instanceof GroundEffect)){ EffectEntity entity = Pools.obtain(EffectEntity.class, EffectEntity::new); entity.effect = effect; - entity.color = color; + entity.color.set(color); entity.rotation = rotation; entity.data = data; entity.id++; @@ -83,7 +83,7 @@ public class Renderer implements ApplicationListener{ }else{ GroundEffectEntity entity = Pools.obtain(GroundEffectEntity.class, GroundEffectEntity::new); entity.effect = effect; - entity.color = color; + entity.color.set(color); entity.rotation = rotation; entity.id++; entity.data = data; diff --git a/core/src/io/anuke/mindustry/entities/Player.java b/core/src/io/anuke/mindustry/entities/Player.java index f49da536f1..e0ff36e456 100644 --- a/core/src/io/anuke/mindustry/entities/Player.java +++ b/core/src/io/anuke/mindustry/entities/Player.java @@ -129,11 +129,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ @Override public boolean collidesGrid(int x, int y){ Tile tile = world.tile(x, y); - if(!isFlying()) return true; - if(!mech.flying && tile != null && !tile.block().synthetic() && tile.block().solid){ - return true; - } - return false; + return !isFlying() || (!mech.flying && tile != null && !tile.block().synthetic() && tile.block().solid); } @Override diff --git a/core/src/io/anuke/mindustry/entities/units/BaseUnit.java b/core/src/io/anuke/mindustry/entities/units/BaseUnit.java index 914c03f49b..695f875864 100644 --- a/core/src/io/anuke/mindustry/entities/units/BaseUnit.java +++ b/core/src/io/anuke/mindustry/entities/units/BaseUnit.java @@ -120,8 +120,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ } public boolean targetHasFlag(BlockFlag flag){ - return target instanceof TileEntity && ((TileEntity) target).tile.block().flags != null && - ((TileEntity) target).tile.block().flags.contains(flag); + return target instanceof TileEntity && ((TileEntity) target).tile.block().flags.contains(flag); } public void updateRespawning(){ @@ -324,6 +323,11 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ @Override public void removed(){ + Tile tile = world.tile(spawner); + if(tile != null){ + tile.block().unitRemoved(tile, this); + } + spawner = noSpawner; } diff --git a/core/src/io/anuke/mindustry/world/Block.java b/core/src/io/anuke/mindustry/world/Block.java index 47c15ddac5..fb89c710a4 100644 --- a/core/src/io/anuke/mindustry/world/Block.java +++ b/core/src/io/anuke/mindustry/world/Block.java @@ -90,7 +90,7 @@ public class Block extends BlockStorage{ /** The block group. Unless {@link #canReplace} is overriden, blocks in the same group can replace each other. */ public BlockGroup group = BlockGroup.none; /** List of block flags. Used for AI indexing. */ - public EnumSet flags; + public EnumSet flags = EnumSet.of(); /** Whether the block can be tapped and selected to configure. */ public boolean configurable; /** Whether this block consumes touchDown events when tapped. */ @@ -235,6 +235,11 @@ public class Block extends BlockStorage{ public void unitOn(Tile tile, Unit unit){ } + /** Called when a unit that spawned at this tile is removed.*/ + public void unitRemoved(Tile tile, Unit unit){ + + } + /** Returns whether ot not this block can be place on the specified tile. */ public boolean canPlaceOn(Tile tile){ return true; diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/MendProjector.java b/core/src/io/anuke/mindustry/world/blocks/defense/MendProjector.java index 5877a7b20d..199d859358 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/MendProjector.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/MendProjector.java @@ -66,8 +66,6 @@ public class MendProjector extends Block{ if(entity.charge >= reload){ float realRange = range + entity.phaseHeat * phaseRangeBoost; - - Effects.effect(Fx.healWaveMend, Tmp.c1.set(color).lerp(phase, entity.phaseHeat), tile.drawx(), tile.drawy(), realRange); entity.charge = 0f; int tileRange = (int)(realRange / tilesize); diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/OverdriveProjector.java b/core/src/io/anuke/mindustry/world/blocks/defense/OverdriveProjector.java index 6e2c303417..28beb4280f 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/OverdriveProjector.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/OverdriveProjector.java @@ -2,7 +2,6 @@ package io.anuke.mindustry.world.blocks.defense; import io.anuke.arc.Core; import io.anuke.arc.collection.IntSet; -import io.anuke.arc.entities.Effects; import io.anuke.arc.graphics.Blending; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; @@ -10,8 +9,6 @@ import io.anuke.arc.graphics.g2d.Lines; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Time; -import io.anuke.arc.util.Tmp; -import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; @@ -31,7 +28,7 @@ public class OverdriveProjector extends Block{ protected int timerUse = timers ++; protected TextureRegion topRegion; - protected float reload = 260f; + protected float reload = 60f; protected float range = 80f; protected float speedBoost = 1.5f; protected float speedBoostPhase = 0.75f; @@ -69,7 +66,6 @@ public class OverdriveProjector extends Block{ float realRange = range + entity.phaseHeat * phaseRangeBoost; float realBoost = (speedBoost + entity.phaseHeat*speedBoostPhase) * entity.power.satisfaction; - Effects.effect(Fx.overdriveWave, Tmp.c1.set(color).lerp(phase, entity.phaseHeat), tile.drawx(), tile.drawy(), realRange); entity.charge = 0f; int tileRange = (int)(realRange / tilesize); @@ -87,8 +83,7 @@ public class OverdriveProjector extends Block{ if(other.getTeamID() == tile.getTeamID() && !healed.contains(other.pos()) && other.entity != null){ other.entity.timeScaleDuration = Math.max(other.entity.timeScaleDuration, reload + 1f); other.entity.timeScale = Math.max(other.entity.timeScale, realBoost); - Effects.effect(Fx.overdriveBlockFull, Tmp.c1.set(color).lerp(phase, entity.phaseHeat), other.drawx(), other.drawy(), other.block().size); - healed.add(other.pos()); + healed.add(other.pos()); } } } diff --git a/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java b/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java index d69ec2b6cd..43dcf09532 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java @@ -34,7 +34,7 @@ public class CoreBlock extends StorageBlock{ solid = true; update = true; hasItems = true; - flags = EnumSet.of(BlockFlag.resupplyPoint, BlockFlag.target); + flags = EnumSet.of(BlockFlag.target); } @Remote(called = Loc.server) diff --git a/core/src/io/anuke/mindustry/world/blocks/units/Reconstructor.java b/core/src/io/anuke/mindustry/world/blocks/units/Reconstructor.java deleted file mode 100644 index 4a60109625..0000000000 --- a/core/src/io/anuke/mindustry/world/blocks/units/Reconstructor.java +++ /dev/null @@ -1,331 +0,0 @@ -package io.anuke.mindustry.world.blocks.units; - -import io.anuke.annotations.Annotations.Loc; -import io.anuke.annotations.Annotations.Remote; -import io.anuke.arc.Core; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.Effects.Effect; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.Lines; -import io.anuke.arc.graphics.g2d.TextureRegion; -import io.anuke.arc.math.Mathf; -import io.anuke.arc.util.Time; -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.entities.Unit; -import io.anuke.mindustry.entities.Units; -import io.anuke.mindustry.entities.traits.SpawnerTrait; -import io.anuke.mindustry.gen.Call; -import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.graphics.Shaders; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Tile; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -import static io.anuke.mindustry.Vars.tilesize; -import static io.anuke.mindustry.Vars.world; - -//TODO re-implement properly -public class Reconstructor extends Block{ - protected float departTime = 30f; - protected float arriveTime = 40f; - /** Stores the percentage of buffered power to be used upon teleporting. */ - protected float powerPerTeleport = 0.5f; - protected Effect arriveEffect = Fx.spawn; - protected TextureRegion openRegion; - - public Reconstructor(String name){ - super(name); - update = true; - solidifes = true; - hasPower = true; - configurable = true; - consumes.powerBuffered(30f); - } - - protected static boolean checkValidTap(Tile tile, ReconstructorEntity entity, Player player){ - return validLink(tile, entity.link) && - Math.abs(player.x - tile.drawx()) <= tile.block().size * tilesize / 2f && - Math.abs(player.y - tile.drawy()) <= tile.block().size * tilesize / 2f && - entity.current == null && entity.power.satisfaction >= ((Reconstructor) tile.block()).powerPerTeleport; - } - - protected static boolean validLink(Tile tile, int position){ - Tile other = world.tile(position); - return other != tile && other != null && other.block() instanceof Reconstructor; - } - - protected static void unlink(ReconstructorEntity entity){ - Tile other = world.tile(entity.link); - - if(other != null && other.block() instanceof Reconstructor){ - ReconstructorEntity oe = other.entity(); - if(oe.link == entity.tile.pos()){ - oe.link = -1; - } - } - - entity.link = -1; - } - - @Remote(targets = Loc.both, called = Loc.server, forward = true) - public static void reconstructPlayer(Player player, Tile tile){ - ReconstructorEntity entity = tile.entity(); - - if(!checkValidTap(tile, entity, player) || entity.power.satisfaction < ((Reconstructor) tile.block()).powerPerTeleport) - return; - - entity.departing = true; - entity.current = player; - entity.solid = false; - entity.power.satisfaction -= Math.min(entity.power.satisfaction, ((Reconstructor) tile.block()).powerPerTeleport); - entity.updateTime = 1f; - entity.set(tile.drawx(), tile.drawy()); - player.rotation = 90f; - player.baseRotation = 90f; - player.setDead(true); - // player.setRespawning(true); - //player.setRespawning(); - } - - @Remote(targets = Loc.both, called = Loc.server, forward = true) - public static void linkReconstructor(Player player, Tile tile, Tile other){ - //just in case the client has invalid data - if(!(tile.entity instanceof ReconstructorEntity) || !(other.entity instanceof ReconstructorEntity)) return; - - ReconstructorEntity entity = tile.entity(); - ReconstructorEntity oe = other.entity(); - - unlink(entity); - unlink(oe); - - entity.link = other.pos(); - oe.link = tile.pos(); - } - - @Remote(targets = Loc.both, called = Loc.server, forward = true) - public static void unlinkReconstructor(Player player, Tile tile, Tile other){ - //just in case the client has invalid data - if(!(tile.entity instanceof ReconstructorEntity) || !(other.entity instanceof ReconstructorEntity)) return; - - ReconstructorEntity entity = tile.entity(); - ReconstructorEntity oe = other.entity(); - - //called in main thread to prevent issues - unlink(entity); - unlink(oe); - } - - @Override - public void load(){ - super.load(); - openRegion = Core.atlas.find(name + "-open"); - } - - @Override - public boolean isSolidFor(Tile tile){ - ReconstructorEntity entity = tile.entity(); - - return entity.solid; - } - - @Override - public void drawConfigure(Tile tile){ - super.drawConfigure(tile); - - ReconstructorEntity entity = tile.entity(); - - if(validLink(tile, entity.link)){ - Tile target = world.tile(entity.link); - - Draw.color(Palette.place); - Lines.square(target.drawx(), target.drawy(), - target.block().size * tilesize / 2f + 1f); - Draw.reset(); - } - - Draw.color(Palette.accent); - Draw.color(); - } - - @Override - public boolean onConfigureTileTapped(Tile tile, Tile other){ - if(tile == other) return false; - - ReconstructorEntity entity = tile.entity(); - - if(entity.link == other.pos()){ - Call.unlinkReconstructor(null, tile, other); - return false; - }else if(other.block() instanceof Reconstructor){ - Call.linkReconstructor(null, tile, other); - return false; - } - - return true; - } - - @Override - public boolean shouldShowConfigure(Tile tile, Player player){ - ReconstructorEntity entity = tile.entity(); - return !checkValidTap(tile, entity, player); - } - - @Override - public boolean shouldHideConfigure(Tile tile, Player player){ - ReconstructorEntity entity = tile.entity(); - return checkValidTap(tile, entity, player); - } - - @Override - public void draw(Tile tile){ - ReconstructorEntity entity = tile.entity(); - - if(entity.solid){ - Draw.rect(region, tile.drawx(), tile.drawy()); - }else{ - Draw.rect(openRegion, tile.drawx(), tile.drawy()); - } - - if(entity.current != null){ - float progress = entity.departing ? entity.updateTime : (1f - entity.updateTime); - - //Player player = entity.current; - - TextureRegion region = entity.current.getIconRegion(); - - Shaders.build.region = region; - Shaders.build.progress = progress; - Shaders.build.color.set(Palette.accent); - Shaders.build.time = -entity.time / 10f; - - Draw.shader(Shaders.build, false); - Shaders.build.apply(); - Draw.rect(region, tile.drawx(), tile.drawy()); - Draw.shader(); - - Draw.color(Palette.accent); - - Lines.lineAngleCenter( - tile.drawx() + Mathf.sin(entity.time, 6f, Vars.tilesize / 3f * size), - tile.drawy(), - 90, - size * Vars.tilesize / 2f); - - Draw.reset(); - } - } - - @Override - public void update(Tile tile){ - ReconstructorEntity entity = tile.entity(); - - boolean stayOpen = false; - - if(entity.current != null){ - entity.time += Time.delta(); - - entity.solid = true; - - if(entity.departing){ - //force respawn if there's suddenly nothing to link to - if(!validLink(tile, entity.link)){ - //entity.current.setRespawning(false); - return; - } - - ReconstructorEntity other = world.tile(entity.link).entity(); - - entity.updateTime -= Time.delta() / departTime; - if(entity.updateTime <= 0f){ - //no power? death. - if(other.power.satisfaction < powerPerTeleport){ - entity.current.setDead(true); - //entity.current.setRespawning(false); - entity.current = null; - return; - } - other.power.satisfaction -= Math.min(other.power.satisfaction, powerPerTeleport); - other.current = entity.current; - other.departing = false; - other.current.set(other.x, other.y); - other.updateTime = 1f; - entity.current = null; - } - }else{ //else, arriving - entity.updateTime -= Time.delta() / arriveTime; - - if(entity.updateTime <= 0f){ - entity.solid = false; - entity.current.setDead(false); - - Effects.effect(arriveEffect, entity.current); - - entity.current = null; - } - } - - }else{ - - if(validLink(tile, entity.link)){ - Tile other = world.tile(entity.link); - if(other.entity.power.satisfaction >= powerPerTeleport && Units.anyEntities(tile, 4f, unit -> unit.getTeam() == entity.getTeam() && unit instanceof Player) && - entity.power.satisfaction >= powerPerTeleport){ - entity.solid = false; - stayOpen = true; - } - } - - if(!stayOpen && !entity.solid && !Units.anyEntities(tile)){ - entity.solid = true; - } - } - } - - @Override - public void tapped(Tile tile, Player player){ - ReconstructorEntity entity = tile.entity(); - - if(!checkValidTap(tile, entity, player)) return; - - Call.reconstructPlayer(player, tile); - } - - @Override - public TileEntity newEntity(){ - return new ReconstructorEntity(); - } - - public class ReconstructorEntity extends TileEntity implements SpawnerTrait{ - Unit current; - float updateTime; - float time; - int link; - boolean solid = true, departing; - - @Override - public void updateSpawning(Unit unit){ - - } - - @Override - public float getSpawnProgress(){ - return 0; - } - - @Override - public void write(DataOutput stream) throws IOException{ - stream.writeInt(link); - } - - @Override - public void read(DataInput stream) throws IOException{ - link = stream.readInt(); - } - } -} diff --git a/core/src/io/anuke/mindustry/world/blocks/units/UnitFactory.java b/core/src/io/anuke/mindustry/world/blocks/units/UnitFactory.java index e8d6a7f1e3..c9a8823fba 100644 --- a/core/src/io/anuke/mindustry/world/blocks/units/UnitFactory.java +++ b/core/src/io/anuke/mindustry/world/blocks/units/UnitFactory.java @@ -12,6 +12,7 @@ import io.anuke.arc.math.Mathf; import io.anuke.mindustry.Vars; import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.Unit; import io.anuke.mindustry.entities.units.BaseUnit; import io.anuke.mindustry.entities.units.UnitType; import io.anuke.mindustry.gen.Call; @@ -41,6 +42,7 @@ public class UnitFactory extends Block{ protected float produceTime = 1000f; protected float launchVelocity = 0f; protected TextureRegion topRegion; + protected int maxSpawn = 4; public UnitFactory(String name){ super(name); @@ -61,6 +63,7 @@ public class UnitFactory extends Block{ UnitFactory factory = (UnitFactory) tile.block(); entity.buildTime = 0f; + entity.spawned ++; Effects.shake(2f, 3f, entity); Effects.effect(Fx.producesmoke, tile.drawx(), tile.drawy()); @@ -93,6 +96,12 @@ public class UnitFactory extends Block{ stats.add(BlockStat.craftSpeed, produceTime / 60f, StatUnit.seconds); } + @Override + public void unitRemoved(Tile tile, Unit unit){ + UnitFactoryEntity entity = tile.entity(); + entity.spawned --; + } + @Override public TextureRegion[] generateIcons(){ return new TextureRegion[]{Core.atlas.find(name), Core.atlas.find(name + "-top")}; @@ -136,6 +145,10 @@ public class UnitFactory extends Block{ entity.time += entity.delta() * entity.speedScl; + if(entity.spawned >= maxSpawn){ + return; + } + if(tile.isEnemyCheat()){ entity.warmup += entity.delta(); } @@ -211,17 +224,20 @@ public class UnitFactory extends Block{ public float time; public float speedScl; public float warmup; //only for enemy spawners + public int spawned; @Override public void write(DataOutput stream) throws IOException{ stream.writeFloat(buildTime); stream.writeFloat(warmup); + stream.writeInt(spawned); } @Override public void read(DataInput stream) throws IOException{ buildTime = stream.readFloat(); warmup = stream.readFloat(); + spawned = stream.readInt(); } } } diff --git a/core/src/io/anuke/mindustry/world/meta/BlockFlag.java b/core/src/io/anuke/mindustry/world/meta/BlockFlag.java index a57e765414..b5c8339854 100644 --- a/core/src/io/anuke/mindustry/world/meta/BlockFlag.java +++ b/core/src/io/anuke/mindustry/world/meta/BlockFlag.java @@ -1,24 +1,16 @@ package io.anuke.mindustry.world.meta; -//TODO fix flagging system, currently doesn't really work public enum BlockFlag{ /**General important target for all types of units.*/ target(0), - /**Point to resupply resources.*/ - resupplyPoint(Float.MAX_VALUE), - /**Point to drop off resources.*/ - dropPoint(Float.MAX_VALUE), /**Producer of important goods.*/ producer(Float.MAX_VALUE), - /**Just a turret.*/ + /**A turret.*/ turret(Float.MAX_VALUE), - /**Producer or storage unit of volatile materials.*/ - explosive(Float.MAX_VALUE), /**Repair point.*/ repair(Float.MAX_VALUE); public final static BlockFlag[] all = values(); - public final float cost; BlockFlag(float cost){