diff --git a/core/assets-raw/sprites/blocks/power/flux-reactor-bottom.png b/core/assets-raw/sprites/blocks/power/flux-reactor-bottom.png new file mode 100644 index 0000000000..45a8dc8331 Binary files /dev/null and b/core/assets-raw/sprites/blocks/power/flux-reactor-bottom.png differ diff --git a/core/assets-raw/sprites/blocks/power/flux-reactor-heat.png b/core/assets-raw/sprites/blocks/power/flux-reactor-heat.png new file mode 100644 index 0000000000..2f5ad4f7fa Binary files /dev/null and b/core/assets-raw/sprites/blocks/power/flux-reactor-heat.png differ diff --git a/core/assets-raw/sprites/blocks/power/flux-reactor-lights.png b/core/assets-raw/sprites/blocks/power/flux-reactor-lights.png new file mode 100644 index 0000000000..871351735b Binary files /dev/null and b/core/assets-raw/sprites/blocks/power/flux-reactor-lights.png differ diff --git a/core/assets-raw/sprites/blocks/power/flux-reactor-mid.png b/core/assets-raw/sprites/blocks/power/flux-reactor-mid.png new file mode 100644 index 0000000000..4f4b6a2b8f Binary files /dev/null and b/core/assets-raw/sprites/blocks/power/flux-reactor-mid.png differ diff --git a/core/assets-raw/sprites/blocks/power/flux-reactor-ventglow.png b/core/assets-raw/sprites/blocks/power/flux-reactor-ventglow.png new file mode 100644 index 0000000000..491e57cb20 Binary files /dev/null and b/core/assets-raw/sprites/blocks/power/flux-reactor-ventglow.png differ diff --git a/core/assets-raw/sprites/blocks/power/flux-reactor.png b/core/assets-raw/sprites/blocks/power/flux-reactor.png new file mode 100644 index 0000000000..0758766a4c Binary files /dev/null and b/core/assets-raw/sprites/blocks/power/flux-reactor.png differ diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 1ae8346c40..761d4926be 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -916,6 +916,7 @@ bar.capacity = Capacity: {0} bar.unitcap = {0} {1}/{2} bar.liquid = Liquid bar.heat = Heat +bar.instability = Instability bar.heatamount = Heat: {0} bar.heatpercent = Heat: {0} ({1}%) bar.power = Power @@ -1671,6 +1672,7 @@ block.diffuse.name = Diffuse block.basic-assembler-module.name = Basic Assembler Module block.smite.name = Smite block.malign.name = Malign +block.flux-reactor.name = Flux Reactor block.switch.name = Switch block.micro-processor.name = Micro Processor diff --git a/core/assets/icons/icons.properties b/core/assets/icons/icons.properties index 55ae84190e..f590226e0b 100755 --- a/core/assets/icons/icons.properties +++ b/core/assets/icons/icons.properties @@ -577,3 +577,4 @@ 63107=smite|block-smite-ui 63106=shockwave-tower|block-shockwave-tower-ui 63105=heat-source|block-heat-source-ui +63104=flux-reactor|block-flux-reactor-ui diff --git a/core/assets/logicids.dat b/core/assets/logicids.dat index f20d083564..c94f7ca2d0 100644 Binary files a/core/assets/logicids.dat and b/core/assets/logicids.dat differ diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 568836b600..cdb1cf9817 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -119,8 +119,7 @@ public class Blocks{ impactReactor, battery, batteryLarge, powerNode, powerNodeLarge, surgeTower, diode, //power - erekir - //TODO rename chemicalCombustionChamber - turbineCondenser, ventCondenser, chemicalCombustionChamber, pyrolysisGenerator, + turbineCondenser, ventCondenser, chemicalCombustionChamber, pyrolysisGenerator, fluxReactor, beamNode, beamTower, beamLink, //production @@ -1258,7 +1257,7 @@ public class Blocks{ size = 2; heatOutput = 3f; regionRotated1 = 1; - consumePower(50f / 60f); + consumePower(100f / 60f); }}; slagHeater = new HeatProducer("slag-heater"){{ @@ -1828,7 +1827,7 @@ public class Blocks{ requirements(Category.effect, with(Items.surgeAlloy, 50, Items.silicon, 150, Items.oxide, 30, Items.tungsten, 100)); size = 3; consumeLiquids(LiquidStack.with(Liquids.cyanogen, 1f / 60f)); - consumePower(80f / 60f); + consumePower(100f / 60f); }}; //TODO 5x5?? @@ -2480,7 +2479,7 @@ public class Blocks{ pyrolysisGenerator = new ConsumeGenerator("pyrolysis-generator"){{ requirements(Category.power, with(Items.graphite, 50, Items.carbide, 50, Items.oxide, 60f, Items.silicon, 50)); - powerProduction = 27f; + powerProduction = 25f; drawer = new DrawMulti(new DrawRegion("-bottom"), new DrawPistons(){{ sinMag = 2.75f; @@ -2507,6 +2506,36 @@ public class Blocks{ ambientSoundVolume = 0.06f; }}; + //TODO still very much WIP, stats are bad + fluxReactor = new VariableReactor("flux-reactor"){{ + requirements(Category.power, with(Items.graphite, 300, Items.carbide, 200, Items.oxide, 100, Items.silicon, 600, Items.surgeAlloy, 300)); + powerProduction = 140f; + maxHeat = 150f; + + consumeLiquid(Liquids.cyanogen, 9f / 60f); + liquidCapacity = 30f; + + size = 5; + + drawer = new DrawMulti( + new DrawRegion("-bottom"), + new DrawLiquidTile(Liquids.cyanogen), + new DrawRegion("-mid"), + new DrawSoftParticles(){{ + alpha = 0.35f; + particleRad = 12f; + particleSize = 9f; + particleLife = 120f; + particles = 27; + }}, + new DrawDefault(), + new DrawHeatInput(), + new DrawGlowRegion("-ventglow"){{ + color = Color.valueOf("32603a"); + }} + ); + }}; + //endregion power //region production @@ -4210,7 +4239,7 @@ public class Blocks{ }}); }}; - consumePower(2f); + consumePower(5f); heatRequirement = 10f; maxHeatEfficiency = 2f; @@ -4316,6 +4345,7 @@ public class Blocks{ trailLength = 18; missileAccelTime = 50f; lowAltitude = true; + //targetAir = false; fogRadius = 6f; @@ -4336,6 +4366,8 @@ public class Blocks{ sizeTo = 130f; }}); + collidesAir = false; + ammoMultiplier = 1f; fragLifeMin = 0.1f; fragBullets = 7; @@ -5016,7 +5048,7 @@ public class Blocks{ velocityRnd = 0.15f; heatRequirement = 90f; maxHeatEfficiency = 2f; - consumePower(5f); + consumePower(10f); shoot = new ShootSummon(0f, 0f, circleRad, 48f); diff --git a/core/src/mindustry/content/Fx.java b/core/src/mindustry/content/Fx.java index a938f8b19a..b04505be68 100644 --- a/core/src/mindustry/content/Fx.java +++ b/core/src/mindustry/content/Fx.java @@ -1202,6 +1202,15 @@ public class Fx{ } }).startDelay(30f), + fluxVapor = new Effect(140f, e -> { + color(e.color); + alpha(e.fout() * 0.7f); + + randLenVectors(e.id, 2, 3f + e.finpow() * 10f, (x, y) -> { + Fill.circle(e.x + x, e.y + y, 0.6f + e.fin() * 5f); + }); + }).layer(Layer.bullet - 1f), + vapor = new Effect(110f, e -> { color(e.color); alpha(e.fout()); diff --git a/core/src/mindustry/world/blocks/distribution/StackConveyor.java b/core/src/mindustry/world/blocks/distribution/StackConveyor.java index b05c911ecb..b8ea87a6ac 100644 --- a/core/src/mindustry/world/blocks/distribution/StackConveyor.java +++ b/core/src/mindustry/world/blocks/distribution/StackConveyor.java @@ -134,13 +134,13 @@ public class StackConveyor extends Block implements Autotiler{ for(int i = 0; i < 4; i++){ int dir = rotation - i; var near = nearby(dir); - if((blendprox & (1 << i)) != 0 && i != 0 && near != null && !near.block.fillsTile){ + if((blendprox & (1 << i)) != 0 && i != 0 && near != null && !near.block.squareSprite){ Draw.rect(sliced(regions[0], SliceMode.bottom), x + Geometry.d4x(dir) * tilesize*0.75f, y + Geometry.d4y(dir) * tilesize*0.75f, (float)(dir*90)); } } }else if(state == stateUnload){ //front unload //TOOD hacky front check - if((blendprox & (1)) != 0 && !front().block.fillsTile){ + if((blendprox & (1)) != 0 && !front().block.squareSprite){ Draw.rect(sliced(regions[0], SliceMode.top), x + Geometry.d4x(rotation) * tilesize*0.75f, y + Geometry.d4y(rotation) * tilesize*0.75f, rotation * 90f); } } diff --git a/core/src/mindustry/world/blocks/power/NuclearReactor.java b/core/src/mindustry/world/blocks/power/NuclearReactor.java index f1c294bd09..bcc3d104b1 100644 --- a/core/src/mindustry/world/blocks/power/NuclearReactor.java +++ b/core/src/mindustry/world/blocks/power/NuclearReactor.java @@ -5,7 +5,6 @@ import arc.audio.*; import arc.graphics.*; import arc.graphics.g2d.*; import arc.math.*; -import arc.math.geom.*; import arc.struct.*; import arc.util.*; import arc.util.io.*; @@ -25,8 +24,6 @@ import static mindustry.Vars.*; public class NuclearReactor extends PowerGenerator{ public final int timerFuel = timers++; - public final Vec2 tr = new Vec2(); - public Color lightColor = Color.valueOf("7f19ea"); public Color coolColor = new Color(1, 1, 1, 0f); public Color hotColor = Color.valueOf("ff9575a3"); diff --git a/core/src/mindustry/world/blocks/power/VariableReactor.java b/core/src/mindustry/world/blocks/power/VariableReactor.java index d1686b1288..d834ad577f 100644 --- a/core/src/mindustry/world/blocks/power/VariableReactor.java +++ b/core/src/mindustry/world/blocks/power/VariableReactor.java @@ -1,24 +1,151 @@ package mindustry.world.blocks.power; +import arc.*; +import arc.audio.*; +import arc.graphics.*; +import arc.graphics.g2d.*; +import arc.math.*; +import arc.util.*; +import arc.util.io.*; +import mindustry.annotations.Annotations.*; +import mindustry.content.*; +import mindustry.entities.*; +import mindustry.entities.effect.*; +import mindustry.gen.*; +import mindustry.graphics.*; +import mindustry.type.*; +import mindustry.ui.*; +import mindustry.world.*; import mindustry.world.blocks.heat.*; +import static mindustry.Vars.*; + public class VariableReactor extends PowerGenerator{ - //TODO - public float maxEfficiency = 1f; - //TODO public float maxHeat = 100f; + /** How quickly instability moves towards 1, per frame. */ + public float unstableSpeed = 1f / 60f / 3f; + public float warmupSpeed = 0.1f; + public Effect effect = Fx.fluxVapor; + public float effectChance = 0.05f; + public Color effectColor = Color.valueOf("ffdf9d"); + + public float flashThreshold = 0.01f, flashAlpha = 0.4f, flashSpeed = 7f; + public Color flashColor1 = Color.red, flashColor2 = Color.valueOf("89e8b6"); + + public int explosionRadius = 12; + public int explosionDamage = 1000; + public Effect explodeEffect = new MultiEffect(Fx.bigShockwave, new WrapEffect(Fx.titanSmoke, Color.valueOf("e3ae6f"))); + public Sound explodeSound = Sounds.explosionbig; + + public int puddles = 70; + public float puddleRange = tilesize * 6f; + public Liquid puddleLiquid = Liquids.slag; + public float puddleAmount = 100f; + + public @Load("@-lights") TextureRegion lightsRegion; public VariableReactor(String name){ super(name); + powerProduction = 20f; + rebuildable = false; } + @Override + public void setBars(){ + super.setBars(); + + addBar("instability", (VariableReactorBuild entity) -> new Bar("bar.instability", Pal.sap, () -> entity.instability)); + + addBar("heat", (VariableReactorBuild entity) -> + new Bar(() -> + Core.bundle.format("bar.heatpercent", (int)entity.heat, (int)(Mathf.clamp(entity.heat / maxHeat) * 100)), + () -> Pal.lightOrange, + () -> entity.heat / maxHeat)); + } + + //TODO: draw warmup fraction on block? public class VariableReactorBuild extends GeneratorBuild implements HeatConsumer{ public float[] sideHeat = new float[4]; - public float heat = 0f; + public float heat = 0f, instability, totalProgress, warmup, flash; @Override public void updateTile(){ heat = calculateHeat(sideHeat); + + productionEfficiency = Mathf.clamp(heat / maxHeat); + warmup = Mathf.lerpDelta(warmup, productionEfficiency > 0 ? 1f : 0f, warmupSpeed); + + if(instability >= 1f){ + kill(); + } + + totalProgress += productionEfficiency * Time.delta; + + if(Mathf.chanceDelta(effectChance * warmup)){ + effect.at(x, y, effectColor); + } + } + + @Override + public void onDestroyed(){ + super.onDestroyed(); + + if(!state.rules.reactorExplosions) return; + + Damage.damage(x, y, explosionRadius * tilesize, explosionDamage); + + explodeEffect.at(this); + explodeSound.at(this); + + for(int i = 0; i < puddles; i++){ + Tmp.v1.trns(Mathf.random(360f), Mathf.random(puddleRange)); + Tile tile = world.tileWorld(x + Tmp.v1.x, y + Tmp.v1.y); + Puddles.deposit(tile, puddleLiquid, puddleAmount); + } + } + + @Override + public void draw(){ + super.draw(); + + if(instability > flashThreshold){ + if(!state.isPaused()) flash += (1f + ((instability - flashThreshold) / (1f - flashThreshold)) * flashSpeed) * Time.delta; + Draw.z(Layer.blockAdditive); + Draw.blend(Blending.additive); + Draw.color(flashColor1, flashColor2, Mathf.absin(flash, 8f, 1f)); + Draw.alpha(flashAlpha * Mathf.clamp((instability - flashThreshold) / (1f - flashThreshold) * 4f)); + Draw.rect(lightsRegion, x, y); + Draw.blend(); + } + } + + @Override + public float totalProgress(){ + return totalProgress; + } + + @Override + public float warmup(){ + return warmup; + } + + @Override + public void updateEfficiencyMultiplier(){ + //at this stage efficiency = how much coolant is provided + + //target efficiency value + float target = Mathf.clamp(heat / maxHeat); + + //fraction of coolant provided (from what is needed) + float efficiencyMet = Mathf.clamp(Mathf.zero(target) ? 1f : efficiency / target); + boolean met = efficiencyMet >= 0.99999f; + + //if all requirements are met, instability moves toward 0 at 50% of speed + //if requirements are not meant, instability approaches 1 at a speed scaled by how much efficiency is *not* met + instability = Mathf.approachDelta(instability, met ? 0f : 1f, met ? 0.5f : unstableSpeed * (1f - efficiencyMet)); + + //now scale efficiency by target, so it consumes less depending on heat + efficiency *= target; } @Override @@ -28,8 +155,25 @@ public class VariableReactor extends PowerGenerator{ @Override public float heatRequirement(){ - //TODO return maxHeat; } + + @Override + public void write(Writes write){ + super.write(write); + + write.f(heat); + write.f(instability); + write.f(warmup); + } + + @Override + public void read(Reads read, byte revision){ + super.read(read, revision); + + heat = read.f(); + instability = read.f(); + warmup = read.f(); + } } } diff --git a/core/src/mindustry/world/draw/DrawMultiWeave.java b/core/src/mindustry/world/draw/DrawMultiWeave.java index a8bd312bbf..1bfda310bd 100644 --- a/core/src/mindustry/world/draw/DrawMultiWeave.java +++ b/core/src/mindustry/world/draw/DrawMultiWeave.java @@ -10,11 +10,17 @@ import mindustry.world.*; public class DrawMultiWeave extends DrawBlock{ public TextureRegion weave, glow; public float rotateSpeed = 1f, rotateSpeed2 = -0.9f; - public Color glowColor = new Color(1f, 0.4f, 0.4f, 0.8f); + public boolean fadeWeave = false; + public Color glowColor = new Color(1f, 0.4f, 0.4f, 0.8f), weaveColor = Color.white.cpy(); public float pulse = 0.3f, pulseScl = 10f; @Override public void draw(Building build){ + Draw.color(weaveColor); + if(fadeWeave){ + Draw.alpha(build.warmup()); + } + Draw.rect(weave, build.x, build.y, build.totalProgress() * rotateSpeed); Draw.rect(weave, build.x, build.y, build.totalProgress() * rotateSpeed * rotateSpeed2); @@ -31,7 +37,7 @@ public class DrawMultiWeave extends DrawBlock{ @Override public TextureRegion[] icons(Block block){ - return new TextureRegion[]{weave}; + return fadeWeave ? new TextureRegion[0] : new TextureRegion[]{weave}; } @Override diff --git a/core/src/mindustry/world/draw/DrawSoftParticles.java b/core/src/mindustry/world/draw/DrawSoftParticles.java new file mode 100644 index 0000000000..b2b8271155 --- /dev/null +++ b/core/src/mindustry/world/draw/DrawSoftParticles.java @@ -0,0 +1,63 @@ +package mindustry.world.draw; + +import arc.*; +import arc.graphics.*; +import arc.graphics.g2d.*; +import arc.math.*; +import arc.math.Interp.*; +import arc.util.*; +import mindustry.gen.*; +import mindustry.world.*; + +public class DrawSoftParticles extends DrawBlock{ + public TextureRegion region; + + public Color color = Color.valueOf("e3ae6f"), color2 = Color.valueOf("d04d46"); + + public float alpha = 0.5f; + public int particles = 30; + public float particleLife = 70f, particleRad = 7f, particleSize = 3f, fadeMargin = 0.4f, rotateScl = 1.5f; + public Interp particleInterp = new PowIn(1.5f); + + @Override + public void draw(Building build){ + + if(build.warmup() > 0f && color.a > 0.001f){ + float a = alpha * build.warmup(); + + Draw.color(color, a); + Draw.blend(Blending.additive); + + float base = (Time.time / particleLife); + rand.setSeed(build.id); + for(int i = 0; i < particles; i++){ + float fin = (rand.random(1f) + base) % 1f, fout = 1f - fin; + fin = 1f - fin; + fout = 1f - fout; + + float angle = rand.random(360f) + (Time.time / rotateScl) % 360f; + float col = rand.random(1f); + Draw.tint(color, color2, col); + float len = particleRad * particleInterp.apply(fout); + Draw.alpha(a * (1f - Mathf.curve(fin, 1f - fadeMargin))); + float r = particleSize * fin * build.warmup()*2f; + Draw.rect( + region, + build.x + Angles.trnsx(angle, len), + build.y + Angles.trnsy(angle, len), + r, r + ); + } + + Draw.blend(); + Draw.reset(); + } + } + + @Override + public void load(Block block){ + super.load(block); + + region = Core.atlas.find("circle-shadow"); + } +}