From e8a5e35f504bde5a5b689dc6b3693685333ef1aa Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 4 Nov 2020 12:45:51 -0500 Subject: [PATCH] More achievement cleanup --- core/src/mindustry/content/StatusEffects.java | 2 +- .../mindustry/entities/comp/BulletComp.java | 7 ++ .../mindustry/entities/comp/PayloadComp.java | 4 + core/src/mindustry/game/EventType.java | 36 ++++++++ core/src/mindustry/game/Schematics.java | 4 +- core/src/mindustry/input/InputHandler.java | 8 +- .../world/blocks/storage/CoreBlock.java | 2 +- .../world/blocks/storage/Unloader.java | 13 ++- .../mindustry/desktop/steam/SAchievement.java | 43 ++++----- .../src/mindustry/desktop/steam/SStat.java | 6 +- .../src/mindustry/desktop/steam/SStats.java | 90 +++++++++++++++---- 11 files changed, 161 insertions(+), 54 deletions(-) diff --git a/core/src/mindustry/content/StatusEffects.java b/core/src/mindustry/content/StatusEffects.java index 0a90a2d6ef..e1298b48d5 100644 --- a/core/src/mindustry/content/StatusEffects.java +++ b/core/src/mindustry/content/StatusEffects.java @@ -69,7 +69,7 @@ public class StatusEffects implements ContentList{ init(() -> { trans(shocked, ((unit, time, newTime, result) -> { unit.damagePierce(14f); - if(unit.team() == state.rules.waveTeam){ + if(unit.team == state.rules.waveTeam){ Events.fire(Trigger.shock); } result.set(this, time); diff --git a/core/src/mindustry/entities/comp/BulletComp.java b/core/src/mindustry/entities/comp/BulletComp.java index bec11c2711..fc8d8ff12b 100644 --- a/core/src/mindustry/entities/comp/BulletComp.java +++ b/core/src/mindustry/entities/comp/BulletComp.java @@ -1,5 +1,6 @@ package mindustry.entities.comp; +import arc.*; import arc.func.*; import arc.graphics.g2d.*; import arc.math.*; @@ -9,10 +10,12 @@ import arc.util.*; import mindustry.annotations.Annotations.*; import mindustry.core.*; import mindustry.entities.bullet.*; +import mindustry.game.EventType.*; import mindustry.game.*; import mindustry.game.Teams.*; import mindustry.gen.*; import mindustry.graphics.*; +import mindustry.world.blocks.defense.Wall.*; import static mindustry.Vars.*; @@ -104,6 +107,10 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw } type.hitEntity(self(), other, health); + + if(owner instanceof WallBuild && player != null && team != player.team() && other instanceof Unit unit && unit.dead){ + Events.fire(Trigger.phaseDeflectHit); + } } @Override diff --git a/core/src/mindustry/entities/comp/PayloadComp.java b/core/src/mindustry/entities/comp/PayloadComp.java index e2945d08f7..c89dc2b10b 100644 --- a/core/src/mindustry/entities/comp/PayloadComp.java +++ b/core/src/mindustry/entities/comp/PayloadComp.java @@ -1,5 +1,6 @@ package mindustry.entities.comp; +import arc.*; import arc.math.*; import arc.struct.*; import arc.util.*; @@ -8,6 +9,7 @@ import mindustry.annotations.Annotations.*; import mindustry.content.*; import mindustry.core.*; import mindustry.entities.*; +import mindustry.game.EventType.*; import mindustry.gen.*; import mindustry.type.*; import mindustry.world.*; @@ -52,12 +54,14 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc, Unitc{ if(Vars.net.client()){ Vars.netClient.clearRemovedEntity(unit.id); } + Events.fire(new PickupEvent(self(), unit)); } void pickup(Building tile){ tile.tile.remove(); payloads.add(new BuildPayload(tile)); Fx.unitPickup.at(tile); + Events.fire(new PickupEvent(self(), tile)); } boolean dropLastPayload(){ diff --git a/core/src/mindustry/game/EventType.java b/core/src/mindustry/game/EventType.java index 8f40d0abc9..43ae282d4c 100644 --- a/core/src/mindustry/game/EventType.java +++ b/core/src/mindustry/game/EventType.java @@ -102,6 +102,14 @@ public class EventType{ } } + public static class SchematicCreateEvent{ + public final Schematic schematic; + + public SchematicCreateEvent(Schematic schematic){ + this.schematic = schematic; + } + } + public static class CommandIssueEvent{ public final Building tile; public final UnitCommand command; @@ -193,6 +201,34 @@ public class EventType{ } } + public static class PickupEvent{ + public final Unit carrier; + public final @Nullable Unit unit; + public final @Nullable Building build; + + public PickupEvent(Unit carrier, Unit unit){ + this.carrier = carrier; + this.unit = unit; + this.build = null; + } + + public PickupEvent(Unit carrier, Building build){ + this.carrier = carrier; + this.build = build; + this.unit = null; + } + } + + public static class UnitControlEvent{ + public final Player player; + public final @Nullable Unit unit; + + public UnitControlEvent(Player player, @Nullable Unit unit){ + this.player = player; + this.unit = unit; + } + } + public static class GameOverEvent{ public final Team winner; diff --git a/core/src/mindustry/game/Schematics.java b/core/src/mindustry/game/Schematics.java index cead506777..52de993d32 100644 --- a/core/src/mindustry/game/Schematics.java +++ b/core/src/mindustry/game/Schematics.java @@ -114,7 +114,7 @@ public class Schematics implements Loadable{ } private void loadLoadouts(){ - Seq.with(Loadouts.basicShard, Loadouts.basicFoundation, Loadouts.basicNucleus).each(s -> checkLoadout(s,false)); + Seq.with(Loadouts.basicShard, Loadouts.basicFoundation, Loadouts.basicNucleus).each(s -> checkLoadout(s, false)); } public void overwrite(Schematic target, Schematic newSchematic){ @@ -354,7 +354,7 @@ public class Schematics implements Loadable{ for(int cy = y; cy <= y2; cy++){ Building linked = world.build(cx, cy); - if(linked != null && linked.block.isVisible() && !(linked.block instanceof ConstructBlock)){ + if(linked != null && (linked.block.isVisible() || linked.block() instanceof CoreBlock) && !(linked.block instanceof ConstructBlock)){ int top = linked.block.size/2; int bot = linked.block.size % 2 == 1 ? -linked.block.size/2 : -(linked.block.size - 1)/2; minx = Math.min(linked.tileX() + bot, minx); diff --git a/core/src/mindustry/input/InputHandler.java b/core/src/mindustry/input/InputHandler.java index 41d1df4b16..b3684c1e04 100644 --- a/core/src/mindustry/input/InputHandler.java +++ b/core/src/mindustry/input/InputHandler.java @@ -326,7 +326,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ } //clear player unit when they possess a core - if((unit instanceof BlockUnitc && ((BlockUnitc)unit).tile() instanceof CoreBuild)){ + if(unit instanceof BlockUnitc block && block.tile() instanceof CoreBuild build){ Fx.spawn.at(player); if(net.client()){ control.input.controlledType = null; @@ -334,8 +334,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ player.clearUnit(); player.deathTimer = 61f; - ((CoreBuild)((BlockUnitc)unit).tile()).requestSpawn(player); - + build.requestSpawn(player); }else if(unit == null){ //just clear the unit (is this used?) player.clearUnit(); //make sure it's AI controlled, so players can't overwrite each other @@ -349,6 +348,8 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ Fx.unitSpirit.at(player.x, player.y, 0f, unit); } } + + Events.fire(new UnitControlEvent(player, unit)); } @Remote(targets = Loc.both, called = Loc.both, forward = true) @@ -543,6 +544,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ schematics.add(lastSchematic); ui.showInfoFade("@schematic.saved"); ui.schematics.showInfo(lastSchematic); + Events.fire(new SchematicCreateEvent(lastSchematic)); } }); } diff --git a/core/src/mindustry/world/blocks/storage/CoreBlock.java b/core/src/mindustry/world/blocks/storage/CoreBlock.java index c1bcca2418..5742d4f7e1 100644 --- a/core/src/mindustry/world/blocks/storage/CoreBlock.java +++ b/core/src/mindustry/world/blocks/storage/CoreBlock.java @@ -77,7 +77,7 @@ public class CoreBlock extends StorageBlock{ public void setStats(){ super.setStats(); - stats.add(Stat.buildTime, 0, StatUnit.seconds); + stats.remove(Stat.buildTime); } @Override diff --git a/core/src/mindustry/world/blocks/storage/Unloader.java b/core/src/mindustry/world/blocks/storage/Unloader.java index 524d6eb939..dcc94ef099 100644 --- a/core/src/mindustry/world/blocks/storage/Unloader.java +++ b/core/src/mindustry/world/blocks/storage/Unloader.java @@ -46,13 +46,17 @@ public class Unloader extends Block{ public class UnloaderBuild extends Building{ public Item sortItem = null; public Building dumpingTo; + public int offset = 0; @Override public void updateTile(){ if(timer(timerUnload, speed / timeScale())){ - for(Building other : proximity){ + for(int i = 0; i < proximity.size; i++){ + int pos = (offset + i) % proximity.size; + var other = proximity.get(pos); + if(other.interactable(team) && other.block.unloadable && other.block.hasItems - && ((sortItem == null && other.items.total() > 0) || (sortItem != null && other.items.has(sortItem)))){ + && ((sortItem == null && other.items.total() > 0) || (sortItem != null && other.items.has(sortItem)))){ //make sure the item can't be dumped back into this block dumpingTo = other; @@ -70,6 +74,11 @@ public class Unloader extends Block{ } } } + + if(proximity.size > 0){ + offset ++; + offset %= proximity.size; + } } } diff --git a/desktop/src/mindustry/desktop/steam/SAchievement.java b/desktop/src/mindustry/desktop/steam/SAchievement.java index a3ec5d162d..38236eabd8 100644 --- a/desktop/src/mindustry/desktop/steam/SAchievement.java +++ b/desktop/src/mindustry/desktop/steam/SAchievement.java @@ -1,41 +1,36 @@ package mindustry.desktop.steam; public enum SAchievement{ - //completeTutorial, kill1kEnemies(SStat.unitsDestroyed, 1000), - kill100kEnemies(SStat.unitsDestroyed, 1000 * 100), - //TODO achievements for reaching 10k/min production or something - launch10kItems(SStat.itemsLaunched, 1000 * 10), - //TODO reduce amounts required here - launch1milItems(SStat.itemsLaunched, 1000 * 1000), + kill100kEnemies(SStat.unitsDestroyed, 100_000), + launch10kItems(SStat.itemsLaunched, 10_000), + launch1milItems(SStat.itemsLaunched, 1_000_000), + + produce1kMin(SStat.maxProduction, 1000), + produce20kMin(SStat.maxProduction, 20_000), win10Attack(SStat.attacksWon, 10), win10PvP(SStat.pvpsWon, 10), defeatAttack5Waves, - //TODO launch30Times(SStat.timesLaunched, 30), - //TODO captureBackground, - //TODO survive100Waves(SStat.maxWavesSurvived, 100), - survive500Waves(SStat.maxWavesSurvived, 500), + //this seems near-impossible? + //survive500Waves(SStat.maxWavesSurvived, 500), researchAll, //TODO - useAllUnits, + //useAllUnits, shockWetEnemy, killEnemyPhaseWall, researchRouter, - place10kBlocks(SStat.blocksBuilt, 10 * 1000), + place10kBlocks(SStat.blocksBuilt, 10_000), destroy1kBlocks(SStat.blocksDestroyed, 1000), overheatReactor(SStat.reactorsOverheated, 1), make10maps(SStat.mapsMade, 10), downloadMapWorkshop, publishMap(SStat.mapsPublished, 1), defeatBoss(SStat.bossesDefeated, 1), - //TODO captureAllSectors, - //TODO - capture10Sectors, - //TODO + control10Sectors, drop10kitems, powerupImpactReactor, obtainThorium, @@ -44,10 +39,12 @@ public enum SAchievement{ buildGroundFactory, issueAttackCommand, active100Units(SStat.maxUnitActive, 100), - build1000Units, - buildAllUnits(SStat.unitsBuilt, 30), - //TODO + build1000Units(SStat.unitsBuilt, 1000), + buildAllUnits(SStat.unitTypesBuilt, 30), + buildT5, + pickupT5, activeAllT5, + active10Polys, dieExclusion, drown, fillCoreAllCampaign, @@ -55,15 +52,11 @@ public enum SAchievement{ buildMeltdownSpectreForeshadow, launchItemPad, chainRouters, - //TODO circleConveyor, - //TODO becomeRouter, - //TODO - save20Schematics, - //TODO - destroyEnemyBase, + create20Schematics(SStat.schematicsCreated, 20), survive10WavesNoBlocks, + captureNoBlocksBroken, useFlameAmmo, coolTurret, enablePixelation, diff --git a/desktop/src/mindustry/desktop/steam/SStat.java b/desktop/src/mindustry/desktop/steam/SStat.java index 48e0b25edf..be67714d4d 100644 --- a/desktop/src/mindustry/desktop/steam/SStat.java +++ b/desktop/src/mindustry/desktop/steam/SStat.java @@ -5,11 +5,12 @@ public enum SStat{ attacksWon, pvpsWon, timesLaunched, - zoneMechsUsed, + zoneMechsUsed, //TODO blocksDestroyed, itemsLaunched, reactorsOverheated, maxUnitActive, + unitTypesBuilt, unitsBuilt, bossesDefeated, maxPlayersServer, @@ -17,6 +18,9 @@ public enum SStat{ mapsPublished, maxWavesSurvived, blocksBuilt, + maxProduction, + sectorsControlled, + schematicsCreated, ; public int get(){ diff --git a/desktop/src/mindustry/desktop/steam/SStats.java b/desktop/src/mindustry/desktop/steam/SStats.java index 3a79708973..d5f7eb88d5 100644 --- a/desktop/src/mindustry/desktop/steam/SStats.java +++ b/desktop/src/mindustry/desktop/steam/SStats.java @@ -9,6 +9,7 @@ import mindustry.content.*; import mindustry.entities.units.*; import mindustry.game.EventType.*; import mindustry.gen.*; +import mindustry.type.*; import mindustry.world.*; import mindustry.world.blocks.distribution.*; @@ -24,6 +25,8 @@ public class SStats implements SteamUserStatsCallback{ private int statSavePeriod = 4; //in minutes private ObjectSet blocksBuilt = new ObjectSet<>(), unitsBuilt = new ObjectSet<>(); + private ObjectSet t5s = new ObjectSet<>(); + private ObjectSet tmpSet = new ObjectSet<>(); public SStats(){ stats.requestCurrentStats(); @@ -36,7 +39,7 @@ public class SStats implements SteamUserStatsCallback{ @Override public void update(){ - if(i.get(60f / 4f)){ + if(i.get(60f)){ checkUpdate(); } } @@ -58,14 +61,15 @@ public class SStats implements SteamUserStatsCallback{ if(campaign()){ SStat.maxUnitActive.max(Groups.unit.count(t -> t.team == player.team())); - //TODO - //if(Groups.unit.count(u -> u.type() == UnitTypes.phantom && u.team() == player.team()) >= 10){ - // active10Phantoms.complete(); - //} + if(Groups.unit.count(u -> u.type == UnitTypes.poly && u.team == player.team()) >= 10){ + active10Polys.complete(); + } - //TODO - if(Groups.unit.count(u -> u.type == UnitTypes.crawler && u.team() == player.team()) >= 50){ - // active50Crawlers.complete(); + tmpSet.clear(); + tmpSet.addAll(t5s); + Groups.unit.each(u -> tmpSet.remove(u.type)); + if(tmpSet.size == 0){ + activeAllT5.complete(); } for(Building entity : player.team().cores()){ @@ -81,6 +85,7 @@ public class SStats implements SteamUserStatsCallback{ Events.on(ClientLoadEvent.class, e -> { unitsBuilt = Core.settings.getJson("units-built" , ObjectSet.class, String.class, ObjectSet::new); blocksBuilt = Core.settings.getJson("blocks-built" , ObjectSet.class, String.class, ObjectSet::new); + t5s = ObjectSet.with(UnitTypes.omura, UnitTypes.reign, UnitTypes.toxopid, UnitTypes.eclipse, UnitTypes.oct, UnitTypes.corvus); }); Events.on(UnitDestroyEvent.class, e -> { @@ -95,6 +100,21 @@ public class SStats implements SteamUserStatsCallback{ } }); + Events.on(TurnEvent.class, e -> { + float total = 0; + for(Planet planet : content.planets()){ + for(Sector sec : planet.sectors){ + if(sec.hasBase()){ + for(var v : sec.info.production.values()){ + total += v.mean; + } + } + } + } + + SStat.maxProduction.max((int)total); + }); + Events.run(Trigger.newGame, () -> Core.app.post(() -> { if(campaign() && player.core() != null && player.core().items.total() >= 10 * 1000){ drop10kitems.complete(); @@ -151,11 +171,25 @@ public class SStats implements SteamUserStatsCallback{ Events.on(UnitCreateEvent.class, e -> { if(campaign()){ if(unitsBuilt.add(e.unit.type.name)){ - SStat.unitsBuilt.set(content.units().count(u -> unitsBuilt.contains(u.name) && !u.isHidden())); + SStat.unitTypesBuilt.set(content.units().count(u -> unitsBuilt.contains(u.name) && !u.isHidden())); + } + + if(t5s.contains(e.unit.type)){ + buildT5.complete(); } } }); + Events.on(UnitControlEvent.class, e -> { + if(e.unit instanceof BlockUnitc block && block.tile().block == Blocks.router){ + becomeRouter.complete(); + } + }); + + Events.on(SchematicCreateEvent.class, e -> { + SStat.schematicsCreated.add(); + }); + Events.on(BlockDestroyEvent.class, e -> { if(campaign() && e.tile.team() != player.team()){ SStat.blocksDestroyed.add(); @@ -207,6 +241,12 @@ public class SStats implements SteamUserStatsCallback{ } }); + Events.on(PickupEvent.class, e -> { + if(e.carrier.isPlayer() && campaign() && e.unit != null && t5s.contains(e.unit.type)){ + pickupT5.complete(); + } + }); + Events.on(UnitCreateEvent.class, e -> { if(campaign() && e.unit.team() == player.team()){ SStat.unitsBuilt.add(); @@ -259,22 +299,34 @@ public class SStats implements SteamUserStatsCallback{ Events.on(ClientLoadEvent.class, e -> checkUnlocks.run()); Events.on(WinEvent.class, e -> { - if(state.hasSector()){ - if(Vars.state.wave <= 5 && state.rules.attackMode){ - defeatAttack5Waves.complete(); - } - - if(Vars.state.rules.attackMode){ - SStat.attacksWon.add(); - } - } - if(state.rules.pvp){ SStat.pvpsWon.add(); } }); + Events.on(SectorCaptureEvent.class, e -> { + if(Vars.state.wave <= 5 && state.rules.attackMode){ + defeatAttack5Waves.complete(); + } + if(state.stats.buildingsDestroyed == 0){ + captureNoBlocksBroken.complete(); + } + + if(Vars.state.rules.attackMode){ + SStat.attacksWon.add(); + } + + if(!e.sector.isBeingPlayed()){ + captureBackground.complete(); + } + + if(!e.sector.planet.sectors.contains(s -> s.hasBase())){ + captureAllSectors.complete(); + } + + SStat.sectorsControlled.set(e.sector.planet.sectors.count(s -> s.hasBase())); + }); //TODO dead achievement /*