From 5c095400641485fc2196104aa658932b64e191e1 Mon Sep 17 00:00:00 2001 From: Slotterleet <62336673+Slotterleet@users.noreply.github.com> Date: Thu, 21 Nov 2024 15:05:27 +0300 Subject: [PATCH] Spewer & Purger polishing --- res/bundles/bundle.properties | 4 + res/bundles/bundle_ru.properties | 4 + .../bugs/spewer/spewer-face-l-outline.png | Bin 0 -> 81 bytes .../bugs/spewer/spewer-face-r-outline.png | Bin 0 -> 81 bytes src/fos/content/FOSFx.java | 14 ++- src/fos/content/FOSUnitTypes.java | 94 ++++++++++++++---- src/fos/entities/Acid.java | 2 +- src/fos/entities/bullet/AcidBulletType.java | 6 +- src/fos/type/units/types/FOSUnitType.java | 53 +++++----- 9 files changed, 124 insertions(+), 53 deletions(-) create mode 100644 res/sprites/units/bugs/spewer/spewer-face-l-outline.png create mode 100644 res/sprites/units/bugs/spewer/spewer-face-r-outline.png diff --git a/res/bundles/bundle.properties b/res/bundles/bundle.properties index 243173e..e3228d0 100644 --- a/res/bundles/bundle.properties +++ b/res/bundles/bundle.properties @@ -415,6 +415,10 @@ unit.fos-brunt.description = Shoots slowing missiles at enemy targets. Activates # TODO: bug names unit.fos-grain.name = Grain unit.fos-grain.description = An agile insect species that burrows underground to evade defenses and ambush ore detectors, shutting down most types in a single slash. +unit.fos-spewer.name = Spewer +unit.fos-spewer.description = Spits acid towards enemy targets upwards, allowing it to ignore obstacles such as walls. +unit.fos-purger.name = Purger +unit.fos-purger.description = Spits barrages of piercing acid at enemy targets. unit.fos-vulture.name = Vulture unit.fos-vulture.description = ??? unit.fos-draug.name = Draug diff --git a/res/bundles/bundle_ru.properties b/res/bundles/bundle_ru.properties index bf539f0..f65b172 100644 --- a/res/bundles/bundle_ru.properties +++ b/res/bundles/bundle_ru.properties @@ -413,6 +413,10 @@ unit.fos-brunt.description = Стреляет замедляющими раке # TODO: названия жуков unit.fos-grain.name = Песчинка unit.fos-grain.description = Ловкий вид насекомых, зарывающийся под землю, чтобы обойти оборону и атаковать детекторы руды, отключая большинство типов одним ударом. +unit.fos-spewer.name = Плеватель +unit.fos-spewer.description = Плюется кислотой в направлении вражеских целей вверх, позволяя ей перелетать через препятствия, например стены. +unit.fos-purger.name = Чистильщик +unit.fos-purger.description = Плюется шквалами пробивающей кислоты по вражеским целям. unit.fos-vulture.name = Стервятник unit.fos-vulture.description = ??? unit.fos-draug.name = Драугр diff --git a/res/sprites/units/bugs/spewer/spewer-face-l-outline.png b/res/sprites/units/bugs/spewer/spewer-face-l-outline.png new file mode 100644 index 0000000000000000000000000000000000000000..6f51cc5fc9cfec1d17ebb933772a758599e7ee8b GIT binary patch literal 81 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1|;Q0k92}K#X;^)4C~IxyaaN%JzX3_IA$g% bFfcJNure?vg&K7Lg&90u{an^LB{Ts5Ai@tj literal 0 HcmV?d00001 diff --git a/res/sprites/units/bugs/spewer/spewer-face-r-outline.png b/res/sprites/units/bugs/spewer/spewer-face-r-outline.png new file mode 100644 index 0000000000000000000000000000000000000000..6f51cc5fc9cfec1d17ebb933772a758599e7ee8b GIT binary patch literal 81 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1|;Q0k92}K#X;^)4C~IxyaaN%JzX3_IA$g% bFfcJNure?vg&K7Lg&90u{an^LB{Ts5Ai@tj literal 0 HcmV?d00001 diff --git a/src/fos/content/FOSFx.java b/src/fos/content/FOSFx.java index 613d660..2c63458 100644 --- a/src/fos/content/FOSFx.java +++ b/src/fos/content/FOSFx.java @@ -6,8 +6,8 @@ import arc.math.*; import arc.math.geom.*; import arc.util.Tmp; -import fos.graphics.FOSPal; import fos.entities.bullet.OhioBeamBulletType; +import fos.graphics.FOSPal; import mindustry.content.Fx; import mindustry.entities.Effect; import mindustry.gen.*; @@ -271,8 +271,16 @@ public class FOSFx { color(Color.valueOf("51c7d8"), 0.6f); randLenVectors(e.id, 4, e.fin() * 28f, (x, y) -> { - Fill.circle(x, y, 5f); + Fill.circle(e.x + x, e.y + y, 5f); if (e.fin() >= 0.99f) bugDeath1.at(x, y); }); - }).layer(Layer.legUnit + 1); + }).layer(Layer.legUnit + 1), + + acidSpit = new Effect(110f, e -> { + color(FOSFluids.bugAcid.color); + + randLenVectors(e.id, 4, 18f * e.fin(new Interp.ExpOut(8f, 5f)), e.rotation, 25f, 8f, (x, y) -> { + Fill.circle(e.x + x, e.y + y, 1.8f * e.fout()); + }); + }).layer(Layer.floor + 1).followParent(false); } diff --git a/src/fos/content/FOSUnitTypes.java b/src/fos/content/FOSUnitTypes.java index 0d140d7..40a56e6 100644 --- a/src/fos/content/FOSUnitTypes.java +++ b/src/fos/content/FOSUnitTypes.java @@ -1320,10 +1320,29 @@ public static void load(){ armor = 5; absorption = 0; speed = 0.6f; - hitSize = 8; + hitSize = 16f; + + legCount = 4; + legBaseOffset = 6f; + legExtension = 1.8f; + legForwardScl = 0.8f; + baseLegStraightness = 0.9f; + legStraightness = 0.4f; + legStraightLength = 0.9f; - legCount = 6; - // TODO: better legs + drawBody = true; + + parts.addAll( + //new RegionPart(), + new RegionPart("-face-l"){{ + rotation = 0f; + moveRot = 10f; + }}, + new RegionPart("-face-r"){{ + rotation = 0f; + moveRot = -10f; + }} + ); abilities.add( new AcidExplodeAbility(){{ @@ -1345,10 +1364,8 @@ public static void load(){ shootSound = FOSSounds.spit; bullet = new AcidBulletType(){{ - speed = 4; lifetime = 37.5f; + speed = 2; lifetime = 75f; damage = 30; - puddleSize = 15f; - orbSize = 3f; despawnHit = true; knockback = 0.1f; collides = false; @@ -1356,9 +1373,18 @@ public static void load(){ collidesAir = false; scaleLife = true; + Interp arc = a -> 1f - Mathf.sqr(a-0.5f) * 4; + + width = height = 8f; + sprite = "circle-bullet"; + backColor = frontColor = bugAcid.color; + shrinkX = shrinkY = 0.9f; + shrinkInterp = arc; + trailLength = 8; - trailWidth = 3f; + trailWidth = 4f; trailColor = bugAcid.color; + trailInterp = arc; acidDamage = 20f / 60; acidLifetime = 300f; @@ -1370,11 +1396,15 @@ public static void load(){ fragBullet = new AcidBulletType(){{ speed = 2.5f; lifetime = 15; damage = 5; - puddleSize = 6f; - orbSize = 2f; despawnHit = true; knockback = 0f; + width = height = 4f; + sprite = "circle-bullet"; + backColor = frontColor = bugAcid.color; + shrinkX = 0.07f; + shrinkY = 0.31f; + trailLength = 4; trailWidth = 2f; trailColor = bugAcid.color; @@ -1395,10 +1425,24 @@ public static void load(){ armor = 8; absorption = 0; speed = 0.55f; - hitSize = 14; + hitSize = 22; - legCount = 8; - // TODO: better legs + legCount = 4; + legLength = 15f; + legBaseOffset = 6f; + legExtension = 1f; + legForwardScl = 0.8f; + baseLegStraightness = 0.9f; + legStraightness = 0.4f; + legStraightLength = 0.9f; + + drawBody = true; + + parts.addAll( + //new RegionPart(), + new RegionPart("-face-l"), + new RegionPart("-face-r") + ); abilities.add( new AcidExplodeAbility(){{ @@ -1410,30 +1454,38 @@ public static void load(){ weapons.add( new AcidWeapon(){{ - x = 0; y = 4; - reload = 110f; + x = 0; y = 2; + reload = 140f; recoil = 0f; mirror = false; - alternate = false; rotate = false; shootCone = 20f; + inaccuracy = 15f; shoot.shots = 5; shoot.shotDelay = 10f; shootSound = FOSSounds.spit; - bullet = new FragLiquidBulletType(bugAcid){{ + bullet = new BasicBulletType(){{ speed = 5; lifetime = 40f; damage = 22; - puddleSize = 0f; - orbSize = 2f; + setDefaults = false; despawnHit = false; knockback = 0.14f; + width = height = 4f; + sprite = "circle-bullet"; + backColor = frontColor = bugAcid.color; + shrinkX = shrinkY = 0.21f; + trailLength = 10; trailWidth = 2f; trailColor = bugAcid.color; + //trailInterp = Interp.slope; + + shootEffect = FOSFx.acidSpit; + parentizeEffects = false; fragOnHit = true; fragBullets = 1; @@ -1443,13 +1495,15 @@ public static void load(){ fragBullet = new AcidBulletType(){{ speed = 2f; lifetime = 20; damage = 5; - puddleSize = 0f; - orbSize = 1.4f; knockback = 0; pierce = true; pierceBuilding = true; pierceCap = 3; + width = height = 3f; + sprite = "circle-bullet"; + backColor = frontColor = bugAcid.color; + trailLength = 4; trailWidth = 1.4f; trailColor = bugAcid.color; diff --git a/src/fos/entities/Acid.java b/src/fos/entities/Acid.java index 1187588..9ef174a 100644 --- a/src/fos/entities/Acid.java +++ b/src/fos/entities/Acid.java @@ -71,7 +71,7 @@ public static void at(Acid a, Team team, float damage, float lifetime, float x, } public static void update(Acid acid) { - if (!acid.alive) return; + if (acid == null || !acid.alive) return; if (Vars.state.isPaused()) return; acid.lifetime -= Time.delta; if (acid.lifetime <= 0) { diff --git a/src/fos/entities/bullet/AcidBulletType.java b/src/fos/entities/bullet/AcidBulletType.java index 9aa42f6..41105fc 100644 --- a/src/fos/entities/bullet/AcidBulletType.java +++ b/src/fos/entities/bullet/AcidBulletType.java @@ -1,17 +1,17 @@ package fos.entities.bullet; -import fos.content.FOSFluids; import fos.entities.Acid; import fos.mod.AcidController; +import mindustry.entities.bullet.BasicBulletType; import mindustry.gen.Bullet; -public class AcidBulletType extends FragLiquidBulletType { +public class AcidBulletType extends BasicBulletType { public float acidDamage = 20f / 60; public float acidLifetime = 60f; public float acidRadius = 6f; public AcidBulletType() { - super(FOSFluids.bugAcid); + super(); despawnHit = true; } diff --git a/src/fos/type/units/types/FOSUnitType.java b/src/fos/type/units/types/FOSUnitType.java index 31958d1..9fbf39b 100644 --- a/src/fos/type/units/types/FOSUnitType.java +++ b/src/fos/type/units/types/FOSUnitType.java @@ -43,12 +43,12 @@ public void createIcons(MultiPacker packer) { ObjectSet outlined = new ObjectSet<>(); - try{ + try { Unit sample = constructor.get(); Func outline = i -> i.outline(outlineColor, 3); Cons outliner = t -> { - if(t != null && t.found()){ + if(t != null && t.found()) { packer.add(PageType.main, t.asAtlas().name, outline.get( Core.atlas.getPixmap(t).crop() )); } }; @@ -56,21 +56,22 @@ public void createIcons(MultiPacker packer) { Seq toOutline = new Seq<>(); getRegionsToOutline(toOutline); - for(TextureRegion region : toOutline){ + for (TextureRegion region : toOutline) { Pixmap pix = Core.atlas.getPixmap(region).crop().outline(outlineColor, outlineRadius); packer.add(PageType.main, region.asAtlas().name, pix); + Log.info("[FOS] generated outline: @", region.asAtlas().name); } Seq weps = weapons.copy(); weps.each(Weapon::load); weps.removeAll(w -> !w.region.found()); - for(Weapon weapon : weps){ - if(outlined.add(weapon.name) && packer.has(weapon.name) && !(this instanceof LumoniPlayerUnitType)) { // don't outline modular weapons twice + for (Weapon weapon : weps) { + if (outlined.add(weapon.name) && packer.has(weapon.name) && !(this instanceof LumoniPlayerUnitType)) { // don't outline modular weapons twice //only non-top weapons need separate outline sprites (this is mostly just mechs) - if(!weapon.top || weapon.parts.contains(p -> p.under)){ + if (!weapon.top || weapon.parts.contains(p -> p.under)) { packer.add(PageType.main, weapon.name + "-outline", outline.get( Core.atlas.getPixmap(weapon.name).crop() )); - }else{ + } else { //replace weapon with outlined version, no use keeping standard around outliner.get(weapon.region); } @@ -78,7 +79,7 @@ public void createIcons(MultiPacker packer) { } //generate tank animation - if(sample instanceof Tankc){ + if (sample instanceof Tankc) { Pixmap pix = Core.atlas.getPixmap(treadRegion).crop(); for(int r = 0; r < treadRects.length; r++){ @@ -108,8 +109,8 @@ public void createIcons(MultiPacker packer) { outliner.get(footRegion); outliner.get(legBaseRegion); outliner.get(baseJointRegion); - if(sample instanceof Legsc) outliner.get(legRegion); - if(sample instanceof Tankc) outliner.get(treadRegion); + if (sample instanceof Legsc) outliner.get(legRegion); + if (sample instanceof Tankc) outliner.get(treadRegion); Pixmap image = segments > 0 ? Core.atlas.getPixmap(segmentRegions[0]).crop() : outline.get(Core.atlas.getPixmap(previewRegion).crop()); @@ -131,11 +132,11 @@ public void createIcons(MultiPacker packer) { boolean anyUnder = false; //draw each extra segment on top before it is saved as outline - if(sample instanceof Crawlc){ - for(int i = 0; i < segments; i++){ + if (sample instanceof Crawlc) { + for (int i = 0; i < segments; i++) { packer.add(PageType.main, name + "-segment-outline" + i, outline.get( Core.atlas.getPixmap(segmentRegions[i]).crop() )); - if(i > 0){ + if (i > 0) { drawCenter(image, Core.atlas.getPixmap(segmentRegions[i]).crop()); } } @@ -143,32 +144,32 @@ public void createIcons(MultiPacker packer) { } //outline is currently never needed, although it could theoretically be necessary - if(needsBodyOutline()){ + if (needsBodyOutline()) { packer.add(PageType.main, name + "-outline", image); - }else if (segments == 0) { + } else if (segments == 0) { packer.add(PageType.main, name, outline.get(Core.atlas.getPixmap(region).crop())); } //draw weapons that are under the base - for(Weapon weapon : weps.select(w -> w.layerOffset < 0)){ + for (Weapon weapon : weps.select(w -> w.layerOffset < 0)) { drawWeapon.get(weapon, outline.get(weaponRegion.get(weapon))); anyUnder = true; } //draw over the weapons under the image - if(anyUnder){ + if (anyUnder) { image.draw(outline.get(Core.atlas.getPixmap(previewRegion).crop()), true); } //draw treads - if(sample instanceof Tankc){ + if (sample instanceof Tankc) { Pixmap treads = outline.get(Core.atlas.getPixmap(treadRegion).crop()); image.draw(treads, image.width / 2 - treads.width / 2, image.height / 2 - treads.height / 2, true); image.draw(Core.atlas.getPixmap(previewRegion), true); } //draw mech parts - if(sample instanceof Mechc){ + if (sample instanceof Mechc) { drawCenter(image, Core.atlas.getPixmap(baseRegion).crop()); drawCenter(image, Core.atlas.getPixmap(legRegion).crop()); drawCenter(image, Core.atlas.getPixmap(legRegion).crop().flipX()); @@ -176,7 +177,7 @@ public void createIcons(MultiPacker packer) { } //draw weapon outlines on base - for(Weapon weapon : weps){ + for (Weapon weapon : weps) { //skip weapons under unit if(weapon.layerOffset < 0) continue; @@ -184,9 +185,9 @@ public void createIcons(MultiPacker packer) { } //draw base region on top to mask weapons - if(drawCell) image.draw(Core.atlas.getPixmap(previewRegion), true); + if (drawCell) image.draw(Core.atlas.getPixmap(previewRegion), true); - if(drawCell){ + if (drawCell) { Pixmap baseCell = Core.atlas.getPixmap(cellRegion).crop(); Pixmap cell = baseCell.copy(); @@ -195,16 +196,16 @@ public void createIcons(MultiPacker packer) { image.draw(cell, image.width / 2 - cell.width / 2, image.height / 2 - cell.height / 2, true); } - for(Weapon weapon : weps){ + for (Weapon weapon : weps) { //skip weapons under unit - if(weapon.layerOffset < 0) continue; + if (weapon.layerOffset < 0) continue; Pixmap reg = weaponRegion.get(weapon); Pixmap wepReg = weapon.top ? outline.get(reg) : reg; drawWeapon.get(weapon, wepReg); - if(weapon.cellRegion.found()){ + if (weapon.cellRegion.found()) { Pixmap weaponCell = Core.atlas.getPixmap(weapon.cellRegion).crop(); weaponCell.replace(in -> in == 0xffffffff ? 0x8ae3dfff : in == 0xdcc6c6ff || in == 0xdcc5c5ff ? 0x51a0b0ff : 0); drawWeapon.get(weapon, weaponCell); @@ -212,7 +213,7 @@ public void createIcons(MultiPacker packer) { } packer.add(PageType.ui, name + "-full", image); - }catch(IllegalArgumentException e){ + } catch (IllegalArgumentException e) { Log.err("WARNING: Skipping unit @: @", name, e.getMessage()); } }