diff --git a/core/assets-raw/sprites/blocks/mechs/alpha-mech-pad.png b/core/assets-raw/sprites/blocks/mechs/alpha-mech-pad.png new file mode 100644 index 0000000000..a092abfeb0 Binary files /dev/null and b/core/assets-raw/sprites/blocks/mechs/alpha-mech-pad.png differ diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 2457ea7ec7..de2cba297b 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -582,6 +582,7 @@ block.pneumatic-drill.name=Pneumatic Drill block.laser-drill.name=Laser Drill block.water-extractor.name=Water Extractor block.cultivator.name=Cultivator +block.alpha-mech-pad.name=Alpha Mech Pad block.dart-ship-pad.name=Dart Ship Pad block.delta-mech-pad.name=Delta Mech Pad block.javelin-ship-pad.name=Javelin Ship Pad diff --git a/core/src/io/anuke/mindustry/content/Recipes.java b/core/src/io/anuke/mindustry/content/Recipes.java index 3a4f25fbfc..29ffe73513 100644 --- a/core/src/io/anuke/mindustry/content/Recipes.java +++ b/core/src/io/anuke/mindustry/content/Recipes.java @@ -6,6 +6,7 @@ import io.anuke.mindustry.game.GameMode; import io.anuke.mindustry.type.ContentType; import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.type.Recipe; +import io.anuke.mindustry.type.Recipe.RecipeVisibility; import static io.anuke.mindustry.type.Category.*; @@ -152,14 +153,15 @@ public class Recipes implements ContentList{ //UNITS //bodies - new Recipe(units, UpgradeBlocks.dartPad, new ItemStack(Items.lead, 150), new ItemStack(Items.copper, 150), new ItemStack(Items.silicon, 200), new ItemStack(Items.titanium, 240)).setDesktop(); //dart is desktop only, because it's the starter mobile ship + new Recipe(units, UpgradeBlocks.dartPad, new ItemStack(Items.lead, 150), new ItemStack(Items.copper, 150), new ItemStack(Items.silicon, 200), new ItemStack(Items.titanium, 240)).setVisible(RecipeVisibility.desktopOnly); new Recipe(units, UpgradeBlocks.tridentPad, new ItemStack(Items.lead, 250), new ItemStack(Items.copper, 250), new ItemStack(Items.silicon, 250), new ItemStack(Items.titanium, 300), new ItemStack(Items.plastanium, 200)); new Recipe(units, UpgradeBlocks.javelinPad, new ItemStack(Items.lead, 350), new ItemStack(Items.silicon, 450), new ItemStack(Items.titanium, 500), new ItemStack(Items.plastanium, 400), new ItemStack(Items.phasematter, 200)); new Recipe(units, UpgradeBlocks.glaivePad, new ItemStack(Items.lead, 450), new ItemStack(Items.silicon, 650), new ItemStack(Items.titanium, 700), new ItemStack(Items.plastanium, 600), new ItemStack(Items.surgealloy, 200)); - new Recipe(units, UpgradeBlocks.tauPad, new ItemStack(Items.lead, 250), new ItemStack(Items.densealloy, 250), new ItemStack(Items.copper, 250), new ItemStack(Items.silicon, 250)).setDesktop(); - new Recipe(units, UpgradeBlocks.deltaPad, new ItemStack(Items.lead, 350), new ItemStack(Items.densealloy, 350), new ItemStack(Items.copper, 400), new ItemStack(Items.silicon, 450), new ItemStack(Items.thorium, 300)).setDesktop(); - new Recipe(units, UpgradeBlocks.omegaPad, new ItemStack(Items.lead, 450), new ItemStack(Items.densealloy, 550), new ItemStack(Items.silicon, 650), new ItemStack(Items.thorium, 600), new ItemStack(Items.surgealloy, 240)).setDesktop(); + new Recipe(units, UpgradeBlocks.alphaPad, new ItemStack(Items.lead, 200), new ItemStack(Items.densealloy, 100), new ItemStack(Items.copper, 150)).setVisible(RecipeVisibility.mobileOnly); + new Recipe(units, UpgradeBlocks.tauPad, new ItemStack(Items.lead, 250), new ItemStack(Items.densealloy, 250), new ItemStack(Items.copper, 250), new ItemStack(Items.silicon, 250)); + new Recipe(units, UpgradeBlocks.deltaPad, new ItemStack(Items.lead, 350), new ItemStack(Items.densealloy, 350), new ItemStack(Items.copper, 400), new ItemStack(Items.silicon, 450), new ItemStack(Items.thorium, 300)); + new Recipe(units, UpgradeBlocks.omegaPad, new ItemStack(Items.lead, 450), new ItemStack(Items.densealloy, 550), new ItemStack(Items.silicon, 650), new ItemStack(Items.thorium, 600), new ItemStack(Items.surgealloy, 240)); //actual unit related stuff new Recipe(units, UnitBlocks.spiritFactory, new ItemStack(Items.copper, 70), new ItemStack(Items.lead, 110), new ItemStack(Items.silicon, 130)); diff --git a/core/src/io/anuke/mindustry/content/blocks/UpgradeBlocks.java b/core/src/io/anuke/mindustry/content/blocks/UpgradeBlocks.java index 843b6d2250..5e991fd9e7 100644 --- a/core/src/io/anuke/mindustry/content/blocks/UpgradeBlocks.java +++ b/core/src/io/anuke/mindustry/content/blocks/UpgradeBlocks.java @@ -5,10 +5,16 @@ import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.blocks.units.MechPad; public class UpgradeBlocks extends BlockList{ - public static Block deltaPad, tauPad, omegaPad, dartPad, javelinPad, tridentPad, glaivePad; + public static Block alphaPad, deltaPad, tauPad, omegaPad, dartPad, javelinPad, tridentPad, glaivePad; @Override public void load(){ + alphaPad = new MechPad("alpha-mech-pad"){{ + mech = Mechs.alpha; + size = 2; + powerCapacity = 50f; + }}; + deltaPad = new MechPad("delta-mech-pad"){{ mech = Mechs.delta; size = 2; diff --git a/core/src/io/anuke/mindustry/editor/MapEditorDialog.java b/core/src/io/anuke/mindustry/editor/MapEditorDialog.java index 418e524061..6beed7a5f1 100644 --- a/core/src/io/anuke/mindustry/editor/MapEditorDialog.java +++ b/core/src/io/anuke/mindustry/editor/MapEditorDialog.java @@ -573,7 +573,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ continue; } - if(Recipe.getByResult(block) != null && Recipe.getByResult(block).desktopOnly && mobile){ + if(Recipe.getByResult(block) != null && !Recipe.getByResult(block).visibility.shown()){ continue; } diff --git a/core/src/io/anuke/mindustry/entities/Player.java b/core/src/io/anuke/mindustry/entities/Player.java index 6ac08f0424..593148c4f3 100644 --- a/core/src/io/anuke/mindustry/entities/Player.java +++ b/core/src/io/anuke/mindustry/entities/Player.java @@ -29,6 +29,7 @@ import io.anuke.mindustry.world.blocks.Floor; import io.anuke.mindustry.world.blocks.storage.CoreBlock.CoreEntity; import io.anuke.ucore.core.*; import io.anuke.ucore.entities.EntityGroup; +import io.anuke.ucore.entities.EntityQuery; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Hue; import io.anuke.ucore.graphics.Lines; @@ -47,6 +48,8 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra private static final int timerShootRight = 1; private static final float liftoffBoost = 0.2f; + private static final Rectangle rect = new Rectangle(); + //region instance variables public float baseRotation; @@ -474,6 +477,21 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra shootHeat = Mathf.lerpDelta(shootHeat, isShooting() ? 1f : 0f, 0.06f); mech.updateAlt(this); //updated regardless + if(boostHeat > liftoffBoost + 0.1f){ + achievedFlight = true; + } + + if(boostHeat <= liftoffBoost + 0.05f && achievedFlight){ + if(tile != null){ + if(mech.shake > 1f){ + Effects.shake(mech.shake, mech.shake, this); + } + Effects.effect(UnitFx.unitLand, tile.floor().minimapColor, x, y, tile.floor().isLiquid ? 1f : 0.5f); + } + mech.onLand(this); + achievedFlight = false; + } + if(!isLocal){ interpolate(); updateBuilding(this); //building happens even with non-locals @@ -509,21 +527,6 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra protected void updateMech(){ Tile tile = world.tileWorld(x, y); - if(boostHeat > liftoffBoost + 0.1f){ - achievedFlight = true; - } - - if(boostHeat <= liftoffBoost + 0.05f && achievedFlight){ - if(tile != null){ - if(mech.shake > 1f){ - Effects.shake(mech.shake, mech.shake, this); - } - Effects.effect(UnitFx.unitLand, tile.floor().minimapColor, x, y, tile.floor().isLiquid ? 1f : 0.5f); - } - mech.onLand(this); - achievedFlight = false; - } - isBoosting = Inputs.keyDown("dash") && !mech.flying; //if player is in solid block @@ -531,7 +534,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra isBoosting = true; } - float speed = isBoosting && !mech.flying ? mech.boostSpeed : mech.speed; + float speed = isBoosting ? mech.boostSpeed : mech.speed; //fraction of speed when at max load float carrySlowdown = 0.7f; @@ -583,7 +586,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra } float prex = x, prey = y; updateVelocityStatus(); - moved = distanceTo(prex, prey) > 0.01f; + moved = distanceTo(prex, prey) > 0.001f; }else{ velocity.setZero(); x = Mathf.lerpDelta(x, getCarrier().getX(), 0.1f); @@ -641,26 +644,46 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra moveTarget = null; } - movement.set(targetX - x, targetY - y).limit(mech.speed); + if(getCarrier() != null){ + velocity.setZero(); + x = Mathf.lerpDelta(x, getCarrier().getX(), 0.1f); + y = Mathf.lerpDelta(y, getCarrier().getY(), 0.1f); + } + + movement.set(targetX - x, targetY - y).limit(isBoosting && !mech.flying ? mech.boostSpeed : mech.speed); movement.setAngle(Mathf.slerp(movement.angle(), velocity.angle(), 0.05f)); if(distanceTo(targetX, targetY) < attractDst){ movement.setZero(); } + float expansion = 3f; + + getHitbox(rect); + rect.x -= expansion; + rect.y -= expansion; + rect.width += expansion*2f; + rect.height += expansion*2f; + + isBoosting = EntityQuery.collisions().overlapsTile(rect) || distanceTo(targetX, targetY) > 85f; + velocity.add(movement.scl(Timers.delta())); - if(velocity.len() <= 0.2f){ + if(velocity.len() <= 0.2f && mech.flying){ rotation += Mathf.sin(Timers.time() + id * 99, 10f, 1f); }else if(target == null){ rotation = Mathf.slerpDelta(rotation, velocity.angle(), velocity.len() / 10f); } + float lx = x, ly = y; updateVelocityStatus(); + moved = distanceTo(lx, ly) > 0.001f && !isCarried(); - //hovering effect - x += Mathf.sin(Timers.time() + id * 999, 25f, 0.08f); - y += Mathf.cos(Timers.time() + id * 999, 25f, 0.08f); + if(mech.flying){ + //hovering effect + x += Mathf.sin(Timers.time() + id * 999, 25f, 0.08f); + y += Mathf.cos(Timers.time() + id * 999, 25f, 0.08f); + } //update shooting if not building, not mining and there's ammo left if(!isBuilding() && getMineTile() == null){ diff --git a/core/src/io/anuke/mindustry/type/Recipe.java b/core/src/io/anuke/mindustry/type/Recipe.java index 627767b284..7332868129 100644 --- a/core/src/io/anuke/mindustry/type/Recipe.java +++ b/core/src/io/anuke/mindustry/type/Recipe.java @@ -4,6 +4,7 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.ObjectMap; import com.badlogic.gdx.utils.OrderedMap; +import io.anuke.mindustry.Vars; import io.anuke.mindustry.game.GameMode; import io.anuke.mindustry.game.UnlockableContent; import io.anuke.mindustry.ui.ContentDisplay; @@ -28,7 +29,7 @@ public class Recipe extends UnlockableContent{ public final Category category; public final float cost; - public boolean desktopOnly = false; + public RecipeVisibility visibility = RecipeVisibility.all; //the only gamemode in which the recipe shows up public GameMode mode; public boolean isPad; @@ -67,7 +68,7 @@ public class Recipe extends UnlockableContent{ arr.clear(); for(Recipe r : content.recipes()){ if(r.category == category && (control.unlocks.isUnlocked(r)) && - !((r.mode != null && r.mode != state.mode) || (r.desktopOnly && mobile) || (r.isPad && !state.mode.showPads))){ + !((r.mode != null && r.mode != state.mode) || !r.visibility.shown() || (r.isPad && !state.mode.showPads))){ arr.add(r); } } @@ -94,8 +95,8 @@ public class Recipe extends UnlockableContent{ return this; } - public Recipe setDesktop(){ - desktopOnly = true; + public Recipe setVisible(RecipeVisibility visibility){ + this.visibility = visibility; return this; } @@ -122,7 +123,7 @@ public class Recipe extends UnlockableContent{ @Override public boolean isHidden(){ - return (desktopOnly && mobile) || hidden; + return !visibility.shown() || hidden; } @Override @@ -196,4 +197,21 @@ public class Recipe extends UnlockableContent{ this.blockDependencies = dependencies; return this; } + + public enum RecipeVisibility{ + mobileOnly(true, false), + desktopOnly(false, true), + all(true, true); + + public final boolean mobile, desktop; + + RecipeVisibility(boolean mobile, boolean desktop){ + this.mobile = mobile; + this.desktop = desktop; + } + + public boolean shown(){ + return (Vars.mobile && mobile) || (!Vars.mobile && desktop); + } + } } diff --git a/core/src/io/anuke/mindustry/ui/fragments/BlocksFragment.java b/core/src/io/anuke/mindustry/ui/fragments/BlocksFragment.java index 0fcddb8189..23632e57b2 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/BlocksFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/BlocksFragment.java @@ -173,7 +173,7 @@ public class BlocksFragment extends Fragment{ //add actual recipes for(Recipe r : recipes){ - if((r.mode != null && r.mode != state.mode) || (r.desktopOnly && mobile) || (r.isPad && !state.mode.showPads)) continue; + if((r.mode != null && r.mode != state.mode) || !r.visibility.shown() || (r.isPad && !state.mode.showPads)) continue; ImageButton image = new ImageButton(new TextureRegion(), "select"); diff --git a/core/src/io/anuke/mindustry/world/blocks/units/MechPad.java b/core/src/io/anuke/mindustry/world/blocks/units/MechPad.java index b0b6d1309b..ab05631341 100644 --- a/core/src/io/anuke/mindustry/world/blocks/units/MechPad.java +++ b/core/src/io/anuke/mindustry/world/blocks/units/MechPad.java @@ -123,7 +123,6 @@ public class MechPad extends Block{ @Override public void tapped(Tile tile, Player player){ - if(mobile && !mech.flying) return; if(checkValidTap(tile, player)){ Call.onMechFactoryTap(player, tile);