mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-02-01 03:26:44 +01:00
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
This commit is contained in:
parent
67e51b1f22
commit
15d43d5ab1
12 changed files with 154 additions and 35 deletions
|
@ -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<Hit> {
|
|||
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<Hit> {
|
|||
@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<Hit> {
|
|||
|
||||
@Override
|
||||
public double getCostEstimate(Pony player) {
|
||||
return 90F;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -64,6 +70,7 @@ public class PegasusRainboomAbility implements Ability<Hit> {
|
|||
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,10 +84,11 @@ public class PegasusRainboomAbility implements Ability<Hit> {
|
|||
return;
|
||||
}
|
||||
|
||||
player.subtractEnergyCost(9);
|
||||
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
|
||||
public void preApply(Pony player, AbilitySlot slot) {
|
||||
|
|
|
@ -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() { }
|
||||
}
|
||||
|
|
|
@ -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()))
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,11 @@ public interface MagicReserves {
|
|||
*/
|
||||
Bar getXp();
|
||||
|
||||
/**
|
||||
* Temporary mana charge collected by performing certain tasks.
|
||||
*/
|
||||
Bar getCharge();
|
||||
|
||||
public interface Bar {
|
||||
|
||||
/**
|
||||
|
|
|
@ -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<String, BarInst> 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,12 +163,18 @@ 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) {
|
||||
if (!pony.isClient()) {
|
||||
pony.asEntity().getDataTracker().set(marker, value);
|
||||
}
|
||||
}
|
||||
|
||||
protected float applyLimits(float value) {
|
||||
return MathHelper.clamp(value, 0, getMax());
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMax() {
|
||||
|
|
|
@ -11,6 +11,8 @@ public interface Motion {
|
|||
|
||||
boolean isGliding();
|
||||
|
||||
boolean isDiving();
|
||||
|
||||
boolean isRainbooming();
|
||||
|
||||
float getWingAngle();
|
||||
|
|
|
@ -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<PlayerEntity> implements Tickab
|
|||
|
||||
private int ticksInAir;
|
||||
private int ticksToGlide;
|
||||
private int ticksDiving;
|
||||
|
||||
private float thrustScale = 0;
|
||||
|
||||
|
@ -118,6 +120,11 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> 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<PlayerEntity> 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<PlayerEntity> 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<PlayerEntity> 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<PlayerEntity> 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);
|
||||
|
|
|
@ -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<PlayerEntity> implements Copyable<Pony>, Update
|
|||
static final TrackedData<Optional<BlockPos>> HANGING_POSITION = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.OPTIONAL_BLOCK_POS);
|
||||
static final TrackedData<Float> MANA = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.FLOAT);
|
||||
static final TrackedData<Float> XP = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.FLOAT);
|
||||
static final TrackedData<Float> CHARGE = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.FLOAT);
|
||||
static final TrackedData<Integer> LEVEL = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.INTEGER);
|
||||
static final TrackedData<Integer> CORRUPTION = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.INTEGER);
|
||||
|
||||
|
@ -266,6 +268,19 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, 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;
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
||||
|
|
|
@ -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" ]
|
||||
]
|
||||
}
|
Loading…
Reference in a new issue