Full implementation of #7014

This commit is contained in:
Anuken
2022-10-04 13:07:23 -04:00
parent e661abaf24
commit 88d6c4c8f9
17 changed files with 70 additions and 26 deletions

View File

@@ -1173,6 +1173,7 @@ rules.enemyCheat = Infinite AI (Red Team) Resources
rules.blockhealthmultiplier = Block Health Multiplier rules.blockhealthmultiplier = Block Health Multiplier
rules.blockdamagemultiplier = Block Damage Multiplier rules.blockdamagemultiplier = Block Damage Multiplier
rules.unitbuildspeedmultiplier = Unit Production Speed Multiplier rules.unitbuildspeedmultiplier = Unit Production Speed Multiplier
rules.unitcostmultiplier = Unit Cost Multiplier
rules.unithealthmultiplier = Unit Health Multiplier rules.unithealthmultiplier = Unit Health Multiplier
rules.unitdamagemultiplier = Unit Damage Multiplier rules.unitdamagemultiplier = Unit Damage Multiplier
rules.solarmultiplier = Solar Power Multiplier rules.solarmultiplier = Solar Power Multiplier

View File

@@ -63,6 +63,8 @@ public class Rules{
public float solarMultiplier = 1f; public float solarMultiplier = 1f;
/** How fast unit factories build units. */ /** How fast unit factories build units. */
public float unitBuildSpeedMultiplier = 1f; public float unitBuildSpeedMultiplier = 1f;
/** Multiplier of resources that units take to build. */
public float unitCostMultiplier = 1f;
/** How much damage any other units deal. */ /** How much damage any other units deal. */
public float unitDamageMultiplier = 1f; public float unitDamageMultiplier = 1f;
/** If true, ghost blocks will appear upon destruction, letting builder blocks/units rebuild them. */ /** 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; return unitBuildSpeedMultiplier * teams.get(team).unitBuildSpeedMultiplier;
} }
public float unitCost(Team team){
return unitCostMultiplier * teams.get(team).unitCostMultiplier;
}
public float unitDamage(Team team){ public float unitDamage(Team team){
return unitDamageMultiplier * teams.get(team).unitDamageMultiplier; return unitDamageMultiplier * teams.get(team).unitDamageMultiplier;
} }
@@ -246,6 +252,8 @@ public class Rules{
public float unitBuildSpeedMultiplier = 1f; public float unitBuildSpeedMultiplier = 1f;
/** How much damage any other units deal. */ /** How much damage any other units deal. */
public float unitDamageMultiplier = 1f; public float unitDamageMultiplier = 1f;
/** Multiplier of resources that units take to build. */
public float unitCostMultiplier = 1f;
/** How much health blocks start with. */ /** How much health blocks start with. */
public float blockHealthMultiplier = 1f; public float blockHealthMultiplier = 1f;
/** How much damage blocks (turrets) deal. */ /** How much damage blocks (turrets) deal. */

View File

@@ -1424,13 +1424,14 @@ public class LExecutor{
} }
case ambientLight -> state.rules.ambientLight.fromDouble(exec.num(value)); case ambientLight -> state.rules.ambientLight.fromDouble(exec.num(value));
case solarMultiplier -> state.rules.solarMultiplier = exec.numf(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); Team team = exec.team(p1);
if(team != null){ if(team != null){
float num = exec.numf(value); float num = exec.numf(value);
switch(rule){ switch(rule){
case buildSpeed -> team.rules().buildSpeedMultiplier = Mathf.clamp(num, 0.001f, 50f); case buildSpeed -> team.rules().buildSpeedMultiplier = Mathf.clamp(num, 0.001f, 50f);
case unitBuildSpeed -> team.rules().unitBuildSpeedMultiplier = Mathf.clamp(num, 0f, 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 unitDamage -> team.rules().unitDamageMultiplier = Math.max(num, 0f);
case blockHealth -> team.rules().blockHealthMultiplier = Math.max(num, 0.001f); case blockHealth -> team.rules().blockHealthMultiplier = Math.max(num, 0.001f);
case blockDamage -> team.rules().blockDamageMultiplier = Math.max(num, 0f); case blockDamage -> team.rules().blockDamageMultiplier = Math.max(num, 0f);

View File

@@ -1370,7 +1370,7 @@ public class LStatements{
fields(table, "w", p3, s -> p3 = s); fields(table, "w", p3, s -> p3 = s);
fields(table, "h", p4, s -> p4 = 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")){ if(p1.equals("0")){
p1 = "@sharded"; p1 = "@sharded";
} }

View File

@@ -19,6 +19,7 @@ public enum LogicRule{
//team specific //team specific
buildSpeed, buildSpeed,
unitBuildSpeed, unitBuildSpeed,
unitCost,
unitDamage, unitDamage,
blockHealth, blockHealth,
blockDamage, blockDamage,

View File

@@ -195,6 +195,7 @@ public class CustomRulesDialog extends BaseDialog{
numberi("@rules.unitcap", f -> rules.unitCap = f, () -> rules.unitCap, -999, 999); numberi("@rules.unitcap", f -> rules.unitCap = f, () -> rules.unitCap, -999, 999);
number("@rules.unitdamagemultiplier", f -> rules.unitDamageMultiplier = f, () -> rules.unitDamageMultiplier); number("@rules.unitdamagemultiplier", f -> rules.unitDamageMultiplier = f, () -> rules.unitDamageMultiplier);
number("@rules.unitbuildspeedmultiplier", f -> rules.unitBuildSpeedMultiplier = f, () -> rules.unitBuildSpeedMultiplier, 0f, 50f); 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(); 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.unitdamagemultiplier", f -> teams.unitDamageMultiplier = f, () -> teams.unitDamageMultiplier);
number("@rules.unitbuildspeedmultiplier", f -> teams.unitBuildSpeedMultiplier = f, () -> teams.unitBuildSpeedMultiplier, 0.001f, 50f); number("@rules.unitbuildspeedmultiplier", f -> teams.unitBuildSpeedMultiplier = f, () -> teams.unitBuildSpeedMultiplier, 0.001f, 50f);
number("@rules.unitcostmultiplier", f -> teams.unitCostMultiplier = f, () -> teams.unitCostMultiplier);
main = wasMain; main = wasMain;
}, () -> shown[0]).growX().row(); }, () -> shown[0]).growX().row();

View File

@@ -121,6 +121,8 @@ public class Reconstructor extends UnitBlock{
} }
} }
consumeBuilder.each(c -> c.multiplier = b -> state.rules.unitCost(b.team));
super.init(); super.init();
} }

