From 15d43d5ab15d31a1770f09d53bdc257676b8c974 Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 9 Aug 2023 22:10:02 +0100 Subject: [PATCH] The rainboom ability now requires you to perform tricks (diving and dashing) to charge it. #107 - 10 dashes or dives = 1 rainboom, but you can charge up multiple at a time by doing more. - Flying whilst exhausted now deals damage but players who push through it are rewarded with another level - Gusts of wind are now reduced by levelling up --- .../ability/PegasusRainboomAbility.java | 18 ++++-- .../unicopia/advancement/UCriteria.java | 1 + .../unicopia/client/gui/ManaRingSlot.java | 1 + .../unicopia/client/minelittlepony/Main.java | 1 + .../client/render/WorldRenderDelegate.java | 8 ++- .../unicopia/entity/player/MagicReserves.java | 5 ++ .../unicopia/entity/player/ManaContainer.java | 61 ++++++++++++------- .../unicopia/entity/player/Motion.java | 2 + .../unicopia/entity/player/PlayerPhysics.java | 41 ++++++++++++- .../unicopia/entity/player/Pony.java | 15 +++++ .../resources/assets/unicopia/lang/en_us.json | 7 +-- .../unicopia/pegasus/second_wind.json | 29 +++++++++ 12 files changed, 154 insertions(+), 35 deletions(-) create mode 100644 src/main/resources/data/unicopia/advancements/unicopia/pegasus/second_wind.json diff --git a/src/main/java/com/minelittlepony/unicopia/ability/PegasusRainboomAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/PegasusRainboomAbility.java index 36557587..4acf9f9f 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/PegasusRainboomAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/PegasusRainboomAbility.java @@ -12,6 +12,7 @@ import com.minelittlepony.unicopia.particle.OrientedBillboardParticleEffect; import com.minelittlepony.unicopia.particle.UParticles; import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; /** * Pegasus ability to perform rainbooms @@ -28,6 +29,11 @@ public class PegasusRainboomAbility implements Ability { return 60; } + @Override + public boolean canActivate(World w, Pony player) { + return player.canUseSuperMove(); + } + @Override public boolean canUse(Race race) { return race.canInteractWithClouds(); @@ -37,7 +43,7 @@ public class PegasusRainboomAbility implements Ability { @Override public Hit tryActivate(Pony player) { - if (!player.asEntity().isCreative() && player.getMagicalReserves().getMana().getPercentFill() < 0.2F) { + if (!player.asEntity().isCreative() && !player.canUseSuperMove()) { return null; } @@ -55,7 +61,7 @@ public class PegasusRainboomAbility implements Ability { @Override public double getCostEstimate(Pony player) { - return 90F; + return 0; } @Override @@ -64,6 +70,7 @@ public class PegasusRainboomAbility implements Ability { if (type == ActivationType.TAP && player.getPhysics().isFlying() && player.getMagicalReserves().getMana().get() > 40) { player.getPhysics().dashForward((float)player.asWorld().random.nextTriangular(2.5F, 0.3F)); player.subtractEnergyCost(4); + player.getMagicalReserves().getCharge().add(2); return true; } @@ -77,9 +84,10 @@ public class PegasusRainboomAbility implements Ability { return; } - player.subtractEnergyCost(9); - player.addParticle(new OrientedBillboardParticleEffect(UParticles.RAINBOOM_RING, player.getPhysics().getMotionAngle()), player.getOriginVector(), Vec3d.ZERO); - SpellType.RAINBOOM.withTraits().apply(player, CastingMethod.INNATE); + if (player.consumeSuperMove()) { + player.addParticle(new OrientedBillboardParticleEffect(UParticles.RAINBOOM_RING, player.getPhysics().getMotionAngle()), player.getOriginVector(), Vec3d.ZERO); + SpellType.RAINBOOM.withTraits().apply(player, CastingMethod.INNATE); + } } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/advancement/UCriteria.java b/src/main/java/com/minelittlepony/unicopia/advancement/UCriteria.java index 63758285..8243d39f 100644 --- a/src/main/java/com/minelittlepony/unicopia/advancement/UCriteria.java +++ b/src/main/java/com/minelittlepony/unicopia/advancement/UCriteria.java @@ -21,6 +21,7 @@ public interface UCriteria { CustomEventCriterion.Trigger KILL_PHANTOM_WHILE_FLYING = CUSTOM_EVENT.createTrigger("kill_phantom_while_flying"); CustomEventCriterion.Trigger USE_CONSUMPTION = CUSTOM_EVENT.createTrigger("use_consumption"); CustomEventCriterion.Trigger USE_SOULMATE = CUSTOM_EVENT.createTrigger("use_soulmate"); + CustomEventCriterion.Trigger SECOND_WIND = CUSTOM_EVENT.createTrigger("second_wind"); static void bootstrap() { } } diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/ManaRingSlot.java b/src/main/java/com/minelittlepony/unicopia/client/gui/ManaRingSlot.java index 2412bb63..afa49488 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/ManaRingSlot.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/ManaRingSlot.java @@ -33,6 +33,7 @@ class ManaRingSlot extends Slot { if (!uHud.client.player.isCreative()) { renderRing(matrices, 13, 9, 0, mana.getXp(), 0x88880099, tickDelta); + renderRing(matrices, 9, 0, 0, mana.getCharge(), 0x0000FF99, tickDelta); double cost = abilities.getStats().stream() .mapToDouble(s -> s.getCost(Unicopia.getConfig().hudPage.get())) diff --git a/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/Main.java b/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/Main.java index a067d83f..62d63018 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/Main.java +++ b/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/Main.java @@ -47,6 +47,7 @@ public class Main extends MineLPDelegate implements ClientModInitializer { Vec3d motion = entity.getVelocity(); double zMotion = Math.sqrt(motion.x * motion.x + motion.z * motion.z); model.getAttributes().isGoingFast |= zMotion > 0.4F; + model.getAttributes().isGoingFast |= pony.getMotion().isDiving(); } model.getAttributes().isGoingFast |= pony.getMotion().isRainbooming(); model.getAttributes().isGoingFast &= !pony.getEntityInArms().isPresent(); diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/WorldRenderDelegate.java b/src/main/java/com/minelittlepony/unicopia/client/render/WorldRenderDelegate.java index 87c2b070..3d82d336 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/WorldRenderDelegate.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/WorldRenderDelegate.java @@ -127,14 +127,18 @@ public class WorldRenderDelegate { matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(roll)); matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(roll)); - if (pony instanceof Pony) { - roll = ((Pony)pony).getCamera().calculateRoll(); + if (pony instanceof Pony p) { + roll = p.getCamera().calculateRoll(); if (negative) { roll -= 180; } matrices.multiply(RotationAxis.NEGATIVE_Y.rotationDegrees(yaw)); matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(roll)); + + float diveAngle = p.getInterpolator().interpolate("g_kdive", p.getMotion().isDiving() ? 80 : 0, 15); + + matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(diveAngle)); matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(yaw)); } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/MagicReserves.java b/src/main/java/com/minelittlepony/unicopia/entity/player/MagicReserves.java index a21cf4cf..47a70a16 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/MagicReserves.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/MagicReserves.java @@ -31,6 +31,11 @@ public interface MagicReserves { */ Bar getXp(); + /** + * Temporary mana charge collected by performing certain tasks. + */ + Bar getCharge(); + public interface Bar { /** diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/ManaContainer.java b/src/main/java/com/minelittlepony/unicopia/entity/player/ManaContainer.java index c753514f..1ad7441f 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/ManaContainer.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/ManaContainer.java @@ -1,5 +1,8 @@ package com.minelittlepony.unicopia.entity.player; +import java.util.HashMap; +import java.util.Map; + import com.minelittlepony.unicopia.util.NbtSerialisable; import com.minelittlepony.unicopia.util.Tickable; @@ -10,37 +13,43 @@ import net.minecraft.util.math.MathHelper; public class ManaContainer implements MagicReserves, Tickable, NbtSerialisable { private final Pony pony; + private final Map bars = new HashMap<>(); + private final BarInst energy; private final BarInst exhaustion; private final BarInst exertion; private final BarInst mana; private final BarInst xp; + private final BarInst charge; public ManaContainer(Pony pony) { this.pony = pony; - this.energy = new BarInst(Pony.ENERGY, 100F, 0); - this.exhaustion = new BarInst(Pony.EXHAUSTION, 100F, 0); - this.exertion = new BarInst(Pony.EXERTION, 10F, 0); - this.xp = new BarInst(Pony.XP, 1, 0); - this.mana = new XpCollectingBar(Pony.MANA, 100F, 100F); + this.energy = addBar("energy", new BarInst(Pony.ENERGY, 100F, 0)); + this.exhaustion = addBar("exhaustion", new BarInst(Pony.EXHAUSTION, 100F, 0)); + this.exertion = addBar("exertion", new BarInst(Pony.EXERTION, 10F, 0)); + this.xp = addBar("xp", new BarInst(Pony.XP, 1, 0)); + this.mana = addBar("mana", new XpCollectingBar(Pony.MANA, 100F, 100F)); + this.charge = addBar("charge", new BarInst(Pony.CHARGE, 10F, 0) { + @Override + protected float applyLimits(float value) { + return Math.max(0, value); + } + }); + } + + protected BarInst addBar(String name, BarInst bar) { + bars.put(name, bar); + return bar; } @Override public void toNBT(NbtCompound compound) { - compound.put("energy", energy.toNBT()); - compound.put("exhaustion", exhaustion.toNBT()); - compound.put("exertion", exertion.toNBT()); - compound.put("mana", mana.toNBT()); - compound.put("xp", xp.toNBT()); + bars.forEach((key, bar) -> compound.put(key, bar.toNBT())); } @Override public void fromNBT(NbtCompound compound) { - energy.fromNBT(compound.getCompound("energy")); - exhaustion.fromNBT(compound.getCompound("exhaustion")); - exertion.fromNBT(compound.getCompound("exertion")); - mana.fromNBT(compound.getCompound("mana")); - xp.fromNBT(compound.getCompound("xp")); + bars.forEach((key, bar) -> bar.fromNBT(compound.getCompound(key))); } @Override @@ -68,12 +77,14 @@ public class ManaContainer implements MagicReserves, Tickable, NbtSerialisable { return xp; } + @Override + public Bar getCharge() { + return charge; + } + @Override public void tick() { - exertion.tick(); - energy.tick(); - mana.tick(); - xp.tick(); + bars.values().forEach(BarInst::tick); exertion.add(-10); @@ -142,7 +153,7 @@ public class ManaContainer implements MagicReserves, Tickable, NbtSerialisable { @Override public float get() { - return pony.asEntity().getDataTracker().get(marker); + return applyLimits(pony.asEntity().getDataTracker().get(marker)); } @Override @@ -152,11 +163,17 @@ public class ManaContainer implements MagicReserves, Tickable, NbtSerialisable { @Override public void set(float value) { - load(MathHelper.clamp(value, 0, getMax())); + load(applyLimits(value)); } private void load(float value) { - pony.asEntity().getDataTracker().set(marker, value); + if (!pony.isClient()) { + pony.asEntity().getDataTracker().set(marker, value); + } + } + + protected float applyLimits(float value) { + return MathHelper.clamp(value, 0, getMax()); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/Motion.java b/src/main/java/com/minelittlepony/unicopia/entity/player/Motion.java index 47049288..a0a400c8 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/Motion.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/Motion.java @@ -11,6 +11,8 @@ public interface Motion { boolean isGliding(); + boolean isDiving(); + boolean isRainbooming(); float getWingAngle(); diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java index 42d5c517..3e7dd386 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java @@ -3,6 +3,7 @@ package com.minelittlepony.unicopia.entity.player; import java.util.function.Supplier; import com.minelittlepony.unicopia.*; +import com.minelittlepony.unicopia.ability.Abilities; import com.minelittlepony.unicopia.ability.magic.SpellPredicate; import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; import com.minelittlepony.unicopia.advancement.UCriteria; @@ -53,6 +54,7 @@ public class PlayerPhysics extends EntityPhysics implements Tickab private int ticksInAir; private int ticksToGlide; + private int ticksDiving; private float thrustScale = 0; @@ -118,6 +120,11 @@ public class PlayerPhysics extends EntityPhysics implements Tickab return ticksToGlide <= 0 && isFlying() && !entity.isSneaking(); } + @Override + public boolean isDiving() { + return ticksDiving > 0; + } + @Override public boolean isRainbooming() { return pony.getSpellSlot().get(SpellType.RAINBOOM, true).isPresent(); @@ -313,6 +320,19 @@ public class PlayerPhysics extends EntityPhysics implements Tickab velocity.y -= 0.2F * getGravitySignum(); velocity.y /= 2F; } + + double horizontalSpeed = this.getHorizontalMotion(); + double verticalSpeed = velocity.y; + + if (Abilities.RAINBOOM.canUse(pony.getActualSpecies()) && horizontalSpeed != 0 && verticalSpeed < -0.3F && (verticalSpeed / horizontalSpeed) < -0.3F) { + ticksDiving++; + } else { + ticksDiving = 0; + } + + if (ticksDiving > 0 && ticksDiving % 25 == 0) { + pony.getMagicalReserves().getCharge().add(25); + } } else { prevStrafe = 0; strafe = 0; @@ -321,6 +341,10 @@ public class PlayerPhysics extends EntityPhysics implements Tickab soundPlaying = false; descentRate = 0; + if (Abilities.RAINBOOM.canUse(pony.getActualSpecies()) && entity.isOnGround()) { + pony.getMagicalReserves().getCharge().set(0); + } + if (!creative && type.isAvian()) { checkAvianTakeoffConditions(velocity); } @@ -461,6 +485,19 @@ public class PlayerPhysics extends EntityPhysics implements Tickab entity.addExhaustion(exhaustion); } + + if (pony.getMagicalReserves().getExhaustion().get() > 99 && ticksInAir % 25 == 0) { + entity.damage(pony.damageOf(UDamageTypes.EXHAUSTION), 2); + + if (entity.getWorld().random.nextInt(110) == 1 && !pony.isClient()) { + pony.getLevel().add(1); + pony.getMagicalReserves().getCharge().add(4); + pony.getMagicalReserves().getExertion().set(0); + pony.getMagicalReserves().getExhaustion().set(0); + mana.set(mana.getMax() * 100); + UCriteria.SECOND_WIND.trigger(entity); + } + } } } } @@ -624,7 +661,9 @@ public class PlayerPhysics extends EntityPhysics implements Tickab private void applyTurbulance(MutableVector velocity) { int globalEffectStrength = MathHelper.clamp(entity.getWorld().getGameRules().getInt(UGameRules.WEATHER_EFFECTS_STRENGTH), 0, 100); float effectStrength = Math.min(1, (float)ticksInAir / MAX_TICKS_TO_WEATHER_EFFECTS) * (globalEffectStrength / 100F); - Vec3d gust = WeatherConditions.getGustStrength(entity.getWorld(), entity.getBlockPos()).multiply(globalEffectStrength / 100D); + Vec3d gust = WeatherConditions.getGustStrength(entity.getWorld(), entity.getBlockPos()) + .multiply(globalEffectStrength / 100D) + .multiply(1 / (1 + Math.floor(pony.getLevel().get() / 10F))); if (effectStrength * gust.getX() >= 1) { SoundEmitter.playSoundAt(entity, USounds.AMBIENT_WIND_GUST, SoundCategory.AMBIENT, 3, 1); diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java index 53e9e918..d82773fb 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java @@ -21,6 +21,7 @@ import com.minelittlepony.unicopia.entity.behaviour.EntityAppearance; import com.minelittlepony.unicopia.entity.duck.LivingEntityDuck; import com.minelittlepony.unicopia.entity.effect.SunBlindnessStatusEffect; import com.minelittlepony.unicopia.entity.effect.UEffects; +import com.minelittlepony.unicopia.entity.player.MagicReserves.Bar; import com.minelittlepony.unicopia.item.FriendshipBraceletItem; import com.minelittlepony.unicopia.item.UItems; import com.minelittlepony.unicopia.item.enchantment.UEnchantments; @@ -71,6 +72,7 @@ public class Pony extends Living implements Copyable, Update static final TrackedData> HANGING_POSITION = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.OPTIONAL_BLOCK_POS); static final TrackedData MANA = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.FLOAT); static final TrackedData XP = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.FLOAT); + static final TrackedData CHARGE = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.FLOAT); static final TrackedData LEVEL = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.INTEGER); static final TrackedData CORRUPTION = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.INTEGER); @@ -266,6 +268,19 @@ public class Pony extends Living implements Copyable, Update return corruption; } + public boolean canUseSuperMove() { + return getMagicalReserves().getCharge().get() >= getMagicalReserves().getCharge().get(); + } + + public boolean consumeSuperMove() { + if (canUseSuperMove()) { + Bar charge = getMagicalReserves().getCharge(); + charge.set(charge.get() - charge.getMax()); + return true; + } + return false; + } + public boolean isSunImmune() { return ticksSunImmunity > 0; } diff --git a/src/main/resources/assets/unicopia/lang/en_us.json b/src/main/resources/assets/unicopia/lang/en_us.json index a00ad1c5..e0767889 100644 --- a/src/main/resources/assets/unicopia/lang/en_us.json +++ b/src/main/resources/assets/unicopia/lang/en_us.json @@ -805,19 +805,16 @@ "advancements.unicopia.sky_route.title": "Path of the Pegasus", "advancements.unicopia.sky_route.description": "Join the Clousdale Pegasi", - "advancements.unicopia.molting_season_1.title": "Molting Season", "advancements.unicopia.molting_season_1.description": "Drop a feather whilst flying", - "advancements.unicopia.molting_season_2.title": "Molting Season 2", "advancements.unicopia.molting_season_2.description": "Drop 5 feathers whilst flying", - "advancements.unicopia.molting_season_3.title": "Molting Season 3", "advancements.unicopia.molting_season_3.description": "Drop 15 feathers whilst flying", - "advancements.unicopia.rainbow_crash.title": "Dammit, Rainbow", "advancements.unicopia.rainbow_crash.description": "Wage war on the evil glass window nation", - + "advancements.unicopia.second_wind.title": "Second Wind", + "advancements.unicopia.second_wind.description": "Fly through the pain", "advancements.unicopia.deter_phantom.title": "What Flies Around", "advancements.unicopia.deter_phantom.description": "Get up there and give those phantoms a taste of their own medicine", diff --git a/src/main/resources/data/unicopia/advancements/unicopia/pegasus/second_wind.json b/src/main/resources/data/unicopia/advancements/unicopia/pegasus/second_wind.json new file mode 100644 index 00000000..86417cee --- /dev/null +++ b/src/main/resources/data/unicopia/advancements/unicopia/pegasus/second_wind.json @@ -0,0 +1,29 @@ +{ + "parent": "unicopia:unicopia/pegasus/sky_route", + "display": { + "icon": { + "item": "unicopia:pegasus_badge" + }, + "title": { + "translate": "advancements.unicopia.second_wind.title" + }, + "description": { + "translate": "advancements.unicopia.second_wind.description" + }, + "frame": "task", + "show_toast": true, + "announce_to_chat": true, + "hidden": false + }, + "criteria": { + "fly_through_the_pain": { + "trigger": "unicopia:custom", + "conditions": { + "event": "second_wind" + } + } + }, + "requirements": [ + [ "fly_through_the_pain" ] + ] +}