diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index c4b9a02281..cffae5e7f3 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -1173,6 +1173,7 @@ rules.enemyCheat = Infinite AI (Red Team) Resources rules.blockhealthmultiplier = Block Health Multiplier rules.blockdamagemultiplier = Block Damage Multiplier rules.unitbuildspeedmultiplier = Unit Production Speed Multiplier +rules.unitcostmultiplier = Unit Cost Multiplier rules.unithealthmultiplier = Unit Health Multiplier rules.unitdamagemultiplier = Unit Damage Multiplier rules.solarmultiplier = Solar Power Multiplier diff --git a/core/src/mindustry/game/Rules.java b/core/src/mindustry/game/Rules.java index 79421b2f7d..898bdcd8de 100644 --- a/core/src/mindustry/game/Rules.java +++ b/core/src/mindustry/game/Rules.java @@ -63,6 +63,8 @@ public class Rules{ public float solarMultiplier = 1f; /** How fast unit factories build units. */ public float unitBuildSpeedMultiplier = 1f; + /** Multiplier of resources that units take to build. */ + public float unitCostMultiplier = 1f; /** How much damage any other units deal. */ public float unitDamageMultiplier = 1f; /** If true, ghost blocks will appear upon destruction, letting builder blocks/units rebuild them. */ @@ -206,6 +208,10 @@ public class Rules{ return unitBuildSpeedMultiplier * teams.get(team).unitBuildSpeedMultiplier; } + public float unitCost(Team team){ + return unitCostMultiplier * teams.get(team).unitCostMultiplier; + } + public float unitDamage(Team team){ return unitDamageMultiplier * teams.get(team).unitDamageMultiplier; } @@ -246,6 +252,8 @@ public class Rules{ public float unitBuildSpeedMultiplier = 1f; /** How much damage any other units deal. */ public float unitDamageMultiplier = 1f; + /** Multiplier of resources that units take to build. */ + public float unitCostMultiplier = 1f; /** How much health blocks start with. */ public float blockHealthMultiplier = 1f; /** How much damage blocks (turrets) deal. */ diff --git a/core/src/mindustry/logic/LExecutor.java b/core/src/mindustry/logic/LExecutor.java index e6b5d3c4bf..dfc055eb7d 100644 --- a/core/src/mindustry/logic/LExecutor.java +++ b/core/src/mindustry/logic/LExecutor.java @@ -1424,13 +1424,14 @@ public class LExecutor{ } case ambientLight -> state.rules.ambientLight.fromDouble(exec.num(value)); case solarMultiplier -> state.rules.solarMultiplier = exec.numf(value); - case unitBuildSpeed, unitDamage, blockHealth, blockDamage, buildSpeed, rtsMinSquad, rtsMinWeight -> { + case unitBuildSpeed, unitCost, unitDamage, blockHealth, blockDamage, buildSpeed, rtsMinSquad, rtsMinWeight -> { Team team = exec.team(p1); if(team != null){ float num = exec.numf(value); switch(rule){ case buildSpeed -> team.rules().buildSpeedMultiplier = Mathf.clamp(num, 0.001f, 50f); case unitBuildSpeed -> team.rules().unitBuildSpeedMultiplier = Mathf.clamp(num, 0f, 50f); + case unitCost -> team.rules().unitCostMultiplier = Math.max(num, 0f); case unitDamage -> team.rules().unitDamageMultiplier = Math.max(num, 0f); case blockHealth -> team.rules().blockHealthMultiplier = Math.max(num, 0.001f); case blockDamage -> team.rules().blockDamageMultiplier = Math.max(num, 0f); diff --git a/core/src/mindustry/logic/LStatements.java b/core/src/mindustry/logic/LStatements.java index c3eb6119f8..6f22b3c158 100644 --- a/core/src/mindustry/logic/LStatements.java +++ b/core/src/mindustry/logic/LStatements.java @@ -1370,7 +1370,7 @@ public class LStatements{ fields(table, "w", p3, s -> p3 = s); fields(table, "h", p4, s -> p4 = s); } - case buildSpeed, unitBuildSpeed, unitDamage, blockHealth, blockDamage, rtsMinSquad, rtsMinWeight -> { + case buildSpeed, unitBuildSpeed, unitCost, unitDamage, blockHealth, blockDamage, rtsMinSquad, rtsMinWeight -> { if(p1.equals("0")){ p1 = "@sharded"; } diff --git a/core/src/mindustry/logic/LogicRule.java b/core/src/mindustry/logic/LogicRule.java index 8314707ff4..48a536b56a 100644 --- a/core/src/mindustry/logic/LogicRule.java +++ b/core/src/mindustry/logic/LogicRule.java @@ -19,6 +19,7 @@ public enum LogicRule{ //team specific buildSpeed, unitBuildSpeed, + unitCost, unitDamage, blockHealth, blockDamage, diff --git a/core/src/mindustry/ui/dialogs/CustomRulesDialog.java b/core/src/mindustry/ui/dialogs/CustomRulesDialog.java index 24b158e046..ebad83d48e 100644 --- a/core/src/mindustry/ui/dialogs/CustomRulesDialog.java +++ b/core/src/mindustry/ui/dialogs/CustomRulesDialog.java @@ -195,6 +195,7 @@ public class CustomRulesDialog extends BaseDialog{ numberi("@rules.unitcap", f -> rules.unitCap = f, () -> rules.unitCap, -999, 999); number("@rules.unitdamagemultiplier", f -> rules.unitDamageMultiplier = f, () -> rules.unitDamageMultiplier); number("@rules.unitbuildspeedmultiplier", f -> rules.unitBuildSpeedMultiplier = f, () -> rules.unitBuildSpeedMultiplier, 0f, 50f); + number("@rules.unitcostmultiplier", f -> rules.unitCostMultiplier = f, () -> rules.unitCostMultiplier); main.button("@bannedunits", () -> showBanned("@bannedunits", ContentType.unit, rules.bannedUnits, u -> !u.isHidden())).left().width(300f).row(); @@ -293,6 +294,7 @@ public class CustomRulesDialog extends BaseDialog{ number("@rules.unitdamagemultiplier", f -> teams.unitDamageMultiplier = f, () -> teams.unitDamageMultiplier); number("@rules.unitbuildspeedmultiplier", f -> teams.unitBuildSpeedMultiplier = f, () -> teams.unitBuildSpeedMultiplier, 0.001f, 50f); + number("@rules.unitcostmultiplier", f -> teams.unitCostMultiplier = f, () -> teams.unitCostMultiplier); main = wasMain; }, () -> shown[0]).growX().row(); diff --git a/core/src/mindustry/world/blocks/units/Reconstructor.java b/core/src/mindustry/world/blocks/units/Reconstructor.java index ebd52b64ed..52b2270b47 100644 --- a/core/src/mindustry/world/blocks/units/Reconstructor.java +++ b/core/src/mindustry/world/blocks/units/Reconstructor.java @@ -121,6 +121,8 @@ public class Reconstructor extends UnitBlock{ } } + consumeBuilder.each(c -> c.multiplier = b -> state.rules.unitCost(b.team)); + super.init(); } diff --git a/core/src/mindustry/world/blocks/units/UnitAssembler.java b/core/src/mindustry/world/blocks/units/UnitAssembler.java index 7c6efb7cb8..68e2f164cf 100644 --- a/core/src/mindustry/world/blocks/units/UnitAssembler.java +++ b/core/src/mindustry/world/blocks/units/UnitAssembler.java @@ -123,6 +123,8 @@ public class UnitAssembler extends PayloadBlock{ updateClipRadius(areaSize * tilesize); consume(consPayload = new ConsumePayloadDynamic((UnitAssemblerBuild build) -> build.plan().requirements)); + consumeBuilder.each(c -> c.multiplier = b -> state.rules.unitCost(b.team)); + super.init(); } diff --git a/core/src/mindustry/world/blocks/units/UnitFactory.java b/core/src/mindustry/world/blocks/units/UnitFactory.java index bfbda241c5..86ab061a83 100644 --- a/core/src/mindustry/world/blocks/units/UnitFactory.java +++ b/core/src/mindustry/world/blocks/units/UnitFactory.java @@ -25,6 +25,8 @@ import mindustry.world.blocks.payloads.*; import mindustry.world.consumers.*; import mindustry.world.meta.*; +import static mindustry.Vars.*; + public class UnitFactory extends UnitBlock{ public int[] capacities = {}; @@ -74,6 +76,8 @@ public class UnitFactory extends UnitBlock{ } } + consumeBuilder.each(c -> c.multiplier = b -> state.rules.unitCost(b.team)); + super.init(); } diff --git a/core/src/mindustry/world/consumers/Consume.java b/core/src/mindustry/world/consumers/Consume.java index 4f9cadffe6..7f73226f8e 100644 --- a/core/src/mindustry/world/consumers/Consume.java +++ b/core/src/mindustry/world/consumers/Consume.java @@ -1,5 +1,6 @@ package mindustry.world.consumers; +import arc.func.*; import arc.scene.ui.layout.*; import mindustry.gen.*; import mindustry.world.*; @@ -13,6 +14,8 @@ public abstract class Consume{ public boolean booster; /** If false, this consumer will still be checked, but it will need to updated manually. */ public boolean update = true; + /** Multiplier for costs. Does not work for power consumers. */ + public Floatf multiplier = b -> 1f; /** * Apply extra filters to a block. diff --git a/core/src/mindustry/world/consumers/ConsumeItemDynamic.java b/core/src/mindustry/world/consumers/ConsumeItemDynamic.java index 094c6b0e6e..45325369cd 100644 --- a/core/src/mindustry/world/consumers/ConsumeItemDynamic.java +++ b/core/src/mindustry/world/consumers/ConsumeItemDynamic.java @@ -37,13 +37,13 @@ public class ConsumeItemDynamic extends Consume{ }); } - private void rebuild(Building tile, Table table){ + private void rebuild(Building build, Table table){ table.clear(); int i = 0; - for(ItemStack stack : items.get(tile)){ - table.add(new ReqImage(new ItemImage(stack.item.uiIcon, stack.amount), - () -> tile.items != null && tile.items.has(stack.item, stack.amount))).padRight(8).left(); + for(ItemStack stack : items.get(build)){ + table.add(new ReqImage(new ItemImage(stack.item.uiIcon, Math.round(stack.amount * multiplier.get(build))), + () -> build.items != null && build.items.has(stack.item, Math.round(stack.amount * multiplier.get(build))))).padRight(8).left(); if(++i % 4 == 0) table.row(); } } @@ -51,12 +51,12 @@ public class ConsumeItemDynamic extends Consume{ @Override public void trigger(Building build){ for(ItemStack stack : items.get(build)){ - build.items.remove(stack); + build.items.remove(stack.item, Math.round(stack.amount * multiplier.get(build))); } } @Override public float efficiency(Building build){ - return build.consumeTriggerValid() || build.items.has(items.get(build)) ? 1f : 0f; + return build.consumeTriggerValid() || build.items.has(items.get(build), multiplier.get(build)) ? 1f : 0f; } } diff --git a/core/src/mindustry/world/consumers/ConsumeItems.java b/core/src/mindustry/world/consumers/ConsumeItems.java index 19de8b5c83..791db5a71d 100644 --- a/core/src/mindustry/world/consumers/ConsumeItems.java +++ b/core/src/mindustry/world/consumers/ConsumeItems.java @@ -33,8 +33,8 @@ public class ConsumeItems extends Consume{ table.table(c -> { int i = 0; for(var stack : items){ - c.add(new ReqImage(new ItemImage(stack.item.uiIcon, stack.amount), - () -> build.items.has(stack.item, stack.amount))).padRight(8); + c.add(new ReqImage(new ItemImage(stack.item.uiIcon, Math.round(stack.amount * multiplier.get(build))), + () -> build.items.has(stack.item, Math.round(stack.amount * multiplier.get(build))))).padRight(8); if(++i % 4 == 0) c.row(); } }).left(); @@ -43,13 +43,13 @@ public class ConsumeItems extends Consume{ @Override public void trigger(Building build){ for(var stack : items){ - build.items.remove(stack); + build.items.remove(stack.item, Math.round(stack.amount * multiplier.get(build))); } } @Override public float efficiency(Building build){ - return build.consumeTriggerValid() || build.items.has(items) ? 1f : 0f; + return build.consumeTriggerValid() || build.items.has(items, multiplier.get(build)) ? 1f : 0f; } @Override diff --git a/core/src/mindustry/world/consumers/ConsumeLiquid.java b/core/src/mindustry/world/consumers/ConsumeLiquid.java index bef8e3a8d6..3581a4f3fa 100644 --- a/core/src/mindustry/world/consumers/ConsumeLiquid.java +++ b/core/src/mindustry/world/consumers/ConsumeLiquid.java @@ -35,7 +35,7 @@ public class ConsumeLiquid extends ConsumeLiquidBase{ @Override public void update(Building build){ - build.liquids.remove(liquid, amount * build.edelta()); + build.liquids.remove(liquid, amount * build.edelta() * multiplier.get(build)); } @Override @@ -43,7 +43,7 @@ public class ConsumeLiquid extends ConsumeLiquidBase{ float ed = build.edelta() * build.efficiencyScale(); if(ed <= 0.00000001f) return 0f; //there can be more liquid than necessary, so cap at 1 - return Math.min(build.liquids.get(liquid) / (amount * ed), 1f); + return Math.min(build.liquids.get(liquid) / (amount * ed * multiplier.get(build)), 1f); } @Override diff --git a/core/src/mindustry/world/consumers/ConsumeLiquidFilter.java b/core/src/mindustry/world/consumers/ConsumeLiquidFilter.java index a1183ef61f..8e97250fd0 100644 --- a/core/src/mindustry/world/consumers/ConsumeLiquidFilter.java +++ b/core/src/mindustry/world/consumers/ConsumeLiquidFilter.java @@ -43,7 +43,7 @@ public class ConsumeLiquidFilter extends ConsumeLiquidBase{ public void update(Building build){ Liquid liq = getConsumed(build); if(liq != null){ - build.liquids.remove(liq, amount * build.edelta()); + build.liquids.remove(liq, amount * build.edelta() * multiplier.get(build)); } } @@ -52,7 +52,7 @@ public class ConsumeLiquidFilter extends ConsumeLiquidBase{ var liq = getConsumed(build); float ed = build.edelta(); if(ed <= 0.00000001f) return 0f; - return liq != null ? Math.min(build.liquids.get(liq) / (amount * ed), 1f) : 0f; + return liq != null ? Math.min(build.liquids.get(liq) / (amount * ed * multiplier.get(build)), 1f) : 0f; } public @Nullable Liquid getConsumed(Building build){ diff --git a/core/src/mindustry/world/consumers/ConsumeLiquids.java b/core/src/mindustry/world/consumers/ConsumeLiquids.java index 62f557f811..69ee3c3930 100644 --- a/core/src/mindustry/world/consumers/ConsumeLiquids.java +++ b/core/src/mindustry/world/consumers/ConsumeLiquids.java @@ -42,18 +42,20 @@ public class ConsumeLiquids extends Consume{ @Override public void update(Building build){ + float mult = multiplier.get(build); for(var stack : liquids){ - build.liquids.remove(stack.liquid, stack.amount * build.edelta()); + build.liquids.remove(stack.liquid, stack.amount * build.edelta() * mult); } } @Override public float efficiency(Building build){ + float mult = multiplier.get(build); float ed = build.edelta(); if(ed <= 0.00000001f) return 0f; float min = 1f; for(var stack : liquids){ - min = Math.min(build.liquids.get(stack.liquid) / (stack.amount * ed), min); + min = Math.min(build.liquids.get(stack.liquid) / (stack.amount * ed * mult), min); } return min; } diff --git a/core/src/mindustry/world/consumers/ConsumePayloadDynamic.java b/core/src/mindustry/world/consumers/ConsumePayloadDynamic.java index 968b963528..d12abb009d 100644 --- a/core/src/mindustry/world/consumers/ConsumePayloadDynamic.java +++ b/core/src/mindustry/world/consumers/ConsumePayloadDynamic.java @@ -18,12 +18,21 @@ public class ConsumePayloadDynamic extends Consume{ @Override public float efficiency(Building build){ - return build.getPayloads().contains(payloads.get(build)) ? 1f : 0f; + float mult = multiplier.get(build); + for(PayloadStack stack : payloads.get(build)){ + if(!build.getPayloads().contains(stack.item, Math.round(stack.amount * mult))){ + return 0f; + } + } + return 1f; } @Override public void trigger(Building build){ - build.getPayloads().remove(payloads.get(build)); + float mult = multiplier.get(build); + for(PayloadStack stack : payloads.get(build)){ + build.getPayloads().remove(stack.item, Math.round(stack.amount * mult)); + } } @Override @@ -54,8 +63,8 @@ public class ConsumePayloadDynamic extends Consume{ table.table(c -> { int i = 0; for(var stack : pay){ - c.add(new ReqImage(new ItemImage(stack.item.uiIcon, stack.amount), - () -> inv.contains(stack.item, stack.amount))).padRight(8); + c.add(new ReqImage(new ItemImage(stack.item.uiIcon, Math.round(stack.amount * multiplier.get(build))), + () -> inv.contains(stack.item, Math.round(stack.amount * multiplier.get(build))))).padRight(8); if(++i % 4 == 0) c.row(); } }).left(); diff --git a/core/src/mindustry/world/consumers/ConsumePayloads.java b/core/src/mindustry/world/consumers/ConsumePayloads.java index 4ae8bedeeb..ae905a4e8b 100644 --- a/core/src/mindustry/world/consumers/ConsumePayloads.java +++ b/core/src/mindustry/world/consumers/ConsumePayloads.java @@ -16,12 +16,21 @@ public class ConsumePayloads extends Consume{ @Override public float efficiency(Building build){ - return build.getPayloads().contains(payloads) ? 1f : 0f; + float mult = multiplier.get(build); + for(PayloadStack stack : payloads){ + if(!build.getPayloads().contains(stack.item, Math.round(stack.amount * mult))){ + return 0f; + } + } + return 1f; } @Override public void trigger(Building build){ - build.getPayloads().remove(payloads); + float mult = multiplier.get(build); + for(PayloadStack stack : payloads){ + build.getPayloads().remove(stack.item, Math.round(stack.amount * mult)); + } } @Override @@ -42,8 +51,8 @@ public class ConsumePayloads extends Consume{ table.table(c -> { int i = 0; for(var stack : payloads){ - c.add(new ReqImage(new ItemImage(stack.item.uiIcon, stack.amount), - () -> inv.contains(stack.item, stack.amount))).padRight(8); + c.add(new ReqImage(new ItemImage(stack.item.uiIcon, Math.round(stack.amount * multiplier.get(build))), + () -> inv.contains(stack.item, Math.round(stack.amount * multiplier.get(build))))).padRight(8); if(++i % 4 == 0) c.row(); } }).left();