diff --git a/core/assets-raw/sprites/blocks/turrets/fuse-heat.png b/core/assets-raw/sprites/blocks/turrets/fuse-heat.png index a8b34b4381..b8c070840b 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/fuse-heat.png and b/core/assets-raw/sprites/blocks/turrets/fuse-heat.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-back1.png b/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-back1.png index 1c75c4270f..3649e6b388 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-back1.png and b/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-back1.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-back2.png b/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-back2.png index 198fcfd6c9..6310ed5bef 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-back2.png and b/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-back2.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-front1.png b/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-front1.png index 09772c1c53..93762fca98 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-front1.png and b/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-front1.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-front2.png b/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-front2.png index 296ac010f5..9dc19c54d0 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-front2.png and b/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-front2.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-heat.png b/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-heat.png index c634758147..b6dcfe6425 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-heat.png and b/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-heat.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-nozzle1.png b/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-nozzle1.png index 3005da0a34..fb3dd30a00 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-nozzle1.png and b/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-nozzle1.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-nozzle2.png b/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-nozzle2.png index 87052d3082..ff0d1859b1 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-nozzle2.png and b/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-nozzle2.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-preview.png b/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-preview.png index 11b2d43d75..b91e9ba13b 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-preview.png and b/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate-preview.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate.png b/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate.png index cf60ee9dbc..7ece32712c 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate.png and b/core/assets-raw/sprites/blocks/turrets/sublimate/sublimate.png differ diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 386482a2ca..614c44d236 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -134,7 +134,6 @@ public class Blocks{ basicAssemblerModule, //payloads - //TODO small deconstructor payloadConveyor, payloadRouter, payloadPropulsionTower, smallDeconstructor, deconstructor, constructor, largeConstructor, payloadLoader, payloadUnloader, //logic @@ -1492,7 +1491,7 @@ public class Blocks{ range = 85f; healPercent = 11f; phaseBoost = 15f; - health = 80 * size * size; + scaledHealth = 80; consumes.item(Items.phaseFabric).boost(); }}; @@ -2406,14 +2405,14 @@ public class Blocks{ requirements(Category.effect, with(Items.titanium, 100)); size = 2; itemCapacity = 300; - health = size * size * 55; + scaledHealth = 55; }}; vault = new StorageBlock("vault"){{ requirements(Category.effect, with(Items.titanium, 250, Items.thorium, 125)); size = 3; itemCapacity = 1000; - health = size * size * 55; + scaledHealth = 55; }}; //TODO move tabs? @@ -2428,14 +2427,14 @@ public class Blocks{ size = 3; //TODO should it really be kept the same, at 1000? itemCapacity = 1200; - health = size * size * 120; + scaledHealth = 120; }}; reinforcedVault = new StorageBlock("reinforced-vault"){{ requirements(Category.effect, with(Items.tungsten, 250, Items.carbide, 125)); size = 4; itemCapacity = 2500; - health = size * size * 120; + scaledHealth = 120; }}; //endregion @@ -2484,7 +2483,7 @@ public class Blocks{ inaccuracy = 17f; shootCone = 35f; - health = 200 * size * size; + scaledHealth = 200; shootSound = Sounds.shootSnap; limitRange(2); @@ -2541,7 +2540,7 @@ public class Blocks{ liquidCapacity = 10f; shootEffect = Fx.shootLiquid; range = 110f; - health = 250 * size * size; + scaledHealth = 250; flags = EnumSet.of(BlockFlag.turret, BlockFlag.extinguisher); }}; @@ -2562,7 +2561,7 @@ public class Blocks{ chargeBeginEffect = Fx.lancerLaserChargeBegin; heatColor = Color.red; size = 2; - health = 280 * size * size; + scaledHealth = 280; targetAir = false; shootSound = Sounds.laser; @@ -2609,7 +2608,7 @@ public class Blocks{ scaledForce = 6f; range = 240f; damage = 0.3f; - health = 160 * size * size; + scaledHealth = 160; rotateSpeed = 10; consumes.powerCond(3f, (TractorBeamBuild e) -> e.target != null); @@ -2629,7 +2628,7 @@ public class Blocks{ range = 240f; xRand = 6f; size = 2; - health = 300 * size * size; + scaledHealth = 300; shootSound = Sounds.missile; limitRange(5f); @@ -2657,7 +2656,7 @@ public class Blocks{ spread = 0f; shots = 4; ammoUseEffect = Fx.casing2; - health = 240 * size * size; + scaledHealth = 240; shootSound = Sounds.shootBig; limitRange(); @@ -2666,7 +2665,7 @@ public class Blocks{ segment = new PointDefenseTurret("segment"){{ requirements(Category.turret, with(Items.silicon, 130, Items.thorium, 80, Items.phaseFabric, 40, Items.titanium, 40)); - health = 250 * size * size; + scaledHealth = 250; range = 180f; hasPower = true; consumes.powerCond(8f, (PointDefenseBuild b) -> b.target != null); @@ -2695,7 +2694,7 @@ public class Blocks{ liquidCapacity = 40f; shootEffect = Fx.shootLiquid; range = 190f; - health = 250 * size * size; + scaledHealth = 250; flags = EnumSet.of(BlockFlag.turret, BlockFlag.extinguisher); }}; @@ -2712,7 +2711,7 @@ public class Blocks{ shootCone = 30; size = 3; - health = 220 * size * size; + scaledHealth = 220; shootSound = Sounds.shotgun; float brange = range + 10f; @@ -2761,7 +2760,7 @@ public class Blocks{ range = 290f; minRange = 50f; - health = 130 * size * size; + scaledHealth = 130; shootSound = Sounds.artillery; }}; @@ -2783,7 +2782,7 @@ public class Blocks{ shootCone = 30f; shootSound = Sounds.shootSnap; - health = 145 * size * size; + scaledHealth = 145; limitRange(); }}; @@ -2824,7 +2823,7 @@ public class Blocks{ coolantMultiplier = 0.4f; - health = 150 * size * size; + scaledHealth = 150; coolantUsage = 1f; consumes.powerCond(10f, TurretBuild::isActive); @@ -2852,7 +2851,7 @@ public class Blocks{ shootCone = 24f; shootSound = Sounds.shootBig; - health = 160 * size * size; + scaledHealth = 160; coolantUsage = 1f; limitRange(); @@ -2887,7 +2886,7 @@ public class Blocks{ ammoMultiplier = 1f; }}; - health = 200 * size * size; + scaledHealth = 200; consumes.add(new ConsumeCoolant(0.5f)).update(false); }}; @@ -2943,7 +2942,7 @@ public class Blocks{ restitution = 0.03f; range = 190; shootCone = 3f; - health = 360 * size * size; + scaledHealth = 280; rotateSpeed = 1.6f; limitRange(); @@ -2952,7 +2951,7 @@ public class Blocks{ //TODO bad name sublimate = new ContinuousTurret("sublimate"){{ //TODO requirements - requirements(Category.turret, with(Items.tungsten, 50, Items.silicon, 60, Items.oxide, 30, Items.carbide, 40)); + requirements(Category.turret, with(Items.tungsten, 120, Items.silicon, 160, Items.oxide, 50)); draw = new DrawTurret("reinforced-"){{ liquidDraw = Liquids.ozone; @@ -2988,15 +2987,17 @@ public class Blocks{ }}; outlineColor = Pal.darkOutline; + //TODO also consume hydrogen as a different ammo consumes.liquids(LiquidStack.with(Liquids.cyanogen, 3f / 60f, Liquids.ozone, 2f / 60f)); range = 170f; - //TODO multi ammo shootType = new ContinuousFlameBulletType(){{ - damage = 4f; + damage = 5f; length = range; }}; + + scaledHealth = 320; shootLength = 7f; size = 3; }}; @@ -3006,15 +3007,15 @@ public class Blocks{ ammo( //TODO 1 more ammo type, decide on base type - Items.fissileMatter, new ArtilleryBulletType(2.5f, 60, "shell"){{ + Items.fissileMatter, new ArtilleryBulletType(2.5f, 100, "shell"){{ hitEffect = new MultiEffect(Fx.titanExplosion, Fx.titanSmoke); despawnEffect = Fx.none; knockback = 2f; lifetime = 140f; - height = 17f; - width = 16f; + height = 19f; + width = 17f; splashDamageRadius = 65f; - splashDamage = 150f; + splashDamage = 250f; backColor = hitColor = trailColor = Color.valueOf("ea8878").lerp(Color.valueOf("feb380"), 0.5f); frontColor = Color.white; ammoMultiplier = 1f; @@ -3022,9 +3023,9 @@ public class Blocks{ status = StatusEffects.blasted; trailLength = 32; - trailWidth = 2.85f; + trailWidth = 3.35f; trailSinScl = 2.5f; - trailSinMag = 1f; + trailSinMag = 0.5f; trailEffect = Fx.none; despawnShake = 7f; @@ -3040,7 +3041,7 @@ public class Blocks{ targetAir = false; shootShake = 4f; recoilAmount = 1f; - reloadTime = 60f * 2f; + reloadTime = 60f * 3f; shootLength = 7f; rotateSpeed = 2.5f; @@ -3073,6 +3074,7 @@ public class Blocks{ consumes.liquids(LiquidStack.with(Liquids.hydrogen, 2f / 60f)); + scaledHealth = 300; range = 390f; size = 4; }}; @@ -3083,7 +3085,7 @@ public class Blocks{ commandCenter = new CommandCenter("command-center"){{ requirements(Category.units, ItemStack.with(Items.copper, 200, Items.lead, 250, Items.silicon, 250, Items.graphite, 100)); size = 2; - health = size * size * 55; + scaledHealth = 55; }}; groundFactory = new UnitFactory("ground-factory"){{ @@ -3411,7 +3413,7 @@ public class Blocks{ hasPower = true; consumes.power(10f); buildCostMultiplier = 0.5f; - health = size * size * 80; + scaledHealth = 80; }}; //endregion campaign diff --git a/core/src/mindustry/content/Items.java b/core/src/mindustry/content/Items.java index 1076c51f04..34dd7bb293 100644 --- a/core/src/mindustry/content/Items.java +++ b/core/src/mindustry/content/Items.java @@ -51,6 +51,7 @@ public class Items{ hardness = 4; radioactivity = 1f; cost = 1.1f; + healthScaling = 0.2f; }}; scrap = new Item("scrap", Color.valueOf("777777")){{ @@ -65,16 +66,19 @@ public class Items{ flammability = 0.1f; explosiveness = 0.2f; cost = 1.3f; + healthScaling = 0.1f; }}; phaseFabric = new Item("phase-fabric", Color.valueOf("f4ba6e")){{ cost = 1.3f; radioactivity = 0.6f; + healthScaling = 0.25f; }}; surgeAlloy = new Item("surge-alloy", Color.valueOf("f3e979")){{ cost = 1.2f; charge = 0.75f; + healthScaling = 0.25f; }}; sporePod = new Item("spore-pod", Color.valueOf("7457ce")){{ @@ -88,25 +92,29 @@ public class Items{ pyratite = new Item("pyratite", Color.valueOf("ffaa5f")){{ flammability = 1.4f; - explosiveness = 0.4f; + explosiveness = 0.5f; }}; beryllium = new Item("beryllium", Color.valueOf("3a8f64")){{ hardness = 4; cost = 1.3f; + healthScaling = 0.6f; }}; tungsten = new Item("tungsten", Color.valueOf("768a9a")){{ hardness = 5; cost = 1.5f; + healthScaling = 0.8f; }}; oxide = new Item("oxide", Color.valueOf("e4ffd6")){{ - cost = 1.1f; + cost = 1.2f; + healthScaling = 0.5f; }}; carbide = new Item("carbide", Color.valueOf("89769a")){{ - cost = 1.3f; + cost = 1.6f; + healthScaling = 1.1f; }}; fissileMatter = new Item("fissile-matter", Color.valueOf("5e988d")){{ diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index af2c06f553..a07477ed3c 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -2513,7 +2513,7 @@ public class UnitTypes{ rotateSpeed = 3.5f; accel = 0.1f; health = 3000f; - armor = 4f; + armor = 5f; hitSize = 36f; payloadCapacity = Mathf.sqr(3f) * tilePayload; @@ -2522,6 +2522,7 @@ public class UnitTypes{ abilities.add(new SuppressionFieldAbility(){{ orbRadius = 5.3f; + y = 1f; }}); float es = 3.9f; diff --git a/core/src/mindustry/entities/abilities/SuppressionFieldAbility.java b/core/src/mindustry/entities/abilities/SuppressionFieldAbility.java index b7755f33bf..c97de62c22 100644 --- a/core/src/mindustry/entities/abilities/SuppressionFieldAbility.java +++ b/core/src/mindustry/entities/abilities/SuppressionFieldAbility.java @@ -23,6 +23,7 @@ public class SuppressionFieldAbility extends Ability{ public Color color1 = Pal.sap.cpy().mul(1.6f), color2 = Pal.sap; public float layer = Layer.effect; + public float x = 0f, y = 0f; public int particles = 15; public float particleSize = 4f; public float particleLen = 7f; @@ -78,12 +79,14 @@ public class SuppressionFieldAbility extends Ability{ Draw.z(layer); float rad = orbRadius + Mathf.absin(orbSinScl, orbSinMag); + Tmp.v1.set(x, y).rotate(unit.rotation - 90f); + float rx = unit.x + Tmp.v1.x, ry = unit.y + Tmp.v1.y; Draw.color(color2); - Fill.circle(unit.x, unit.y, rad); + Fill.circle(rx, ry, rad); Draw.color(color1); - Fill.circle(unit.x, unit.y, rad * orbMidScl); + Fill.circle(rx, ry, rad * orbMidScl); float base = (Time.time / particleLife); rand.setSeed(unit.id); @@ -93,8 +96,8 @@ public class SuppressionFieldAbility extends Ability{ float angle = rand.random(360f) + (Time.time / rotateScl + unit.rotation) % 360f; float len = particleLen * particleInterp.apply(fout); Fill.circle( - unit.x + Angles.trnsx(angle, len), - unit.y + Angles.trnsy(angle, len), + rx + Angles.trnsx(angle, len), + ry + Angles.trnsy(angle, len), particleSize * Mathf.slope(fin) ); } @@ -103,7 +106,7 @@ public class SuppressionFieldAbility extends Ability{ if(heat > 0.001f){ Draw.color(Pal.sapBullet); Lines.stroke(1.2f * heat * Mathf.absin(10f, 1f)); - Lines.circle(unit.x, unit.y, range); + Lines.circle(rx, ry, range); } Draw.reset(); diff --git a/core/src/mindustry/type/Item.java b/core/src/mindustry/type/Item.java index 5cf5220213..fde04f9363 100644 --- a/core/src/mindustry/type/Item.java +++ b/core/src/mindustry/type/Item.java @@ -32,7 +32,9 @@ public class Item extends UnlockableContent{ * 1 cost = 1 tick added to build time */ public float cost = 1f; - /** if true, this item is of lowest priority to drills. */ + /** When this item is present in the build cost, a block's default health is multiplied by 1 + scaling, where 'scaling' is summed together for all item requirement types. */ + public float healthScaling = 0f; + /** if true, this item is of the lowest priority to drills. */ public boolean lowPriority; /** If >0, this item is animated. */ diff --git a/core/src/mindustry/world/Block.java b/core/src/mindustry/world/Block.java index ed29bb73b5..a379818b10 100644 --- a/core/src/mindustry/world/Block.java +++ b/core/src/mindustry/world/Block.java @@ -134,7 +134,9 @@ public class Block extends UnlockableContent{ public @Nullable Item itemDrop = null; /** Array of affinities to certain things. */ public Attributes attributes = new Attributes(); - /** tile entity health */ + /** Health per square tile that this block occupies; essentially, this is multiplied by size * size. Overridden if health is > 0. If <0, the default is 40. */ + public float scaledHealth = -1; + /** building health; -1 to use scaledHealth */ public int health = -1; /** damage absorption, similar to unit armor */ public float armor = 0f; @@ -914,7 +916,25 @@ public class Block extends UnlockableContent{ public void init(){ //initialize default health based on size if(health == -1){ - health = size * size * 40; + boolean round = false; + if(scaledHealth < 0){ + scaledHealth = 40; + + float scaling = 1f; + for(var stack : requirements){ + scaling += stack.item.healthScaling; + } + + if(scaling > 1){ + Log.info("@: @ -> @", name, scaledHealth * size * size, (Mathf.round(scaledHealth * scaling, 5) * size * size)); + } + scaledHealth *= scaling; + round = true; + } + + health = round ? + Mathf.round(size * size * scaledHealth, 5) : + (int)(size * size * scaledHealth); } clipSize = Math.max(clipSize, size * tilesize); diff --git a/core/src/mindustry/world/blocks/defense/turrets/ItemTurret.java b/core/src/mindustry/world/blocks/defense/turrets/ItemTurret.java index 05a4017aaf..b1688d1596 100644 --- a/core/src/mindustry/world/blocks/defense/turrets/ItemTurret.java +++ b/core/src/mindustry/world/blocks/defense/turrets/ItemTurret.java @@ -40,6 +40,7 @@ public class ItemTurret extends Turret{ for(var entry : ammoTypes.copy().entries()){ var copy = entry.value.copy(); float realRange = copy.rangeChange + range; + //doesn't handle drag copy.lifetime = (realRange + margin) / copy.speed; ammoTypes.put(entry.key, copy); } @@ -59,7 +60,8 @@ public class ItemTurret extends Turret{ @Override public void build(Building build, Table table){ MultiReqImage image = new MultiReqImage(); - content.items().each(i -> filter.get(i) && i.unlockedNow(), item -> image.add(new ReqImage(new ItemImage(item.uiIcon), + content.items().each(i -> filter.get(i) && i.unlockedNow(), + item -> image.add(new ReqImage(new ItemImage(item.uiIcon), () -> build instanceof ItemTurretBuild it && !it.ammo.isEmpty() && ((ItemEntry)it.ammo.peek()).item == item))); table.add(image).size(8 * 4);