View File

@@ -123,6 +123,8 @@ public class UnitAssembler extends PayloadBlock{
updateClipRadius(areaSize * tilesize); updateClipRadius(areaSize * tilesize);
consume(consPayload = new ConsumePayloadDynamic((UnitAssemblerBuild build) -> build.plan().requirements)); consume(consPayload = new ConsumePayloadDynamic((UnitAssemblerBuild build) -> build.plan().requirements));
consumeBuilder.each(c -> c.multiplier = b -> state.rules.unitCost(b.team));
super.init(); super.init();
} }

View File

@@ -25,6 +25,8 @@ import mindustry.world.blocks.payloads.*;
import mindustry.world.consumers.*; import mindustry.world.consumers.*;
import mindustry.world.meta.*; import mindustry.world.meta.*;
import static mindustry.Vars.*;
public class UnitFactory extends UnitBlock{ public class UnitFactory extends UnitBlock{
public int[] capacities = {}; 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(); super.init();
} }

View File

@@ -1,5 +1,6 @@
package mindustry.world.consumers; package mindustry.world.consumers;
import arc.func.*;
import arc.scene.ui.layout.*; import arc.scene.ui.layout.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.world.*; import mindustry.world.*;
@@ -13,6 +14,8 @@ public abstract class Consume{
public boolean booster; public boolean booster;
/** If false, this consumer will still be checked, but it will need to updated manually. */ /** If false, this consumer will still be checked, but it will need to updated manually. */
public boolean update = true; public boolean update = true;
/** Multiplier for costs. Does not work for power consumers. */
public Floatf<Building> multiplier = b -> 1f;
/** /**
* Apply extra filters to a block. * Apply extra filters to a block.

View File

@@ -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(); table.clear();
int i = 0; int i = 0;
for(ItemStack stack : items.get(tile)){ for(ItemStack stack : items.get(build)){
table.add(new ReqImage(new ItemImage(stack.item.uiIcon, stack.amount), table.add(new ReqImage(new ItemImage(stack.item.uiIcon, Math.round(stack.amount * multiplier.get(build))),
() -> tile.items != null && tile.items.has(stack.item, stack.amount))).padRight(8).left(); () -> build.items != null && build.items.has(stack.item, Math.round(stack.amount * multiplier.get(build))))).padRight(8).left();
if(++i % 4 == 0) table.row(); if(++i % 4 == 0) table.row();
} }
} }
@@ -51,12 +51,12 @@ public class ConsumeItemDynamic extends Consume{
@Override @Override
public void trigger(Building build){ public void trigger(Building build){
for(ItemStack stack : items.get(build)){ for(ItemStack stack : items.get(build)){
build.items.remove(stack); build.items.remove(stack.item, Math.round(stack.amount * multiplier.get(build)));
} }
} }
@Override @Override
public float efficiency(Building build){ 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;
} }
} }

View File

@@ -33,8 +33,8 @@ public class ConsumeItems extends Consume{
table.table(c -> { table.table(c -> {
int i = 0; int i = 0;
for(var stack : items){ for(var stack : items){
c.add(new ReqImage(new ItemImage(stack.item.uiIcon, stack.amount), c.add(new ReqImage(new ItemImage(stack.item.uiIcon, Math.round(stack.amount * multiplier.get(build))),
() -> build.items.has(stack.item, stack.amount))).padRight(8); () -> build.items.has(stack.item, Math.round(stack.amount * multiplier.get(build))))).padRight(8);
if(++i % 4 == 0) c.row(); if(++i % 4 == 0) c.row();
} }
}).left(); }).left();
@@ -43,13 +43,13 @@ public class ConsumeItems extends Consume{
@Override @Override
public void trigger(Building build){ public void trigger(Building build){
for(var stack : items){ for(var stack : items){
build.items.remove(stack); build.items.remove(stack.item, Math.round(stack.amount * multiplier.get(build)));
} }
} }
@Override @Override
public float efficiency(Building build){ 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 @Override

View File

@@ -35,7 +35,7 @@ public class ConsumeLiquid extends ConsumeLiquidBase{
@Override @Override
public void update(Building build){ public void update(Building build){
build.liquids.remove(liquid, amount * build.edelta()); build.liquids.remove(liquid, amount * build.edelta() * multiplier.get(build));
} }
@Override @Override
@@ -43,7 +43,7 @@ public class ConsumeLiquid extends ConsumeLiquidBase{
float ed = build.edelta() * build.efficiencyScale(); float ed = build.edelta() * build.efficiencyScale();
if(ed <= 0.00000001f) return 0f; if(ed <= 0.00000001f) return 0f;
//there can be more liquid than necessary, so cap at 1 //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 @Override

View File

@@ -43,7 +43,7 @@ public class ConsumeLiquidFilter extends ConsumeLiquidBase{
public void update(Building build){ public void update(Building build){
Liquid liq = getConsumed(build); Liquid liq = getConsumed(build);
if(liq != null){ 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); var liq = getConsumed(build);
float ed = build.edelta(); float ed = build.edelta();
if(ed <= 0.00000001f) return 0f; 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){ public @Nullable Liquid getConsumed(Building build){

View File

@@ -42,18 +42,20 @@ public class ConsumeLiquids extends Consume{
@Override @Override
public void update(Building build){ public void update(Building build){
float mult = multiplier.get(build);
for(var stack : liquids){ for(var stack : liquids){
build.liquids.remove(stack.liquid, stack.amount * build.edelta()); build.liquids.remove(stack.liquid, stack.amount * build.edelta() * mult);
} }
} }
@Override @Override
public float efficiency(Building build){ public float efficiency(Building build){
float mult = multiplier.get(build);
float ed = build.edelta(); float ed = build.edelta();
if(ed <= 0.00000001f) return 0f; if(ed <= 0.00000001f) return 0f;
float min = 1f; float min = 1f;
for(var stack : liquids){ 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; return min;
} }

View File

@@ -18,12 +18,21 @@ public class ConsumePayloadDynamic extends Consume{
@Override @Override
public float efficiency(Building build){ 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 @Override
public void trigger(Building build){ 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 @Override
@@ -54,8 +63,8 @@ public class ConsumePayloadDynamic extends Consume{
table.table(c -> { table.table(c -> {
int i = 0; int i = 0;
for(var stack : pay){ for(var stack : pay){
c.add(new ReqImage(new ItemImage(stack.item.uiIcon, stack.amount), c.add(new ReqImage(new ItemImage(stack.item.uiIcon, Math.round(stack.amount * multiplier.get(build))),
() -> inv.contains(stack.item, stack.amount))).padRight(8); () -> inv.contains(stack.item, Math.round(stack.amount * multiplier.get(build))))).padRight(8);
if(++i % 4 == 0) c.row(); if(++i % 4 == 0) c.row();
} }
}).left(); }).left();

View File

@@ -16,12 +16,21 @@ public class ConsumePayloads extends Consume{
@Override @Override
public float efficiency(Building build){ 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 @Override
public void trigger(Building build){ 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 @Override
@@ -42,8 +51,8 @@ public class ConsumePayloads extends Consume{
table.table(c -> { table.table(c -> {
int i = 0; int i = 0;
for(var stack : payloads){ for(var stack : payloads){
c.add(new ReqImage(new ItemImage(stack.item.uiIcon, stack.amount), c.add(new ReqImage(new ItemImage(stack.item.uiIcon, Math.round(stack.amount * multiplier.get(build))),
() -> inv.contains(stack.item, stack.amount))).padRight(8); () -> inv.contains(stack.item, Math.round(stack.amount * multiplier.get(build))))).padRight(8);
if(++i % 4 == 0) c.row(); if(++i % 4 == 0) c.row();
} }
}).left(); }).left();