From 6973ed7d555d1cdfa0f6f3666ecd25dd6da0e790 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 17 Jul 2021 08:52:24 -0400 Subject: [PATCH] PvP defeated team cleanup --- core/assets/bundles/bundle.properties | 1 + core/src/mindustry/core/Logic.java | 26 +++++------------ core/src/mindustry/game/Rules.java | 2 ++ core/src/mindustry/game/Teams.java | 29 +++++++++++++++++++ .../ui/dialogs/CustomRulesDialog.java | 1 + gradle.properties | 2 +- 6 files changed, 41 insertions(+), 20 deletions(-) diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 89e7c59f2c..5e19a8781e 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -996,6 +996,7 @@ rules.wavetimer = Wave Timer rules.waves = Waves rules.attack = Attack Mode rules.buildai = AI Building +rules.cleanupdeadteams = Clean Up Defeated Team Buildings (PvP) rules.corecapture = Capture Core On Destruction rules.polygoncoreprotection = Polygonal Core Protection rules.enemyCheat = Infinite AI (Red Team) Resources diff --git a/core/src/mindustry/core/Logic.java b/core/src/mindustry/core/Logic.java index b9ddb2cef9..d0a6b24a35 100644 --- a/core/src/mindustry/core/Logic.java +++ b/core/src/mindustry/core/Logic.java @@ -129,25 +129,7 @@ public class Logic implements ApplicationListener{ Events.on(SectorCaptureEvent.class, e -> { if(!net.client() && e.sector == state.getSector() && e.sector.isBeingPlayed()){ - for(Tile tile : world.tiles){ - //convert all blocks to neutral, randomly killing them - if(tile.isCenter() && tile.build != null && tile.build.team == state.rules.waveTeam){ - Building b = tile.build; - Call.setTeam(b, Team.derelict); - Time.run(Mathf.random(0f, 60f * 6f), () -> { - if(Mathf.chance(0.25)){ - b.kill(); - } - }); - } - } - - //kill all units - Groups.unit.each(u -> { - if(u.team == state.rules.waveTeam){ - Time.run(Mathf.random(0f, 60f * 5f), u::kill); - } - }); + state.rules.waveTeam.data().destroyToDerelict(); } }); @@ -163,6 +145,12 @@ public class Logic implements ApplicationListener{ } }); + //listen to core changes; if all cores have been destroyed, set to derelict. + Events.on(CoreChangeEvent.class, e -> Core.app.post(() -> { + if(state.rules.cleanupDeadTeams && state.rules.pvp && !e.core.isAdded() && e.core.team != Team.derelict && e.core.team.cores().isEmpty()){ + e.core.team.data().destroyToDerelict(); + } + })); } /** Adds starting items, resets wave time, and sets state to playing. */ diff --git a/core/src/mindustry/game/Rules.java b/core/src/mindustry/game/Rules.java index 2fa767518d..f66dd658ea 100644 --- a/core/src/mindustry/game/Rules.java +++ b/core/src/mindustry/game/Rules.java @@ -70,6 +70,8 @@ public class Rules{ public float enemyCoreBuildRadius = 400f; /** If true, no-build zones are calculated based on the closest core. */ public boolean polygonCoreProtection = false; + /** If true, dead teams in PvP automatically have their blocks & units converted to derelict upon death. */ + public boolean cleanupDeadTeams = true; /** Radius around enemy wave drop zones.*/ public float dropZoneRadius = 300f; /** Time between waves in ticks. */ diff --git a/core/src/mindustry/game/Teams.java b/core/src/mindustry/game/Teams.java index 9d73661ef5..97638ed1e2 100644 --- a/core/src/mindustry/game/Teams.java +++ b/core/src/mindustry/game/Teams.java @@ -1,6 +1,7 @@ package mindustry.game; import arc.func.*; +import arc.math.*; import arc.math.geom.*; import arc.struct.Queue; import arc.struct.*; @@ -260,6 +261,34 @@ public class Teams{ this.ai = new BaseAI(this); } + /** Destroys this team's presence on the map, killing part of its buildings and converting everything to 'derelict'. */ + public void destroyToDerelict(){ + + //grab all buildings from quadtree. + var builds = new Seq(); + if(buildings != null){ + buildings.getObjects(builds); + } + + //convert all team tiles to neutral, randomly killing them + for(var b : builds){ + //TODO this may cause a lot of packet spam, optimize? + Call.setTeam(b, Team.derelict); + + if(Mathf.chance(0.25)){ + Time.run(Mathf.random(0f, 60f * 6f), b::kill); + } + } + + //kill all units randomly + units.each(u -> Time.run(Mathf.random(0f, 60f * 5f), () -> { + //ensure unit hasn't switched teams for whatever reason + if(u.team == team){ + u.kill(); + } + })); + } + @Nullable public Seq unitCache(UnitType type){ if(unitsByType == null || unitsByType.length <= type.id || unitsByType[type.id] == null) return null; diff --git a/core/src/mindustry/ui/dialogs/CustomRulesDialog.java b/core/src/mindustry/ui/dialogs/CustomRulesDialog.java index 7c77c47d75..346a9b48bb 100644 --- a/core/src/mindustry/ui/dialogs/CustomRulesDialog.java +++ b/core/src/mindustry/ui/dialogs/CustomRulesDialog.java @@ -142,6 +142,7 @@ public class CustomRulesDialog extends BaseDialog{ check("@rules.reactorexplosions", b -> rules.reactorExplosions = b, () -> rules.reactorExplosions); check("@rules.schematic", b -> rules.schematicsAllowed = b, () -> rules.schematicsAllowed); check("@rules.coreincinerates", b -> rules.coreIncinerates = b, () -> rules.coreIncinerates); + check("@rules.cleanupdeadteams", b -> rules.cleanupDeadTeams = b, () -> rules.cleanupDeadTeams, () -> rules.pvp); number("@rules.buildcostmultiplier", false, f -> rules.buildCostMultiplier = f, () -> rules.buildCostMultiplier, () -> !rules.infiniteResources); number("@rules.buildspeedmultiplier", f -> rules.buildSpeedMultiplier = f, () -> rules.buildSpeedMultiplier, 0.001f, 50f); number("@rules.deconstructrefundmultiplier", false, f -> rules.deconstructRefundMultiplier = f, () -> rules.deconstructRefundMultiplier, () -> !rules.infiniteResources); diff --git a/gradle.properties b/gradle.properties index 7f911ff584..680c4b703a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,4 +10,4 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=735ab5cb989b89d6978892788e3e0ad089131926 +archash=3fe3fc594d041fa0a7e096e50ce1a032ffe3dae0