Merge branches 'crafting-rework' and 'master' of https://github.com/Anuken/Mindustry into crafting-rework
# Conflicts: # core/src/io/anuke/mindustry/content/blocks/CraftingBlocks.java # core/src/io/anuke/mindustry/content/blocks/TurretBlocks.java # core/src/io/anuke/mindustry/core/Renderer.java # core/src/io/anuke/mindustry/world/blocks/power/ItemGenerator.java
This commit is contained in:
@@ -22,7 +22,6 @@ public class CraftingBlocks extends BlockList implements ContentList{
|
||||
craftEffect = BlockFx.smeltsmoke;
|
||||
result = Items.silicon;
|
||||
craftTime = 40f;
|
||||
powerCapacity = 20f;
|
||||
size = 2;
|
||||
hasLiquids = false;
|
||||
flameColor = Color.valueOf("ffef99");
|
||||
@@ -36,7 +35,6 @@ public class CraftingBlocks extends BlockList implements ContentList{
|
||||
liquidCapacity = 60f;
|
||||
craftTime = 60f;
|
||||
output = Items.plastanium;
|
||||
powerCapacity = 40f;
|
||||
size = 2;
|
||||
health = 320;
|
||||
hasPower = hasLiquids = true;
|
||||
@@ -52,7 +50,6 @@ public class CraftingBlocks extends BlockList implements ContentList{
|
||||
craftEffect = BlockFx.smeltsmoke;
|
||||
result = Items.phasefabric;
|
||||
craftTime = 120f;
|
||||
powerCapacity = 50f;
|
||||
size = 2;
|
||||
|
||||
consumes.items(new ItemStack(Items.thorium, 4), new ItemStack(Items.sand, 10));
|
||||
@@ -63,7 +60,6 @@ public class CraftingBlocks extends BlockList implements ContentList{
|
||||
craftEffect = BlockFx.smeltsmoke;
|
||||
result = Items.surgealloy;
|
||||
craftTime = 75f;
|
||||
powerCapacity = 60f;
|
||||
size = 3;
|
||||
|
||||
useFlux = true;
|
||||
|
||||
@@ -39,28 +39,26 @@ public class DebugBlocks extends BlockList implements ContentList{
|
||||
public void load(){
|
||||
powerVoid = new PowerBlock("powervoid"){
|
||||
{
|
||||
powerCapacity = Float.MAX_VALUE;
|
||||
consumes.power(Float.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(){
|
||||
super.init();
|
||||
stats.remove(BlockStat.powerCapacity);
|
||||
stats.remove(BlockStat.powerUse);
|
||||
}
|
||||
};
|
||||
|
||||
powerInfinite = new PowerNode("powerinfinite"){
|
||||
{
|
||||
powerCapacity = 10000f;
|
||||
maxNodes = 100;
|
||||
outputsPower = true;
|
||||
consumesPower = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
super.update(tile);
|
||||
tile.entity.power.amount = powerCapacity;
|
||||
public float getPowerProduction(Tile tile){
|
||||
return 10000f;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -71,19 +71,18 @@ public class DefenseBlocks extends BlockList implements ContentList{
|
||||
}};
|
||||
|
||||
mendProjector = new MendProjector("mend-projector"){{
|
||||
consumes.power(0.2f);
|
||||
consumes.power(0.2f, 1.0f);
|
||||
size = 2;
|
||||
consumes.item(Items.phasefabric).optional(true);
|
||||
}};
|
||||
|
||||
overdriveProjector = new OverdriveProjector("overdrive-projector"){{
|
||||
consumes.power(0.35f);
|
||||
consumes.power(0.35f, 1.0f);
|
||||
size = 2;
|
||||
consumes.item(Items.phasefabric).optional(true);
|
||||
}};
|
||||
|
||||
forceProjector = new ForceProjector("force-projector"){{
|
||||
consumes.power(0.2f);
|
||||
size = 3;
|
||||
consumes.item(Items.phasefabric).optional(true);
|
||||
}};
|
||||
|
||||
@@ -35,7 +35,7 @@ public class DistributionBlocks extends BlockList implements ContentList{
|
||||
phaseConveyor = new ItemBridge("phase-conveyor"){{
|
||||
range = 12;
|
||||
hasPower = true;
|
||||
consumes.power(0.03f);
|
||||
consumes.power(0.03f, 1.0f);
|
||||
}};
|
||||
|
||||
sorter = new Sorter("sorter");
|
||||
|
||||
@@ -20,7 +20,6 @@ public class LiquidBlocks extends BlockList implements ContentList{
|
||||
pumpAmount = 0.2f;
|
||||
consumes.power(0.015f);
|
||||
liquidCapacity = 30f;
|
||||
powerCapacity = 20f;
|
||||
hasPower = true;
|
||||
size = 2;
|
||||
tier = 1;
|
||||
@@ -31,7 +30,6 @@ public class LiquidBlocks extends BlockList implements ContentList{
|
||||
consumes.power(0.03f);
|
||||
liquidCapacity = 40f;
|
||||
hasPower = true;
|
||||
powerCapacity = 20f;
|
||||
size = 2;
|
||||
tier = 2;
|
||||
}};
|
||||
@@ -66,7 +64,7 @@ public class LiquidBlocks extends BlockList implements ContentList{
|
||||
phaseConduit = new LiquidBridge("phase-conduit"){{
|
||||
range = 12;
|
||||
hasPower = true;
|
||||
consumes.power(0.03f);
|
||||
consumes.power(0.03f, 1.0f);
|
||||
}};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import io.anuke.mindustry.content.Liquids;
|
||||
import io.anuke.mindustry.content.fx.BlockFx;
|
||||
import io.anuke.mindustry.game.ContentList;
|
||||
import io.anuke.mindustry.world.Block;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.power.*;
|
||||
|
||||
public class PowerBlocks extends BlockList implements ContentList{
|
||||
@@ -13,48 +14,43 @@ public class PowerBlocks extends BlockList implements ContentList{
|
||||
@Override
|
||||
public void load(){
|
||||
combustionGenerator = new BurnerGenerator("combustion-generator"){{
|
||||
powerOutput = 0.09f;
|
||||
powerCapacity = 40f;
|
||||
powerProduction = 0.09f;
|
||||
itemDuration = 40f;
|
||||
}};
|
||||
|
||||
thermalGenerator = new LiquidHeatGenerator("thermal-generator"){{
|
||||
maxLiquidGenerate = 2f;
|
||||
powerCapacity = 40f;
|
||||
powerPerLiquid = 0.35f;
|
||||
powerProduction = 2f;
|
||||
generateEffect = BlockFx.redgeneratespark;
|
||||
size = 2;
|
||||
}};
|
||||
|
||||
turbineGenerator = new TurbineGenerator("turbine-generator"){{
|
||||
powerOutput = 0.28f;
|
||||
powerCapacity = 40f;
|
||||
powerProduction = 0.28f;
|
||||
itemDuration = 30f;
|
||||
powerPerLiquid = 0.7f;
|
||||
consumes.liquid(Liquids.water, 0.05f);
|
||||
size = 2;
|
||||
}};
|
||||
|
||||
rtgGenerator = new DecayGenerator("rtg-generator"){{
|
||||
powerCapacity = 40f;
|
||||
size = 2;
|
||||
powerOutput = 0.3f;
|
||||
powerProduction = 0.3f;
|
||||
itemDuration = 220f;
|
||||
}};
|
||||
|
||||
solarPanel = new SolarGenerator("solar-panel"){{
|
||||
generation = 0.0045f;
|
||||
powerProduction = 0.0045f;
|
||||
}};
|
||||
|
||||
largeSolarPanel = new SolarGenerator("solar-panel-large"){{
|
||||
size = 3;
|
||||
generation = 0.055f;
|
||||
powerProduction = 0.055f;
|
||||
}};
|
||||
|
||||
thoriumReactor = new NuclearReactor("thorium-reactor"){{
|
||||
size = 3;
|
||||
health = 700;
|
||||
powerMultiplier = 1.1f;
|
||||
powerProduction = 1.1f;
|
||||
}};
|
||||
|
||||
fusionReactor = new FusionReactor("fusion-reactor"){{
|
||||
@@ -63,12 +59,12 @@ public class PowerBlocks extends BlockList implements ContentList{
|
||||
}};
|
||||
|
||||
battery = new Battery("battery"){{
|
||||
powerCapacity = 320f;
|
||||
consumes.powerBuffered(320f, 1f);
|
||||
}};
|
||||
|
||||
batteryLarge = new Battery("battery-large"){{
|
||||
size = 3;
|
||||
powerCapacity = 2000f;
|
||||
consumes.powerBuffered(2000f, 1f);
|
||||
}};
|
||||
|
||||
powerNode = new PowerNode("power-node"){{
|
||||
|
||||
@@ -92,8 +92,8 @@ public class TurretBlocks extends BlockList implements ContentList{
|
||||
recoil = 2f;
|
||||
reload = 120f;
|
||||
cooldown = 0.03f;
|
||||
powerUsed = 20f;
|
||||
powerCapacity = 60f;
|
||||
powerUsed = 1 / 3f;
|
||||
consumes.powerBuffered(60f);
|
||||
shootShake = 2f;
|
||||
shootEffect = ShootFx.lancerLaserShoot;
|
||||
smokeEffect = ShootFx.lancerLaserShootSmoke;
|
||||
@@ -111,8 +111,8 @@ public class TurretBlocks extends BlockList implements ContentList{
|
||||
shootShake = 0f;
|
||||
shootCone = 40f;
|
||||
rotatespeed = 8f;
|
||||
powerUsed = 3f;
|
||||
powerCapacity = 30f;
|
||||
powerUsed = 1f / 3f;
|
||||
consumes.powerBuffered(30f);
|
||||
range = 50f;
|
||||
shootEffect = ShootFx.lightningShoot;
|
||||
heatColor = Color.RED;
|
||||
@@ -249,8 +249,8 @@ public class TurretBlocks extends BlockList implements ContentList{
|
||||
recoil = 4f;
|
||||
size = 4;
|
||||
shootShake = 2f;
|
||||
powerUsed = 60f;
|
||||
powerCapacity = 120f;
|
||||
powerUsed = 0.5f;
|
||||
consumes.powerBuffered(120f);
|
||||
range = 160f;
|
||||
reload = 200f;
|
||||
firingMoveFract = 0.1f;
|
||||
|
||||
@@ -9,52 +9,53 @@ public class UpgradeBlocks extends BlockList{
|
||||
|
||||
@Override
|
||||
public void load(){
|
||||
|
||||
alphaPad = new MechPad("alpha-mech-pad"){{
|
||||
mech = Mechs.alpha;
|
||||
size = 2;
|
||||
powerCapacity = 50f;
|
||||
consumes.powerBuffered(50f);
|
||||
}};
|
||||
|
||||
deltaPad = new MechPad("delta-mech-pad"){{
|
||||
mech = Mechs.delta;
|
||||
size = 2;
|
||||
powerCapacity = 70f;
|
||||
consumes.powerBuffered(70f);
|
||||
}};
|
||||
|
||||
tauPad = new MechPad("tau-mech-pad"){{
|
||||
mech = Mechs.tau;
|
||||
size = 2;
|
||||
powerCapacity = 100f;
|
||||
consumes.powerBuffered(100f);
|
||||
}};
|
||||
|
||||
omegaPad = new MechPad("omega-mech-pad"){{
|
||||
mech = Mechs.omega;
|
||||
size = 3;
|
||||
powerCapacity = 120f;
|
||||
consumes.powerBuffered(120f);
|
||||
}};
|
||||
|
||||
dartPad = new MechPad("dart-ship-pad"){{
|
||||
mech = Mechs.dart;
|
||||
size = 2;
|
||||
powerCapacity = 50f;
|
||||
consumes.powerBuffered(50f);
|
||||
}};
|
||||
|
||||
javelinPad = new MechPad("javelin-ship-pad"){{
|
||||
mech = Mechs.javelin;
|
||||
size = 2;
|
||||
powerCapacity = 80f;
|
||||
consumes.powerBuffered(80f);
|
||||
}};
|
||||
|
||||
tridentPad = new MechPad("trident-ship-pad"){{
|
||||
mech = Mechs.trident;
|
||||
size = 2;
|
||||
powerCapacity = 100f;
|
||||
consumes.powerBuffered(100f);
|
||||
}};
|
||||
|
||||
glaivePad = new MechPad("glaive-ship-pad"){{
|
||||
mech = Mechs.glaive;
|
||||
size = 3;
|
||||
powerCapacity = 120f;
|
||||
consumes.powerBuffered(120f);
|
||||
}};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,7 +297,7 @@ public class Renderer implements ApplicationListener{
|
||||
|
||||
public void clampScale(){
|
||||
float s = io.anuke.arc.scene.ui.layout.Unit.dp.scl(1f);
|
||||
targetscale = Mathf.clamp(targetscale, Math.round(s * 2), Math.round(s * 6));
|
||||
targetscale = Mathf.clamp(targetscale, s * 2.5f, Math.round(s * 7));
|
||||
}
|
||||
|
||||
public void takeMapScreenshot(){
|
||||
|
||||
@@ -310,7 +310,7 @@ public interface BuilderTrait extends Entity{
|
||||
return;
|
||||
}
|
||||
|
||||
Draw.color(Palette.accent);
|
||||
Lines.stroke(1f, Palette.accent);
|
||||
float focusLen = 3.8f + Mathf.absin(Time.time(), 1.1f, 0.6f);
|
||||
float px = unit.x + Angles.trnsx(unit.rotation, focusLen);
|
||||
float py = unit.y + Angles.trnsy(unit.rotation, focusLen);
|
||||
|
||||
@@ -67,6 +67,7 @@ public class DesktopInput extends InputHandler{
|
||||
|
||||
@Override
|
||||
public void drawOutlined(){
|
||||
Lines.stroke(1f);
|
||||
int cursorX = tileX(Core.input.mouseX());
|
||||
int cursorY = tileY(Core.input.mouseY());
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
|
||||
//gesture data
|
||||
private Vector2 vector = new Vector2();
|
||||
private float lastDistance = -1f;
|
||||
private boolean canPan;
|
||||
/** Set of completed guides. */
|
||||
private ObjectSet<String> guides = new ObjectSet<>();
|
||||
@@ -691,8 +692,11 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
|
||||
@Override
|
||||
public boolean zoom(float initialDistance, float distance){
|
||||
float amount = (distance > initialDistance ? 0.1f : -0.1f) * Time.delta();
|
||||
if(lastDistance == -1) lastDistance = initialDistance;
|
||||
|
||||
float amount = (distance > lastDistance ? 0.07f : -0.07f) * Time.delta();
|
||||
renderer.scaleCamera(io.anuke.arc.scene.ui.layout.Unit.dp.scl(amount));
|
||||
lastDistance = distance;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import java.util.zip.InflaterInputStream;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
//TODO load backup meta if possible
|
||||
public class SaveIO{
|
||||
public static final IntArray breakingVersions = IntArray.with(47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 63);
|
||||
public static final IntMap<SaveFileVersion> versions = new IntMap<>();
|
||||
@@ -65,9 +66,7 @@ public class SaveIO{
|
||||
public static boolean isSaveValid(DataInputStream stream){
|
||||
|
||||
try{
|
||||
int version = stream.readInt();
|
||||
SaveFileVersion ver = versions.get(version);
|
||||
ver.getData(stream);
|
||||
getData(stream);
|
||||
return true;
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
|
||||
@@ -180,7 +180,7 @@ public class FortressGenerator{
|
||||
Block block = tile.block();
|
||||
|
||||
if(block instanceof PowerTurret){
|
||||
tile.entity.power.amount = block.powerCapacity;
|
||||
tile.entity.power.satisfaction = 1.0f;
|
||||
}else if(block instanceof ItemTurret){
|
||||
ItemTurret turret = (ItemTurret)block;
|
||||
AmmoType[] type = turret.getAmmoTypes();
|
||||
|
||||
@@ -26,12 +26,11 @@ public abstract class BaseBlock extends MappableContent{
|
||||
public boolean outputsLiquid = false;
|
||||
public boolean singleLiquid = true;
|
||||
public boolean consumesPower = true;
|
||||
public boolean outputsPower;
|
||||
public boolean outputsPower = false;
|
||||
|
||||
public int itemCapacity = 10;
|
||||
public float liquidCapacity = 10f;
|
||||
public float liquidFlowFactor = 4.9f;
|
||||
public float powerCapacity = 10f;
|
||||
|
||||
public Consumers consumes = new Consumers();
|
||||
public Producers produces = new Producers();
|
||||
@@ -40,6 +39,10 @@ public abstract class BaseBlock extends MappableContent{
|
||||
return true;
|
||||
}
|
||||
|
||||
public float getPowerProduction(Tile tile){
|
||||
return 0f;
|
||||
}
|
||||
|
||||
/**Returns the amount of items this block can accept.*/
|
||||
public int acceptStack(Item item, int amount, Tile tile, Unit source){
|
||||
if(acceptItem(item, tile, tile) && hasItems && (source == null || source.getTeam() == tile.getTeam())){
|
||||
@@ -98,19 +101,6 @@ public abstract class BaseBlock extends MappableContent{
|
||||
tile.entity.liquids.add(liquid, amount);
|
||||
}
|
||||
|
||||
public boolean acceptPower(Tile tile, Tile source, float amount){
|
||||
return true;
|
||||
}
|
||||
|
||||
/**Returns how much power is accepted.*/
|
||||
public float addPower(Tile tile, float amount){
|
||||
float canAccept = Math.min(powerCapacity - tile.entity.power.amount, amount);
|
||||
|
||||
tile.entity.power.amount += canAccept;
|
||||
|
||||
return canAccept;
|
||||
}
|
||||
|
||||
public void tryDumpLiquid(Tile tile, Liquid liquid){
|
||||
Array<Tile> proximity = tile.entity.proximity();
|
||||
int dump = tile.getDump();
|
||||
|
||||
@@ -28,6 +28,7 @@ import io.anuke.mindustry.graphics.Palette;
|
||||
import io.anuke.mindustry.type.ContentType;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.type.ItemStack;
|
||||
import io.anuke.mindustry.world.consumers.ConsumePower;
|
||||
import io.anuke.mindustry.world.meta.*;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
@@ -179,6 +180,14 @@ public class Block extends BaseBlock {
|
||||
return out;
|
||||
}
|
||||
|
||||
protected float getProgressIncrease(TileEntity entity, float baseTime){
|
||||
float progressIncrease = 1f / baseTime * entity.delta();
|
||||
if(hasPower){
|
||||
progressIncrease *= entity.power.satisfaction; // Reduced increase in case of low power
|
||||
}
|
||||
return progressIncrease;
|
||||
}
|
||||
|
||||
public boolean isLayer(Tile tile){
|
||||
return true;
|
||||
}
|
||||
@@ -321,7 +330,7 @@ public class Block extends BaseBlock {
|
||||
|
||||
consumes.forEach(cons -> cons.display(stats));
|
||||
|
||||
if(hasPower) stats.add(BlockStat.powerCapacity, powerCapacity, StatUnit.powerUnits);
|
||||
// Note: Power stats are added by the consumers.
|
||||
if(hasLiquids) stats.add(BlockStat.liquidCapacity, liquidCapacity, StatUnit.liquidUnits);
|
||||
if(hasItems) stats.add(BlockStat.itemCapacity, itemCapacity, StatUnit.items);
|
||||
}
|
||||
@@ -379,8 +388,8 @@ public class Block extends BaseBlock {
|
||||
explosiveness += tile.entity.liquids.sum((liquid, amount) -> liquid.flammability * amount / 2f);
|
||||
}
|
||||
|
||||
if(hasPower){
|
||||
power += tile.entity.power.amount;
|
||||
if(consumes.has(ConsumePower.class) && consumes.get(ConsumePower.class).isBuffered){
|
||||
power += tile.entity.power.satisfaction * consumes.get(ConsumePower.class).powerCapacity;
|
||||
}
|
||||
|
||||
if(hasLiquids){
|
||||
@@ -529,4 +538,4 @@ public class Block extends BaseBlock {
|
||||
"entity.graph", tile.entity.power != null && tile.entity.power.graph != null ? tile.entity.power.graph.getID() : null
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,22 +59,6 @@ public class BlockPart extends Block{
|
||||
block.handleLiquid(tile.getLinked(), source, liquid, amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float addPower(Tile tile, float amount){
|
||||
Block block = linked(tile);
|
||||
if(block.hasPower){
|
||||
return block.addPower(tile.getLinked(), amount);
|
||||
}else{
|
||||
return amount;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptPower(Tile tile, Tile from, float amount){
|
||||
Block block = linked(tile);
|
||||
return block.hasPower && block.acceptPower(tile.getLinked(), from, amount);
|
||||
}
|
||||
|
||||
private Block linked(Tile tile){
|
||||
return tile.getLinked().block();
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import io.anuke.mindustry.graphics.Palette;
|
||||
import io.anuke.mindustry.world.Block;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.consumers.ConsumeLiquidFilter;
|
||||
import io.anuke.mindustry.world.consumers.ConsumePower;
|
||||
import io.anuke.mindustry.world.meta.BlockStat;
|
||||
import io.anuke.mindustry.world.meta.StatUnit;
|
||||
|
||||
@@ -40,9 +41,12 @@ public class ForceProjector extends Block {
|
||||
protected float cooldownNormal = 1.75f;
|
||||
protected float cooldownLiquid = 1.5f;
|
||||
protected float cooldownBrokenBase = 0.35f;
|
||||
protected float basePowerDraw = 0.2f;
|
||||
protected float powerDamage = 0.1f;
|
||||
protected final ConsumeForceProjectorPower consumePower;
|
||||
protected TextureRegion topRegion;
|
||||
|
||||
|
||||
public ForceProjector(String name) {
|
||||
super(name);
|
||||
update = true;
|
||||
@@ -50,9 +54,10 @@ public class ForceProjector extends Block {
|
||||
hasPower = true;
|
||||
canOverdrive = false;
|
||||
hasLiquids = true;
|
||||
powerCapacity = 60f;
|
||||
hasItems = true;
|
||||
consumes.add(new ConsumeLiquidFilter(liquid -> liquid.temperature <= 0.5f && liquid.flammability < 0.1f, 0.1f)).optional(true).update(false);
|
||||
consumePower = new ConsumeForceProjectorPower(60f, 60f);
|
||||
consumes.add(consumePower);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -65,6 +70,7 @@ public class ForceProjector extends Block {
|
||||
public void setStats(){
|
||||
super.setStats();
|
||||
|
||||
stats.add(BlockStat.powerUse, basePowerDraw * 60f, StatUnit.powerSecond);
|
||||
stats.add(BlockStat.powerDamage, powerDamage, StatUnit.powerUnits);
|
||||
}
|
||||
|
||||
@@ -90,15 +96,27 @@ public class ForceProjector extends Block {
|
||||
Effects.effect(BlockFx.reactorsmoke, tile.drawx() + Mathf.range(tilesize/2f), tile.drawy() + Mathf.range(tilesize/2f));
|
||||
}
|
||||
|
||||
if(!entity.cons.valid() && !cheat){
|
||||
// Use Cases:
|
||||
// - There is enough power in the buffer, and there are no shots fired => Draw base power and keep shield up
|
||||
// - There is enough power in the buffer, but not enough power to cope for shots being fired => Draw all power and break shield
|
||||
// - There is enough power in the buffer and enough power to cope for shots being fired => Draw base power + additional power based on shots absorbed
|
||||
// - There is not enough base power in the buffer => Draw all power and break shield
|
||||
// - The generator is in the AI base and uses cheat mode => Only draw power from shots being absorbed
|
||||
|
||||
float relativePowerDraw = 0.0f;
|
||||
if(!cheat){
|
||||
relativePowerDraw = basePowerDraw / consumePower.powerCapacity;
|
||||
}
|
||||
|
||||
if(entity.power.satisfaction < relativePowerDraw){
|
||||
entity.warmup = Mathf.lerpDelta(entity.warmup, 0f, 0.15f);
|
||||
entity.power.satisfaction = .0f;
|
||||
if(entity.warmup <= 0.09f){
|
||||
entity.broken = true;
|
||||
}
|
||||
}else{
|
||||
entity.warmup = Mathf.lerpDelta(entity.warmup, 1f, 0.1f);
|
||||
float powerUse = Math.min(powerDamage * entity.delta() * (1f + entity.buildup / breakage), powerCapacity);
|
||||
entity.power.amount -= powerUse;
|
||||
entity.power.satisfaction -= Math.min(entity.power.satisfaction, relativePowerDraw);
|
||||
}
|
||||
|
||||
if(entity.buildup > 0){
|
||||
@@ -133,12 +151,12 @@ public class ForceProjector extends Block {
|
||||
if(trait.canBeAbsorbed() && trait.getTeam() != tile.getTeam() && isInsideHexagon(trait.getX(), trait.getY(), realRadius * 2f, tile.drawx(), tile.drawy())){
|
||||
trait.absorb();
|
||||
Effects.effect(BulletFx.absorb, trait);
|
||||
float hit = trait.getShieldDamage()*powerDamage;
|
||||
float relativeDamagePowerDraw = trait.getShieldDamage() * powerDamage / consumePower.powerCapacity;
|
||||
entity.hit = 1f;
|
||||
entity.power.amount -= Math.min(hit, entity.power.amount);
|
||||
|
||||
if(entity.power.amount <= 0.0001f){
|
||||
entity.buildup += trait.getShieldDamage() * entity.warmup*2f;
|
||||
entity.power.satisfaction -= Math.min(relativeDamagePowerDraw, entity.power.satisfaction);
|
||||
if(entity.power.satisfaction <= 0.0001f){
|
||||
entity.buildup += trait.getShieldDamage() * entity.warmup * 2f;
|
||||
}
|
||||
entity.buildup += trait.getShieldDamage() * entity.warmup;
|
||||
}
|
||||
@@ -245,4 +263,14 @@ public class ForceProjector extends Block {
|
||||
return shieldGroup;
|
||||
}
|
||||
}
|
||||
|
||||
public class ConsumeForceProjectorPower extends ConsumePower{
|
||||
public ConsumeForceProjectorPower(float powerCapacity, float ticksToFill){
|
||||
super(powerCapacity / ticksToFill, 0.0f, powerCapacity, true);
|
||||
}
|
||||
@Override
|
||||
public boolean valid(Block block, TileEntity entity){
|
||||
return entity.power.satisfaction >= basePowerDraw / powerCapacity && super.valid(block, entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ public class MendProjector extends Block{
|
||||
other = other.target();
|
||||
|
||||
if(other.getTeamID() == tile.getTeamID() && !healed.contains(other.pos()) && other.entity != null && other.entity.health < other.entity.maxHealth()){
|
||||
other.entity.healBy(other.entity.maxHealth() * (healPercent + entity.phaseHeat*phaseBoost)/100f);
|
||||
other.entity.healBy(other.entity.maxHealth() * (healPercent + entity.phaseHeat*phaseBoost)/100f * entity.power.satisfaction);
|
||||
Effects.effect(BlockFx.healBlockFull, Tmp.c1.set(color).lerp(phase, entity.phaseHeat), other.drawx(), other.drawy(), other.block().size);
|
||||
healed.add(other.pos());
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ public class OverdriveProjector extends Block{
|
||||
|
||||
if(entity.charge >= reload){
|
||||
float realRange = range + entity.phaseHeat * phaseRangeBoost;
|
||||
float realBoost = speedBoost + entity.phaseHeat*speedBoostPhase;
|
||||
float realBoost = (speedBoost + entity.phaseHeat*speedBoostPhase) * entity.power.satisfaction;
|
||||
|
||||
Effects.effect(BlockFx.overdriveWave, Tmp.c1.set(color).lerp(phase, entity.phaseHeat), tile.drawx(), tile.drawy(), realRange);
|
||||
entity.charge = 0f;
|
||||
|
||||
@@ -6,6 +6,7 @@ import io.anuke.mindustry.world.meta.BlockStat;
|
||||
import io.anuke.mindustry.world.meta.StatUnit;
|
||||
|
||||
public abstract class PowerTurret extends CooledTurret{
|
||||
/** The percentage of power which will be used per shot. */
|
||||
protected float powerUsed = 0.5f;
|
||||
protected AmmoType shootType;
|
||||
|
||||
@@ -23,13 +24,15 @@ public abstract class PowerTurret extends CooledTurret{
|
||||
|
||||
@Override
|
||||
public boolean hasAmmo(Tile tile){
|
||||
return tile.entity.power.amount >= powerUsed;
|
||||
// Allow shooting as long as the turret is at least at 50% power
|
||||
return tile.entity.power.satisfaction >= powerUsed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AmmoType useAmmo(Tile tile){
|
||||
if(tile.isEnemyCheat()) return shootType;
|
||||
tile.entity.power.amount -= powerUsed;
|
||||
// Make sure that power can not go negative in case of threading issues or similar
|
||||
tile.entity.power.satisfaction -= Math.min(powerUsed, tile.entity.power.satisfaction);
|
||||
return shootType;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,11 @@ public class LiquidBridge extends ItemBridge{
|
||||
tryDumpLiquid(tile, entity.liquids.current());
|
||||
}else{
|
||||
if(entity.cons.valid()){
|
||||
entity.uptime = Mathf.lerpDelta(entity.uptime, 1f, 0.04f);
|
||||
float alpha = 0.04f;
|
||||
if(hasPower){
|
||||
alpha *= entity.power.satisfaction; // Exceed boot time unless power is at max.
|
||||
}
|
||||
entity.uptime = Mathf.lerpDelta(entity.uptime, 1f, alpha);
|
||||
}else{
|
||||
entity.uptime = Mathf.lerpDelta(entity.uptime, 0f, 0.02f);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import io.anuke.mindustry.graphics.Palette;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.world.Block;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.consumers.ConsumePower;
|
||||
import io.anuke.mindustry.world.meta.BlockStat;
|
||||
import io.anuke.mindustry.world.meta.StatUnit;
|
||||
|
||||
@@ -48,6 +49,7 @@ public class MassDriver extends Block{
|
||||
protected Effect smokeEffect = ShootFx.shootBigSmoke2;
|
||||
protected Effect recieveEffect = BlockFx.mineBig;
|
||||
protected float shake = 3f;
|
||||
protected final static float powerPercentageUsed = 1.0f;
|
||||
protected TextureRegion turretRegion;
|
||||
|
||||
public MassDriver(String name){
|
||||
@@ -58,6 +60,8 @@ public class MassDriver extends Block{
|
||||
hasItems = true;
|
||||
layer = Layer.turret;
|
||||
hasPower = true;
|
||||
consumes.powerBuffered(30f);
|
||||
consumes.require(ConsumePower.class);
|
||||
}
|
||||
|
||||
@Remote(targets = Loc.both, called = Loc.server, forward = true)
|
||||
@@ -77,7 +81,8 @@ public class MassDriver extends Block{
|
||||
MassDriverEntity other = target.entity();
|
||||
|
||||
entity.reload = 1f;
|
||||
entity.power.amount = 0f;
|
||||
|
||||
entity.power.satisfaction -= Math.min(entity.power.satisfaction, powerPercentageUsed);
|
||||
|
||||
DriverBulletData data = Pools.obtain(DriverBulletData.class, DriverBulletData::new);
|
||||
data.from = entity;
|
||||
@@ -125,7 +130,7 @@ public class MassDriver extends Block{
|
||||
public void setStats(){
|
||||
super.setStats();
|
||||
|
||||
stats.add(BlockStat.powerShot, powerCapacity, StatUnit.powerUnits);
|
||||
stats.add(BlockStat.powerShot, consumes.get(ConsumePower.class).powerCapacity * powerPercentageUsed, StatUnit.powerUnits);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -164,8 +169,8 @@ public class MassDriver extends Block{
|
||||
|
||||
entity.rotation = Mathf.slerpDelta(entity.rotation, tile.angleTo(waiter), rotateSpeed);
|
||||
}else if(tile.entity.items.total() >= minDistribute &&
|
||||
linkValid(tile) && //only fire when at least at half-capacity and power
|
||||
tile.entity.power.amount >= powerCapacity * 0.8f &&
|
||||
linkValid(tile) && //only fire when at 100% power capacity
|
||||
tile.entity.power.satisfaction >= powerPercentageUsed &&
|
||||
link.block().itemCapacity - link.entity.items.total() >= minDistribute && entity.reload <= 0.0001f){
|
||||
|
||||
MassDriverEntity other = link.entity();
|
||||
|
||||
@@ -6,7 +6,7 @@ import io.anuke.mindustry.type.Liquid;
|
||||
public class BurnerGenerator extends ItemLiquidGenerator{
|
||||
|
||||
public BurnerGenerator(String name){
|
||||
super(name);
|
||||
super(InputType.LiquidsAndItems, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package io.anuke.mindustry.world.blocks.power;
|
||||
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.type.Liquid;
|
||||
|
||||
public class DecayGenerator extends ItemGenerator{
|
||||
public class DecayGenerator extends ItemLiquidGenerator{
|
||||
|
||||
public DecayGenerator(String name){
|
||||
super(name);
|
||||
super(InputType.ItemsOnly, name);
|
||||
hasItems = true;
|
||||
hasLiquids = false;
|
||||
}
|
||||
|
||||
@@ -9,13 +9,13 @@ import io.anuke.arc.math.Mathf;
|
||||
import io.anuke.arc.util.Time;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.production.GenericCrafter.GenericCrafterEntity;
|
||||
import io.anuke.mindustry.world.meta.BlockStat;
|
||||
import io.anuke.mindustry.world.meta.StatUnit;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
public class FusionReactor extends PowerGenerator{
|
||||
protected int plasmas = 4;
|
||||
protected float maxPowerProduced = 2f;
|
||||
protected float warmupSpeed = 0.001f;
|
||||
|
||||
protected Color plasma1 = Color.valueOf("ffd06b"), plasma2 = Color.valueOf("ff361b");
|
||||
@@ -25,33 +25,27 @@ public class FusionReactor extends PowerGenerator{
|
||||
super(name);
|
||||
hasPower = true;
|
||||
hasLiquids = true;
|
||||
powerCapacity = 100f;
|
||||
powerProduction = 2.0f;
|
||||
liquidCapacity = 30f;
|
||||
hasItems = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStats(){
|
||||
super.setStats();
|
||||
|
||||
stats.add(BlockStat.basePowerGeneration, maxPowerProduced * 60f, StatUnit.powerSecond);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
FusionReactorEntity entity = tile.entity();
|
||||
|
||||
float increaseOrDecrease = 1.0f;
|
||||
if(entity.cons.valid()){
|
||||
entity.warmup = Mathf.lerpDelta(entity.warmup, 1f, warmupSpeed);
|
||||
}else{
|
||||
entity.warmup = Mathf.lerpDelta(entity.warmup, 0f, 0.01f);
|
||||
increaseOrDecrease = -1.0f;
|
||||
}
|
||||
|
||||
float powerAdded = Math.min(powerCapacity - entity.power.amount, maxPowerProduced * Mathf.pow(entity.warmup, 4f) * Time.delta());
|
||||
entity.power.amount += powerAdded;
|
||||
entity.totalProgress += entity.warmup * Time.delta();
|
||||
float efficiencyAdded = Mathf.pow(entity.warmup, 4f) * Time.delta();
|
||||
entity.productionEfficiency = Mathf.clamp(entity.productionEfficiency + efficiencyAdded * increaseOrDecrease);
|
||||
|
||||
tile.entity.power.graph.update();
|
||||
super.update(tile);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -95,7 +89,7 @@ public class FusionReactor extends PowerGenerator{
|
||||
|
||||
Draw.rect(name + "-top", tile.drawx(), tile.drawy());
|
||||
|
||||
Draw.color(ind1, ind2, entity.warmup + Mathf.absin(entity.totalProgress, 3f, entity.warmup * 0.5f));
|
||||
Draw.color(ind1, ind2, entity.warmup + Mathf.absin(entity.productionEfficiency, 3f, entity.warmup * 0.5f));
|
||||
Draw.rect(name + "-light", tile.drawx(), tile.drawy());
|
||||
|
||||
Draw.color();
|
||||
@@ -122,7 +116,19 @@ public class FusionReactor extends PowerGenerator{
|
||||
//TODO catastrophic failure
|
||||
}
|
||||
|
||||
public static class FusionReactorEntity extends GenericCrafterEntity{
|
||||
public static class FusionReactorEntity extends GeneratorEntity{
|
||||
public float warmup;
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
super.write(stream);
|
||||
stream.writeFloat(warmup);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream) throws IOException{
|
||||
super.read(stream);
|
||||
warmup = stream.readFloat();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
package io.anuke.mindustry.world.blocks.power;
|
||||
|
||||
import io.anuke.arc.Core;
|
||||
import io.anuke.arc.graphics.Color;
|
||||
import io.anuke.arc.graphics.g2d.TextureRegion;
|
||||
import io.anuke.mindustry.content.fx.BlockFx;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.consumers.ConsumeItemFilter;
|
||||
import io.anuke.mindustry.world.meta.BlockStat;
|
||||
import io.anuke.mindustry.world.meta.StatUnit;
|
||||
import io.anuke.arc.entities.Effects;
|
||||
import io.anuke.arc.entities.Effects.Effect;
|
||||
import io.anuke.arc.util.Time;
|
||||
import io.anuke.arc.graphics.g2d.Draw;
|
||||
import io.anuke.arc.math.Mathf;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
import static io.anuke.mindustry.Vars.tilesize;
|
||||
|
||||
public abstract class ItemGenerator extends PowerGenerator{
|
||||
protected float minItemEfficiency = 0.2f;
|
||||
protected float powerOutput;
|
||||
protected float itemDuration = 70f;
|
||||
protected Effect generateEffect = BlockFx.generatespark, explodeEffect =
|
||||
BlockFx.generatespark;
|
||||
protected Color heatColor = Color.valueOf("ff9b59");
|
||||
protected TextureRegion topRegion;
|
||||
|
||||
public ItemGenerator(String name){
|
||||
super(name);
|
||||
hasItems = true;
|
||||
|
||||
consumes.add(new ConsumeItemFilter(item -> getItemEfficiency(item) >= minItemEfficiency)).update(false).optional(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(){
|
||||
super.load();
|
||||
topRegion = Core.atlas.find(name + "-top");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStats(){
|
||||
super.setStats();
|
||||
|
||||
stats.add(BlockStat.basePowerGeneration, powerOutput * 60f * 0.5f, StatUnit.powerSecond);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
super.draw(tile);
|
||||
|
||||
GeneratorEntity entity = tile.entity();
|
||||
|
||||
if(entity.generateTime > 0){
|
||||
Draw.color(heatColor);
|
||||
float alpha = (entity.items.total() > 0 ? 1f : Mathf.clamp(entity.generateTime));
|
||||
alpha = alpha * 0.7f + Mathf.absin(Time.time(), 12f, 0.3f) * alpha;
|
||||
Draw.alpha(alpha);
|
||||
Draw.rect(topRegion, tile.drawx(), tile.drawy());
|
||||
Draw.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
return getItemEfficiency(item) >= minItemEfficiency && tile.entity.items.total() < itemCapacity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
ItemGeneratorEntity entity = tile.entity();
|
||||
|
||||
float maxPower = Math.min(powerCapacity - entity.power.amount, powerOutput * entity.delta()) * entity.efficiency;
|
||||
|
||||
if(entity.generateTime <= 0f && entity.items.total() > 0){
|
||||
Effects.effect(generateEffect, tile.worldx() + Mathf.range(3f), tile.worldy() + Mathf.range(3f));
|
||||
Item item = entity.items.take();
|
||||
entity.efficiency = getItemEfficiency(item);
|
||||
entity.explosiveness = item.explosiveness;
|
||||
entity.generateTime = 1f;
|
||||
}
|
||||
|
||||
entity.power.graph.update();
|
||||
|
||||
if(entity.generateTime > 0f){
|
||||
entity.generateTime -= 1f / itemDuration * entity.delta();
|
||||
entity.power.amount += maxPower;
|
||||
entity.generateTime = Mathf.clamp(entity.generateTime);
|
||||
|
||||
if(Mathf.chance(entity.delta() * 0.06 * Mathf.clamp(entity.explosiveness - 0.25f))){
|
||||
//this block is run last so that in the event of a block destruction, no code relies on the block type
|
||||
entity.damage(Mathf.random(8f));
|
||||
Effects.effect(explodeEffect, tile.worldx() + Mathf.range(size * tilesize / 2f), tile.worldy() + Mathf.range(size * tilesize / 2f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract float getItemEfficiency(Item item);
|
||||
|
||||
@Override
|
||||
public TileEntity newEntity(){
|
||||
return new ItemGeneratorEntity();
|
||||
}
|
||||
|
||||
public static class ItemGeneratorEntity extends GeneratorEntity{
|
||||
public float efficiency;
|
||||
public float explosiveness;
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
stream.writeFloat(efficiency);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream) throws IOException{
|
||||
efficiency = stream.readFloat();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,107 +1,186 @@
|
||||
package io.anuke.mindustry.world.blocks.power;
|
||||
|
||||
import io.anuke.arc.Core;
|
||||
import io.anuke.arc.entities.Effects;
|
||||
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.util.Time;
|
||||
import io.anuke.mindustry.content.fx.BlockFx;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.type.Liquid;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.consumers.ConsumeItemFilter;
|
||||
import io.anuke.mindustry.world.consumers.ConsumeLiquidFilter;
|
||||
import io.anuke.arc.entities.Effects;
|
||||
import io.anuke.arc.graphics.g2d.Draw;
|
||||
import io.anuke.arc.math.Mathf;
|
||||
|
||||
import static io.anuke.mindustry.Vars.content;
|
||||
import static io.anuke.mindustry.Vars.tilesize;
|
||||
|
||||
public abstract class ItemLiquidGenerator extends ItemGenerator{
|
||||
/**
|
||||
* Power generation block which can use items, liquids or both as input sources for power production.
|
||||
* Liquids will take priority over items.
|
||||
*/
|
||||
public class ItemLiquidGenerator extends PowerGenerator{
|
||||
|
||||
protected float minItemEfficiency = 0.2f;
|
||||
/** The time in number of ticks during which a single item will produce power. */
|
||||
protected float itemDuration = 70f;
|
||||
|
||||
protected float minLiquidEfficiency = 0.2f;
|
||||
protected float powerPerLiquid = 0.13f;
|
||||
/**Maximum liquid used per frame.*/
|
||||
/** Maximum liquid used per frame. */
|
||||
protected float maxLiquidGenerate = 0.4f;
|
||||
|
||||
public ItemLiquidGenerator(String name){
|
||||
super(name);
|
||||
hasLiquids = true;
|
||||
liquidCapacity = 10f;
|
||||
protected Effects.Effect generateEffect = BlockFx.generatespark;
|
||||
protected Effects.Effect explodeEffect = BlockFx.generatespark;
|
||||
protected Color heatColor = Color.valueOf("ff9b59");
|
||||
protected TextureRegion topRegion;
|
||||
|
||||
consumes.add(new ConsumeLiquidFilter(liquid -> getLiquidEfficiency(liquid) >= minLiquidEfficiency, 0.001f, true)).update(false).optional(true);
|
||||
public enum InputType{
|
||||
ItemsOnly,
|
||||
LiquidsOnly,
|
||||
LiquidsAndItems
|
||||
}
|
||||
|
||||
public ItemLiquidGenerator(InputType inputType, String name){
|
||||
super(name);
|
||||
this.hasItems = inputType != InputType.LiquidsOnly;
|
||||
this.hasLiquids = inputType != InputType.ItemsOnly;
|
||||
|
||||
if(hasItems){
|
||||
itemCapacity = 20;
|
||||
consumes.add(new ConsumeItemFilter(item -> getItemEfficiency(item) >= minItemEfficiency)).update(false).optional(true);
|
||||
}
|
||||
|
||||
if(hasLiquids){
|
||||
liquidCapacity = 10f;
|
||||
consumes.add(new ConsumeLiquidFilter(liquid -> getLiquidEfficiency(liquid) >= minLiquidEfficiency, 0.001f, true)).update(false).optional(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(){
|
||||
super.init();
|
||||
public void load(){
|
||||
super.load();
|
||||
if(hasItems){
|
||||
topRegion = Core.atlas.find(name + "-top");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
ItemGeneratorEntity entity = tile.entity();
|
||||
ItemLiquidGeneratorEntity entity = tile.entity();
|
||||
|
||||
entity.power.graph.update();
|
||||
// Note: Do not use this delta when calculating the amount of power or the power efficiency, but use it for resource consumption if necessary.
|
||||
// Power amount is delta'd by PowerGraph class already.
|
||||
float calculationDelta = entity.delta();
|
||||
|
||||
if(!entity.cons.valid()){
|
||||
entity.productionEfficiency = 0.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
Liquid liquid = null;
|
||||
for(Liquid other : content.liquids()){
|
||||
if(entity.liquids.get(other) >= 0.001f && getLiquidEfficiency(other) >= minLiquidEfficiency){
|
||||
if(hasLiquids && entity.liquids.get(other) >= 0.001f && getLiquidEfficiency(other) >= minLiquidEfficiency){
|
||||
liquid = other;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//liquid takes priority over solids
|
||||
if(liquid != null && entity.liquids.get(liquid) >= 0.001f && entity.cons.valid()){
|
||||
float powerPerLiquid = getLiquidEfficiency(liquid) * this.powerPerLiquid;
|
||||
float used = Math.min(entity.liquids.get(liquid), maxLiquidGenerate * entity.delta());
|
||||
used = Math.min(used, (powerCapacity - entity.power.amount) / powerPerLiquid);
|
||||
if(hasLiquids && liquid != null && entity.liquids.get(liquid) >= 0.001f){
|
||||
float baseLiquidEfficiency = getLiquidEfficiency(liquid);
|
||||
float maximumPossible = maxLiquidGenerate * calculationDelta;
|
||||
float used = Math.min(entity.liquids.get(liquid) * calculationDelta, maximumPossible);
|
||||
|
||||
entity.liquids.remove(liquid, used);
|
||||
entity.power.amount += used * powerPerLiquid;
|
||||
|
||||
// Note: 0.5 = 100%. PowerGraph will multiply this efficiency by two on its own.
|
||||
entity.productionEfficiency = Mathf.clamp(baseLiquidEfficiency * used / maximumPossible);
|
||||
|
||||
if(used > 0.001f && Mathf.chance(0.05 * entity.delta())){
|
||||
Effects.effect(generateEffect, tile.drawx() + Mathf.range(3f), tile.drawy() + Mathf.range(3f));
|
||||
}
|
||||
}else if(entity.cons.valid()){
|
||||
|
||||
float maxPower = Math.min(powerCapacity - entity.power.amount, powerOutput * entity.delta()) * entity.efficiency;
|
||||
|
||||
}else if(hasItems){
|
||||
// No liquids accepted or none supplied, try using items if accepted
|
||||
if(entity.generateTime <= 0f && entity.items.total() > 0){
|
||||
Effects.effect(generateEffect, tile.worldx() + Mathf.range(3f), tile.worldy() + Mathf.range(3f));
|
||||
Item item = entity.items.take();
|
||||
entity.efficiency = getItemEfficiency(item);
|
||||
entity.productionEfficiency = getItemEfficiency(item);
|
||||
entity.explosiveness = item.explosiveness;
|
||||
entity.generateTime = 1f;
|
||||
}
|
||||
|
||||
if(entity.generateTime > 0f){
|
||||
entity.generateTime -= 1f / itemDuration * entity.delta();
|
||||
entity.power.amount += maxPower;
|
||||
entity.generateTime = Mathf.clamp(entity.generateTime);
|
||||
entity.generateTime -= Math.min(1f / itemDuration * entity.delta(), entity.generateTime);
|
||||
|
||||
if(Mathf.chance(entity.delta() * 0.06 * Mathf.clamp(entity.explosiveness - 0.25f))){
|
||||
//this block is run last so that in the event of a block destruction, no code relies on the block type
|
||||
entity.damage(Mathf.random(8f));
|
||||
Effects.effect(explodeEffect, tile.worldx() + Mathf.range(size * tilesize / 2f), tile.worldy() + Mathf.range(size * tilesize / 2f));
|
||||
}
|
||||
}else{
|
||||
entity.productionEfficiency = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
super.update(tile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
return hasItems && getItemEfficiency(item) >= minItemEfficiency && tile.entity.items.total() < itemCapacity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){
|
||||
return hasLiquids && getLiquidEfficiency(liquid) >= minLiquidEfficiency && tile.entity.liquids.get(liquid) < liquidCapacity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
super.draw(tile);
|
||||
|
||||
TileEntity entity = tile.entity();
|
||||
GeneratorEntity entity = tile.entity();
|
||||
|
||||
Draw.color(entity.liquids.current().color);
|
||||
Draw.alpha(entity.liquids.currentAmount() / liquidCapacity);
|
||||
drawLiquidCenter(tile);
|
||||
Draw.color();
|
||||
}
|
||||
if(hasItems){
|
||||
if(entity.generateTime > 0){
|
||||
Draw.color(heatColor);
|
||||
float alpha = (entity.items.total() > 0 ? 1f : Mathf.clamp(entity.generateTime));
|
||||
alpha = alpha * 0.7f + Mathf.absin(Time.time(), 12f, 0.3f) * alpha;
|
||||
Draw.alpha(alpha);
|
||||
Draw.rect(topRegion, tile.drawx(), tile.drawy());
|
||||
Draw.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){
|
||||
return getLiquidEfficiency(liquid) >= minLiquidEfficiency && tile.entity.liquids.get(liquid) < liquidCapacity;
|
||||
if(hasLiquids){
|
||||
Draw.color(entity.liquids.current().color);
|
||||
Draw.alpha(entity.liquids.currentAmount() / liquidCapacity);
|
||||
drawLiquidCenter(tile);
|
||||
Draw.color();
|
||||
}
|
||||
}
|
||||
|
||||
public void drawLiquidCenter(Tile tile){
|
||||
Draw.rect("blank", tile.drawx(), tile.drawy(), 2, 2);
|
||||
}
|
||||
|
||||
protected abstract float getLiquidEfficiency(Liquid liquid);
|
||||
protected float getItemEfficiency(Item item){
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
protected float getLiquidEfficiency(Liquid liquid){
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileEntity newEntity(){
|
||||
return new ItemLiquidGeneratorEntity();
|
||||
}
|
||||
|
||||
public static class ItemLiquidGeneratorEntity extends GeneratorEntity{
|
||||
public float explosiveness;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
package io.anuke.mindustry.world.blocks.power;
|
||||
|
||||
import io.anuke.mindustry.content.fx.BlockFx;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.type.Liquid;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.power.ItemGenerator.ItemGeneratorEntity;
|
||||
import io.anuke.mindustry.world.consumers.ConsumeLiquidFilter;
|
||||
import io.anuke.arc.entities.Effects;
|
||||
import io.anuke.arc.entities.Effects.Effect;
|
||||
import io.anuke.arc.graphics.g2d.Draw;
|
||||
import io.anuke.arc.math.Mathf;
|
||||
|
||||
public abstract class LiquidGenerator extends PowerGenerator{
|
||||
protected float minEfficiency = 0.2f;
|
||||
protected float powerPerLiquid;
|
||||
/**Maximum liquid used per frame.*/
|
||||
protected float maxLiquidGenerate;
|
||||
protected Effect generateEffect = BlockFx.generatespark;
|
||||
|
||||
public LiquidGenerator(String name){
|
||||
super(name);
|
||||
liquidCapacity = 30f;
|
||||
hasLiquids = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStats(){
|
||||
consumes.add(new ConsumeLiquidFilter(liquid -> getEfficiency(liquid) >= minEfficiency, maxLiquidGenerate)).update(false);
|
||||
super.setStats();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
super.draw(tile);
|
||||
|
||||
TileEntity entity = tile.entity();
|
||||
|
||||
Draw.color(entity.liquids.current().color);
|
||||
Draw.alpha(entity.liquids.total() / liquidCapacity);
|
||||
drawLiquidCenter(tile);
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
public void drawLiquidCenter(Tile tile){
|
||||
Draw.rect("blank", tile.drawx(), tile.drawy(), 2, 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
TileEntity entity = tile.entity();
|
||||
|
||||
if(entity.liquids.get(entity.liquids.current()) >= 0.001f){
|
||||
float powerPerLiquid = getEfficiency(entity.liquids.current()) * this.powerPerLiquid;
|
||||
float used = Math.min(entity.liquids.currentAmount(), maxLiquidGenerate * entity.delta());
|
||||
used = Math.min(used, (powerCapacity - entity.power.amount) / powerPerLiquid);
|
||||
|
||||
entity.liquids.remove(entity.liquids.current(), used);
|
||||
entity.power.amount += used * powerPerLiquid;
|
||||
|
||||
if(used > 0.001f && Mathf.chance(0.05 * entity.delta())){
|
||||
Effects.effect(generateEffect, tile.drawx() + Mathf.range(3f), tile.drawy() + Mathf.range(3f));
|
||||
}
|
||||
}
|
||||
|
||||
tile.entity.power.graph.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){
|
||||
return getEfficiency(liquid) >= minEfficiency && super.acceptLiquid(tile, source, liquid, amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileEntity newEntity(){
|
||||
return new ItemGeneratorEntity();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an efficiency value for the specified liquid.
|
||||
* Greater efficiency means more power generation.
|
||||
* If a liquid's efficiency is below {@link #minEfficiency}, it is not accepted.
|
||||
*/
|
||||
protected abstract float getEfficiency(Liquid liquid);
|
||||
}
|
||||
@@ -1,24 +1,27 @@
|
||||
package io.anuke.mindustry.world.blocks.power;
|
||||
|
||||
import io.anuke.mindustry.content.Liquids;
|
||||
import io.anuke.mindustry.type.Liquid;
|
||||
import io.anuke.mindustry.world.meta.BlockStat;
|
||||
import io.anuke.mindustry.world.meta.StatUnit;
|
||||
|
||||
public class LiquidHeatGenerator extends LiquidGenerator{
|
||||
public class LiquidHeatGenerator extends ItemLiquidGenerator{
|
||||
|
||||
public LiquidHeatGenerator(String name){
|
||||
super(name);
|
||||
super(InputType.LiquidsOnly, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStats(){
|
||||
super.setStats();
|
||||
|
||||
stats.add(BlockStat.basePowerGeneration, maxLiquidGenerate * powerPerLiquid * 60f * 0.5f, StatUnit.powerSecond);
|
||||
stats.remove(BlockStat.basePowerGeneration);
|
||||
// Right now, Lava is the only thing that can be used.
|
||||
stats.add(BlockStat.basePowerGeneration, powerProduction * getLiquidEfficiency(Liquids.lava) / maxLiquidGenerate * 60f, StatUnit.powerSecond);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getEfficiency(Liquid liquid){
|
||||
protected float getLiquidEfficiency(Liquid liquid){
|
||||
return liquid.temperature - 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ public class NuclearReactor extends PowerGenerator{
|
||||
protected Color coolColor = new Color(1, 1, 1, 0f);
|
||||
protected Color hotColor = Color.valueOf("ff9575a3");
|
||||
protected int fuelUseTime = 120; //time to consume 1 fuel
|
||||
protected float powerMultiplier = 0.45f; //power per frame, depends on full capacity
|
||||
protected float heating = 0.013f; //heating per frame
|
||||
protected float coolantPower = 0.015f; //how much heat decreases per coolant unit
|
||||
protected float smokeThreshold = 0.3f; //threshold at which block starts smoking
|
||||
@@ -48,7 +47,6 @@ public class NuclearReactor extends PowerGenerator{
|
||||
super(name);
|
||||
itemCapacity = 30;
|
||||
liquidCapacity = 50;
|
||||
powerCapacity = 80f;
|
||||
hasItems = true;
|
||||
hasLiquids = true;
|
||||
|
||||
@@ -67,7 +65,10 @@ public class NuclearReactor extends PowerGenerator{
|
||||
public void setStats(){
|
||||
super.setStats();
|
||||
stats.add(BlockStat.inputLiquid, new LiquidFilterValue(liquid -> liquid.temperature <= 0.5f));
|
||||
stats.add(BlockStat.basePowerGeneration, powerMultiplier * 60f * 0.5f, StatUnit.powerSecond);
|
||||
|
||||
stats.remove(BlockStat.basePowerGeneration);
|
||||
// Display the power which will be produced at 50% efficiency
|
||||
stats.add(BlockStat.basePowerGeneration, powerProduction * 60f * 0.5f, StatUnit.powerSecond);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -76,11 +77,11 @@ public class NuclearReactor extends PowerGenerator{
|
||||
|
||||
int fuel = entity.items.get(consumes.item());
|
||||
float fullness = (float) fuel / itemCapacity;
|
||||
entity.productionEfficiency = fullness / 2.0f; // Currently, efficiency of 0.5 = 100%
|
||||
|
||||
if(fuel > 0){
|
||||
entity.heat += fullness * heating * Math.min(entity.delta(), 4f);
|
||||
entity.power.amount += powerMultiplier * fullness * entity.delta();
|
||||
entity.power.amount = Mathf.clamp(entity.power.amount, 0f, powerCapacity);
|
||||
|
||||
if(entity.timer.get(timerFuel, fuelUseTime)){
|
||||
entity.items.remove(consumes.item(), 1);
|
||||
}
|
||||
@@ -115,7 +116,7 @@ public class NuclearReactor extends PowerGenerator{
|
||||
if(entity.heat >= 0.999f){
|
||||
entity.kill();
|
||||
}else{
|
||||
tile.entity.power.graph.update();
|
||||
super.update(tile);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,20 @@
|
||||
package io.anuke.mindustry.world.blocks.power;
|
||||
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.world.meta.BlockFlag;
|
||||
import io.anuke.arc.collection.EnumSet;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.meta.BlockFlag;
|
||||
import io.anuke.mindustry.world.meta.BlockStat;
|
||||
import io.anuke.mindustry.world.meta.StatUnit;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
public class PowerGenerator extends PowerDistributor{
|
||||
/** The amount of power produced per tick in case of an efficiency of 1.0, which currently represents 200%. */
|
||||
protected float powerProduction;
|
||||
public BlockStat generationType = BlockStat.basePowerGeneration;
|
||||
|
||||
public PowerGenerator(String name){
|
||||
super(name);
|
||||
@@ -12,6 +22,20 @@ public class PowerGenerator extends PowerDistributor{
|
||||
flags = EnumSet.of(BlockFlag.producer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStats(){
|
||||
super.setStats();
|
||||
// Divide power production by two since that is what is produced at an efficiency of 0.5, which currently represents 100%
|
||||
stats.add(generationType, powerProduction * 60.0f / 2.0f, StatUnit.powerSecond);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getPowerProduction(Tile tile){
|
||||
// While 0.5 efficiency currently reflects 100%, we do not need to multiply by any factor since powerProduction states the
|
||||
// power which would be produced at 1.0 efficiency
|
||||
return powerProduction * tile.<GeneratorEntity>entity().productionEfficiency;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean outputsItems(){
|
||||
return false;
|
||||
@@ -24,5 +48,17 @@ public class PowerGenerator extends PowerDistributor{
|
||||
|
||||
public static class GeneratorEntity extends TileEntity{
|
||||
public float generateTime;
|
||||
/** The efficiency of the producer. Currently, an efficiency of 0.5 means 100% */
|
||||
public float productionEfficiency = 0.0f;
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
stream.writeFloat(productionEfficiency);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream) throws IOException{
|
||||
productionEfficiency = stream.readFloat();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,11 @@ import io.anuke.arc.collection.Array;
|
||||
import io.anuke.arc.collection.IntSet;
|
||||
import io.anuke.arc.collection.ObjectSet;
|
||||
import io.anuke.arc.collection.Queue;
|
||||
import io.anuke.arc.math.Mathf;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.consumers.Consume;
|
||||
import io.anuke.mindustry.world.consumers.ConsumePower;
|
||||
import io.anuke.mindustry.world.consumers.Consumers;
|
||||
|
||||
public class PowerGraph{
|
||||
private final static Queue<Tile> queue = new Queue<>();
|
||||
@@ -15,6 +19,7 @@ public class PowerGraph{
|
||||
|
||||
private final ObjectSet<Tile> producers = new ObjectSet<>();
|
||||
private final ObjectSet<Tile> consumers = new ObjectSet<>();
|
||||
private final ObjectSet<Tile> batteries = new ObjectSet<>();
|
||||
private final ObjectSet<Tile> all = new ObjectSet<>();
|
||||
|
||||
private long lastFrameUpdated;
|
||||
@@ -29,71 +34,127 @@ public class PowerGraph{
|
||||
return graphID;
|
||||
}
|
||||
|
||||
public float getPowerProduced(){
|
||||
float powerProduced = 0f;
|
||||
for(Tile producer : producers){
|
||||
powerProduced += producer.block().getPowerProduction(producer) * producer.entity.delta();
|
||||
}
|
||||
return powerProduced;
|
||||
}
|
||||
|
||||
public float getPowerNeeded(){
|
||||
float powerNeeded = 0f;
|
||||
for(Tile consumer : consumers){
|
||||
Consumers consumes = consumer.block().consumes;
|
||||
if(consumes.has(ConsumePower.class)){
|
||||
ConsumePower consumePower = consumes.get(ConsumePower.class);
|
||||
if(otherConsumersAreValid(consumer, consumePower)){
|
||||
powerNeeded += consumePower.requestedPower(consumer.block(), consumer.entity) * consumer.entity.delta();
|
||||
}
|
||||
}
|
||||
}
|
||||
return powerNeeded;
|
||||
}
|
||||
|
||||
public float getBatteryStored(){
|
||||
float totalAccumulator = 0f;
|
||||
for(Tile battery : batteries){
|
||||
Consumers consumes = battery.block().consumes;
|
||||
if(consumes.has(ConsumePower.class)){
|
||||
totalAccumulator += battery.entity.power.satisfaction * consumes.get(ConsumePower.class).powerCapacity;
|
||||
}
|
||||
}
|
||||
return totalAccumulator;
|
||||
}
|
||||
|
||||
public float getBatteryCapacity(){
|
||||
float totalCapacity = 0f;
|
||||
for(Tile battery : batteries){
|
||||
Consumers consumes = battery.block().consumes;
|
||||
if(consumes.has(ConsumePower.class)){
|
||||
totalCapacity += consumes.get(ConsumePower.class).requestedPower(battery.block(), battery.entity) * battery.entity.delta();
|
||||
}
|
||||
}
|
||||
return totalCapacity;
|
||||
}
|
||||
|
||||
public float useBatteries(float needed){
|
||||
float stored = getBatteryStored();
|
||||
if(Mathf.isEqual(stored, 0f)){ return 0f; }
|
||||
|
||||
float used = Math.min(stored, needed);
|
||||
float consumedPowerPercentage = Math.min(1.0f, needed / stored);
|
||||
for(Tile battery : batteries){
|
||||
Consumers consumes = battery.block().consumes;
|
||||
if(consumes.has(ConsumePower.class)){
|
||||
ConsumePower consumePower = consumes.get(ConsumePower.class);
|
||||
if(consumePower.powerCapacity > 0f){
|
||||
battery.entity.power.satisfaction = Math.max(0.0f, battery.entity.power.satisfaction - consumedPowerPercentage);
|
||||
}
|
||||
}
|
||||
}
|
||||
return used;
|
||||
}
|
||||
|
||||
public float chargeBatteries(float excess){
|
||||
float capacity = getBatteryCapacity();
|
||||
if(Mathf.isEqual(capacity, 0f)){ return 0f; }
|
||||
|
||||
for(Tile battery : batteries){
|
||||
Consumers consumes = battery.block().consumes;
|
||||
if(consumes.has(ConsumePower.class)){
|
||||
ConsumePower consumePower = consumes.get(ConsumePower.class);
|
||||
if(consumePower.powerCapacity > 0f){
|
||||
float additionalPowerPercentage = Math.min(1.0f, excess / consumePower.powerCapacity);
|
||||
battery.entity.power.satisfaction = Math.min(1.0f, battery.entity.power.satisfaction + additionalPowerPercentage);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Math.min(excess, capacity);
|
||||
}
|
||||
|
||||
public void distributePower(float needed, float produced){
|
||||
if(Mathf.isEqual(needed, 0f)){ return; }
|
||||
|
||||
float coverage = Math.min(1, produced / needed);
|
||||
for(Tile consumer : consumers){
|
||||
Consumers consumes = consumer.block().consumes;
|
||||
if(consumes.has(ConsumePower.class)){
|
||||
ConsumePower consumePower = consumes.get(ConsumePower.class);
|
||||
if(!otherConsumersAreValid(consumer, consumePower)){
|
||||
consumer.entity.power.satisfaction = 0.0f; // Only supply power if the consumer would get valid that way
|
||||
}else{
|
||||
if(consumePower.isBuffered){
|
||||
// Add an equal percentage of power to all buffers, based on the global power coverage in this graph
|
||||
float maximumRate = consumePower.requestedPower(consumer.block(), consumer.entity()) * coverage * consumer.entity.delta();
|
||||
consumer.entity.power.satisfaction = Mathf.clamp(consumer.entity.power.satisfaction + maximumRate / consumePower.powerCapacity);
|
||||
}else{
|
||||
consumer.entity.power.satisfaction = coverage;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void update(){
|
||||
if(Core.graphics.getFrameId() == lastFrameUpdated || consumers.size == 0 || producers.size == 0){
|
||||
if(Core.graphics.getFrameId() == lastFrameUpdated || consumers.size == 0 && producers.size == 0 && batteries.size == 0){
|
||||
return;
|
||||
}
|
||||
|
||||
lastFrameUpdated = Core.graphics.getFrameId();
|
||||
|
||||
boolean charge = false;
|
||||
float powerNeeded = getPowerNeeded();
|
||||
float powerProduced = getPowerProduced();
|
||||
|
||||
float totalInput = 0f;
|
||||
float bufferInput = 0f;
|
||||
for(Tile producer : producers){
|
||||
if(producer.block().consumesPower){
|
||||
bufferInput += producer.entity.power.amount;
|
||||
}else{
|
||||
totalInput += producer.entity.power.amount;
|
||||
if(!Mathf.isEqual(powerNeeded, powerProduced)){
|
||||
if(powerNeeded > powerProduced){
|
||||
powerProduced += useBatteries(powerNeeded - powerProduced);
|
||||
}else if(powerProduced > powerNeeded){
|
||||
powerProduced -= chargeBatteries(powerProduced - powerNeeded);
|
||||
}
|
||||
}
|
||||
|
||||
float maxOutput = 0f;
|
||||
float bufferOutput = 0f;
|
||||
for(Tile consumer : consumers){
|
||||
if(consumer.block().outputsPower){
|
||||
bufferOutput += consumer.block().powerCapacity - consumer.entity.power.amount;
|
||||
}else{
|
||||
maxOutput += consumer.block().powerCapacity - consumer.entity.power.amount;
|
||||
}
|
||||
}
|
||||
|
||||
if(maxOutput < totalInput){
|
||||
charge = true;
|
||||
}
|
||||
|
||||
if(totalInput + bufferInput <= 0.0001f || maxOutput + bufferOutput <= 0.0001f){
|
||||
return;
|
||||
}
|
||||
|
||||
float bufferUsed;
|
||||
if(charge){
|
||||
bufferUsed = Math.min((totalInput - maxOutput) / bufferOutput, 1f);
|
||||
}else{
|
||||
bufferUsed = Math.min((maxOutput - totalInput) / bufferInput, 1f);
|
||||
}
|
||||
|
||||
float inputUsed = charge ? Math.min((maxOutput + bufferOutput) / totalInput, 1f) : 1f;
|
||||
for(Tile producer : producers){
|
||||
if(producer.block().consumesPower){
|
||||
if(!charge){
|
||||
producer.entity.power.amount -= producer.entity.power.amount * bufferUsed;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
producer.entity.power.amount -= producer.entity.power.amount * inputUsed;
|
||||
}
|
||||
|
||||
float outputSatisfied = charge ? 1f : Math.min((totalInput + bufferInput) / maxOutput, 1f);
|
||||
for(Tile consumer : consumers){
|
||||
if(consumer.block().outputsPower){
|
||||
if(charge){
|
||||
consumer.entity.power.amount += (consumer.block().powerCapacity - consumer.entity.power.amount) * bufferUsed;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
consumer.entity.power.amount += (consumer.block().powerCapacity - consumer.entity.power.amount) * outputSatisfied;
|
||||
}
|
||||
distributePower(powerNeeded, powerProduced);
|
||||
}
|
||||
|
||||
public void add(PowerGraph graph){
|
||||
@@ -106,22 +167,29 @@ public class PowerGraph{
|
||||
tile.entity.power.graph = this;
|
||||
all.add(tile);
|
||||
|
||||
if(tile.block().outputsPower){
|
||||
if(tile.block().outputsPower && tile.block().consumesPower){
|
||||
batteries.add(tile);
|
||||
}else if(tile.block().outputsPower){
|
||||
producers.add(tile);
|
||||
}
|
||||
|
||||
if(tile.block().consumesPower){
|
||||
}else if(tile.block().consumesPower){
|
||||
consumers.add(tile);
|
||||
}
|
||||
}
|
||||
|
||||
public void clear(){
|
||||
for(Tile other : all){
|
||||
if(other.entity != null && other.entity.power != null) other.entity.power.graph = null;
|
||||
if(other.entity != null && other.entity.power != null){
|
||||
if(other.block().consumes.has(ConsumePower.class) && !other.block().consumes.get(ConsumePower.class).isBuffered){
|
||||
// Reset satisfaction to zero in case of direct consumer. There is no reason to clear power from buffered consumers.
|
||||
other.entity.power.satisfaction = 0.0f;
|
||||
}
|
||||
other.entity.power.graph = null;
|
||||
}
|
||||
}
|
||||
all.clear();
|
||||
producers.clear();
|
||||
consumers.clear();
|
||||
batteries.clear();
|
||||
}
|
||||
|
||||
public void reflow(Tile tile){
|
||||
@@ -146,7 +214,7 @@ public class PowerGraph{
|
||||
closedSet.clear();
|
||||
|
||||
for(Tile other : tile.block().getPowerConnections(tile, outArray1)){
|
||||
if(other.entity.power == null || other.entity.power.graph != null) continue;
|
||||
if(other.entity.power == null || other.entity.power.graph != null){ continue; }
|
||||
PowerGraph graph = new PowerGraph();
|
||||
queue.clear();
|
||||
queue.addLast(other);
|
||||
@@ -161,17 +229,29 @@ public class PowerGraph{
|
||||
}
|
||||
}
|
||||
}
|
||||
// Update the graph once so direct consumers without any connected producer lose their power
|
||||
graph.update();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean otherConsumersAreValid(Tile tile, Consume consumePower){
|
||||
for(Consume cons : tile.block().consumes.all()){
|
||||
if(cons != consumePower && !cons.isOptional() && !cons.valid(tile.block(), tile.entity())){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return "PowerGraph{" +
|
||||
"producers=" + producers +
|
||||
", consumers=" + consumers +
|
||||
", all=" + all +
|
||||
", lastFrameUpdated=" + lastFrameUpdated +
|
||||
", graphID=" + graphID +
|
||||
'}';
|
||||
"producers=" + producers +
|
||||
", consumers=" + consumers +
|
||||
", batteries=" + batteries +
|
||||
", all=" + all +
|
||||
", lastFrameUpdated=" + lastFrameUpdated +
|
||||
", graphID=" + graphID +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,6 @@ public class PowerNode extends PowerBlock{
|
||||
super(name);
|
||||
expanded = true;
|
||||
layer = Layer.power;
|
||||
powerCapacity = 5f;
|
||||
configurable = true;
|
||||
consumesPower = false;
|
||||
outputsPower = false;
|
||||
|
||||
@@ -1,34 +1,30 @@
|
||||
package io.anuke.mindustry.world.blocks.power;
|
||||
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.meta.BlockStat;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.world.meta.StatUnit;
|
||||
import io.anuke.arc.util.Time;
|
||||
import io.anuke.arc.collection.EnumSet;
|
||||
|
||||
public class SolarGenerator extends PowerGenerator{
|
||||
/**
|
||||
* power generated per frame
|
||||
*/
|
||||
protected float generation = 0.005f;
|
||||
|
||||
public SolarGenerator(String name){
|
||||
super(name);
|
||||
// Remove the BlockFlag.producer flag to make this a lower priority target than other generators.
|
||||
flags = EnumSet.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStats(){
|
||||
super.setStats();
|
||||
|
||||
stats.add(BlockStat.basePowerGeneration, generation * 60f, StatUnit.powerSecond);
|
||||
// Solar Generators don't really have an efficiency (yet), so for them 100% = 1.0f
|
||||
stats.remove(generationType);
|
||||
stats.add(generationType, powerProduction * 60.0f, StatUnit.powerSecond);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
addPower(tile, generation * Time.delta());
|
||||
|
||||
tile.entity.power.graph.update();
|
||||
public TileEntity newEntity(){
|
||||
return new PowerGenerator.GeneratorEntity(){{
|
||||
productionEfficiency = 1.0f;
|
||||
}};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -189,6 +189,9 @@ public class Drill extends Block{
|
||||
if(entity.consumed(ConsumeLiquid.class) && !liquidRequired){
|
||||
speed = liquidBoostIntensity;
|
||||
}
|
||||
if(hasPower){
|
||||
speed *= entity.power.satisfaction; // Drill slower when not at full power
|
||||
}
|
||||
|
||||
entity.warmup = Mathf.lerpDelta(entity.warmup, speed, warmupSpeed);
|
||||
entity.progress += entity.delta()
|
||||
|
||||
@@ -64,7 +64,7 @@ public class Fracker extends SolidPump{
|
||||
|
||||
if(entity.cons.valid() && entity.accumulator < itemUseTime){
|
||||
super.update(tile);
|
||||
entity.accumulator += entity.delta();
|
||||
entity.accumulator += entity.delta() * entity.power.satisfaction;
|
||||
}else{
|
||||
tryDumpLiquid(tile, result);
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ public class GenericCrafter extends Block{
|
||||
|
||||
if(entity.cons.valid() && tile.entity.items.get(output) < itemCapacity){
|
||||
|
||||
entity.progress += 1f / craftTime * entity.delta();
|
||||
entity.progress += getProgressIncrease(entity, craftTime);
|
||||
entity.totalProgress += entity.delta();
|
||||
entity.warmup = Mathf.lerpDelta(entity.warmup, 1f, 0.02f);
|
||||
|
||||
|
||||
@@ -25,7 +25,8 @@ public class Incinerator extends Block{
|
||||
update = true;
|
||||
solid = true;
|
||||
|
||||
consumes.power(0.05f);
|
||||
// Incinerator has no speed which could be adjusted, so it will only operate fully powered for now
|
||||
consumes.power(0.05f, 1.0f);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -49,6 +49,9 @@ public class LiquidMixer extends LiquidBlock{
|
||||
|
||||
if(tile.entity.cons.valid()){
|
||||
float use = Math.min(consumes.get(ConsumeLiquid.class).used() * entity.delta(), liquidCapacity - entity.liquids.get(outputLiquid));
|
||||
if(hasPower){
|
||||
use *= entity.power.satisfaction; // Produce less liquid if power is not maxed
|
||||
}
|
||||
entity.accumulator += use;
|
||||
entity.liquids.add(outputLiquid, use);
|
||||
for(int i = 0; i < (int) (entity.accumulator / liquidPerItem); i++){
|
||||
|
||||
@@ -65,7 +65,7 @@ public class PowerCrafter extends Block{
|
||||
GenericCrafterEntity entity = tile.entity();
|
||||
|
||||
if(entity.cons.valid()){
|
||||
entity.progress += 1f / craftTime * entity.delta();
|
||||
entity.progress += getProgressIncrease(entity, craftTime);
|
||||
entity.totalProgress += entity.delta();
|
||||
}
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ public class PowerSmelter extends PowerBlock{
|
||||
}
|
||||
}
|
||||
|
||||
entity.craftTime += entity.delta();
|
||||
entity.craftTime += entity.delta() * entity.power.satisfaction;
|
||||
|
||||
if(entity.items.get(result) >= itemCapacity //output full
|
||||
|| entity.heat <= minHeat //not burning
|
||||
|
||||
@@ -96,6 +96,9 @@ public class Pump extends LiquidBlock{
|
||||
|
||||
if(tile.entity.cons.valid() && liquidDrop != null){
|
||||
float maxPump = Math.min(liquidCapacity - tile.entity.liquids.total(), tiles * pumpAmount * tile.entity.delta());
|
||||
if(hasPower){
|
||||
maxPump *= tile.entity.power.satisfaction; // Produce slower if not at full power
|
||||
}
|
||||
tile.entity.liquids.add(liquidDrop, maxPump);
|
||||
}
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ public class Separator extends Block{
|
||||
entity.totalProgress += entity.warmup * entity.delta();
|
||||
|
||||
if(entity.cons.valid()){
|
||||
entity.progress += 1f / filterTime*entity.delta();
|
||||
entity.progress += getProgressIncrease(entity, filterTime);
|
||||
entity.warmup = Mathf.lerpDelta(entity.warmup, 1f, 0.02f);
|
||||
}else{
|
||||
entity.warmup = Mathf.lerpDelta(entity.warmup, 0f, 0.02f);
|
||||
|
||||
@@ -77,7 +77,7 @@ public class SolidPump extends Pump{
|
||||
}
|
||||
|
||||
if(tile.entity.cons.valid() && typeLiquid(tile) < liquidCapacity - 0.001f){
|
||||
float maxPump = Math.min(liquidCapacity - typeLiquid(tile), pumpAmount * entity.delta() * fraction);
|
||||
float maxPump = Math.min(liquidCapacity - typeLiquid(tile), pumpAmount * entity.delta() * fraction * entity.power.satisfaction);
|
||||
tile.entity.liquids.add(result, maxPump);
|
||||
entity.warmup = Mathf.lerpDelta(entity.warmup, 1f, 0.02f);
|
||||
if(Mathf.chance(entity.delta() * updateEffectChance))
|
||||
|
||||
@@ -24,7 +24,6 @@ import io.anuke.mindustry.graphics.Shaders;
|
||||
import io.anuke.mindustry.type.Mech;
|
||||
import io.anuke.mindustry.world.Block;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.consumers.ConsumePowerExact;
|
||||
import io.anuke.mindustry.world.meta.BlockStat;
|
||||
|
||||
import java.io.DataInput;
|
||||
@@ -37,6 +36,7 @@ import static io.anuke.mindustry.Vars.tilesize;
|
||||
public class MechPad extends Block{
|
||||
protected Mech mech;
|
||||
protected float buildTime = 60 * 5;
|
||||
protected float requiredSatisfaction = 1f;
|
||||
|
||||
protected TextureRegion openRegion;
|
||||
|
||||
@@ -49,16 +49,9 @@ public class MechPad extends Block{
|
||||
|
||||
@Override
|
||||
public void init(){
|
||||
consumes.add(new ConsumePowerExact(powerCapacity * 0.8f));
|
||||
super.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStats(){
|
||||
super.setStats();
|
||||
stats.remove(BlockStat.powerUse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldConsume(Tile tile){
|
||||
return false;
|
||||
@@ -66,10 +59,14 @@ public class MechPad extends Block{
|
||||
|
||||
@Remote(targets = Loc.both, called = Loc.server)
|
||||
public static void onMechFactoryTap(Player player, Tile tile){
|
||||
if(player == null || !checkValidTap(tile, player)) return;
|
||||
if(player == null || !checkValidTap(tile, player) || !(tile.block() instanceof MechPad)) return;
|
||||
|
||||
MechFactoryEntity entity = tile.entity();
|
||||
entity.power.amount = 0f;
|
||||
MechPad pad = (MechPad)tile.block();
|
||||
|
||||
if(entity.power.satisfaction < pad.requiredSatisfaction) return;
|
||||
|
||||
entity.power.satisfaction -= Math.min(entity.power.satisfaction, pad.requiredSatisfaction);
|
||||
player.beginRespawning(entity);
|
||||
}
|
||||
|
||||
@@ -102,7 +99,7 @@ public class MechPad extends Block{
|
||||
|
||||
protected static boolean checkValidTap(Tile tile, Player player){
|
||||
MechFactoryEntity entity = tile.entity();
|
||||
return Math.abs(player.x - tile.drawx()) <= tile.block().size * tilesize / 2f &&
|
||||
return Math.abs(player.x - tile.drawx()) <= tile.block().size * tilesize / 2f &&
|
||||
Math.abs(player.y - tile.drawy()) <= tile.block().size * tilesize / 2f && entity.cons.valid() && entity.player == null;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,8 @@ import static io.anuke.mindustry.Vars.world;
|
||||
public class Reconstructor extends Block{
|
||||
protected float departTime = 30f;
|
||||
protected float arriveTime = 40f;
|
||||
protected float powerPerTeleport = 5f;
|
||||
/** Stores the percentage of buffered power to be used upon teleporting. */
|
||||
protected float powerPerTeleport = 0.5f;
|
||||
protected Effect arriveEffect = Fx.spawn;
|
||||
protected TextureRegion openRegion;
|
||||
|
||||
@@ -44,13 +45,14 @@ public class Reconstructor extends Block{
|
||||
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.amount >= ((Reconstructor) tile.block()).powerPerTeleport;
|
||||
entity.current == null && entity.power.satisfaction >= ((Reconstructor) tile.block()).powerPerTeleport;
|
||||
}
|
||||
|
||||
protected static boolean validLink(Tile tile, int position){
|
||||
@@ -75,13 +77,13 @@ public class Reconstructor extends Block{
|
||||
public static void reconstructPlayer(Player player, Tile tile){
|
||||
ReconstructorEntity entity = tile.entity();
|
||||
|
||||
if(!checkValidTap(tile, entity, player) || entity.power.amount < ((Reconstructor) tile.block()).powerPerTeleport)
|
||||
if(!checkValidTap(tile, entity, player) || entity.power.satisfaction < ((Reconstructor) tile.block()).powerPerTeleport)
|
||||
return;
|
||||
|
||||
entity.departing = true;
|
||||
entity.current = player;
|
||||
entity.solid = false;
|
||||
entity.power.amount -= ((Reconstructor) tile.block()).powerPerTeleport;
|
||||
entity.power.satisfaction -= Math.min(entity.power.satisfaction, ((Reconstructor) tile.block()).powerPerTeleport);
|
||||
entity.updateTime = 1f;
|
||||
entity.set(tile.drawx(), tile.drawy());
|
||||
player.rotation = 90f;
|
||||
@@ -242,13 +244,13 @@ public class Reconstructor extends Block{
|
||||
entity.updateTime -= Time.delta() / departTime;
|
||||
if(entity.updateTime <= 0f){
|
||||
//no power? death.
|
||||
if(other.power.amount < powerPerTeleport){
|
||||
if(other.power.satisfaction < powerPerTeleport){
|
||||
entity.current.setDead(true);
|
||||
//entity.current.setRespawning(false);
|
||||
entity.current = null;
|
||||
return;
|
||||
}
|
||||
other.power.amount -= powerPerTeleport;
|
||||
other.power.satisfaction -= Math.min(other.power.satisfaction, powerPerTeleport);
|
||||
other.current = entity.current;
|
||||
other.departing = false;
|
||||
other.current.set(other.x, other.y);
|
||||
@@ -272,8 +274,8 @@ public class Reconstructor extends Block{
|
||||
|
||||
if(validLink(tile, entity.link)){
|
||||
Tile other = world.tile(entity.link);
|
||||
if(other.entity.power.amount >= powerPerTeleport && Units.anyEntities(tile, 4f, unit -> unit.getTeam() == entity.getTeam() && unit instanceof Player) &&
|
||||
entity.power.amount >= powerPerTeleport){
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -18,7 +18,10 @@ import io.anuke.mindustry.graphics.Palette;
|
||||
import io.anuke.mindustry.graphics.Shapes;
|
||||
import io.anuke.mindustry.world.Block;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.consumers.ConsumePower;
|
||||
import io.anuke.mindustry.world.meta.BlockFlag;
|
||||
import io.anuke.mindustry.world.meta.BlockStat;
|
||||
import io.anuke.mindustry.world.meta.StatUnit;
|
||||
|
||||
public class RepairPoint extends Block{
|
||||
private static Rectangle rect = new Rectangle();
|
||||
@@ -27,6 +30,8 @@ public class RepairPoint extends Block{
|
||||
|
||||
protected float repairRadius = 50f;
|
||||
protected float repairSpeed = 0.3f;
|
||||
protected float powerPerEvent = 0.06f;
|
||||
protected ConsumePower consumePower;
|
||||
|
||||
protected TextureRegion topRegion;
|
||||
|
||||
@@ -38,8 +43,7 @@ public class RepairPoint extends Block{
|
||||
layer = Layer.turret;
|
||||
layer2 = Layer.laser;
|
||||
hasPower = true;
|
||||
powerCapacity = 20f;
|
||||
consumes.power(0.06f);
|
||||
consumePower = consumes.powerBuffered(20f);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -49,6 +53,12 @@ public class RepairPoint extends Block{
|
||||
topRegion = Core.atlas.find(name + "-turret");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStats(){
|
||||
super.setStats();
|
||||
stats.add(BlockStat.powerUse, powerPerEvent * 60f, StatUnit.powerSecond);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawSelect(Tile tile){
|
||||
Draw.color(Palette.accent);
|
||||
@@ -84,16 +94,22 @@ public class RepairPoint extends Block{
|
||||
public void update(Tile tile){
|
||||
RepairPointEntity entity = tile.entity();
|
||||
|
||||
boolean targetIsBeingRepaired = false;
|
||||
if(entity.target != null && (entity.target.isDead() || entity.target.dst(tile) > repairRadius ||
|
||||
entity.target.health >= entity.target.maxHealth())){
|
||||
entity.target = null;
|
||||
}else if(entity.target != null){
|
||||
entity.target.health += repairSpeed * Time.delta() * entity.strength;
|
||||
entity.target.clampHealth();
|
||||
entity.rotation = Mathf.slerpDelta(entity.rotation, entity.angleTo(entity.target), 0.5f);
|
||||
float relativeConsumption = powerPerEvent / consumePower.powerCapacity;
|
||||
if(entity.power.satisfaction > 0.0f){
|
||||
entity.target.health += repairSpeed * Time.delta() * entity.strength * Mathf.clamp(entity.power.satisfaction / relativeConsumption);
|
||||
entity.target.clampHealth();
|
||||
entity.rotation = Mathf.slerpDelta(entity.rotation, entity.angleTo(entity.target), 0.5f);
|
||||
entity.power.satisfaction -= Math.min(entity.power.satisfaction, relativeConsumption);
|
||||
targetIsBeingRepaired = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(entity.target != null && entity.cons.valid()){
|
||||
if(entity.target != null && targetIsBeingRepaired){
|
||||
entity.strength = Mathf.lerpDelta(entity.strength, 1f, 0.08f * Time.delta());
|
||||
}else{
|
||||
entity.strength = Mathf.lerpDelta(entity.strength, 0f, 0.07f * Time.delta());
|
||||
|
||||
@@ -148,7 +148,7 @@ public class UnitFactory extends Block{
|
||||
|
||||
if(hasRequirements(entity.items, entity.buildTime / produceTime) && entity.cons.valid()){
|
||||
|
||||
entity.buildTime += entity.delta();
|
||||
entity.buildTime += entity.delta() * entity.power.satisfaction;
|
||||
entity.speedScl = Mathf.lerpDelta(entity.speedScl, 1f, 0.05f);
|
||||
}else{
|
||||
entity.speedScl = Mathf.lerpDelta(entity.speedScl, 0f, 0.05f);
|
||||
|
||||
@@ -1,22 +1,53 @@
|
||||
package io.anuke.mindustry.world.consumers;
|
||||
|
||||
import io.anuke.arc.math.Mathf;
|
||||
import io.anuke.arc.scene.ui.layout.Table;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.world.Block;
|
||||
import io.anuke.mindustry.world.meta.BlockStat;
|
||||
import io.anuke.mindustry.world.meta.BlockStats;
|
||||
import io.anuke.mindustry.world.meta.StatUnit;
|
||||
import io.anuke.arc.scene.ui.layout.Table;
|
||||
|
||||
/** Consumer class for blocks which consume power while being connected to a power graph. */
|
||||
public class ConsumePower extends Consume{
|
||||
protected final float use;
|
||||
/** The maximum amount of power which can be processed per tick. This might influence efficiency or load a buffer. */
|
||||
protected final float powerPerTick;
|
||||
/** The minimum power satisfaction (fraction of powerPerTick) which must be achieved before the module may work. */
|
||||
public final float minimumSatisfaction;
|
||||
/** The maximum power capacity in power units. */
|
||||
public final float powerCapacity;
|
||||
/** True if the module can store power. */
|
||||
public final boolean isBuffered;
|
||||
|
||||
public ConsumePower(float use){
|
||||
this.use = use;
|
||||
protected ConsumePower(float powerPerTick, float minimumSatisfaction, float powerCapacity, boolean isBuffered){
|
||||
this.powerPerTick = powerPerTick;
|
||||
this.minimumSatisfaction = minimumSatisfaction;
|
||||
this.powerCapacity = powerCapacity;
|
||||
this.isBuffered = isBuffered;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the owner consume powerPerTick each tick and disables it unless minimumSatisfaction (1.0 = 100%) of that power is being supplied.
|
||||
* @param powerPerTick The maximum amount of power which is required per tick for 100% efficiency.
|
||||
* @param minimumSatisfaction The percentage of powerPerTick which must be available for the module to work.
|
||||
*/
|
||||
public static ConsumePower consumePowerDirect(float powerPerTick, float minimumSatisfaction){
|
||||
return new ConsumePower(powerPerTick, minimumSatisfaction, 0.0f, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a power buffer to the owner which takes ticksToFill number of ticks to be filled.
|
||||
* Note that this object does not remove power from the buffer.
|
||||
* @param powerCapacity The maximum capacity in power units.
|
||||
* @param ticksToFill The number of ticks it shall take to fill the buffer.
|
||||
*/
|
||||
public static ConsumePower consumePowerBuffered(float powerCapacity, float ticksToFill){
|
||||
return new ConsumePower(powerCapacity / ticksToFill, 0.0f, powerCapacity, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildTooltip(Table table){
|
||||
|
||||
// No tooltip for power
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -26,21 +57,41 @@ public class ConsumePower extends Consume{
|
||||
|
||||
@Override
|
||||
public void update(Block block, TileEntity entity){
|
||||
if(entity.power == null) return;
|
||||
entity.power.amount -= Math.min(use(block, entity), entity.power.amount);
|
||||
// Nothing to do since PowerGraph directly updates entity.power.satisfaction
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean valid(Block block, TileEntity entity){
|
||||
return entity.power != null && entity.power.amount >= use(block, entity);
|
||||
if(isBuffered){
|
||||
return true;
|
||||
}else{
|
||||
return entity.power.satisfaction >= minimumSatisfaction;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void display(BlockStats stats){
|
||||
stats.add(BlockStat.powerUse, use * 60f, StatUnit.powerSecond);
|
||||
if(isBuffered){
|
||||
stats.add(BlockStat.powerCapacity, powerCapacity, StatUnit.powerSecond);
|
||||
}else{
|
||||
stats.add(BlockStat.powerUse, powerPerTick * 60f, StatUnit.powerSecond);
|
||||
}
|
||||
}
|
||||
|
||||
protected float use(Block block, TileEntity entity){
|
||||
return Math.min(use * entity.delta(), block.powerCapacity);
|
||||
/**
|
||||
* Retrieves the amount of power which is requested for the given block and entity.
|
||||
* @param block The block which needs power.
|
||||
* @param entity The entity which contains the power module.
|
||||
* @return The amount of power which is requested per tick.
|
||||
*/
|
||||
public float requestedPower(Block block, TileEntity entity){
|
||||
if(isBuffered){
|
||||
// Stop requesting power once the buffer is full.
|
||||
return Mathf.isEqual(entity.power.satisfaction, 1.0f) ? 0.0f : powerPerTick;
|
||||
}else{
|
||||
return powerPerTick;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
package io.anuke.mindustry.world.consumers;
|
||||
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.world.Block;
|
||||
|
||||
public class ConsumePowerExact extends ConsumePower{
|
||||
|
||||
public ConsumePowerExact(float use){
|
||||
super(use);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float use(Block block, TileEntity entity){
|
||||
return this.use;
|
||||
}
|
||||
}
|
||||
@@ -30,18 +30,52 @@ public class Consumers{
|
||||
}
|
||||
}
|
||||
|
||||
public ConsumePower power(float amount){
|
||||
ConsumePower p = new ConsumePower(amount);
|
||||
add(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
public ConsumeLiquid liquid(Liquid liquid, float amount){
|
||||
ConsumeLiquid c = new ConsumeLiquid(liquid, amount);
|
||||
add(c);
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a consumer which directly uses power without buffering it. The module will work while at least 50% of power is supplied.
|
||||
* @param powerPerTick The amount of power which is required each tick for 100% efficiency.
|
||||
* @return the created consumer object.
|
||||
*/
|
||||
public ConsumePower power(float powerPerTick){
|
||||
return power(powerPerTick, 0.5f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a consumer which directly uses power without buffering it. The module will work while the available power is greater than or equal to the minimumSatisfaction percentage (0..1).
|
||||
* @param powerPerTick The amount of power which is required each tick for 100% efficiency.
|
||||
* @return the created consumer object.
|
||||
*/
|
||||
public ConsumePower power(float powerPerTick, float minimumSatisfaction){
|
||||
ConsumePower c = ConsumePower.consumePowerDirect(powerPerTick, minimumSatisfaction);
|
||||
add(c);
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a consumer which stores power and uses it only in case of certain events (e.g. a turret firing).
|
||||
* It will take 180 ticks (three second) to fill the buffer, given enough power supplied.
|
||||
* @param powerCapacity The maximum capacity in power units.
|
||||
*/
|
||||
public ConsumePower powerBuffered(float powerCapacity){
|
||||
return powerBuffered(powerCapacity, 1f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a consumer which stores power and uses it only in case of certain events (e.g. a turret firing).
|
||||
* @param powerCapacity The maximum capacity in power units.
|
||||
* @param ticksToFill The number of ticks it shall take to fill the buffer.
|
||||
*/
|
||||
public ConsumePower powerBuffered(float powerCapacity, float ticksToFill){
|
||||
ConsumePower c = ConsumePower.consumePowerBuffered(powerCapacity, ticksToFill);
|
||||
add(c);
|
||||
return c;
|
||||
}
|
||||
|
||||
public ConsumeItem item(Item item){
|
||||
return item(item, 1);
|
||||
}
|
||||
@@ -75,7 +109,7 @@ public class Consumers{
|
||||
}
|
||||
|
||||
public Consume add(Consume consume){
|
||||
map.put(consume.getClass(), consume);
|
||||
map.put((consume instanceof ConsumePower ? ConsumePower.class : consume.getClass()), consume);
|
||||
return consume;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,14 +8,18 @@ import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
public class PowerModule extends BlockModule{
|
||||
public float amount;
|
||||
/** In case of unbuffered consumers, this is the percentage (1.0f = 100%) of the demanded power which can be supplied.
|
||||
* Blocks will work at a reduced efficiency if this is not equal to 1.0f.
|
||||
* In case of buffered consumers, this is the percentage of power stored in relation to the maximum capacity.
|
||||
*/
|
||||
public float satisfaction = 0.0f;
|
||||
/** Specifies power which is required additionally, e.g. while a force projector is being shot at. */
|
||||
public float extraUse = 0f;
|
||||
public PowerGraph graph = new PowerGraph();
|
||||
public IntArray links = new IntArray();
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
stream.writeFloat(amount);
|
||||
|
||||
stream.writeShort(links.size);
|
||||
for(int i = 0; i < links.size; i++){
|
||||
stream.writeInt(links.get(i));
|
||||
@@ -24,15 +28,6 @@ public class PowerModule extends BlockModule{
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream) throws IOException{
|
||||
amount = stream.readFloat();
|
||||
if(Float.isNaN(amount)){
|
||||
amount = 0f;
|
||||
}
|
||||
// Workaround: If power went negative for some reason, at least fix it when reloading the map
|
||||
if(amount < 0f){
|
||||
amount = 0f;
|
||||
}
|
||||
|
||||
short amount = stream.readShort();
|
||||
for(int i = 0; i < amount; i++){
|
||||
links.add(stream.readInt());
|
||||
|
||||
Reference in New Issue
Block a user