Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -3322,6 +3322,7 @@ public class Blocks{
|
||||
coolant = consumeCoolant(0.1f);
|
||||
coolantMultiplier = 10f;
|
||||
researchCostMultiplier = 0.05f;
|
||||
depositCooldown = 2.0f;
|
||||
|
||||
limitRange(5f);
|
||||
}};
|
||||
@@ -3407,6 +3408,7 @@ public class Blocks{
|
||||
shootSound = Sounds.shootScatter;
|
||||
coolant = consumeCoolant(0.2f);
|
||||
researchCostMultiplier = 0.05f;
|
||||
depositCooldown = 0.5f;
|
||||
|
||||
limitRange(2);
|
||||
}};
|
||||
@@ -3453,6 +3455,7 @@ public class Blocks{
|
||||
health = 400;
|
||||
shootSound = Sounds.shootFlame;
|
||||
coolant = consumeCoolant(0.1f);
|
||||
depositCooldown = 1.0f;
|
||||
}};
|
||||
|
||||
hail = new ItemTurret("hail"){{
|
||||
@@ -3517,6 +3520,7 @@ public class Blocks{
|
||||
shootSound = Sounds.shootArtillerySmall;
|
||||
coolant = consumeCoolant(0.1f);
|
||||
coolantMultiplier = 10f;
|
||||
depositCooldown = 2.0f;
|
||||
limitRange(0f);
|
||||
}};
|
||||
|
||||
@@ -3581,6 +3585,7 @@ public class Blocks{
|
||||
chargeEffect = new MultiEffect(Fx.lancerLaserCharge, Fx.lancerLaserChargeBegin);
|
||||
|
||||
buildingDamageMultiplier = 0.25f;
|
||||
armorMultiplier = 4f;
|
||||
hitEffect = Fx.hitLancer;
|
||||
hitSize = 4;
|
||||
lifetime = 16f;
|
||||
@@ -3706,7 +3711,7 @@ public class Blocks{
|
||||
}};
|
||||
|
||||
shootY = 4.5f;
|
||||
reload = 30f;
|
||||
reload = 60f * 4f / 7f;
|
||||
inaccuracy = 10f;
|
||||
range = 240f;
|
||||
consumeAmmoOnce = false;
|
||||
@@ -3717,6 +3722,7 @@ public class Blocks{
|
||||
|
||||
limitRange(5f);
|
||||
coolant = consumeCoolant(0.3f);
|
||||
depositCooldown = 2.0f;
|
||||
}};
|
||||
|
||||
salvo = new ItemTurret("salvo"){{
|
||||
@@ -3818,6 +3824,7 @@ public class Blocks{
|
||||
|
||||
limitRange();
|
||||
coolant = consumeCoolant(0.2f);
|
||||
depositCooldown = 2.0f;
|
||||
}};
|
||||
|
||||
segment = new PointDefenseTurret("segment"){{
|
||||
@@ -3935,6 +3942,7 @@ public class Blocks{
|
||||
shootEffect = smokeEffect = Fx.thoriumShoot;
|
||||
}}
|
||||
);
|
||||
depositCooldown = 1.0f;
|
||||
}};
|
||||
|
||||
ripple = new ItemTurret("ripple"){{
|
||||
@@ -4063,6 +4071,7 @@ public class Blocks{
|
||||
coolant = consumeCoolant(0.3f);
|
||||
|
||||
scaledHealth = 130;
|
||||
depositCooldown = 2.0f;
|
||||
shootSound = Sounds.shootRipple;
|
||||
}};
|
||||
|
||||
@@ -4168,7 +4177,7 @@ public class Blocks{
|
||||
}
|
||||
}};
|
||||
|
||||
reload = 8f;
|
||||
reload = 10f;
|
||||
range = 200f;
|
||||
size = 3;
|
||||
recoil = 1.5f;
|
||||
@@ -4180,6 +4189,7 @@ public class Blocks{
|
||||
coolant = consumeCoolant(0.3f);
|
||||
|
||||
scaledHealth = 145;
|
||||
depositCooldown = 2.0f;
|
||||
limitRange();
|
||||
}};
|
||||
|
||||
@@ -4224,6 +4234,7 @@ public class Blocks{
|
||||
scaledHealth = 150;
|
||||
|
||||
coolant = consumeCoolant(1f);
|
||||
depositCooldown = 2.0f;
|
||||
consumePower(10f);
|
||||
}};
|
||||
|
||||
@@ -4290,6 +4301,7 @@ public class Blocks{
|
||||
scaledHealth = 160;
|
||||
coolant = consumeCoolant(1f);
|
||||
|
||||
depositCooldown = 2.0f;
|
||||
limitRange();
|
||||
}};
|
||||
|
||||
|
||||
@@ -181,6 +181,8 @@ public class BulletType extends Content implements Cloneable{
|
||||
public boolean fragOnAbsorb = true;
|
||||
/** If true, unit armor is ignored in damage calculations. */
|
||||
public boolean pierceArmor = false;
|
||||
/** Multiplies the unit armor used in damage calculations. Used for armor weakness, armor piercing, and anti-armor. */
|
||||
public float armorMultiplier = 1f;
|
||||
/** If true, the bullet will "stick" to enemies and get deactivated on collision. */
|
||||
public boolean sticky = false;
|
||||
/** Extra time added to bullet when it sticks to something. */
|
||||
@@ -483,6 +485,8 @@ public class BulletType extends Content implements Cloneable{
|
||||
}
|
||||
if(pierceArmor){
|
||||
h.damagePierce(damage);
|
||||
}else if(armorMultiplier != 1){
|
||||
h.damageArmorMult(damage, armorMultiplier);
|
||||
}else{
|
||||
h.damage(damage);
|
||||
}
|
||||
|
||||
@@ -1727,7 +1727,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
|
||||
float damage = other.type.buildingDamage(other);
|
||||
if(!other.type.pierceArmor){
|
||||
damage = Damage.applyArmor(damage, block.armor);
|
||||
damage = Damage.applyArmor(damage, block.armor * other.type.armorMultiplier);
|
||||
}
|
||||
|
||||
damage(other, other.team, damage);
|
||||
|
||||
@@ -58,6 +58,16 @@ abstract class HealthComp implements Entityc, Posc{
|
||||
damagePierce(amount, true);
|
||||
}
|
||||
|
||||
/** Damage and multiply armor received. */
|
||||
void damageArmorMult(float amount, float armorMult, boolean withEffect){
|
||||
damage(amount, withEffect);
|
||||
}
|
||||
|
||||
/** Damage and multiply armor received. */
|
||||
void damageArmorMult(float amount, float armorMult){
|
||||
damageArmorMult(amount, armorMult, true);
|
||||
}
|
||||
|
||||
void damage(float amount){
|
||||
if(Float.isNaN(health)) health = 0f;
|
||||
|
||||
@@ -86,6 +96,10 @@ abstract class HealthComp implements Entityc, Posc{
|
||||
damagePierce(amount * Time.delta, hitTime <= -20 + hitDuration);
|
||||
}
|
||||
|
||||
void damageContinuousArmorMult(float amount, float armorMult){
|
||||
damageArmorMult(amount * Time.delta, armorMult, hitTime <= -20 + hitDuration);
|
||||
}
|
||||
|
||||
void clampHealth(){
|
||||
health = Math.min(health, maxHealth);
|
||||
if(Float.isNaN(health)) health = 0f;
|
||||
|
||||
@@ -42,6 +42,18 @@ abstract class ShieldComp implements Healthc, Posc{
|
||||
}
|
||||
}
|
||||
|
||||
@Replace
|
||||
@Override
|
||||
public void damageArmorMult(float amount, float armorMult, boolean withEffect){
|
||||
float pre = hitTime;
|
||||
|
||||
rawDamage(Damage.applyArmor(amount, armorOverride >= 0f ? armorOverride * armorMult : armor * armorMult) / healthMultiplier / Vars.state.rules.unitHealth(team));
|
||||
|
||||
if(!withEffect){
|
||||
hitTime = pre;
|
||||
}
|
||||
}
|
||||
|
||||
protected void rawDamage(float amount){
|
||||
boolean hadShields = shield > 0.0001f;
|
||||
|
||||
|
||||
@@ -248,7 +248,7 @@ public class OverlayRenderer{
|
||||
|
||||
Building build = world.buildWorld(v.x, v.y);
|
||||
if(input.canDropItem() && build != null && build.interactable(player.team()) && build.acceptStack(player.unit().item(), player.unit().stack.amount, player.unit()) > 0 && player.within(build, itemTransferRange) &&
|
||||
input.itemDepositCooldown <= 0f){
|
||||
input.canDepositItem(build)){
|
||||
|
||||
boolean invalid = !build.allowDeposit();
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ import mindustry.ui.fragments.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.ConstructBlock.*;
|
||||
import mindustry.world.blocks.*;
|
||||
import mindustry.world.blocks.defense.turrets.*;
|
||||
import mindustry.world.blocks.distribution.*;
|
||||
import mindustry.world.blocks.payloads.*;
|
||||
import mindustry.world.blocks.storage.*;
|
||||
@@ -2149,7 +2150,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
if(build != null && build.acceptStack(stack.item, stack.amount, player.unit()) > 0 && build.interactable(player.team()) &&
|
||||
build.block.hasItems && player.unit().stack().amount > 0 && build.interactable(player.team())){
|
||||
|
||||
if(build.allowDeposit() && itemDepositCooldown <= 0f){
|
||||
if(build.allowDeposit() && canDepositItem(build)){
|
||||
Call.transferInventory(player, build);
|
||||
itemDepositCooldown = state.rules.itemDepositCooldown;
|
||||
}
|
||||
@@ -2158,6 +2159,14 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canDepositItem(Building build){
|
||||
//takes advantage of itemDepositCooldown being able to be negative, allows the cooldown to be different for each building
|
||||
if(build.block.depositCooldown >= 0){
|
||||
return itemDepositCooldown - state.rules.itemDepositCooldown <= -build.block.depositCooldown;
|
||||
}
|
||||
return itemDepositCooldown <= 0;
|
||||
}
|
||||
|
||||
public void rebuildArea(int x1, int y1, int x2, int y2){
|
||||
NormalizeResult result = Placement.normalizeArea(x1, y1, x2, y2, rotation, false, 999999999);
|
||||
Tmp.r1.set(result.x * tilesize, result.y * tilesize, (result.x2 - result.x) * tilesize, (result.y2 - result.y) * tilesize);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user