diff --git a/core/assets-raw/sprites/blocks/production/carbide-crucible-bottom.png b/core/assets-raw/sprites/blocks/production/carbide-crucible-bottom.png new file mode 100644 index 0000000000..cc9cacb3f8 Binary files /dev/null and b/core/assets-raw/sprites/blocks/production/carbide-crucible-bottom.png differ diff --git a/core/assets-raw/sprites/blocks/production/carbide-crucible-heat.png b/core/assets-raw/sprites/blocks/production/carbide-crucible-heat.png new file mode 100644 index 0000000000..59a1fd5c36 Binary files /dev/null and b/core/assets-raw/sprites/blocks/production/carbide-crucible-heat.png differ diff --git a/core/assets-raw/sprites/blocks/production/carbide-crucible-top.png b/core/assets-raw/sprites/blocks/production/carbide-crucible-top.png new file mode 100644 index 0000000000..a5bef0741f Binary files /dev/null and b/core/assets-raw/sprites/blocks/production/carbide-crucible-top.png differ diff --git a/core/assets-raw/sprites/blocks/production/carbide-crucible.png b/core/assets-raw/sprites/blocks/production/carbide-crucible.png new file mode 100644 index 0000000000..bb09add910 Binary files /dev/null and b/core/assets-raw/sprites/blocks/production/carbide-crucible.png differ diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index b3b8d5fca0..c06e4f3b90 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -952,18 +952,18 @@ public class Blocks implements ContentList{ carbideCrucible = new HeatCrafter("carbide-crucible"){{ requirements(Category.crafting, with(Items.tungsten, 60, Items.graphite, 30)); - craftEffect = Fx.smeltsmoke; + craftEffect = Fx.none; outputItem = new ItemStack(Items.carbide, 1); - craftTime = 30f; + craftTime = 60f * 4f; size = 3; + itemCapacity = 20; hasPower = hasItems = true; - drawer = new DrawSmelter(Color.valueOf("ffc099")); + drawer = new DrawMulti(new DrawCrucible(), new DrawHeat()); ambientSound = Sounds.smelter; ambientSoundVolume = 0.07f; heatRequirement = 10f; - //TODO use heat! consumes.items(with(Items.tungsten, 1, Items.graphite, 2)); consumes.power(2f); }}; diff --git a/core/src/mindustry/content/Fx.java b/core/src/mindustry/content/Fx.java index b0e0047ffb..a3faa52d6a 100644 --- a/core/src/mindustry/content/Fx.java +++ b/core/src/mindustry/content/Fx.java @@ -1659,6 +1659,17 @@ public class Fx{ } }).layer(Layer.bullet - 1f), + crucibleSmoke = new Effect(100, e -> { + color(Pal.redLight); + alpha(e.fslope() * 0.8f); + + rand.setSeed(e.id); + for(int i = 0; i < 5; i++){ + v.trns(rand.random(360f), rand.random(e.finpow() * 14f)).add(e.x, e.y); + Fill.circle(v.x, v.y, rand.random(1.4f, 2.8f)); + } + }).layer(Layer.bullet - 1f), + generatespark = new Effect(18, e -> { randLenVectors(e.id, 5, e.fin() * 8f, (x, y) -> { float len = e.fout() * 4f; diff --git a/core/src/mindustry/content/Items.java b/core/src/mindustry/content/Items.java index 160c59cc15..c450e38bb9 100644 --- a/core/src/mindustry/content/Items.java +++ b/core/src/mindustry/content/Items.java @@ -108,7 +108,7 @@ public class Items implements ContentList{ tungsten = new Item("tungsten", Color.valueOf("768a9a")){{ hardness = 5; - cost = 1.2f; + cost = 1.5f; }}; carbide = new Item("carbide", Color.valueOf("89769a")){{ diff --git a/core/src/mindustry/world/blocks/defense/BuildTurret.java b/core/src/mindustry/world/blocks/defense/BuildTurret.java index a38adfa38f..07fbe5249a 100644 --- a/core/src/mindustry/world/blocks/defense/BuildTurret.java +++ b/core/src/mindustry/world/blocks/defense/BuildTurret.java @@ -22,7 +22,7 @@ import static mindustry.Vars.*; public class BuildTurret extends BaseTurret{ public final int timerTarget = timers++, timerTarget2 = timers++; - public int targetInterval = 60; + public int targetInterval = 30; public @Load(value = "@-base", fallback = "block-@size") TextureRegion baseRegion; public float buildSpeed = 1f; diff --git a/core/src/mindustry/world/blocks/heat/HeatProducer.java b/core/src/mindustry/world/blocks/heat/HeatProducer.java index 9c1f39fb38..7e0cdb6188 100644 --- a/core/src/mindustry/world/blocks/heat/HeatProducer.java +++ b/core/src/mindustry/world/blocks/heat/HeatProducer.java @@ -19,7 +19,7 @@ import mindustry.world.meta.*; public class HeatProducer extends Block{ public float heatOutput = 10f; - public float warmupRate = 0.25f; + public float warmupRate = 0.15f; public float consumeTime = 100; public @Load("@-heat") TextureRegion heatRegion; diff --git a/core/src/mindustry/world/blocks/production/GenericCrafter.java b/core/src/mindustry/world/blocks/production/GenericCrafter.java index 6df7ff8eca..aea5700c02 100644 --- a/core/src/mindustry/world/blocks/production/GenericCrafter.java +++ b/core/src/mindustry/world/blocks/production/GenericCrafter.java @@ -117,7 +117,7 @@ public class GenericCrafter extends Block{ progress += getProgressIncrease(craftTime); totalProgress += delta(); - warmup = Mathf.approachDelta(warmup, 1f, warmupSpeed); + warmup = Mathf.approachDelta(warmup, warmupTarget(), warmupSpeed); if(Mathf.chanceDelta(updateEffectChance)){ updateEffect.at(x + Mathf.range(size * 4f), y + Mathf.range(size * 4)); @@ -133,6 +133,10 @@ public class GenericCrafter extends Block{ dumpOutputs(); } + public float warmupTarget(){ + return 1f; + } + public void craft(){ consume(); diff --git a/core/src/mindustry/world/blocks/production/HeatCrafter.java b/core/src/mindustry/world/blocks/production/HeatCrafter.java index 85503e032e..f0546d68d8 100644 --- a/core/src/mindustry/world/blocks/production/HeatCrafter.java +++ b/core/src/mindustry/world/blocks/production/HeatCrafter.java @@ -7,14 +7,16 @@ import mindustry.graphics.*; import mindustry.ui.*; import mindustry.world.blocks.heat.*; +import java.util.*; + /** A crafter that requires contact from heater blocks to craft. */ public class HeatCrafter extends GenericCrafter{ /** Base heat requirement for 100% efficiency. */ public float heatRequirement = 10f; /** After heat meets this requirement, excess heat will be scaled by this number. */ - public float overheatScale = 0.25f; + public float overheatScale = 1f; /** Maximum possible efficiency after overheat. */ - public float maxEfficiency = 2f; + public float maxEfficiency = 4f; public HeatCrafter(String name){ super(name); @@ -24,14 +26,14 @@ public class HeatCrafter extends GenericCrafter{ public void setBars(){ super.setBars(); - bars.add("heat", (AttributeCrafterBuild entity) -> + bars.add("heat", (HeatCrafterBuild entity) -> new Bar(() -> - Core.bundle.format("bar.heatpercent", (int)entity.lastHeat), + Core.bundle.format("bar.heatpercent", (int)entity.heat), () -> Pal.lightOrange, - () -> entity.lastHeat / heatRequirement)); + () -> entity.heat / heatRequirement)); //TODO unnecessary? - bars.add("efficiency", (AttributeCrafterBuild entity) -> + bars.add("efficiency", (HeatCrafterBuild entity) -> new Bar(() -> Core.bundle.format("bar.efficiency", (int)(entity.efficiencyScale() * 100)), () -> Pal.ammo, @@ -45,30 +47,46 @@ public class HeatCrafter extends GenericCrafter{ //TODO heat stats } - public class AttributeCrafterBuild extends GenericCrafterBuild{ - public float lastHeat = 0f; + public class HeatCrafterBuild extends GenericCrafterBuild{ + //TODO sideHeat could be smooth + public float[] sideHeat = new float[4]; + public float heat = 0f; @Override public void updateTile(){ - lastHeat = 0f; + Arrays.fill(sideHeat, 0f); + heat = 0f; + for(var edge : getEdges()){ Building build = nearby(edge.x, edge.y); if(build != null && build.team == team && build instanceof HeatBlock heater && (!build.block.rotate || (relativeTo(build) + 2) % 4 == build.rotation)){ //heat is distributed across building size - lastHeat += heater.heat() / build.block.size; + float add = heater.heat() / build.block.size; + + sideHeat[Mathf.mod(relativeTo(build), 4)] += add; + heat += add; } } super.updateTile(); } + public float heatRequirement(){ + return heatRequirement; + } + + @Override + public float warmupTarget(){ + return Mathf.clamp(heat / heatRequirement); + } + @Override public float getProgressIncrease(float base){ return super.getProgressIncrease(base) * efficiencyScale(); } public float efficiencyScale(){ - float over = Math.max(lastHeat - heatRequirement, 0f); - return Math.min(Mathf.clamp(lastHeat / heatRequirement) + over / heatRequirement * overheatScale, maxEfficiency); + float over = Math.max(heat - heatRequirement, 0f); + return Math.min(Mathf.clamp(heat / heatRequirement) + over / heatRequirement * overheatScale, maxEfficiency); } } } diff --git a/core/src/mindustry/world/draw/DrawArcSmelter.java b/core/src/mindustry/world/draw/DrawArcSmelter.java index 51706aafbe..1291d35722 100644 --- a/core/src/mindustry/world/draw/DrawArcSmelter.java +++ b/core/src/mindustry/world/draw/DrawArcSmelter.java @@ -49,8 +49,8 @@ public class DrawArcSmelter extends DrawBlock{ Draw.reset(); } - Draw.rect(top, build.x, build.y); Draw.rect(build.block.region, build.x, build.y); + if(top.found()) Draw.rect(top, build.x, build.y); } @Override diff --git a/core/src/mindustry/world/draw/DrawCrucible.java b/core/src/mindustry/world/draw/DrawCrucible.java new file mode 100644 index 0000000000..83eabcaf4c --- /dev/null +++ b/core/src/mindustry/world/draw/DrawCrucible.java @@ -0,0 +1,72 @@ +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.world.*; +import mindustry.world.blocks.production.GenericCrafter.*; + +//TODO +public class DrawCrucible extends DrawBlock{ + public TextureRegion top, bottom; + public Color flameColor = Color.valueOf("f58349"), midColor = Color.valueOf("f2d585"); + public float flameRad = 1f, circleSpace = 2f, flameRadiusScl = 10f, flameRadiusMag = 0.6f, circleStroke = 1.5f; + + public float alpha = 0.5f; + public int particles = 30; + public float particleLife = 70f, particleRad = 7f, particleSize = 3f, fadeMargin = 0.4f; + public Interp particleInterp = new PowIn(1.5f); + + @Override + public void draw(GenericCrafterBuild build){ + Draw.rect(bottom, build.x, build.y); + + if(build.warmup > 0f && flameColor.a > 0.001f){ + Lines.stroke(circleStroke * build.warmup); + + float si = Mathf.absin(flameRadiusScl, flameRadiusMag); + float a = alpha * build.warmup; + Draw.blend(Blending.additive); + + Draw.color(midColor, a); + Fill.circle(build.x, build.y, flameRad + si); + + Draw.color(flameColor, a); + Lines.circle(build.x, build.y, (flameRad + circleSpace + si) * build.warmup); + + 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; + float angle = rand.random(360f); + float len = particleRad * particleInterp.apply(fout); + Draw.alpha(a * (1f - Mathf.curve(fin, 1f - fadeMargin))); + Fill.circle( + build.x + Angles.trnsx(angle, len), + build.y + Angles.trnsy(angle, len), + particleSize * fin * build.warmup + ); + } + + Draw.blend(); + Draw.reset(); + } + + Draw.rect(build.block.region, build.x, build.y); + if(top.found()) Draw.rect(top, build.x, build.y); + } + + @Override + public void load(Block block){ + top = Core.atlas.find(block.name + "-top"); + bottom = Core.atlas.find(block.name + "-bottom"); + } + + @Override + public TextureRegion[] icons(Block block){ + return new TextureRegion[]{bottom, block.region, top}; + } +} diff --git a/core/src/mindustry/world/draw/DrawHeat.java b/core/src/mindustry/world/draw/DrawHeat.java new file mode 100644 index 0000000000..a67c10f4d3 --- /dev/null +++ b/core/src/mindustry/world/draw/DrawHeat.java @@ -0,0 +1,41 @@ +package mindustry.world.draw; + +import arc.*; +import arc.graphics.*; +import arc.graphics.g2d.*; +import arc.math.*; +import mindustry.graphics.*; +import mindustry.world.*; +import mindustry.world.blocks.production.GenericCrafter.*; +import mindustry.world.blocks.production.HeatCrafter.*; + +public class DrawHeat extends DrawBlock{ + public Color heatColor = new Color(1f, 0.22f, 0.22f, 0.8f); + public float heatPulse = 0.3f, heatPulseScl = 10f; + + public TextureRegion heat; + + @Override + public void draw(GenericCrafterBuild build){ + + Draw.z(Layer.blockAdditive); + if(build instanceof HeatCrafterBuild hc){ + for(int i = 0; i < 4; i++){ + if(hc.sideHeat[i] > 0){ + Draw.blend(Blending.additive); + Draw.color(heatColor, hc.sideHeat[i] / hc.heatRequirement() * (heatColor.a * (1f - heatPulse + Mathf.absin(heatPulseScl, heatPulse)))); + Draw.rect(heat, build.x, build.y, i * 90f); + Draw.blend(); + Draw.color(); + } + } + } + Draw.z(Layer.block); + + } + + @Override + public void load(Block block){ + heat = Core.atlas.find(block.name + "-heat"); + } +} diff --git a/core/src/mindustry/world/draw/DrawMulti.java b/core/src/mindustry/world/draw/DrawMulti.java new file mode 100644 index 0000000000..78262a2dd1 --- /dev/null +++ b/core/src/mindustry/world/draw/DrawMulti.java @@ -0,0 +1,45 @@ +package mindustry.world.draw; + +import arc.graphics.g2d.*; +import mindustry.world.*; +import mindustry.world.blocks.production.GenericCrafter.*; + +/** combined several DrawBlocks into one */ +public class DrawMulti extends DrawBlock{ + public DrawBlock[] drawers = {}; + /** specifies the drawer index that sources the icon (since there can only be one icon source) */ + public int iconIndex = 0; + + public DrawMulti(){ + } + + public DrawMulti(DrawBlock... drawers){ + this.drawers = drawers; + } + + @Override + public void draw(GenericCrafterBuild build){ + for(var draw : drawers){ + draw.draw(build); + } + } + + @Override + public void drawLight(GenericCrafterBuild build){ + for(var draw : drawers){ + draw.drawLight(build); + } + } + + @Override + public void load(Block block){ + for(var draw : drawers){ + draw.load(block); + } + } + + @Override + public TextureRegion[] icons(Block block){ + return drawers.length <= iconIndex ? super.icons(block) : drawers[iconIndex].icons(block); + } +} diff --git a/tools/build.gradle b/tools/build.gradle index 17872781a8..20f2995b6b 100644 --- a/tools/build.gradle +++ b/tools/build.gradle @@ -38,7 +38,7 @@ def transformColors = { List> list -> transformColors([["4a4b53", "6e7080", "989aa4"], ["3a5651", "3a8f64", "92dd7e"], ["bf92f9", "8a73c6", "665c9f"], /*["6e7080", "989aa4", "b0bac0"],*/ ["bc5452", "ea8878", "feb380"], ["de9458", "f8c266", "ffe18f"], ["feb380", "ea8878", "bc5452"], ["d4816b", "eab678", "ffd37f"], ["ffffff", "dcc6c6", "9d7f7f"], ["df7646", "b23a4d", "752249"], ["3c3837", "515151", "646567"], - ["5757c1", "6f80e8", "88a4ff"], ["8f665b", "b28768", "c9a58f"]]) + ["5757c1", "6f80e8", "88a4ff"], ["8f665b", "b28768", "c9a58f"], ["4c5878", "768a9a", "a0b0c8"]]) def antialias = { File file -> if(!doAntialias) return