From 1fb88c13b0f8182a6558cdfce8be9e32b7d68b4b Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 6 Feb 2022 22:05:43 -0500 Subject: [PATCH] Initial core unit dock implementation --- core/src/mindustry/content/UnitTypes.java | 14 +++++- .../src/mindustry/entities/comp/LegsComp.java | 3 ++ .../src/mindustry/entities/comp/UnitComp.java | 2 + core/src/mindustry/input/InputHandler.java | 46 +++++++++++++++++++ .../maps/planet/ErekirPlanetGenerator.java | 2 +- 5 files changed, 64 insertions(+), 3 deletions(-) diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index d3229cc1e0..4378828ea1 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -2681,6 +2681,13 @@ public class UnitTypes{ health = 7000; armor = 5f; + lockLegBase = true; + legContinuousMove = true; + legGroupSize = 3; + legStraightness = 0.4f; + baseLegStraightness = 0.5f; + maxStretch = 1.3f; + abilities.add(new ShieldArcAbility(){{ region = "bulwark-shield"; radius = 34f; @@ -2694,7 +2701,7 @@ public class UnitTypes{ rotateSpeed = 2.1f; - legCount = 4; + legCount = 6; legLength = 15f; legTrns = 0.45f; legMoveSpace = 1.4f; @@ -3117,6 +3124,7 @@ public class UnitTypes{ //TODO bad name evoke = new ErekirUnitType("evoke"){{ + coreUnitDock = false; defaultController = BuilderAI::new; isCounted = false; envDisabled = 0; @@ -3165,12 +3173,13 @@ public class UnitTypes{ healColor = Pal.accent; bullet = new BulletType(){{ - maxRange = 70f; + maxRange = 60f; }}; }}); }}; incite = new ErekirUnitType("incite"){{ + coreUnitDock = false; defaultController = BuilderAI::new; isCounted = false; envDisabled = 0; @@ -3229,6 +3238,7 @@ public class UnitTypes{ }}; emanate = new ErekirUnitType("emanate"){{ + coreUnitDock = false; defaultController = BuilderAI::new; isCounted = false; envDisabled = 0; diff --git a/core/src/mindustry/entities/comp/LegsComp.java b/core/src/mindustry/entities/comp/LegsComp.java index ccd3be83b2..1a6ceb8c52 100644 --- a/core/src/mindustry/entities/comp/LegsComp.java +++ b/core/src/mindustry/entities/comp/LegsComp.java @@ -30,6 +30,7 @@ abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc{ transient float moveSpace; transient float baseRotation; transient Floor lastDeepFloor; + transient Vec2 curMoveOffset = new Vec2(); @Replace @Override @@ -134,6 +135,8 @@ abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc{ //rotation + offset vector boolean moving = moving(); Vec2 moveOffset = !moving ? Tmp.v4.setZero() : Tmp.v4.trns(Angles.angle(deltaX(), deltaY()), trns); + //make it smooth, not jumpy + moveOffset = curMoveOffset.lerpDelta(moveOffset, 0.1f); lastDeepFloor = null; int deeps = 0; diff --git a/core/src/mindustry/entities/comp/UnitComp.java b/core/src/mindustry/entities/comp/UnitComp.java index 83bba188c5..30911bec5a 100644 --- a/core/src/mindustry/entities/comp/UnitComp.java +++ b/core/src/mindustry/entities/comp/UnitComp.java @@ -48,6 +48,8 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I double flag; transient @Nullable Trail trail; + //TODO could be better represented as a unit + transient @Nullable UnitType dockedType; transient float shadowAlpha = -1f; transient float healTime; diff --git a/core/src/mindustry/input/InputHandler.java b/core/src/mindustry/input/InputHandler.java index c9b5d9b370..47783b10fc 100644 --- a/core/src/mindustry/input/InputHandler.java +++ b/core/src/mindustry/input/InputHandler.java @@ -34,6 +34,7 @@ import mindustry.world.blocks.ConstructBlock.*; import mindustry.world.blocks.*; import mindustry.world.blocks.distribution.*; import mindustry.world.blocks.payloads.*; +import mindustry.world.blocks.storage.*; import mindustry.world.meta.*; import java.util.*; @@ -419,8 +420,21 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ player.justSwitchTo = unit; } + //TODO range check for docking + var before = player.unit(); + player.unit(unit); + //TODO test this in multiplayer + if(unit.type.coreUnitDock && before != null && !before.isNull()){ + if(before.spawnedByCore){ + unit.dockedType = before.type; + }else if(before.dockedType != null){ + //direct dock transfer??? + unit.dockedType = before.dockedType; + } + } + Time.run(Fx.unitSpirit.lifetime, () -> Fx.unitControl.at(unit.x, unit.y, 0f, unit)); if(!player.dead()){ Fx.unitSpirit.at(player.x, player.y, 0f, unit); @@ -437,6 +451,38 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ public static void unitClear(Player player){ if(player == null) return; + //TODO test this in multiplayer + if(!player.dead() && player.unit().type.coreUnitDock && !player.unit().spawnedByCore){ + //TODO respawn ON the unit, with an animation? + var docked = player.unit().dockedType; + if(docked == null){ + var closest = player.bestCore(); + if(closest != null){ + docked = ((CoreBlock)closest.block).unitType; + } + } + + if(docked != null){ + //TODO animation, etc + Fx.spawn.at(player); + + if(!net.client()){ + Unit unit = docked.create(player.team()); + unit.set(player.unit()); + unit.rotation(player.unit().rotation); + //unit.impulse(0f, -3f); + //TODO should there be an impulse? + unit.controller(player); + unit.spawnedByCore(true); + unit.add(); + } + + return; + } + + } + //should only get to this code if docking failed or this isn't a docking unit + //problem: this gets called on both ends. it shouldn't be. Fx.spawn.at(player); player.clearUnit(); diff --git a/core/src/mindustry/maps/planet/ErekirPlanetGenerator.java b/core/src/mindustry/maps/planet/ErekirPlanetGenerator.java index e56f2bb053..0a0ab6996a 100644 --- a/core/src/mindustry/maps/planet/ErekirPlanetGenerator.java +++ b/core/src/mindustry/maps/planet/ErekirPlanetGenerator.java @@ -357,7 +357,7 @@ public class ErekirPlanetGenerator extends PlanetGenerator{ while(ventCount < minVents && iterations++ < maxIterations){ outer: for(Tile tile : tiles){ - if(rand.chance(0.00018 * (1 + iterations))){ + if(rand.chance(0.00018 * (1 + iterations)) && !Mathf.within(tile.x, tile.y, spawnX, spawnY, 5f)){ //skip crystals, but only when directly on them if(tile.floor() == Blocks.crystallineStone || tile.floor() == Blocks.crystalFloor){ continue;