diff --git a/core/assets-raw/sprites/units/incite.png b/core/assets-raw/sprites/units/incite.png index 01d7d777bb..b6c2aeeeaa 100644 Binary files a/core/assets-raw/sprites/units/incite.png and b/core/assets-raw/sprites/units/incite.png differ diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index dcc3eb1d52..ee3e371cca 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -810,6 +810,7 @@ bar.capacity = Capacity: {0} bar.unitcap = {0} {1}/{2} bar.liquid = Liquid bar.heat = Heat +bar.heatpercent = Heat: {0} bar.power = Power bar.progress = Build Progress bar.input = Input diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 3a0706c7e7..b3b8d5fca0 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -950,17 +950,19 @@ public class Blocks implements ContentList{ consumes.item(Items.fissileMatter, 1); }}; - carbideCrucible = new GenericCrafter("carbide-crucible"){{ + carbideCrucible = new HeatCrafter("carbide-crucible"){{ requirements(Category.crafting, with(Items.tungsten, 60, Items.graphite, 30)); craftEffect = Fx.smeltsmoke; outputItem = new ItemStack(Items.carbide, 1); craftTime = 30f; - size = 2; + size = 3; hasPower = hasItems = true; drawer = new DrawSmelter(Color.valueOf("ffc099")); 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/world/Block.java b/core/src/mindustry/world/Block.java index 4577287cd7..30b775d1bf 100644 --- a/core/src/mindustry/world/Block.java +++ b/core/src/mindustry/world/Block.java @@ -604,6 +604,14 @@ public class Block extends UnlockableContent{ } } + public Point2[] getEdges(){ + return Edges.getEdges(size); + } + + public Point2[] getInsideEdges(){ + return Edges.getInsideEdges(size); + } + /** Iterate through ever grid position taken up by this block. */ public void iterateTaken(int x, int y, Intc2 placer){ if(isMultiblock()){ diff --git a/core/src/mindustry/world/Build.java b/core/src/mindustry/world/Build.java index c4317a542b..88482114f5 100644 --- a/core/src/mindustry/world/Build.java +++ b/core/src/mindustry/world/Build.java @@ -221,12 +221,12 @@ public class Build{ public static boolean contactsShallows(int x, int y, Block block){ if(block.isMultiblock()){ - for(Point2 point : Edges.getInsideEdges(block.size)){ + for(Point2 point : block.getInsideEdges()){ Tile tile = world.tile(x + point.x, y + point.y); if(tile != null && !tile.floor().isDeep()) return true; } - for(Point2 point : Edges.getEdges(block.size)){ + for(Point2 point : block.getEdges()){ Tile tile = world.tile(x + point.x, y + point.y); if(tile != null && !tile.floor().isDeep()) return true; } diff --git a/core/src/mindustry/world/blocks/heat/HeatBlock.java b/core/src/mindustry/world/blocks/heat/HeatBlock.java index da72507e18..797435e323 100644 --- a/core/src/mindustry/world/blocks/heat/HeatBlock.java +++ b/core/src/mindustry/world/blocks/heat/HeatBlock.java @@ -1,14 +1,6 @@ package mindustry.world.blocks.heat; -/** Basic interface for any block that produces or requires heat.*/ +/** Basic interface for any block that produces heat.*/ public interface HeatBlock{ float heat(); - - //potentially unnecessary - /* - void heat(float value); - - default void addHeat(float amount){ - heat(heat() + amount); - }*/ } diff --git a/core/src/mindustry/world/blocks/heat/HeatProducer.java b/core/src/mindustry/world/blocks/heat/HeatProducer.java index 849ca04d64..9c1f39fb38 100644 --- a/core/src/mindustry/world/blocks/heat/HeatProducer.java +++ b/core/src/mindustry/world/blocks/heat/HeatProducer.java @@ -6,6 +6,8 @@ import arc.math.*; import arc.util.*; import arc.util.io.*; import mindustry.annotations.Annotations.*; +import mindustry.content.*; +import mindustry.entities.*; import mindustry.entities.units.*; import mindustry.gen.*; import mindustry.graphics.*; @@ -26,6 +28,7 @@ public class HeatProducer extends Block{ public @Load("@-top2") TextureRegion topRegion2; public Color heatColor = new Color(1f, 0.22f, 0.22f, 0.8f); public float heatPulse = 0.3f, heatPulseScl = 10f, glowMult = 1.2f; + public Effect consumeEffect = Fx.none; public HeatProducer(String name){ super(name); @@ -55,7 +58,6 @@ public class HeatProducer extends Block{ Draw.rect(req.rotation > 1 ? topRegion2 : topRegion1, req.drawx(), req.drawy(), req.rotation * 90); } - @Override public TextureRegion[] icons(){ return new TextureRegion[]{region, topRegion1}; @@ -72,6 +74,7 @@ public class HeatProducer extends Block{ if(progress >= 1f){ consume(); + consumeEffect.at(this); progress -= 1f; } } diff --git a/core/src/mindustry/world/blocks/production/HeatCrafter.java b/core/src/mindustry/world/blocks/production/HeatCrafter.java new file mode 100644 index 0000000000..85503e032e --- /dev/null +++ b/core/src/mindustry/world/blocks/production/HeatCrafter.java @@ -0,0 +1,74 @@ +package mindustry.world.blocks.production; + +import arc.*; +import arc.math.*; +import mindustry.gen.*; +import mindustry.graphics.*; +import mindustry.ui.*; +import mindustry.world.blocks.heat.*; + +/** 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; + /** Maximum possible efficiency after overheat. */ + public float maxEfficiency = 2f; + + public HeatCrafter(String name){ + super(name); + } + + @Override + public void setBars(){ + super.setBars(); + + bars.add("heat", (AttributeCrafterBuild entity) -> + new Bar(() -> + Core.bundle.format("bar.heatpercent", (int)entity.lastHeat), + () -> Pal.lightOrange, + () -> entity.lastHeat / heatRequirement)); + + //TODO unnecessary? + bars.add("efficiency", (AttributeCrafterBuild entity) -> + new Bar(() -> + Core.bundle.format("bar.efficiency", (int)(entity.efficiencyScale() * 100)), + () -> Pal.ammo, + entity::efficiencyScale)); + } + + @Override + public void setStats(){ + super.setStats(); + + //TODO heat stats + } + + public class AttributeCrafterBuild extends GenericCrafterBuild{ + public float lastHeat = 0f; + + @Override + public void updateTile(){ + lastHeat = 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; + } + } + super.updateTile(); + } + + @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); + } + } +}