diff --git a/core/src/mindustry/entities/bullet/BulletType.java b/core/src/mindustry/entities/bullet/BulletType.java index 74fb8a7365..e3e025bd36 100644 --- a/core/src/mindustry/entities/bullet/BulletType.java +++ b/core/src/mindustry/entities/bullet/BulletType.java @@ -346,7 +346,7 @@ public class BulletType extends Content implements Cloneable{ return spawnUnit.estimateDps(); } - float sum = damage * (pierce ? pierceCap == -1 ? 2 : Mathf.clamp(pierceCap, 1, 2) : 1f) * splashDamage*0.75f; + float sum = (damage + splashDamage*0.75f) * (pierce ? pierceCap == -1 ? 2 : Mathf.clamp(pierceCap, 1, 2) : 1f); if(fragBullet != null && fragBullet != this){ sum += fragBullet.estimateDPS() * fragBullets / 2f; } @@ -549,7 +549,7 @@ public class BulletType extends Content implements Cloneable{ if(!fragOnHit){ createFrags(b, b.x, b.y); } - + despawnEffect.at(b.x, b.y, b.rotation(), hitColor); despawnSound.at(b); @@ -675,7 +675,7 @@ public class BulletType extends Content implements Cloneable{ } } } - + public void updateTrail(Bullet b){ if(!headless && trailLength > 0){ if(b.trail == null){ @@ -716,7 +716,7 @@ public class BulletType extends Content implements Cloneable{ if(lightRadius <= -1){ lightRadius = Math.max(18, hitSize * 5f); } - + drawSize = Math.max(drawSize, trailLength * speed * 2f); range = calculateRange(); } diff --git a/core/src/mindustry/game/SectorInfo.java b/core/src/mindustry/game/SectorInfo.java index c4ee046c6c..e0b18826fd 100644 --- a/core/src/mindustry/game/SectorInfo.java +++ b/core/src/mindustry/game/SectorInfo.java @@ -82,7 +82,7 @@ public class SectorInfo{ public transient ItemSeq lastImported = new ItemSeq(); /** Special variables for simulation. */ - public float sumHealth, sumRps, sumDps, waveHealthBase, waveHealthSlope, waveDpsBase, waveDpsSlope, bossHealth, bossDps, curEnemyHealth, curEnemyDps; + public float sumHealth, sumRps, sumDps, bossHealth, bossDps, curEnemyHealth, curEnemyDps; /** Wave where first boss shows up. */ public int bossWave = -1; diff --git a/core/src/mindustry/maps/SectorDamage.java b/core/src/mindustry/maps/SectorDamage.java index de34be2753..db7136cdae 100644 --- a/core/src/mindustry/maps/SectorDamage.java +++ b/core/src/mindustry/maps/SectorDamage.java @@ -3,12 +3,11 @@ package mindustry.maps; import arc.math.*; import arc.math.geom.*; import arc.struct.*; -import arc.util.*; import mindustry.ai.*; +import mindustry.ai.types.*; import mindustry.content.*; import mindustry.core.*; import mindustry.entities.*; -import mindustry.entities.abilities.*; import mindustry.game.*; import mindustry.gen.*; import mindustry.logic.*; @@ -22,7 +21,7 @@ import mindustry.world.blocks.storage.*; import static mindustry.Vars.*; public class SectorDamage{ - public static final int maxRetWave = 40, maxWavesSimulated = 50; + public static final int maxRetWave = 50, maxWavesSimulated = 60; //direct damage is for testing only private static final boolean rubble = true; @@ -42,7 +41,7 @@ public class SectorDamage{ return (int)getDamage(info, maxRetWave, true); } - /** @return calculated capture progress of the enemy if retWave if false, otherwise return the maximum waves survived as int. + /** @return calculated capture progress of the enemy if retWave is false, otherwise return the maximum waves survived as int. * if it survives all the waves, returns maxRetWave. */ public static float getDamage(SectorInfo info, int wavesPassed, boolean retWave){ float health = info.sumHealth; @@ -60,15 +59,29 @@ public class SectorDamage{ waveBegin = waveEnd - maxWavesSimulated; } + int groundSpawns = Math.max(spawner.countFlyerSpawns(), 1), airSpawns = Math.max(spawner.countGroundSpawns(), 1); + for(int i = waveBegin; i <= waveEnd; i++){ + float enemyDps = 0f, enemyHealth = 0f; + + for(SpawnGroup group : state.rules.spawns){ + //calculate the amount of spawn points used + //if there's a spawn position override, there is only one potential place they spawn + //assume that all overridden positions are valid, should always be true in properly designed campaign maps + int spawnCount = group.spawn != -1 ? 1 : group.type.flying ? airSpawns : groundSpawns; + + float healthMult = 1f + Mathf.clamp(group.type.armor / 20f); + StatusEffect effect = (group.effect == null ? StatusEffects.none : group.effect); + int spawned = group.getSpawned(i) * spawnCount; + if(spawned <= 0) continue; + enemyHealth += spawned * (group.getShield(i) + group.type.health * effect.healthMultiplier * healthMult); + enemyDps += spawned * group.type.dpsEstimate * effect.damageMultiplier; + } float efficiency = health / info.sumHealth; float dps = info.sumDps * efficiency; float rps = info.sumRps * efficiency; - float enemyDps = info.waveDpsBase + info.waveDpsSlope * (i); - float enemyHealth = info.waveHealthBase + info.waveHealthSlope * (i); - if(info.bossWave == i){ enemyDps += info.bossDps; enemyHealth += info.bossHealth; @@ -320,13 +333,9 @@ public class SectorDamage{ if(unit.team == state.rules.defaultTeam){ sumHealth += unit.health*healthMult + unit.shield; sumDps += unit.type.dpsEstimate; - if(Structs.find(unit.abilities, a -> a instanceof RepairFieldAbility) instanceof RepairFieldAbility h){ - sumRps += h.amount / h.reload * 60f; - } - sumRps += unit.type.weapons.sumf(w -> w.shotsPerSec() * (w.bullet.healPercent * 60f + w.bullet.healAmount)); - if(unit.canBuild()){ - //assume it rebuilds 1 block with 'standard' build cost (20) and health (50) every 2 seconds - sumRps += unit.type.buildSpeed * (60f / 20f) * (1f / 2f) * 50f; + sumRps += unit.type.weapons.sumf(w -> w.shotsPerSec() * (w.bullet.healPercent/100f * 20f + w.bullet.healAmount)); + if(unit.controller() instanceof CommandAI ai && ai.command == UnitCommand.rebuildCommand){ + sumRps += unit.type.buildSpeed * 20f; } }else{ float bossMult = unit.isBoss() ? 3f : 1f; @@ -335,41 +344,11 @@ public class SectorDamage{ } } - //calculate DPS and health for the next few waves and store in list - var reg = new LinearRegression(); - SpawnGroup bossGroup = null; - Seq waveDps = new Seq<>(), waveHealth = new Seq<>(); - int groundSpawns = Math.max(spawner.countFlyerSpawns(), 1), airSpawns = Math.max(spawner.countGroundSpawns(), 1); - - //TODO storing all this is dumb when you can just calculate it exactly from the rules... - for(int wave = state.wave; wave < state.wave + 10; wave ++){ - float sumWaveDps = 0f, sumWaveHealth = 0f; - - for(SpawnGroup group : state.rules.spawns){ - //calculate the amount of spawn points used - //if there's a spawn position override, there is only one potential place they spawn - //assume that all overridden positions are valid, should always be true in properly designed campaign maps - int spawnCount = group.spawn != -1 ? 1 : group.type.flying ? airSpawns : groundSpawns; - - float healthMult = 1f + Mathf.clamp(group.type.armor / 20f); - StatusEffect effect = (group.effect == null ? StatusEffects.none : group.effect); - int spawned = group.getSpawned(wave) * spawnCount; - //save the boss group - if(group.effect == StatusEffects.boss){ - bossGroup = group; - continue; - } - if(spawned <= 0) continue; - sumWaveHealth += spawned * (group.getShield(wave) + group.type.health * effect.healthMultiplier * healthMult); - sumWaveDps += spawned * group.type.dpsEstimate * effect.damageMultiplier; - } - waveDps.add(new Vec2(wave, sumWaveDps)); - waveHealth.add(new Vec2(wave, sumWaveHealth)); - } + SpawnGroup bossGroup = state.rules.spawns.find(s -> s.effect == StatusEffects.boss); if(bossGroup != null){ float bossMult = 1.2f; - //calculate first boss appearaance + //calculate first boss appearance for(int wave = state.wave; wave < state.wave + 60; wave++){ int spawned = bossGroup.getSpawned(wave - 1); if(spawned > 0){ @@ -382,15 +361,6 @@ public class SectorDamage{ } } - //calculate linear regression of the wave data and store it - reg.calculate(waveHealth); - info.waveHealthBase = reg.intercept; - info.waveHealthSlope = reg.slope; - - reg.calculate(waveDps); - info.waveDpsBase = reg.intercept; - info.waveDpsSlope = reg.slope; - info.sumHealth = sumHealth * 0.9f; info.sumDps = sumDps; info.sumRps = sumRps; diff --git a/core/src/mindustry/type/UnitType.java b/core/src/mindustry/type/UnitType.java index 15ed66ce9c..af3cd1b562 100644 --- a/core/src/mindustry/type/UnitType.java +++ b/core/src/mindustry/type/UnitType.java @@ -892,7 +892,7 @@ public class UnitType extends UnlockableContent implements Senseable{ //suicide enemy if(weapons.contains(w -> w.bullet.killShooter)){ //scale down DPS to be insignificant - dpsEstimate /= 25f; + dpsEstimate /= 15f; } } @@ -1313,12 +1313,12 @@ public class UnitType extends UnlockableContent implements Senseable{ Draw.reset(); } - + //...where do I put this public Color shieldColor(Unit unit){ return shieldColor == null ? unit.team.color : shieldColor; } - + public void drawMining(Unit unit){ if(!unit.mining()) return;