From 5ac3e08b1d021070e2d3e5e81869cbf677471f92 Mon Sep 17 00:00:00 2001 From: Anuken Date: Mon, 13 Dec 2021 14:42:16 -0500 Subject: [PATCH] Tungsten walls --- .../blocks/walls/thorium-wall-large.png | Bin 796 -> 794 bytes .../blocks/walls/tungsten-wall-large.png | Bin 0 -> 835 bytes .../sprites/blocks/walls/tungsten-wall.png | Bin 0 -> 289 bytes core/assets/icons/icons.properties | 3 + core/assets/logicids.dat | Bin 3789 -> 3825 bytes core/src/mindustry/content/Blocks.java | 27 ++++++++- core/src/mindustry/content/UnitTypes.java | 46 +------------- core/src/mindustry/entities/Damage.java | 5 ++ .../mindustry/entities/comp/BuildingComp.java | 2 +- .../mindustry/entities/comp/ShieldComp.java | 10 +--- .../src/mindustry/entities/comp/TankComp.java | 32 +++++++++- core/src/mindustry/type/BlockStack.java | 56 ++++++++++++++++++ core/src/mindustry/type/ItemStack.java | 4 +- core/src/mindustry/world/Block.java | 5 ++ .../world/blocks/units/UnitAssembler.java | 40 ++++++++++--- 15 files changed, 164 insertions(+), 66 deletions(-) create mode 100644 core/assets-raw/sprites/blocks/walls/tungsten-wall-large.png create mode 100644 core/assets-raw/sprites/blocks/walls/tungsten-wall.png create mode 100644 core/src/mindustry/type/BlockStack.java diff --git a/core/assets-raw/sprites/blocks/walls/thorium-wall-large.png b/core/assets-raw/sprites/blocks/walls/thorium-wall-large.png index ef8f313f099af415e00faa51dc338197013ba045..20c23043ac9a884bddcaa0e8c784ffee735717ea 100644 GIT binary patch delta 731 zcmbQkHj8b7Vf__P7srr_Id7x9gP0t7Y6D^#irParedN;H+Z#IX0P~KIYV(dP4KH90 z-LTlANv~vs@plh!&Aw~(d;d~>27|lr!d;iE zOys^`RlzWW$$?*`f`$K&0K<<-4@7Mk&K#1z{g-wKHFn0g^^d!PJ z?#7#IZ{|4g?t9{YvMh*k%7ftJNe^t!-g*#xyy*LBtpz2IC-X7N)tfmf-m||q$$VqR z+^v5SzcLywp7)xKv;IV=LYhgK*4m4&{7cnuIDb&g`kSb|;95ks`i>d;lRY;)P23=w zAXxKi){NXPd&}QCtP!m8aniv}OKLYU?YZ|ejLAD7nlJym_QtoSE5kL|j2P$W>DXLv zW|^qFQ9?uI$hnOwjjN}vGK#2g{^<64hQNB=Pm$~Pc`2taPrJTCboSj}zeQgxUA;Lb zoM#)K<$)%aE?#aSCuw)j4dSX9Nj@8XZL4^1p|oJTtO9S3@Y{>e3v&Zb+QGTbdgf;&A%%mv=gvUMGYU1RKm7RfQrxGj3f`+qy)-Nd5xX`|FCWo8x&l zie50XUeOp9@!^wa!M7ZitnzT}*mqr%tnNuW)w->Cx;K}1 z9@AAx#nmcNrzAr!Kaxo{{32A7xp?Z@hW!yz#nNljH%s|w9-P{6v?ga%p z-3nQFN(v*MU$(tGKd?gb@Vm0_x3}N@{PN`I%da2)dc_uYCQLOoV_TrQi$@SwfrR)UJhg>7?H9hh`gwg`Fbw4cSyrt|D{e6nd} z;^yeh#Z0C@CfTdr_GArc^6x!*pmO%sgUgQi4M1CmEJr z`_yjA-y!)m#@yqF^ExKO#T$b%d&BBir8n8K$S=Akzl|xYck4M8@z1G7oZI&BY-7@C z^1my*+4rM*`uwE~s~;S$PWGCx#Xqd!y7_&t1kS9}58u|QZriK&mGh{BT7xk+_xi62 zjw#+cY+RfhvvoWltXjH?r~X>Po{Ls$N3y$XrmbFo>BP;IH%+sSrfvWCi=}Gj)yQ?) zY|+PM5*(S1wy|<9?47J~qg%+tP%WZ1dQbTrfeW|!Ca@jr{Pv_GMp{H#Y^uVR!kh^k zobOUnb8*Z$ieav^wf@hP+G@k44ofy`glX=O&!1UMC z#WAE}&fBQlzAA%f_$8!Hpxx(W(6ghr=wM2k)}Ob|341 zC0BkvDYmvx{_eWW?}xu#e1CiQevbw3cZUQUM?8_5Ki@pA>P(vsqr-0%5l)6%YK=+^ z8Pi#2F)Z*E>RZaJqH?86X^l_so}Q7wAajhy)62V zzRh{CaKeL~rG0w!|9(y4Du2zL^&X#bg0wzHCyMKOZ|dR8C4tQ zR5DVYdk6>zL@iO}6x-z5DWJXJ{chW9ThEnV7tc(czTg(q8l?kUP8juV-J)g8)L@l( z)yRao?dXNahxbOzlqz0nd~g<1mR_9E@?ByRl+;fcDW00RVCw2`jGB$L_b<*|!e%J6 zY=WL0KL_h^n-V>yDJK%=+XXoGbx1mPjY#yVpufVq6?rAyP+un!#WjMtC zq{V=<>zeu%g~p5hpBQIfSKpd^+VXVJ{=C|Sel0iNOzdNla=meM`98)?YlCNLvuzHE z*z_Z4c4~y_T2`kGc87)YSUkj@c{Z(Pl~MX9Y_OfF_;4@7`)Wq9bz%o}&it-B_{Ybf z<(baGPZ2$83)0-gqBG7O^6+PxuK<&~^!GvdQ{+Ytz;8X0fz$PRiC-)qe$a!*}T3Gn-1?fA-J_HM~ZQ9i{i u3`Rn;R2Uw3W=vyfP+pkH)L_KV7Tq+ z;usRq`gXb_UyA{U>&lsnUmQ!(Tjc%TaHevF`{cYgu~xe~&p9w=zg(undqI4`m)CLc zO%EMBwvpZYb)9{M{41si=LHPY1oCE0zrlZA>7?rCD~t>+wc1PyD<5rV-KyYc9Kif& zq3^M;Q?1VYZa6k+`-4*t=kT+svt7vX=v~k8;8fMLV;dMO^P4O9uWVtvz#zrIJwe$g zoHWz}XIgt~4H^>LiBk5%Fb`~BTr`%#vO;o?RnTOMWJlG42N;*!)n-SWho90p+&u5M0ZQF`iTJDz?f0O>>$djJ3c delta 16 Xcmew;dsdc-;rvD>Tb|9yJbg?6G&u!$ diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index a6af38a9b2..68c267de10 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -72,7 +72,7 @@ public class Blocks{ powerSource, powerVoid, itemSource, itemVoid, liquidSource, liquidVoid, payloadSource, payloadVoid, illuminator, //defense - copperWall, copperWallLarge, titaniumWall, titaniumWallLarge, plastaniumWall, plastaniumWallLarge, thoriumWall, thoriumWallLarge, door, doorLarge, + copperWall, copperWallLarge, titaniumWall, titaniumWallLarge, plastaniumWall, plastaniumWallLarge, tungstenWall, tungstenWallLarge, thoriumWall, thoriumWallLarge, door, doorLarge, phaseWall, phaseWallLarge, surgeWall, surgeWallLarge, mender, mendProjector, overdriveProjector, overdriveDome, forceProjector, shockMine, scrapWall, scrapWallLarge, scrapWallHuge, scrapWallGigantic, thruster, //ok, these names are getting ridiculous, but at least I don't have humongous walls yet @@ -128,6 +128,9 @@ public class Blocks{ additiveReconstructor, multiplicativeReconstructor, exponentialReconstructor, tetrativeReconstructor, repairPoint, repairTurret, + //unit - erekir + tankAssembler, + //payloads //TODO small deconstructor payloadConveyor, payloadRouter, payloadPropulsionTower, smallDeconstructor, deconstructor, constructor, largeConstructor, payloadLoader, payloadUnloader, @@ -1355,6 +1358,19 @@ public class Blocks{ schematicPriority = 10; }}; + tungstenWall = new Wall("tungsten-wall"){{ + requirements(Category.defense, with(Items.tungsten, 6)); + health = 180 * wallHealthMultiplier; + armor = 7f; + }}; + + tungstenWallLarge = new Wall("tungsten-wall-large"){{ + requirements(Category.defense, ItemStack.mult(tungstenWall.requirements, 4)); + health = 180 * wallHealthMultiplier * 4; + armor = 7f; + size = 2; + }}; + thoriumWall = new Wall("thorium-wall"){{ requirements(Category.defense, with(Items.thorium, 6)); health = 200 * wallHealthMultiplier; @@ -3293,6 +3309,15 @@ public class Blocks{ acceptCoolant = true; }}; + //endregion + //region units - erekir + + tankAssembler = new UnitAssembler("tank-assembler"){{ + size = 3; + output = UnitTypes.vanquish; + requirements = BlockStack.list(Blocks.thoriumWallLarge, 4); + }}; + //endregion //region payloads diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index bc2f2a2f53..929e6c6496 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -2446,7 +2446,7 @@ public class UnitTypes{ mirror = false; x = 0f; y = 0; - shadow = 30f; + shadow = 28f; bullet = new BasicBulletType(7f, 50){{ sprite = "missile-large"; @@ -2465,45 +2465,6 @@ public class UnitTypes{ trailLength = 8; hitEffect = despawnEffect = Fx.blastExplosion; }}; - - //TODO better bullet / weapon - /* - bullet = new ArtilleryBulletType(2f, 20, "shell"){{ - hitEffect = Fx.massiveExplosion; - knockback = 0.8f; - lifetime = 100f; - width = height = 14f; - collidesTiles = false; - splashDamageRadius = 60f; - splashDamage = 60f; - backColor = Color.valueOf("feb380"); - frontColor = Color.white; - - width = 9f; - height = 15f; - - status = StatusEffects.blasted; - lightning = 5; - - trailLength = 28; - trailWidth = 4f; - trailEffect = Fx.none; - trailColor = backColor; - - shrinkX = 0.1f; - shrinkY = 0.5f; - - fragBullets = 9; - fragVelocityMin = 0.7f; - fragLifeMin = 0f; - fragBullet = new BasicBulletType(3.5f, 15){{ - width = 7f; - height = 9f; - lifetime = 25f; - backColor = Color.valueOf("feb380"); - frontColor = Color.white; - }}; - }};*/ }}); int i = 0; @@ -2526,7 +2487,7 @@ public class UnitTypes{ hitColor = backColor = trailColor = Color.valueOf("feb380"); frontColor = Color.white; trailWidth = 1.5f; - trailLength = 6; + trailLength = 4; hitEffect = despawnEffect = Fx.hitBulletColor; }}; }}); @@ -2708,9 +2669,6 @@ public class UnitTypes{ height = 12f; shootEffect = Fx.sparkShoot; smokeEffect = Fx.shootBigSmoke; - pierceCap = 2; - pierce = true; - pierceBuilding = true; hitColor = backColor = trailColor = Pal.bulletYellowBack; frontColor = Color.white; trailWidth = 1.5f; diff --git a/core/src/mindustry/entities/Damage.java b/core/src/mindustry/entities/Damage.java index df2cd699bc..0ab16352f9 100644 --- a/core/src/mindustry/entities/Damage.java +++ b/core/src/mindustry/entities/Damage.java @@ -510,4 +510,9 @@ public class Damage{ float scaled = Mathf.lerp(1f - dist / radius, 1f, falloff); return damage * scaled; } + + /** @return resulting armor calculated based off of damage */ + public static float applyArmor(float damage, float armor){ + return Math.max(damage - armor, minArmorDamage * damage); + } } diff --git a/core/src/mindustry/entities/comp/BuildingComp.java b/core/src/mindustry/entities/comp/BuildingComp.java index b5afe88109..4c6f90b4b0 100644 --- a/core/src/mindustry/entities/comp/BuildingComp.java +++ b/core/src/mindustry/entities/comp/BuildingComp.java @@ -1549,7 +1549,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, if(Mathf.zero(dm)){ damage = health + 1; }else{ - damage /= dm; + damage = Damage.applyArmor(damage, block.armor) / dm; } Call.tileDamage(self(), health - handleDamage(damage)); diff --git a/core/src/mindustry/entities/comp/ShieldComp.java b/core/src/mindustry/entities/comp/ShieldComp.java index aa77d1e8bc..659630ecf0 100644 --- a/core/src/mindustry/entities/comp/ShieldComp.java +++ b/core/src/mindustry/entities/comp/ShieldComp.java @@ -3,11 +3,10 @@ package mindustry.entities.comp; import arc.util.*; import mindustry.annotations.Annotations.*; import mindustry.content.*; +import mindustry.entities.*; import mindustry.game.*; import mindustry.gen.*; -import static mindustry.Vars.*; - @Component abstract class ShieldComp implements Healthc, Posc{ @Import float health, hitTime, x, y, healthMultiplier; @@ -24,11 +23,8 @@ abstract class ShieldComp implements Healthc, Posc{ @Replace @Override public void damage(float amount){ - //apply armor - amount = Math.max(amount - armor, minArmorDamage * amount); - amount /= healthMultiplier; - - rawDamage(amount); + //apply armor and scaling effects + rawDamage(Damage.applyArmor(amount, armor) / healthMultiplier); } @Replace diff --git a/core/src/mindustry/entities/comp/TankComp.java b/core/src/mindustry/entities/comp/TankComp.java index 6dfa5d0044..67168e301c 100644 --- a/core/src/mindustry/entities/comp/TankComp.java +++ b/core/src/mindustry/entities/comp/TankComp.java @@ -3,20 +3,24 @@ package mindustry.entities.comp; import arc.math.*; import arc.math.geom.*; import arc.util.*; +import mindustry.*; import mindustry.annotations.Annotations.*; +import mindustry.content.*; import mindustry.entities.*; import mindustry.gen.*; import mindustry.type.*; +import mindustry.world.*; import mindustry.world.blocks.environment.*; import static mindustry.Vars.*; @Component abstract class TankComp implements Posc, Flyingc, Hitboxc, Unitc, ElevationMovec{ - @Import float x, y, hitSize, rotation; + @Import float x, y, hitSize, rotation, speedMultiplier; + @Import boolean hovering; @Import UnitType type; - transient private float treadEffectTime; + transient private float treadEffectTime, lastSlowdown = 1f; transient float treadTime; transient boolean walked; @@ -43,6 +47,22 @@ abstract class TankComp implements Posc, Flyingc, Hitboxc, Unitc, ElevationMovec } } + //calculate overlapping tiles so it slows down when going "over" walls + //TODO is this a necessary mechanic? + int r = Math.max(Math.round(hitSize * 0.6f / tilesize), 1); + + int solids = 0, total = (r*2+1)*(r*2+1); + for(int dx = -r; dx <= r; dx++){ + for(int dy = -r; dy <= r; dy++){ + Tile t = Vars.world.tileWorld(x + dx*tilesize, y + dy*tilesize); + if(t == null || t.solid()){ + solids ++; + } + } + } + + lastSlowdown = Mathf.lerp(1f, type.crawlSlowdown, Mathf.clamp((float)solids / total / type.crawlSlowdownFrac)); + //trigger animation only when walking manually if(walked || net.client()){ float len = deltaLen(); @@ -51,6 +71,14 @@ abstract class TankComp implements Posc, Flyingc, Hitboxc, Unitc, ElevationMovec } } + @Override + @Replace + public float floorSpeedMultiplier(){ + Floor on = isFlying() || hovering ? Blocks.air.asFloor() : floorOn(); + //TODO take into account extra blocks + return on.speedMultiplier * speedMultiplier * lastSlowdown; + } + @Replace @Override public @Nullable Floor drownFloor(){ diff --git a/core/src/mindustry/type/BlockStack.java b/core/src/mindustry/type/BlockStack.java new file mode 100644 index 0000000000..0199bbb9a4 --- /dev/null +++ b/core/src/mindustry/type/BlockStack.java @@ -0,0 +1,56 @@ +package mindustry.type; + +import arc.struct.*; +import mindustry.content.*; +import mindustry.world.*; + +public class BlockStack implements Comparable{ + public Block block = Blocks.router; + public int amount = 1; + + public BlockStack(Block block, int amount){ + this.block = block; + this.amount = amount; + } + + public BlockStack(Block block){ + this.block = block; + } + + public BlockStack(){ + } + + public static BlockStack[] with(Object... items){ + var stacks = new BlockStack[items.length / 2]; + for(int i = 0; i < items.length; i += 2){ + stacks[i / 2] = new BlockStack((Block)items[i], ((Number)items[i + 1]).intValue()); + } + return stacks; + } + + public static Seq list(Object... items){ + Seq stacks = new Seq<>(items.length / 2); + for(int i = 0; i < items.length; i += 2){ + stacks.add(new BlockStack((Block)items[i], ((Number)items[i + 1]).intValue())); + } + return stacks; + } + + @Override + public int compareTo(BlockStack stack){ + return block.compareTo(stack.block); + } + + @Override + public boolean equals(Object o){ + return this == o || (o instanceof BlockStack stack && stack.amount == amount && block == stack.block); + } + + @Override + public String toString(){ + return "BlockStack{" + + "block=" + block + + ", amount=" + amount + + '}'; + } +} diff --git a/core/src/mindustry/type/ItemStack.java b/core/src/mindustry/type/ItemStack.java index ec15207760..253d6d4033 100644 --- a/core/src/mindustry/type/ItemStack.java +++ b/core/src/mindustry/type/ItemStack.java @@ -67,9 +67,7 @@ public class ItemStack implements Comparable{ @Override public boolean equals(Object o){ - if(this == o) return true; - if(!(o instanceof ItemStack stack)) return false; - return amount == stack.amount && item == stack.item; + return this == o || (o instanceof ItemStack stack && stack.amount == amount && item == stack.item); } @Override diff --git a/core/src/mindustry/world/Block.java b/core/src/mindustry/world/Block.java index 8064ee77e7..9a1e18e1d5 100644 --- a/core/src/mindustry/world/Block.java +++ b/core/src/mindustry/world/Block.java @@ -134,6 +134,8 @@ public class Block extends UnlockableContent{ public Attributes attributes = new Attributes(); /** tile entity health */ public int health = -1; + /** damage absorption, similar to unit armor */ + public float armor = 0f; /** base block explosiveness */ public float baseExplosiveness = 0f; /** bullet that this block spawns when destroyed */ @@ -429,6 +431,9 @@ public class Block extends UnlockableContent{ if(synthetic()){ stats.add(Stat.health, health, StatUnit.none); + if(armor > 0){ + stats.add(Stat.armor, armor, StatUnit.none); + } } if(canBeBuilt() && requirements.length > 0){ diff --git a/core/src/mindustry/world/blocks/units/UnitAssembler.java b/core/src/mindustry/world/blocks/units/UnitAssembler.java index 4b5b915ac2..5617930bda 100644 --- a/core/src/mindustry/world/blocks/units/UnitAssembler.java +++ b/core/src/mindustry/world/blocks/units/UnitAssembler.java @@ -3,6 +3,7 @@ package mindustry.world.blocks.units; import arc.math.geom.*; import arc.struct.*; import arc.util.*; +import arc.util.io.*; import mindustry.content.*; import mindustry.gen.*; import mindustry.graphics.*; @@ -20,8 +21,12 @@ import static mindustry.Vars.*; * */ public class UnitAssembler extends PayloadBlock{ public int areaSize = 10; - public UnitType unitType; - public int unitsCreated = 4; + public UnitType droneType; + public int dronesCreated = 4; + + //TODO should be different for every tier. + public Seq requirements = new Seq<>(); + public UnitType output = UnitTypes.vanquish; public UnitAssembler(String name){ super(name); @@ -47,17 +52,19 @@ public class UnitAssembler extends PayloadBlock{ Drawf.dashRect(valid ? Pal.accent : Pal.remove, Tmp.r1); } - public class UnitAssemblerBuild extends PayloadBlockBuild{ + public class UnitAssemblerBuild extends PayloadBlockBuild{ public Seq units = new Seq<>(); - public Seq payloads = new Seq<>(); + + //TODO how should payloads be stored? counts of blocks? intmap? references? + //public Seq payloads = new Seq<>(); @Override public void updateTile(){ units.removeAll(u -> !u.isAdded() || u.dead); - if(consValid() && units.size < unitsCreated){ + if(consValid() && units.size < dronesCreated){ //TODO build animation? distribute spawning? - var unit = unitType.create(team); + var unit = droneType.create(team); if(unit instanceof BuildingTetherc bt){ bt.building(this); } @@ -69,12 +76,29 @@ public class UnitAssembler extends PayloadBlock{ units.add(unit); } - //TODO drones need to indicate that they are in position + //TODO drones need to indicate that they are in position and actually play an animation + } + + @Override + public void handlePayload(Building source, Payload payload){ + //super.handlePayload(source, payload); + + //payloads.add((BuildPayload)payload); } @Override public boolean acceptPayload(Building source, Payload payload){ - return super.acceptPayload(source, payload); + return payload instanceof BuildPayload bp && requirements.contains(b -> b.block == bp.block()); + } + + @Override + public void write(Writes write){ + super.write(write); + } + + @Override + public void read(Reads read, byte revision){ + super.read(read, revision); } } }