From f1477547f66321024b371e9c4d3c05a4629a991d Mon Sep 17 00:00:00 2001 From: buthed010203 Date: Fri, 25 Oct 2024 01:24:49 -0400 Subject: [PATCH] Update to 1.0-RC, fixed pulsar and quasar commands being set across all modes and cleaned up the code to allow for easier updates. --- assets/mod.hjson | 10 +- build.gradle | 73 ++++++- gradle.properties | 4 +- rules.pro | 7 + src/floodcompat/FloodCompat.kt | 214 +++++++++++++++++++ src/floodcompat/floodcompat.java | 340 ------------------------------- 6 files changed, 292 insertions(+), 356 deletions(-) create mode 100644 rules.pro create mode 100644 src/floodcompat/FloodCompat.kt delete mode 100644 src/floodcompat/floodcompat.java diff --git a/assets/mod.hjson b/assets/mod.hjson index 8c90d00..c687670 100644 --- a/assets/mod.hjson +++ b/assets/mod.hjson @@ -1,9 +1,9 @@ displayName: "[cyan]FloodCompat" -name: "[cyan]FloodCompat" +name: "floodcompat" author: "io community" -main: "floodcompat.floodcompat" -description: "Reduces desyncs & applies flood changes on join. [v0.6]" -version: "0.6" +main: "floodcompat.FloodCompat" +description: "Reduces desyncs & applies flood changes on join." +version: "1.0" minGameVersion: 146 java: true -hidden: true +hidden: true \ No newline at end of file diff --git a/build.gradle b/build.gradle index 9b10371..423b6c1 100644 --- a/build.gradle +++ b/build.gradle @@ -1,3 +1,19 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + +buildscript { + repositories { + mavenCentral() + } + dependencies { + classpath "com.guardsquare:proguard-gradle:7.1.0" + } +} + +plugins { + id "org.jetbrains.kotlin.jvm" version "2.0.10" +// id "com.gradleup.gr8" version "0.10" +} + apply plugin: "java" version '1.0' @@ -6,6 +22,7 @@ targetCompatibility = 8 sourceCompatibility = JavaVersion.VERSION_16 sourceSets.main.java.srcDirs = ["src"] +sourceSets.main.kotlin.srcDirs = ["src"] repositories{ mavenCentral() @@ -33,10 +50,12 @@ dependencies{ compileOnly "com.github.Anuken.Mindustry:core:$mindustryVersion" annotationProcessor "com.github.Anuken:jabel:$jabelVersion" + + implementation "org.jetbrains.kotlin:kotlin-stdlib" } -task jarAndroid{ - dependsOn "jar" +tasks.register('jarAndroid') { + dependsOn minimize doLast{ if(!sdkRoot || !new File(sdkRoot).exists()) throw new GradleException("No valid Android SDK found. Ensure that ANDROID_HOME is set to your Android SDK directory."); @@ -49,13 +68,13 @@ task jarAndroid{ def dependencies = (configurations.compileClasspath.asList() + configurations.runtimeClasspath.asList() + [new File(platformRoot, "android.jar")]).collect{ "--classpath $it.path" }.join(" ") //dex and desugar files - this requires d8 in your PATH - "d8 $dependencies --min-api 14 --output ${project.archivesBaseName}Android.jar ${project.archivesBaseName}Desktop.jar" + "d8 $dependencies --min-api 14 --output FloodCompatAndroid.jar FloodCompatDesktop.jar" .execute(null, new File("$buildDir/libs")).waitForProcessOutput(System.out, System.err) } } jar{ - archiveFileName = "${project.archivesBaseName}Desktop.jar" + archiveFileName = "FloodCompatUnshrunk.jar" from{ configurations.runtimeClasspath.collect{ it.isDirectory() ? it : zipTree(it) } @@ -70,17 +89,51 @@ jar{ } } -task deploy(type: Jar){ +tasks.register("deploy", Jar){ dependsOn jarAndroid - dependsOn jar - archiveFileName = "${project.archivesBaseName}.jar" + dependsOn minimize + archiveFileName = "FloodCompat.jar" - from{ [zipTree("$buildDir/libs/${project.archivesBaseName}Desktop.jar"), zipTree("$buildDir/libs/${project.archivesBaseName}Android.jar")] } + from{ [zipTree("$buildDir/libs/FloodCompatDesktop.jar"), zipTree("$buildDir/libs/FloodCompatAndroid.jar")] } doLast{ delete{ - delete "$buildDir/libs/${project.archivesBaseName}Desktop.jar" - delete "$buildDir/libs/${project.archivesBaseName}Android.jar" + delete "$buildDir/libs/FloodCompatDesktop.jar" + delete "$buildDir/libs/FloodCompatAndroid.jar" } } } + +kotlin.compilerOptions { + jvmTarget = JvmTarget.JVM_1_8 + freeCompilerArgs.add("-Xjdk-release=1.8") +} + +tasks.register("minimize", proguard.gradle.ProGuardTask) { // We shrink because of kotlin being >1MB + dependsOn jar + + injars "build/libs/FloodCompatUnshrunk.jar", filter: '!module-info.class,!META-INF/**,!**.kotlin_builtins' + outjars "build/libs/FloodCompatDesktop.jar" + + // Automatically handle the Java version of this build. + if (System.getProperty('java.version').startsWith('1.')) { + // Before Java 9, the runtime classes were packaged in a single jar file. + libraryjars "${System.getProperty('java.home')}/lib/rt.jar" + } else { + // As of Java 9, the runtime classes are packaged in modular jmod files. + libraryjars "${System.getProperty('java.home')}/jmods/java.base.jmod", jarfilter: '!**.jar', filter: '!module-info.class' + } + + configuration "rules.pro" +} + +//gr8 { +// var shadowedJar = create("gr8") { +// proguardFile("rules.pro") +// configuration("shade") +// } +// +// replaceOutgoingJar(shadowedJar) +// +//// removeGradleApifromapi() +//} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 2bcb316..ea3e943 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,4 +10,6 @@ org.gradle.jvmargs=--illegal-access=permit \ --add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED \ --add-exports=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED \ --add-exports=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED \ ---add-exports=java.base/sun.reflect.annotation=ALL-UNNAMED \ No newline at end of file +--add-exports=java.base/sun.reflect.annotation=ALL-UNNAMED + +kotlin.stdlib.default.dependency=false \ No newline at end of file diff --git a/rules.pro b/rules.pro new file mode 100644 index 0000000..21e163e --- /dev/null +++ b/rules.pro @@ -0,0 +1,7 @@ +-dontobfuscate +-keepattributes SourceFile, LineNumberTable +-dontwarn arc.** +-dontwarn mindustry.** + + +-keep class floodcompat.FloodCompat { *; } diff --git a/src/floodcompat/FloodCompat.kt b/src/floodcompat/FloodCompat.kt new file mode 100644 index 0000000..be11ba8 --- /dev/null +++ b/src/floodcompat/FloodCompat.kt @@ -0,0 +1,214 @@ +package floodcompat + +import arc.* +import arc.graphics.* +import arc.struct.* +import arc.util.* +import mindustry.Vars.* +import mindustry.ai.* +import mindustry.content.* +import mindustry.content.Blocks.* +import mindustry.content.UnitTypes.* +import mindustry.entities.abilities.* +import mindustry.entities.bullet.* +import mindustry.game.* +import mindustry.gen.* +import mindustry.graphics.* +import mindustry.mod.* +import mindustry.world.blocks.defense.turrets.* +import java.lang.reflect.* + +// Based on old foo's implementation +class FloodCompat : Mod() { + /** Vanilla values of changed vars for restoration later */ + private val defaults: MutableList = mutableListOf() + /* Flood changes the bullet type and the overwrites system doesn't support that so we have to manage this manually */ + private var foreshadowBulletVanilla: BulletType? = null + + /** Used to prevent flood from applying twice */ + private var applied: Boolean = false + + + override fun init() { + Log.info("Flood Compatibility loaded!") + + + Events.on(EventType.ResetEvent::class.java) { + disable() + applied = false + } + Events.on(EventType.WorldLoadEvent::class.java) { Log.info("Send flood"); Call.serverPacketReliable("flood", "1.0") } + netClient.addPacketHandler("flood") { if (Strings.canParseInt(it)) enable() } + } + + /** Applies flood changes */ + private fun enable() { + if (applied) throw AssertionError("Tried to enable flood even though it was already enabled!") + applied = true + Log.info("Enabling FloodCompat") + Time.mark() + + // Rules (not overwrites since the game overwrites them automatically when returning to menu + state.rules.hideBannedBlocks = true + state.rules.bannedBlocks.addAll(lancer, arc) + state.rules.revealedBlocks.addAll(coreShard, scrapWall, scrapWallLarge, scrapWallHuge, scrapWallGigantic) + + overwrites( // This system is mostly functional and saves a lot of copy pasting. + //Blocks + scrapWall, "solid", false, + titaniumWall, "solid", false, + thoriumWall, "solid", false, + berylliumWall, "absorbLasers", false, + tungstenWall, "absorbLasers", false, + carbideWall, "absorbLasers", false, + phaseWall, "chanceDeflect", 0, + surgeWall, "lightningChance", 0, + reinforcedSurgeWall, "lightningChance", 0, + mender, "reload", 800, + mendProjector, "reload", 500, + radar, "health", 500, + shockwaveTower, "health", 2000, + thoriumReactor, "health", 1400, + massDriver, "health", 1250, + impactReactor, "rebuildable", false, + *(fuse as ItemTurret).ammoTypes.flatMap { Seq.with(it.value, "pierce", false) }.toTypedArray(), + (fuse as ItemTurret).ammoTypes.get(Items.titanium), "damage", 10, + (fuse as ItemTurret).ammoTypes.get(Items.thorium), "damage", 20, + *(scathe as ItemTurret).ammoTypes.flatMap { Seq.with( + it.value, "buildingDamageMultiplier", 0.3F, + it.value, "damage", 700, + it.value, "splashDamage", 80) + }.toTypedArray(), + lancer, "shootType.damage", 10, + arc, "shootType.damage", 4, + arc, "shootType.lightningLength", 15, + parallax, "force", 8, + parallax, "scaledForce", 7, + parallax, "range", 230, + parallax, "damage", 6, + forceProjector, "shieldHealth", 2500, + // Units + pulsar, "commands", arrayOf(UnitCommand.moveCommand, UnitCommand.boostCommand, UnitCommand.mineCommand), + quasar, "commands", arrayOf(UnitCommand.moveCommand, UnitCommand.boostCommand, UnitCommand.mineCommand), + pulsar, "abilities", Seq(0), // pulsar.abilities.clear() + bryde, "abilities", Seq(0), // pulsar.abilities.clear() + *merui.weapons.flatMap { Seq.with(it.bullet, "collides", true) }.toArray(), + *quad.weapons.flatMap { Seq.with( + it, "bullet.damage", 100, + it, "bullet.splashDamage", 250, + it, "bullet.splashDamageRadius", 100, + ) }.toArray(), + *fortress.weapons.flatMap { Seq.with( + it, "bullet.damage", 40, + it, "bullet.splashDamageRadius", 60 + ) }.toArray(), + *scepter.weapons.flatMap { if (it.name == "scepter-weapon") Seq.with( + it, "bullet.pierce", true, + it, "bullet.pierceCap", 3 + ) else Seq.with(it, "bullet.damage", 25) }.toArray(), + *reign.weapons.flatMap { Seq.with( + it, "bullet.damage", 120, + it, "bullet.fragBullet.damage", 30 + ) }.toArray(), + crawler, "targetAir", false, + spiroct, "targetAir", false, + spiroct, "speed", 0.4F, + *spiroct.weapons.flatMap { Seq.with(it, "bullet.damage", if (it.name == "spiroct-weapon") 25 else 20 ).apply { if (it.bullet is SapBulletType) this.add(it, "bullet.sapStrength", 0) } }.toArray(), + arkyid, "targetAir", false, + arkyid, "speed", 0.5F, + arkyid, "hitSize", 21, + *arkyid.weapons.flatMap { + if (it.bullet is SapBulletType) Seq.with(it, "bullet.sapStrength", 0) + else Seq.with(it, "bullet.pierceBuilding", true, + it, "bullet.pierceCap", 7 + ) + }.toArray(), + crawler, "health", 100, + crawler, "speed", 1.5F, + crawler, "accel", 0.08F, + crawler, "drag", 0.016F, + crawler, "hitSize", 6, + atrax, "speed", 0.5F, + toxopid, "hitSize", 21, + *toxopid.weapons.flatMap { if (it.name == "toxopid-cannon") Seq.with( + it.bullet.fragBullet, "pierce", true, // TODO: Make all of the other bullet references it.bullet, "blah" instead of it, "bullet.blah" + it.bullet.fragBullet, "pierceCap", 2 + ) else Seq.with() }.toArray(), + flare, "health", 275, + flare, "engineOffset", 5.5F, + flare, "range", 140, + horizon, "health", 440, + horizon, "speed", 1.7F, + horizon, "itemCapacity", 20, + zenith, "health", 1400, + zenith, "speed", 1.8F, + *vela.weapons.flatMap { Seq.with(it.bullet, "damage", 20) }.toArray(), + *oct.abilities.flatMap { if (it is ForceFieldAbility) Seq.with( + it, "regen", 16, + it, "max", 15_000 + ) else Seq.with() }.toArray(), + *minke.weapons.flatMap { if (it.bullet is FlakBulletType) Seq.with(it.bullet, "collidesGround", true) else Seq.with()}.toArray() + ) + + // TODO: Implement anticreep packet + + + foreshadowBulletVanilla = (foreshadow as ItemTurret).ammoTypes.put(Items.surgeAlloy, foreshadowBulletFlood) + Log.debug("Enabled FloodCompat in ${Time.elapsed()}ms") + } + + /** Reverts flood changes */ + private fun disable() { + Log.debug("Disabling FloodCompat") + Time.mark() + + defaults.indices.step(3).forEach { (defaults[it + 1] as Field).set(defaults[it], defaults[it + 2]) } // (obj, field, value) -> field.set(obj, value) + defaults.clear() + Log.debug("Disabled FloodCompat in ${Time.elapsed()}ms") + } + + + // Utility functions + + /** Convenient way of adding multiple overwrites at once */ + private fun overwrites(vararg args: Any) = + args.indices.step(3).forEach { overwrite(args[it], args[it + 1] as String, args[it + 2]) } + + private fun overwrite(obj: O, name: String, value: T) { + val split = name.split('.', limit = 2) + val field = obj::class.java.getField(split[0]) + field.isAccessible = true + + // In the case of a string with periods, run the function recursively until we get to the last item which is then set + if (split.size > 1) return overwrite(field.get(obj), split[1], value) + + defaults.add(obj) + defaults.add(field) + defaults.add(field.get(obj)) + field.set(obj, value) + } + + + + private val foreshadowBulletFlood = LaserBulletType().apply { + length = 460f + damage = 560f + width = 75f + lifetime = 65f + lightningSpacing = 35f + lightningLength = 5 + lightningDelay = 1.1f + lightningLengthRand = 15 + lightningDamage = 50f + lightningAngleRand = 40f + largeHit = true + lightningColor = Pal.heal + lightColor = lightningColor + shootEffect = Fx.greenLaserCharge + sideAngle = 15f + sideWidth = 0f + sideLength = 0f + colors = arrayOf(Color.clear, Color.clear, Color.clear) // TODO: Make this properly invisible + } + +} \ No newline at end of file diff --git a/src/floodcompat/floodcompat.java b/src/floodcompat/floodcompat.java deleted file mode 100644 index 3584f26..0000000 --- a/src/floodcompat/floodcompat.java +++ /dev/null @@ -1,340 +0,0 @@ -package floodcompat; - -import arc.*; -import arc.audio.Sound; -import arc.math.Mathf; -import arc.math.geom.Geometry; -import arc.struct.ObjectSet; -import arc.struct.Seq; -import arc.util.*; -import mindustry.ai.UnitCommand; -import mindustry.content.*; -import mindustry.core.*; -import mindustry.entities.abilities.*; -import mindustry.entities.bullet.*; -import mindustry.game.*; -import mindustry.gen.*; -import mindustry.graphics.Pal; -import mindustry.mod.*; -import mindustry.world.Tile; -import mindustry.world.blocks.defense.*; -import mindustry.world.blocks.defense.turrets.*; -import mindustry.world.blocks.power.ImpactReactor; - -import java.util.Objects; - -import static mindustry.content.UnitTypes.*; -import static mindustry.content.Blocks.*; -import static mindustry.Vars.*; - -public class floodcompat extends Mod{ - static boolean flood, applied, enabled; - static Ability pulsarAbility, brydeAbility; - static ObjectSet allTiles = new ObjectSet<>(); - public floodcompat(){ - Log.info("Flood Compatibility loaded!"); - - Events.on(EventType.ContentInitEvent.class, e -> { - var cmds = new UnitCommand[]{UnitCommand.moveCommand, UnitCommand.boostCommand, UnitCommand.mineCommand}; - pulsar.commands = cmds; - quasar.commands = cmds; - - pulsarAbility = pulsar.abilities.first(); - brydeAbility = bryde.abilities.first(); - }); - - Events.on(EventType.ClientLoadEvent.class, e -> { - if(Structs.contains(Version.class.getDeclaredFields(), var -> var.getName().equals("foos"))){ - enabled = false; - }else enabled = true; - }); - - netClient.addPacketHandler("flood", (integer) -> { - if(Strings.canParseInt(integer)){ - ui.chatfrag.addMessage("[lime]Server check succeeded!"); - flood = true; - - if(applied || !enabled) return; - ui.chatfrag.addMessage("[accent]Applying flood changes!"); - - state.rules.hideBannedBlocks = true; - state.rules.bannedBlocks.addAll(Blocks.lancer, Blocks.arc); - state.rules.revealedBlocks.addAll(Blocks.coreShard, Blocks.scrapWall, Blocks.scrapWallLarge, Blocks.scrapWallHuge, Blocks.scrapWallGigantic); - - Seq.with(scrapWall, titaniumWall, thoriumWall).each(w -> w.solid = false); - Seq.with(berylliumWall, tungstenWall, carbideWall).each(w -> w.absorbLasers = true); - ((Wall) phaseWall).chanceDeflect = 0; - ((Wall) surgeWall).lightningChance = 0; - ((Wall) reinforcedSurgeWall).lightningChance = 0; - ((MendProjector) mender).reload = 800; - ((MendProjector) mendProjector).reload = 500; - radar.health = 500; - shockwaveTower.health = 2000; - thoriumReactor.health = 1400; - massDriver.health = 1250; - impactReactor.rebuildable = false; - ((ItemTurret) fuse).ammoTypes.values().toSeq().each(a -> a.pierce = false); - ((ItemTurret) fuse).ammoTypes.get(Items.titanium).damage = 10; - ((ItemTurret) fuse).ammoTypes.get(Items.thorium).damage = 20; - ((ItemTurret) scathe).ammoTypes.values().toSeq().each(a -> { - a.buildingDamageMultiplier = 0.3f; - a.damage = 700; - a.splashDamage = 80; - }); - ((PowerTurret) lancer).shootType.damage = 10; - ((PowerTurret) arc).shootType.damage = 4; - ((PowerTurret) arc).shootType.lightningLength = 15; - ((TractorBeamTurret) parallax).force = 8; - ((TractorBeamTurret) parallax).scaledForce = 7; - ((TractorBeamTurret) parallax).range = 230; - ((TractorBeamTurret) parallax).damage = 6; - ((ForceProjector) forceProjector).shieldHealth = 2500; - - merui.weapons.each(w -> w.bullet.collides = true); - quad.weapons.each(w -> { - w.bullet.damage = 100; - w.bullet.splashDamage = 250; - w.bullet.splashDamageRadius = 100f; - }); - fortress.weapons.each(w -> { - w.bullet.damage = 40; - w.bullet.splashDamageRadius = 60f; - }); - scepter.weapons.each(w -> { - if(Objects.equals(w.name, "scepter-weapon")){ - w.bullet.pierce = true; - w.bullet.pierceCap = 3; - }else{ - w.bullet.damage = 25; - } - }); - reign.weapons.each(w -> { - w.bullet.damage = 120; - w.bullet.fragBullet.damage = 30; - }); - Seq.with(crawler, spiroct, arkyid).each(u -> u.targetAir = false); - crawler.health = 100; - crawler.speed = 1.5f; - crawler.accel = 0.08f; - crawler.drag = 0.016f; - crawler.hitSize = 6f; - atrax.speed = 0.5f; - pulsar.abilities.clear(); - bryde.abilities.clear(); - spiroct.speed = 0.4f; - spiroct.weapons.each(w -> { - if(Objects.equals(w.name, "spiroct-weapon")){ - w.bullet.damage = 25; - }else w.bullet.damage = 20; - if(w.bullet instanceof SapBulletType b) b.sapStrength = 0; - }); - arkyid.speed = 0.5f; - arkyid.hitSize = 21f; - arkyid.weapons.each(w -> { - if(w.bullet instanceof SapBulletType b){ - b.sapStrength = 0; - }else{ - w.bullet.pierceBuilding = true; - w.bullet.pierceCap = 7; - } - }); - toxopid.hitSize = 21f; - toxopid.weapons.each(w -> { - if(Objects.equals(w.name, "toxopid-cannon")) { - w.bullet.fragBullet.pierce = true; - w.bullet.fragBullet.pierceCap = 2; - } - }); - flare.health = 275; - flare.engineOffset = 5.5f; // why? - flare.range = 140; - horizon.health = 440; - horizon.speed = 1.7f; - horizon.itemCapacity = 20; - zenith.health = 1400; - zenith.speed = 1.8f; - vela.weapons.each(w -> w.bullet.damage = 20f); - oct.abilities.each(a -> { - if(a instanceof ForceFieldAbility f){ - f.regen = 16f; - f.max = 15000f; - } - }); - minke.weapons.each(w -> { - if(w.bullet instanceof FlakBulletType){ - w.bullet.collidesGround = true; - } - }); - - applied = true; - } - }); - - netClient.addPacketHandler("anticreep", (string) -> { - String[] vars = string.split(":"); - - int pos = Strings.parseInt(vars[0]), rad = Strings.parseInt(vars[1]), - time = Strings.parseInt(vars[2]), team = Strings.parseInt(vars[3]); - - if(pos > 0 && rad > 0 && time > 0 && team > 0){ - Tile tile = world.tiles.getp(pos); - var color = Team.get(team).color; - - Seq tiles = new Seq<>(); - Geometry.circle(tile.x, tile.y, rad, (cx, cy) -> { - Tile t = world.tile(cx, cy); - if(t != null && !allTiles.contains(t)){ - tiles.add(t); - } - }); - allTiles.addAll(tiles); - - var startTime = Time.millis(); - - Timer.schedule(() -> { - tiles.each(t -> { - Timer.schedule(() -> { - var sizeMultiplier = 1 - (Time.millis() - startTime) / 1000f / time; - NetClient.effect(Fx.lightBlock, t.getX(), t.getY(), Mathf.random(0.01f, 1.5f * sizeMultiplier), color); - }, Mathf.random(1f)); - }); - }, 0, 1, time); - - Timer.schedule(() -> { - allTiles.removeAll(tiles); - tiles.clear(); - }, time); - } - }); - - Events.on(EventType.WorldLoadEvent.class, e -> { - allTiles.clear(); - - // no delay if the client's hosting, that would break stuff! - int delay = net.client() ? 3 : 0; - flood = false; - - if(delay > 0) Call.serverPacketReliable("flood", "0.6"); - Timer.schedule(() -> { - // this is for cleanup only - if(!flood && enabled){ - if(net.client()) ui.chatfrag.addMessage("[scarlet]Server check failed...\n[accent]Playing on flood? Try rejoining!\nHave a nice day!"); - if(applied){ - Seq.with(scrapWall, titaniumWall, thoriumWall).each(w -> w.solid = true); - Seq.with(berylliumWall, tungstenWall, carbideWall).each(w -> { - w.insulated = w.absorbLasers = false; - }); - ((Wall) phaseWall).chanceDeflect = 10; - ((Wall) surgeWall).lightningChance = 0.05f; - ((Wall) reinforcedSurgeWall).lightningChance = 0.05f; - ((MendProjector) mender).reload = 200; - ((MendProjector) mendProjector).reload = 250; - radar.health = 60; - shockwaveTower.health = 915; - thoriumReactor.health = 700; - massDriver.health = 430; - impactReactor.rebuildable = true; - ((ItemTurret) fuse).ammoTypes.values().toSeq().each(a -> a.pierce = true); - ((ItemTurret) fuse).ammoTypes.get(Items.titanium).damage = 66; - ((ItemTurret) fuse).ammoTypes.get(Items.thorium).damage = 105; - ((ItemTurret) scathe).ammoTypes.values().toSeq().each(a -> { - a.buildingDamageMultiplier = 0.2f; - a.damage = 1500; - a.splashDamage = 160; - }); - ((PowerTurret) lancer).shootType.damage = 140; - ((PowerTurret) arc).shootType.damage = 20; - ((PowerTurret) arc).shootType.lightningLength = 25; - ((TractorBeamTurret) parallax).force = 12f; - ((TractorBeamTurret) parallax).scaledForce = 6f; - ((TractorBeamTurret) parallax).range = 240f; - ((TractorBeamTurret) parallax).damage = 0.3f; - ((ForceProjector) forceProjector).shieldHealth = 750; - - merui.weapons.each(w -> w.bullet.collides = false); - quad.weapons.each(w -> { - w.bullet.damage = -1; - w.bullet.splashDamage = 220; - w.bullet.splashDamageRadius = 80f; - }); - fortress.weapons.each(w -> { - w.bullet.damage = 20; - w.bullet.splashDamageRadius = 35f; - }); - scepter.weapons.each(w -> { - if(Objects.equals(w.name, "scepter-weapon")){ - w.bullet.pierce = false; - w.bullet.pierceCap = -1; - }else{ - w.bullet.damage = 10; - } - }); - reign.weapons.each(w -> { - w.bullet.damage = 80; - w.bullet.fragBullet.damage = 20; - }); - Seq.with(crawler, spiroct, arkyid).each(u -> u.targetAir = true); - crawler.health = 200; - crawler.speed = 1f; - crawler.accel = 0; - crawler.drag = 0; - crawler.hitSize = 8f; - atrax.speed = 0.6f; - pulsar.abilities.add(pulsarAbility); - bryde.abilities.add(brydeAbility); - spiroct.speed = 0.54f; - spiroct.weapons.each(w -> { - if(Objects.equals(w.name, "spiroct-weapon")){ - w.bullet.damage = 23; - }else w.bullet.damage = 18; - if(w.bullet instanceof SapBulletType b){ - if(Objects.equals(w.name, "spiroct-weapon")){ - b.sapStrength = 0.5f; - }else b.sapStrength = 0.8f; - } - }); - arkyid.speed = 0.62f; - arkyid.hitSize = 23f; - arkyid.weapons.each(w -> { - if(w.bullet instanceof SapBulletType b) { - b.sapStrength = 0.85f; - }else{ - w.bullet.pierceBuilding = false; - w.bullet.pierceCap = -1; - } - }); - toxopid.hitSize = 26f; - toxopid.weapons.each(w -> { - if(Objects.equals(w.name, "toxopid-cannon")) { - w.bullet.fragBullet.pierce = false; - w.bullet.fragBullet.pierceCap = -1; - } - }); - flare.health = 70; - flare.range = 104; - horizon.health = 340; - horizon.speed = 1.65f; - horizon.itemCapacity = 0; - zenith.health = 700; - zenith.speed = 1.7f; - vela.weapons.each(w -> w.bullet.damage = 35f); - oct.abilities.each(a -> { - if(a instanceof ForceFieldAbility f){ - f.regen = 4f; - f.max = 7000f; - } - }); - minke.weapons.each(w -> { - if(w.bullet instanceof FlakBulletType){ - w.bullet.collidesGround = false; - } - }); - - ui.chatfrag.addMessage("[accent]Flood changes reverted!\nConsider using /sync if playing on a server!\nIf you are the host, ignore this message!"); - applied = false; - } - } - }, delay); - }); - } -}