Reactivity and Assorted Changes (#11245)

* Implemented turretDepositCooldown (1)

* Implemented activationTime for Turrets (1)

* activationTime for Turrets Fixes (2)
readSync() line isn't needed,
Overdrive should not make the cooldown go faster, it stays as is unless there is a good argument against it.

* activationTime (3): Descriptions and SetBars()
Updated arc and lancer descriptions.
Added setBars() stuff for clearness.

* turretDepositCooldown (2):
now depositCooldown and is now on a per turret basis if needed... will potentially need further iteration

* turretDepositCooldown (3): made it opt in
added an internal gamerule (long name, need to reduce it later) to enable the balance (oriented for pvp)
depositCooldown = 0 by def
added depositCooldown entries in Blocks.java

* activationTime (4): Minor Adjustments to UI

* activitationTime (5): Implemented drawInactive() and inactiveColo, and arc/lancer sprite
Thinking if I should set the sprites to be white, then use Color.gray...

* turretDepositCooldown (4): Made the cooldown only affect turrets

* Reload Turret Coolant Fixes (1)
Made coolant and overdrive effects not get chopped off from Math.min when its too high

* activationTime (6): activationTime is now at the Base Turret Level
Also implemented the code for TractorBeamTurret thanks to the code changes
Parallax can have the feature if needed for future balancing.
Hopefully nothing was screwed up in the transition...

* Counterbalance (1): Swarmer 8 -> 7 firerate nerf, and Cyclone 7.5 -> 6 firerate nerf [First Attempt]

* Reload Turret Coolant Fixes (2): added a buffer if the excessReload exceeds more than 2 reloads.

* Reload Turret Coolant Fixes (3): hotfix, the buffer actually works this time

* turretDepositCooldown (5): Made the cooldown seperate from itemDepositCooldown

* Implemented armorMultiplier (1)

* fixing a merge

* (AT:7a) Reverted Saving Capability

* (AT:7b) Removed activation timer from lancer and arc as well as sprites

* (AT:7c) Removed visuals for activation timer
will be reimplemented via a greyscale effect if returned rather than via sprites

* (AT:7aa) oops

* Made the default value 0 when placed - Activation Timer (8)

* (depositCooldown : 6) Moved depositCooldown to Blocks.java, cleaned up canDepositItem(), removed enableTurretDepositCooldown

* armorMultiplier (2) - oops, made armorMultipler = 0 correspond to 100% armorPiercing

* Update core/src/mindustry/input/InputHandler.java

* Reload Turret Coolant Fixes (4): A bit too high

---------

Co-authored-by: Anuken <arnukren@gmail.com>
This commit is contained in:
SomeonesShade
2025-12-31 14:39:22 -05:00
committed by GitHub
co-authored by Anuken
parent 87e2dc69a2
commit 4122a9d51d
16 changed files with 155 additions and 15 deletions
+2
View File
@@ -66,6 +66,8 @@ public class Block extends UnlockableContent implements Senseable{
public boolean acceptsItems = false;
/** If true, this block won't be affected by the onlyDepositCore rule. */
public boolean alwaysAllowDeposit = false;
/** Cooldown, in seconds, applied to player item depositing when any item is deposited to this block. Overrides the itemDepositCooldown if non-negative. */
public float depositCooldown = -1f;
/** If true, all item capacities of this block are separate instead of pooled as one number. */
public boolean separateItemCapacity = false;
/** maximum items this block can carry (usually, this is per-type of item) */
@@ -1,5 +1,7 @@
package mindustry.world.blocks.defense.turrets;
import arc.*;
import arc.graphics.*;
import arc.math.*;
import arc.struct.*;
import arc.util.*;
@@ -8,6 +10,7 @@ import mindustry.entities.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.logic.*;
import mindustry.ui.*;
import mindustry.world.*;
import mindustry.world.blocks.*;
import mindustry.world.consumers.*;
@@ -21,6 +24,8 @@ public class BaseTurret extends Block{
public float rotateSpeed = 5;
public float fogRadiusMultiplier = 1f;
public boolean disableOverlapCheck = false;
/** How much time to start shooting after placement. */
public float activationTime = 0f;
/** Effect displayed when coolant is used. */
public Effect coolEffect = Fx.fuelburn;
@@ -90,10 +95,31 @@ public class BaseTurret extends Block{
super.setStats();
stats.add(Stat.shootRange, range / tilesize, StatUnit.blocks);
if(activationTime > 0) stats.add(Stat.activationTime, activationTime / 60f, StatUnit.seconds);
}
@Override
public void setBars(){
super.setBars();
if(activationTime > 0){
addBar("activationtimer", (BaseTurretBuild entity) ->
new Bar(() ->
(entity.activationTimer > 0)? Core.bundle.format("bar.activationtimer", Mathf.ceil(entity.activationTimer / 60f)) : Core.bundle.get("bar.activated"),
() -> (entity.activationTimer > 0)? Pal.lightOrange : Pal.techBlue,
() -> 1 - entity.activationTimer / activationTime));
}
}
public class BaseTurretBuild extends Building implements Ranged, RotBlock{
public float rotation = 90;
public float activationTimer = 0;
@Override
public void placed(){
super.placed();
activationTimer = activationTime;
}
@Override
public float range(){
@@ -113,5 +139,10 @@ public class BaseTurret extends Block{
public float estimateDps(){
return 0f;
}
@Override
public BlockStatus status() {
return (activationTimer <= 0)? super.status() : BlockStatus.inactive;
}
}
}
@@ -26,7 +26,7 @@ public class ReloadTurret extends BaseTurret{
public float reloadCounter;
protected void updateCooling(){
if(reloadCounter < reload && coolant != null && coolant.efficiency(this) > 0 && efficiency > 0){
if(canReload() && coolant != null && coolant.efficiency(this) > 0 && efficiency > 0){
float capacity = coolant instanceof ConsumeLiquidFilter filter ? filter.getConsumed(this).heatCapacity : (coolant.consumes(liquids.current()) ? liquids.current().heatCapacity : 0.4f);
float amount = coolant.amount * coolant.efficiency(this);
coolant.update(this);
@@ -45,5 +45,9 @@ public class ReloadTurret extends BaseTurret{
protected float baseReloadSpeed(){
return efficiency;
}
protected boolean canReload(){
return reloadCounter < reload;
}
}
}
@@ -76,6 +76,11 @@ public class TractorBeamTurret extends BaseTurret{
@Override
public void updateTile(){
if(activationTimer > 0){
activationTimer -= Time.delta;
return;
}
float eff = efficiency * coolantMultiplier, edelta = eff * delta();
//retarget
@@ -278,6 +278,8 @@ public class Turret extends ReloadTurret{
public @Nullable float[] curRecoils;
public float shootWarmup, charge, warmupHold = 0f;
public int totalShots, barrelCounter;
public float excessReload = 0;
public int reloadShots = 0;
public boolean logicShooting = false;
public @Nullable Posc target;
public Vec2 targetPos = new Vec2();
@@ -419,7 +421,7 @@ public class Turret extends ReloadTurret{
}
public boolean isActive(){
return (target != null || wasShooting) && enabled;
return (target != null || wasShooting) && enabled && activationTimer <= 0;
}
public void targetPosition(Posc pos){
@@ -481,8 +483,6 @@ public class Turret extends ReloadTurret{
shootWarmup = Mathf.lerpDelta(shootWarmup, warmupTarget, shootWarmupSpeed * (warmupTarget > 0 ? efficiency : 1f));
}
wasShooting = false;
curRecoil = Mathf.approachDelta(curRecoil, 0, 1 / recoilTime);
if(recoils > 0){
if(curRecoils == null) curRecoils = new float[recoils];
@@ -515,8 +515,11 @@ public class Turret extends ReloadTurret{
if(reloadWhileCharging || !charging()){
updateReload();
updateCooling();
capReload();
}
wasShooting = false;
if(state.rules.fog){
float newRange = hasAmmo() ? peekAmmo().rangeChange : 0f;
if(newRange != lastRangeChange){
@@ -525,6 +528,11 @@ public class Turret extends ReloadTurret{
}
}
if(activationTimer > 0){
activationTimer -= Time.delta;
return;
}
if(hasAmmo()){
if(Float.isNaN(reloadCounter)) reloadCounter = 0;
@@ -673,11 +681,30 @@ public class Turret extends ReloadTurret{
return queuedBullets > 0 && shoot.firstShotDelay > 0;
}
protected void updateReload(){
reloadCounter += delta() * ammoReloadMultiplier() * baseReloadSpeed();
@Override
protected boolean canReload(){
//keep reloading as the turret keeps shooting
return reloadShots < 1 || wasShooting;
}
//cap reload for visual reasons
protected void updateReload(){
if(!canReload()) return;
reloadCounter += delta() * ammoReloadMultiplier() * baseReloadSpeed();
}
protected void capReload(){
//cap reload for visual reasons, need to store the excess reload to keep the firerate consistent
if(canReload() && reloadCounter >= reload){
reloadShots += (int)(reloadCounter / reload);
excessReload += reloadCounter % reload;
}
reloadCounter = Math.min(reloadCounter, reload);
reloadShots = Math.min(reloadShots, 5);
if(!wasShooting){
reloadShots = 0;
excessReload = 0;
}
}
@Override
@@ -687,12 +714,14 @@ public class Turret extends ReloadTurret{
protected void updateShooting(){
if(reloadCounter >= reload && !charging() && shootWarmup >= minWarmup){
if(reloadShots > 0 && !charging() && shootWarmup >= minWarmup){
BulletType type = peekAmmo();
shoot(type);
reloadCounter %= reload;
reloadCounter = excessReload;
excessReload = 0;
reloadShots--;
}
}
@@ -7,7 +7,8 @@ public enum BlockStatus{
active(Color.valueOf("5ce677")),
noOutput(Color.orange),
noInput(Pal.remove),
logicDisable(Color.valueOf("8a73c6"));
logicDisable(Color.valueOf("8a73c6")),
inactive(Color.lightGray);
public final Color color;
+1
View File
@@ -95,6 +95,7 @@ public class Stat implements Comparable<Stat>{
shieldHealth = new Stat("shieldHealth", StatCat.function),
cooldownTime = new Stat("cooldownTime", StatCat.function),
regenerationRate = new Stat("regenerationRate", StatCat.function),
activationTime = new Stat("activationTime", StatCat.function),
moduleTier = new Stat("moduletier", StatCat.function),
unitType = new Stat("unittype", StatCat.function),
@@ -704,6 +704,16 @@ public class StatValues{
sep(bt, "@bullet.armorpierce");
}
if(type.armorMultiplier != 1f){
if(type.armorMultiplier > 1f){
sep(bt, Core.bundle.format("bullet.armorweakness", (int)(type.armorMultiplier * 100)));
}else if(Mathf.sign(type.armorMultiplier) == 1){
sep(bt, Core.bundle.format("bullet.armorpiercing", (int)((1 - type.armorMultiplier) * 100)));
}else{
sep(bt, Core.bundle.format("bullet.antiarmor", (-type.armorMultiplier)));
}
}
if(type.maxDamageFraction > 0){
sep(bt, Core.bundle.format("bullet.maxdamagefraction", (int)(type.maxDamageFraction * 100)));
}