diff --git a/core/src/io/anuke/mindustry/input/InputHandler.java b/core/src/io/anuke/mindustry/input/InputHandler.java index 4edafec28f..a960a98a14 100644 --- a/core/src/io/anuke/mindustry/input/InputHandler.java +++ b/core/src/io/anuke/mindustry/input/InputHandler.java @@ -198,7 +198,7 @@ public abstract class InputHandler extends InputAdapter{ } public void tryDropItems(Tile tile, float x, float y){ - if(!droppingItem || !player.inventory.hasItem() || !tile.block().hasItems || canTapPlayer(x, y)){ + if(!droppingItem || !player.inventory.hasItem() || canTapPlayer(x, y)){ droppingItem = false; return; } @@ -207,7 +207,7 @@ public abstract class InputHandler extends InputAdapter{ ItemStack stack = player.inventory.getItem(); - if(tile.block().acceptStack(stack.item, stack.amount, tile, player) > 0){ + if(tile.block().acceptStack(stack.item, stack.amount, tile, player) > 0 && tile.block().hasItems){ CallBlocks.transferInventory(player, tile); }else{ CallEntity.dropItem(player, player.angleTo(x, y)); diff --git a/core/src/io/anuke/mindustry/world/BaseBlock.java b/core/src/io/anuke/mindustry/world/BaseBlock.java index caefb27f90..32cd293903 100644 --- a/core/src/io/anuke/mindustry/world/BaseBlock.java +++ b/core/src/io/anuke/mindustry/world/BaseBlock.java @@ -122,7 +122,7 @@ public abstract class BaseBlock { next = next.target(); if(next.block().hasLiquids && tile.entity.liquids.amount > 0f){ - if(next.entity.liquids.liquid == tile.entity.liquids.liquid) { + if(next.entity.liquids.liquid == tile.entity.liquids.liquid || next.entity.liquids.amount <= 0.01f) { float ofract = next.entity.liquids.amount / next.block().liquidCapacity; float fract = tile.entity.liquids.amount / liquidCapacity; float flow = Math.min(Mathf.clamp((fract - ofract) * (1f)) * (liquidCapacity), tile.entity.liquids.amount); diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/RepairTurret.java b/core/src/io/anuke/mindustry/world/blocks/defense/RepairTurret.java deleted file mode 100644 index 8c75659031..0000000000 --- a/core/src/io/anuke/mindustry/world/blocks/defense/RepairTurret.java +++ /dev/null @@ -1,98 +0,0 @@ -package io.anuke.mindustry.world.blocks.defense; - -import com.badlogic.gdx.math.MathUtils; -import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.entities.Units; -import io.anuke.mindustry.graphics.Layer; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.blocks.defense.turrets.PowerTurret; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Hue; -import io.anuke.ucore.graphics.Lines; -import io.anuke.ucore.util.Angles; -import io.anuke.ucore.util.Mathf; - -//TODO remove -public class RepairTurret extends PowerTurret { - protected float repairFrac = 1f / 135f; - - public RepairTurret(String name) { - super(name); - powerUsed = 0.1f; - layer2 = Layer.laser; - } - - @Override - public void setStats(){ - super.setStats(); - - //stats.add("repairssecond", Strings.toFixed(60f/reload * repairFrac * 100, 1) + "%"); - } - - @Override - public void update(Tile tile){ - TurretEntity entity = tile.entity(); - - if(entity.power.amount < powerUsed){ - return; - } - - if(entity.blockTarget != null && entity.blockTarget.isDead()){ - entity.blockTarget = null; - } - - if(entity.timer.get(timerTarget, targetInterval)){ - entity.blockTarget = Units.findAllyTile(tile.getTeam(),tile.worldx(), tile.worldy(), range, - test -> test != tile && test.entity.health < test.block().health); - } - - if(entity.blockTarget != null){ - if(Float.isNaN(entity.rotation)){ - entity.rotation = 0; - } - - float target = entity.angleTo(entity.blockTarget); - entity.rotation = Mathf.slerpDelta(entity.rotation, target, 0.16f); - - int maxhealth = entity.blockTarget.tile.block().health; - - //TODO - if(entity.timer.get(100, reload) && Angles.angleDist(target, entity.rotation) < shootCone){ - entity.blockTarget.health += maxhealth * repairFrac; - - if(entity.blockTarget.health > maxhealth) - entity.blockTarget.health = maxhealth; - - entity.power.amount -= powerUsed; - } - } - } - - @Override - public void drawLayer2(Tile tile){ - TurretEntity entity = tile.entity(); - TileEntity target = entity.blockTarget; - - if(entity.power.amount >= powerUsed && target != null && Angles.angleDist(entity.angleTo(target), entity.rotation) < 10){ - Tile targetTile = target.tile; - float len = 4f; - - float x = tile.drawx() + Angles.trnsx(entity.rotation, len), y = tile.drawy() + Angles.trnsy(entity.rotation, len); - float x2 = targetTile.drawx(), y2 = targetTile.drawy(); - - Draw.color(Hue.rgb(138, 244, 138, (MathUtils.sin(Timers.time()) + 1f) / 14f)); - Draw.alpha(0.3f); - Lines.stroke(4f); - Lines.line(x, y, x2, y2); - Lines.stroke(2f); - Draw.rect("circle", x2, y2, 7f, 7f); - Draw.alpha(1f); - Lines.stroke(2f); - Lines.line(x, y, x2, y2); - Lines.stroke(1f); - Draw.rect("circle", x2, y2, 5f, 5f); - Draw.reset(); - } - } -} diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/CooledTurret.java b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/CooledTurret.java new file mode 100644 index 0000000000..e317efda1b --- /dev/null +++ b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/CooledTurret.java @@ -0,0 +1,50 @@ +package io.anuke.mindustry.world.blocks.defense.turrets; + +import io.anuke.mindustry.content.fx.BlockFx; +import io.anuke.mindustry.entities.effect.Fire; +import io.anuke.mindustry.type.Liquid; +import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.blocks.defense.Turret; +import io.anuke.ucore.core.Effects; +import io.anuke.ucore.core.Effects.Effect; +import io.anuke.ucore.core.Timers; +import io.anuke.ucore.util.Mathf; + +import static io.anuke.mindustry.Vars.tilesize; + +public class CooledTurret extends Turret { + /**How much reload is lowered by for each unit of liquid of heat capacity 1.*/ + protected float coolantMultiplier = 1f; + protected float maxUsed = 1f; + protected Effect coolEffect = BlockFx.fuelburn; + + public CooledTurret(String name) { + super(name); + hasLiquids = true; + } + + @Override + protected void updateShooting(Tile tile) { + super.updateShooting(tile); + + TurretEntity entity = tile.entity(); + + float used = Math.min(Math.min(entity.liquids.amount, maxUsed * Timers.delta()), ((reload - entity.reload) / coolantMultiplier) / entity.liquids.liquid.heatCapacity); + entity.reload += (used * entity.liquids.liquid.heatCapacity) / entity.liquids.liquid.heatCapacity; + entity.liquids.amount -= used; + + if(Mathf.chance(0.04 * used)){ + Effects.effect(coolEffect, tile.drawx() + Mathf.range(size * tilesize/2f), tile.drawy() + Mathf.range(size * tilesize/2f)); + } + + //don't use oil as coolant, thanks + if(Mathf.chance(entity.liquids.liquid.flammability / 10f * used)){ + Fire.create(tile); + } + } + + @Override + public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount) { + return super.acceptLiquid(tile, source, liquid, amount) && liquid.temperature <= 0.5f; + } +} diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/ItemTurret.java b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/ItemTurret.java index 23082d1c41..82da3d3efa 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/ItemTurret.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/ItemTurret.java @@ -6,11 +6,10 @@ import io.anuke.mindustry.type.AmmoEntry; import io.anuke.mindustry.type.AmmoType; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.BarType; -import io.anuke.mindustry.world.meta.BlockBar; import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.blocks.defense.Turret; +import io.anuke.mindustry.world.meta.BlockBar; -public class ItemTurret extends Turret { +public class ItemTurret extends CooledTurret { protected int maxAmmo = 100; //TODO implement this! /**A value of 'null' means this turret does not need ammo.*/ @@ -73,6 +72,7 @@ public class ItemTurret extends Turret { @Override public void setBars(){ + super.setBars(); bars.replace(new BlockBar(BarType.inventory, true, tile -> (float)tile.entity().totalAmmo / maxAmmo)); } diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/PowerTurret.java b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/PowerTurret.java index 3b2f65f531..945fad33e5 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/PowerTurret.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/PowerTurret.java @@ -2,10 +2,9 @@ package io.anuke.mindustry.world.blocks.defense.turrets; import io.anuke.mindustry.type.AmmoType; import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.blocks.defense.Turret; import io.anuke.mindustry.world.meta.BlockStat; -public abstract class PowerTurret extends Turret { +public abstract class PowerTurret extends CooledTurret { protected float powerUsed = 0.5f; protected AmmoType shootType; diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/WarpGate.java b/core/src/io/anuke/mindustry/world/blocks/distribution/WarpGate.java index 4caffe77cd..622170e01a 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/WarpGate.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/WarpGate.java @@ -7,8 +7,6 @@ import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.mindustry.content.Liquids; import io.anuke.mindustry.content.fx.BlockFx; -import io.anuke.mindustry.content.fx.ExplosionFx; -import io.anuke.mindustry.entities.Damage; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.gen.CallBlocks; @@ -29,7 +27,6 @@ import io.anuke.ucore.scene.ui.ButtonGroup; import io.anuke.ucore.scene.ui.ImageButton; import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Translator; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -295,34 +292,7 @@ public class WarpGate extends PowerBlock{ if(entity.activeScl < 0.5f) return; - float explosionRadius = 50f; - float explosionDamage = 20f; - - Translator tr = new Translator(); - - Effects.shake(6f, 16f, tile.worldx(), tile.worldy()); - Effects.effect(ExplosionFx.nuclearShockwave, tile.worldx(), tile.worldy()); - for(int i = 0; i < 6; i ++){ - Timers.run(Mathf.random(40), () -> { - Effects.effect(BlockFx.nuclearcloud, tile.worldx(), tile.worldy()); - }); - } - - Damage.damage(tile.worldx(), tile.worldy(), explosionRadius * tilesize, explosionDamage * 4); - - for(int i = 0; i < 20; i ++){ - Timers.run(Mathf.random(50), ()->{ - tr.rnd(Mathf.random(40f)); - Effects.effect(ExplosionFx.explosion, tr.x + tile.worldx(), tr.y + tile.worldy()); - }); - } - - for(int i = 0; i < 70; i ++){ - Timers.run(Mathf.random(80), ()->{ - tr.rnd(Mathf.random(120f)); - Effects.effect(BlockFx.nuclearsmoke, tr.x + tile.worldx(), tr.y + tile.worldy()); - }); - } + //TODO catastrophic failure } private void catastrophicFailure(Tile tile){ diff --git a/core/src/io/anuke/mindustry/world/blocks/effect/EffectCore.java b/core/src/io/anuke/mindustry/world/blocks/effect/EffectCore.java new file mode 100644 index 0000000000..adf1a243df --- /dev/null +++ b/core/src/io/anuke/mindustry/world/blocks/effect/EffectCore.java @@ -0,0 +1,26 @@ +package io.anuke.mindustry.world.blocks.effect; + +import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Tile; +import io.anuke.ucore.graphics.Draw; +import io.anuke.ucore.graphics.Lines; + +import static io.anuke.mindustry.Vars.tilesize; + +public abstract class EffectCore extends Block{ + protected int range = 7; + + public EffectCore(String name) { + super(name); + update = true; + solid = true; + } + + @Override + public void drawSelect(Tile tile) { + Draw.color(Palette.accent); + Lines.dashCircle(tile.drawx(), tile.drawy(), range * tilesize); + Draw.reset(); + } +} diff --git a/core/src/io/anuke/mindustry/world/blocks/effect/MendingCore.java b/core/src/io/anuke/mindustry/world/blocks/effect/MendingCore.java new file mode 100644 index 0000000000..571cd4112d --- /dev/null +++ b/core/src/io/anuke/mindustry/world/blocks/effect/MendingCore.java @@ -0,0 +1,30 @@ +package io.anuke.mindustry.world.blocks.effect; + +import io.anuke.mindustry.world.Tile; +import io.anuke.ucore.core.Timers; +import io.anuke.ucore.util.Mathf; + +import static io.anuke.mindustry.Vars.world; + +public class MendingCore extends EffectCore { + /**Mending speed as a percentage of block health, per frame.*/ + protected float mendSpeed = 0.8f; + + public MendingCore(String name) { + super(name); + } + + @Override + public void update(Tile tile) { + + for (int dx = Math.max(-range + tile.x, 0); dx <= Math.min(range + tile.y, world.width() - 1); dx++) { + for (int dy = Math.max(-range + tile.y, 0); dy <= Math.min(range + tile.y, world.height() - 1); dy++) { + Tile other = world.tile(dx, dy); + + if(other.entity != null){ + other.entity.health = Mathf.clamp(other.entity.health + 1f / other.block().health * mendSpeed * Timers.delta(), 0, other.block().health); + } + } + } + } +} diff --git a/core/src/io/anuke/mindustry/world/blocks/power/FusionReactor.java b/core/src/io/anuke/mindustry/world/blocks/power/FusionReactor.java index ddfa00ac43..f1bed4b378 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/FusionReactor.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/FusionReactor.java @@ -47,13 +47,32 @@ public class FusionReactor extends PowerGenerator { entity.warmup = Mathf.lerpDelta(entity.warmup, 0f, 0.01f); } - float powerAdded = Math.min(powerCapacity - entity.power.amount, maxPowerProduced * Mathf.pow(entity.warmup, 3f) * Timers.delta()); + float powerAdded = Math.min(powerCapacity - entity.power.amount, maxPowerProduced * Mathf.pow(entity.warmup, 4f) * Timers.delta()); entity.power.amount += powerAdded; entity.totalProgress += entity.warmup * Timers.delta(); distributePower(tile); } + @Override + public float handleDamage(Tile tile, float amount) { + FusionReactorEntity entity = tile.entity(); + + if(entity.warmup < 0.4f) return amount; + + float healthFract = tile.entity.health/health; + + //5% chance to explode when hit at <50% HP with a normal bullet + if(amount > 5f && healthFract <= 0.5f && Mathf.chance(0.05)){ + return health; + //10% chance to explode when hit at <25% HP with a powerful bullet + }else if(amount > 8f && healthFract <= 0.2f && Mathf.chance(0.1)){ + return health; + } + + return amount; + } + @Override public void draw(Tile tile) { FusionReactorEntity entity = tile.entity(); @@ -99,6 +118,17 @@ public class FusionReactor extends PowerGenerator { return super.acceptLiquid(tile, source, liquid, amount) && liquid == inputLiquid; } + @Override + public void onDestroyed(Tile tile) { + super.onDestroyed(tile); + + FusionReactorEntity entity = tile.entity(); + + if(entity.warmup < 0.4f) return; + + //TODO catastrophic failure + } + public static class FusionReactorEntity extends GenericCrafterEntity{ }