Balancing Payload Logistics: PMD, Assorted Changes, and Deconstructor Behavioral Changes (#12182)

* Payload Changes 3 (final)

* Deconstructor Behavior Changes Final

* Added full-storage icon

* adjustments

* removed fontello file

* Removed full-storage.png

* Tweaked itemBuffer

* Update IconConverter.java

* Apply suggestion from @Anuken

---------

Co-authored-by: EggleEgg <125359838+EggleEgg@users.noreply.github.com>
Co-authored-by: Anuken <arnukren@gmail.com>
This commit is contained in:
SomeonesShade
2026-08-31 20:57:06 -04:00
committed by GitHub
co-authored by EggleEgg Anuken
parent 616cc98098
commit 42ce901da2
4 changed files with 85 additions and 24 deletions
+2 -2
View File
@@ -2134,7 +2134,7 @@ block.constructor.description = Fabricates structures up to 2x2 tiles in size.
block.large-constructor.name = Large Constructor
block.large-constructor.description = Fabricates structures up to 4x4 tiles in size.
block.deconstructor.name = Large Deconstructor
block.deconstructor.description = Deconstructs structures and units. Returns 100% of build cost.
block.deconstructor.description = Deconstructs inputted structures and units. Returns 100% of build cost. Holds items into seperate item capacities.
block.payload-loader.name = Payload Loader
block.payload-loader.description = Load liquids and items into blocks.
block.payload-unloader.name = Payload Unloader
@@ -2742,7 +2742,7 @@ block.ship-refabricator.description = Upgrades inputted ship units to the second
block.mech-refabricator.description = Upgrades inputted mech units to the second tier.
block.prime-refabricator.description = Upgrades inputted units to the third tier.
block.basic-assembler-module.description = Increases assembler tier when placed next to a construction boundary. Requires power. Can be used as a payload input.
block.small-deconstructor.description = Deconstructs inputted structures and units. Returns 100% of the build cost.
block.small-deconstructor.description = Deconstructs inputted structures and units. Returns 100% of the build cost. Holds items into seperate item capacities.
block.reinforced-payload-conveyor.description = Moves payloads forward.
block.reinforced-payload-router.description = Distributes payloads into adjacent blocks. Functions as a sorter when a filter is set.
block.payload-mass-driver.description = Long-range payload transport structure. Shoots received payloads to linked payload mass drivers.
+14 -7
View File
@@ -6622,8 +6622,8 @@ public class Blocks{
requirements(Category.units, with(Items.tungsten, 40, Items.silicon, 50, Items.graphite, 20));
regionSuffix = "-dark";
size = 3;
reload = 130f;
chargeTime = 90f;
reload = 45f;
chargeTime = 70f;
range = 700f;
maxPayloadSize = 2.5f;
fogRadius = 5;
@@ -6631,7 +6631,7 @@ public class Blocks{
}};
largePayloadMassDriver = new PayloadMassDriver("large-payload-mass-driver"){{
requirements(Category.units, with(Items.phaseFabric, 20, Items.tungsten, 200, Items.silicon, 200, Items.graphite, 100, Items.oxide, 30));
requirements(Category.units, with(Items.phaseFabric, 10, Items.tungsten, 120, Items.silicon, 150, Items.graphite, 60, Items.oxide, 30));
regionSuffix = "-dark";
size = 5;
reload = 130f;
@@ -6642,21 +6642,28 @@ public class Blocks{
}};
smallDeconstructor = new PayloadDeconstructor("small-deconstructor"){{
requirements(Category.units, with(Items.beryllium, 100, Items.silicon, 100, Items.oxide, 40, Items.graphite, 80));
requirements(Category.units, with(Items.beryllium, 70, Items.silicon, 70, Items.oxide, 25, Items.graphite, 50));
regionSuffix = "-dark";
itemCapacity = 100;
itemBuffer = itemCapacity - 20;
consumePower(1f);
size = 3;
deconstructSpeed = 3f;
separateItemCapacity = true;
//it just looks weird for anything larger
maxPayloadSize = 3;
}};
deconstructor = new PayloadDeconstructor("deconstructor"){{
requirements(Category.units, with(Items.beryllium, 250, Items.oxide, 100, Items.silicon, 250, Items.carbide, 50));
regionSuffix = "-dark";
itemCapacity = 250;
itemCapacity = 320;
itemBuffer = itemCapacity - 20;
consumePower(3f);
size = 5;
deconstructSpeed = 6f;
separateItemCapacity = true;
}};
constructor = new Constructor("constructor"){{
@@ -6675,12 +6682,12 @@ public class Blocks{
requirements(Category.units, with(Items.silicon, 150, Items.oxide, 100, Items.tungsten, 200, Items.thorium, 80));
regionSuffix = "-dark";
hasPower = true;
buildSpeed = 0.75f;
buildSpeed = 5f;
maxBlockSize = 4;
minBlockSize = 3;
size = 5;
consumePower(3f);
consumePower(5f);
}};
payloadLoader = new PayloadLoader("payload-loader"){{
@@ -1,5 +1,6 @@
package mindustry.world.blocks.payloads;
import arc.graphics.*;
import arc.*;
import arc.graphics.g2d.*;
import arc.math.*;
@@ -19,6 +20,8 @@ public class PayloadDeconstructor extends PayloadBlock{
public float maxPayloadSize = 4;
public float deconstructSpeed = 2.5f;
public int dumpRate = 4;
/** Any payload with build requirements equalling or exceeding this value is accepted regardless. */
public int itemBuffer = 0;
public PayloadDeconstructor(String name){
super(name);
@@ -58,6 +61,8 @@ public class PayloadDeconstructor extends PayloadBlock{
public @Nullable float[] accum;
public float progress;
public float time, speedScl;
public static final float overlayDuration = 40f;
public float overlayTime = 0;
@Override
public void draw(){
@@ -90,6 +95,23 @@ public class PayloadDeconstructor extends PayloadBlock{
});
}
//draw warning
if(overlayTime > 0 && deconstructing == null){
float z = Draw.z();
Draw.z(Layer.flyingUnitLow + 2f);
var region = Icon.warning.getRegion();
Draw.color(Color.scarlet);
Draw.alpha(0.8f * Interp.exp5Out.apply(overlayTime));
float size = 8f;
Draw.rect(region, this.x, this.y, size, size);
Draw.reset();
overlayTime = Math.max(overlayTime - Time.delta/overlayDuration, 0f);
Draw.z(z);
}
Draw.rect(topRegion, x, y);
}
@@ -107,9 +129,28 @@ public class PayloadDeconstructor extends PayloadBlock{
@Override
public boolean acceptPayload(Building source, Payload payload){
return deconstructing == null && this.payload == null && super.acceptPayload(source, payload) && payload.requirements().length > 0 && payload.fits(maxPayloadSize);
}
boolean isFull = false;
//source equalling this building means it comes from a unit payenter
if(source != this){
for(var req : payload.requirements()){
float realAmount = req.amount * (payload instanceof BuildPayload ? state.rules.buildCostMultiplier : state.rules.unitCost(team));
if(items.get(req.item) + realAmount >= itemCapacity) isFull = true;
//if the payload's requirements are too large within the buffer, receive anyway.
if(realAmount >= itemBuffer){
isFull = false;
break;
}
}
if(isFull && deconstructing == null){
overlayTime = 2.5f;
}
}
return !isFull && deconstructing == null && this.payload == null && super.acceptPayload(source, payload) && payload.requirements().length > 0 && payload.fits(maxPayloadSize);
}
@Override
public void updateTile(){
super.updateTile();
@@ -132,13 +173,11 @@ public class PayloadDeconstructor extends PayloadBlock{
}
//check if there is enough space to get the items for deconstruction
boolean canProgress = items.total() <= itemCapacity;
if(canProgress){
for(var ac : accum){
if(ac >= 1f){
canProgress = false;
break;
}
boolean canProgress = true;
for(var req : reqs){
if(items.get(req.item) >= itemCapacity){
canProgress = false;
break;
}
}
@@ -169,7 +208,7 @@ public class PayloadDeconstructor extends PayloadBlock{
//transfer items from accumulation buffer into block inventory when they reach integers
for(int i = 0; i < reqs.length; i++){
int taken = Math.min((int)accum[i], itemCapacity - items.total());
int taken = Math.min((int)accum[i], itemCapacity - items.get(reqs[i].item));
if(taken > 0){
items.add(reqs[i].item, taken);
accum[i] -= taken;
+20 -5
View File
@@ -12,11 +12,26 @@ public class IconConverter{
public static void main(String[] __){
/*
Process for adding an icon to the font:
1. Have an SVG ready, possibly created with this tool.
2. Go to Fontello and load the config.json from core/assets-raw/fontgen/config.json
3. Drag the SVG in.
4. Export the config and font file, replace the old config.
5. Take the font (ttf) from the zip, open it in FontForge, and merge it into font.woff and icon.ttf. Usually, you would do view -> go to (the 0x unicode index).
//CONVERTING A PNG INTO A SVG
1. Add your png to core/assets-raw/icons/
2. Run gradle tools:pack. This will add the png to icons.properties
3. If you haven't done it already, download inkscape and add in path enviroment variables your inkscape installation so "inkscape --etc" commands can run
4. Run gradle tools:icongen. This step will not work if you haven't done step 3
5. Locate your icon.svg under core/assets-raw/fontgen/extra/
6. Often generated icons cannot be read by fontello correctly ("If image looks not as expected please convert to compound path manually..."), follow the steps in the wiki linked (https://github.com/fontello/fontello/wiki/How-to-use-custom-images#importing-svg-images)
//ADDING TO FONTS
1. Go to Fontello and load the config.json from core/assets-raw/fontgen/config.json
2. Drag the SVG in
3. Click on your new fontello icon to select it. If selected the icon circle should show a red outline
4. Export the config and font file ("Download webfont" button), replace the old config
5. Intall FontForge if you havent done it already
6. Take the font (.ttf) from the zip, open it in FontForge, and merge it into font.woff (Element -> Merge fonts) inside core/assets/fonts/. You will be prompted whether you want to keep the existing kerning, usually select Yes
7. Optionally, go view -> go to (the 0x unicode index, or search by name) to check if the icon has been added
8. Go to file -> generate fonts, uncheck font validation, click generate and replace the old font.woff. Saving the sfd file is not necessary
9. Repeat steps 6 and 8 for icon.ttf
10. Done! do note when using icons if they contain any dashes (-) they will be converted into camelcase. So something like foo-bar.svg becomes Icon.fooBar
**/
Log.info("Converting icons...");