Ammo resupply point implementation
@@ -792,6 +792,7 @@ rules.buildspeedmultiplier = Build Speed Multiplier
|
|||||||
rules.deconstructrefundmultiplier = Deconstruct Refund Multiplier
|
rules.deconstructrefundmultiplier = Deconstruct Refund Multiplier
|
||||||
rules.waitForWaveToEnd = Waves Wait for Enemies
|
rules.waitForWaveToEnd = Waves Wait for Enemies
|
||||||
rules.dropzoneradius = Drop Zone Radius:[lightgray] (tiles)
|
rules.dropzoneradius = Drop Zone Radius:[lightgray] (tiles)
|
||||||
|
rules.unitammo = Units Require Ammo
|
||||||
rules.title.waves = Waves
|
rules.title.waves = Waves
|
||||||
rules.title.resourcesbuilding = Resources & Building
|
rules.title.resourcesbuilding = Resources & Building
|
||||||
rules.title.enemy = Enemies
|
rules.title.enemy = Enemies
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 645 KiB After Width: | Height: | Size: 652 KiB |
|
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 130 KiB |
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 130 KiB |
@@ -79,7 +79,7 @@ public class Blocks implements ContentList{
|
|||||||
//units
|
//units
|
||||||
groundFactory, airFactory, navalFactory,
|
groundFactory, airFactory, navalFactory,
|
||||||
additiveReconstructor, multiplicativeReconstructor, exponentialReconstructor, tetrativeReconstructor,
|
additiveReconstructor, multiplicativeReconstructor, exponentialReconstructor, tetrativeReconstructor,
|
||||||
repairPoint,
|
repairPoint, resupplyPoint,
|
||||||
|
|
||||||
//campaign
|
//campaign
|
||||||
launchPad, launchPadLarge, coreSilo, dataProcessor,
|
launchPad, launchPadLarge, coreSilo, dataProcessor,
|
||||||
@@ -1754,6 +1754,15 @@ public class Blocks implements ContentList{
|
|||||||
powerUse = 1f;
|
powerUse = 1f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
resupplyPoint = new ResupplyPoint("resupply-point"){{
|
||||||
|
requirements(Category.units, BuildVisibility.ammoOnly, ItemStack.with(Items.lead, 20, Items.copper, 15, Items.silicon, 15));
|
||||||
|
|
||||||
|
size = 2;
|
||||||
|
range = 80f;
|
||||||
|
|
||||||
|
consumes.item(Items.copper, 1);
|
||||||
|
}};
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
//region sandbox
|
//region sandbox
|
||||||
|
|
||||||
|
|||||||
@@ -98,6 +98,9 @@ public class Logic implements ApplicationListener{
|
|||||||
SectorDamage.apply(state.rules.sector.getTurnsPassed());
|
SectorDamage.apply(state.rules.sector.getTurnsPassed());
|
||||||
state.rules.sector.setTurnsPassed(0);
|
state.rules.sector.setTurnsPassed(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//enable infinite ammo for wave team by default
|
||||||
|
state.rules.waveTeam.rules().infiniteAmmo = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
//TODO dying takes up a turn (?)
|
//TODO dying takes up a turn (?)
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc{
|
|||||||
mount.targetRotation = angleTo(mount.aimX, mount.aimY);
|
mount.targetRotation = angleTo(mount.aimX, mount.aimY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mount.shoot && (ammo > 0 || !state.rules.unitAmmo)){
|
if(mount.shoot && (ammo > 0 || !state.rules.unitAmmo || team().rules().infiniteAmmo)){
|
||||||
float rotation = this.rotation - 90;
|
float rotation = this.rotation - 90;
|
||||||
|
|
||||||
//shoot if applicable
|
//shoot if applicable
|
||||||
@@ -118,10 +118,10 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc{
|
|||||||
|
|
||||||
if(mount.weapon.mirror) mount.side = !mount.side;
|
if(mount.weapon.mirror) mount.side = !mount.side;
|
||||||
mount.reload = weapon.reload;
|
mount.reload = weapon.reload;
|
||||||
}
|
|
||||||
|
|
||||||
ammo --;
|
ammo --;
|
||||||
if(ammo < 0) ammo = 0;
|
if(ammo < 0) ammo = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,6 +105,8 @@ public class Rules{
|
|||||||
public boolean cheat;
|
public boolean cheat;
|
||||||
/** If true, resources are not consumed when building. */
|
/** If true, resources are not consumed when building. */
|
||||||
public boolean infiniteResources;
|
public boolean infiniteResources;
|
||||||
|
/** If true, this team has infinite unit ammo. */
|
||||||
|
public boolean infiniteAmmo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Copies this ruleset exactly. Not efficient at all, do not use often. */
|
/** Copies this ruleset exactly. Not efficient at all, do not use often. */
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ public class UnitType extends UnlockableContent{
|
|||||||
public boolean flipBackLegs = true;
|
public boolean flipBackLegs = true;
|
||||||
|
|
||||||
public int itemCapacity = 30;
|
public int itemCapacity = 30;
|
||||||
public int ammoCapacity = 100;
|
public int ammoCapacity = 220;
|
||||||
public int drillTier = -1;
|
public int drillTier = -1;
|
||||||
public float buildSpeed = 1f, mineSpeed = 1f;
|
public float buildSpeed = 1f, mineSpeed = 1f;
|
||||||
|
|
||||||
|
|||||||
@@ -155,6 +155,7 @@ public class CustomRulesDialog extends BaseDialog{
|
|||||||
main.row();
|
main.row();
|
||||||
|
|
||||||
title("$rules.title.unit");
|
title("$rules.title.unit");
|
||||||
|
check("$rules.unitammo", b -> rules.unitAmmo = b, () -> rules.unitAmmo);
|
||||||
number("$rules.unithealthmultiplier", f -> rules.unitHealthMultiplier = f, () -> rules.unitHealthMultiplier);
|
number("$rules.unithealthmultiplier", f -> rules.unitHealthMultiplier = f, () -> rules.unitHealthMultiplier);
|
||||||
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);
|
number("$rules.unitbuildspeedmultiplier", f -> rules.unitBuildSpeedMultiplier = f, () -> rules.unitBuildSpeedMultiplier);
|
||||||
|
|||||||
@@ -163,10 +163,17 @@ public interface Autotiler{
|
|||||||
|
|
||||||
/** @return whether this tile is looking at the other tile, or the other tile is looking at this one.
|
/** @return whether this tile is looking at the other tile, or the other tile is looking at this one.
|
||||||
* If the other tile does not rotate, it is always considered to be facing this one. */
|
* If the other tile does not rotate, it is always considered to be facing this one. */
|
||||||
default boolean lookingAt(Tile tile, int rotation, int otherx, int othery, int otherrot, Block otherblock){
|
default boolean lookingAtEither(Tile tile, int rotation, int otherx, int othery, int otherrot, Block otherblock){
|
||||||
return (Point2.equals(tile.x + Geometry.d4(rotation).x, tile.y + Geometry.d4(rotation).y, otherx, othery)
|
return (Point2.equals(tile.x + Geometry.d4(rotation).x, tile.y + Geometry.d4(rotation).y, otherx, othery)
|
||||||
|| (!otherblock.rotatedOutput(otherx, othery) || Point2.equals(otherx + Geometry.d4(otherrot).x, othery + Geometry.d4(otherrot).y, tile.x, tile.y)));
|
|| (!otherblock.rotatedOutput(otherx, othery) || Point2.equals(otherx + Geometry.d4(otherrot).x, othery + Geometry.d4(otherrot).y, tile.x, tile.y)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return whether this tile is looking at the other tile. */
|
||||||
|
default boolean lookingAt(Tile tile, int rotation, int otherx, int othery, Block otherblock){
|
||||||
|
Tile facing = Edges.getFacingEdge(otherblock, otherx, othery, tile);
|
||||||
|
return facing != null &&
|
||||||
|
Point2.equals(tile.x + Geometry.d4(rotation).x, tile.y + Geometry.d4(rotation).y, facing.x, facing.y);
|
||||||
|
}
|
||||||
|
|
||||||
boolean blends(Tile tile, int rotation, int otherx, int othery, int otherrot, Block otherblock);
|
boolean blends(Tile tile, int rotation, int otherx, int othery, int otherrot, Block otherblock);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,8 @@ public class Conveyor extends Block implements Autotiler{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean blends(Tile tile, int rotation, int otherx, int othery, int otherrot, Block otherblock){
|
public boolean blends(Tile tile, int rotation, int otherx, int othery, int otherrot, Block otherblock){
|
||||||
return otherblock.outputsItems() && lookingAt(tile, rotation, otherx, othery, otherrot, otherblock);
|
return (otherblock.outputsItems() || lookingAt(tile, rotation, otherx, othery, otherblock))
|
||||||
|
&& lookingAtEither(tile, rotation, otherx, othery, otherrot, otherblock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ public class StackConveyor extends Block implements Autotiler{
|
|||||||
if(tile.entity instanceof StackConveyorEntity){
|
if(tile.entity instanceof StackConveyorEntity){
|
||||||
int state = ((StackConveyorEntity)tile.entity).state;
|
int state = ((StackConveyorEntity)tile.entity).state;
|
||||||
if(state == stateLoad){ //standard conveyor mode
|
if(state == stateLoad){ //standard conveyor mode
|
||||||
return otherblock.outputsItems() && lookingAt(tile, rotation, otherx, othery, otherrot, otherblock);
|
return otherblock.outputsItems() && lookingAtEither(tile, rotation, otherx, othery, otherrot, otherblock);
|
||||||
}else if(state == stateUnload){ //router mode
|
}else if(state == stateUnload){ //router mode
|
||||||
return (otherblock.hasItems || otherblock.outputsItems() || otherblock.acceptsItems) &&
|
return (otherblock.hasItems || otherblock.outputsItems() || otherblock.acceptsItems) &&
|
||||||
(notLookingAt(tile, rotation, otherx, othery, otherrot, otherblock) ||
|
(notLookingAt(tile, rotation, otherx, othery, otherrot, otherblock) ||
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ public class Conduit extends LiquidBlock implements Autotiler{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean blends(Tile tile, int rotation, int otherx, int othery, int otherrot, Block otherblock){
|
public boolean blends(Tile tile, int rotation, int otherx, int othery, int otherrot, Block otherblock){
|
||||||
return otherblock.hasLiquids && otherblock.outputsLiquid && lookingAt(tile, rotation, otherx, othery, otherrot, otherblock);
|
return otherblock.hasLiquids && otherblock.outputsLiquid && lookingAtEither(tile, rotation, otherx, othery, otherrot, otherblock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -43,14 +43,14 @@ public class LiquidConverter extends GenericCrafter{
|
|||||||
ConsumeLiquidBase cl = consumes.get(ConsumeType.liquid);
|
ConsumeLiquidBase cl = consumes.get(ConsumeType.liquid);
|
||||||
|
|
||||||
if(cons.valid()){
|
if(cons.valid()){
|
||||||
float use = Math.min(cl.amount * delta(), liquidCapacity - liquids.get(outputLiquid.liquid)) * efficiency();
|
float use = Math.min(cl.amount * edelta(), liquidCapacity - liquids.get(outputLiquid.liquid));
|
||||||
|
|
||||||
useContent(outputLiquid.liquid);
|
useContent(outputLiquid.liquid);
|
||||||
progress += use / cl.amount / craftTime;
|
progress += use / cl.amount;
|
||||||
liquids.add(outputLiquid.liquid, use);
|
liquids.add(outputLiquid.liquid, use);
|
||||||
if(progress >= 1f){
|
if(progress >= craftTime){
|
||||||
consume();
|
consume();
|
||||||
progress = 0f;
|
progress %= craftTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import mindustry.type.*;
|
|||||||
import mindustry.ui.*;
|
import mindustry.ui.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
import mindustry.world.blocks.*;
|
import mindustry.world.blocks.*;
|
||||||
|
import mindustry.world.blocks.units.*;
|
||||||
import mindustry.world.meta.*;
|
import mindustry.world.meta.*;
|
||||||
import mindustry.world.modules.*;
|
import mindustry.world.modules.*;
|
||||||
|
|
||||||
@@ -25,6 +26,13 @@ import static mindustry.Vars.*;
|
|||||||
public class CoreBlock extends StorageBlock{
|
public class CoreBlock extends StorageBlock{
|
||||||
public UnitType unitType = UnitTypes.alpha;
|
public UnitType unitType = UnitTypes.alpha;
|
||||||
|
|
||||||
|
public final int timerResupply = timers++;
|
||||||
|
|
||||||
|
public int ammoAmount = 5;
|
||||||
|
public float resupplyRate = 10f;
|
||||||
|
public float resupplyRange = 60f;
|
||||||
|
public Item resupplyItem = Items.copper;
|
||||||
|
|
||||||
public CoreBlock(String name){
|
public CoreBlock(String name){
|
||||||
super(name);
|
super(name);
|
||||||
|
|
||||||
@@ -101,6 +109,15 @@ public class CoreBlock extends StorageBlock{
|
|||||||
Call.onPlayerSpawn(tile, player);
|
Call.onPlayerSpawn(tile, player);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateTile(){
|
||||||
|
|
||||||
|
//resupply nearby units
|
||||||
|
if(items.has(resupplyItem) && timer(timerResupply, resupplyRate) && ResupplyPoint.resupply(this, resupplyRange, ammoAmount, resupplyItem.color)){
|
||||||
|
items.remove(resupplyItem, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawLight(){
|
public void drawLight(){
|
||||||
Drawf.light(team, x, y, 30f * size, Pal.accent, 0.5f + Mathf.absin(20f, 0.1f));
|
Drawf.light(team, x, y, 30f * size, Pal.accent, 0.5f + Mathf.absin(20f, 0.1f));
|
||||||
|
|||||||
65
core/src/mindustry/world/blocks/units/ResupplyPoint.java
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
package mindustry.world.blocks.units;
|
||||||
|
|
||||||
|
import arc.graphics.*;
|
||||||
|
import mindustry.content.*;
|
||||||
|
import mindustry.entities.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
import mindustry.graphics.*;
|
||||||
|
import mindustry.world.*;
|
||||||
|
|
||||||
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
|
public class ResupplyPoint extends Block{
|
||||||
|
public final int timerResupply = timers++;
|
||||||
|
|
||||||
|
public int ammoAmount = 10;
|
||||||
|
public float resupplyRate = 5f;
|
||||||
|
public float range = 60f;
|
||||||
|
public Color ammoColor = Items.copper.color;
|
||||||
|
|
||||||
|
public ResupplyPoint(String name){
|
||||||
|
super(name);
|
||||||
|
solid = update = true;
|
||||||
|
hasItems = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean outputsItems(){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawPlace(int x, int y, int rotation, boolean valid){
|
||||||
|
Drawf.dashCircle(x * tilesize + offset(), y * tilesize + offset(), range, Pal.placing);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ResupplyPointEntity extends TileEntity{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawSelect(){
|
||||||
|
Drawf.dashCircle(x, y, range, team.color);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateTile(){
|
||||||
|
if(consValid() && timer(timerResupply, resupplyRate / timeScale) && resupply(this, range, ammoAmount, ammoColor)){
|
||||||
|
consume();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Tries to resupply nearby units.
|
||||||
|
* @return whether resupplying was successful. If unit ammo is disabled, always returns false. */
|
||||||
|
public static boolean resupply(TileEntity tile, float range, int ammoAmount, Color ammoColor){
|
||||||
|
if(!state.rules.unitAmmo) return false;
|
||||||
|
|
||||||
|
Unitc unit = Units.closest(tile.team, tile.x, tile.y, range, u -> u.ammo() <= u.type().ammoCapacity - ammoAmount);
|
||||||
|
if(unit != null){
|
||||||
|
Fx.itemTransfer.at(tile.x, tile.y, ammoAmount / 2f, ammoColor, unit);
|
||||||
|
unit.ammo(Math.min(unit.ammo() + ammoAmount, unit.type().ammoCapacity));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,7 +9,8 @@ public enum BuildVisibility{
|
|||||||
debugOnly(() -> false),
|
debugOnly(() -> false),
|
||||||
sandboxOnly(() -> Vars.state.rules.infiniteResources),
|
sandboxOnly(() -> Vars.state.rules.infiniteResources),
|
||||||
campaignOnly(() -> Vars.state.isCampaign()),
|
campaignOnly(() -> Vars.state.isCampaign()),
|
||||||
lightingOnly(() -> Vars.state.rules.lighting);
|
lightingOnly(() -> Vars.state.rules.lighting),
|
||||||
|
ammoOnly(() -> Vars.state.rules.unitAmmo);
|
||||||
|
|
||||||
private final Boolp visible;
|
private final Boolp visible;
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
org.gradle.daemon=true
|
org.gradle.daemon=true
|
||||||
org.gradle.jvmargs=-Xms256m -Xmx1024m
|
org.gradle.jvmargs=-Xms256m -Xmx1024m
|
||||||
archash=06c938d6dced0d9bf9f8ec98d4767b38f633f8fa
|
archash=f76b0c94953c07ef2ac40858b3b615a34911bdf7
|
||||||
|
|||||||