diff --git a/src/main/java/com/minelittlepony/unicopia/ClientHooks.java b/src/main/java/com/minelittlepony/unicopia/ClientHooks.java index 4cc047be..f83782ba 100644 --- a/src/main/java/com/minelittlepony/unicopia/ClientHooks.java +++ b/src/main/java/com/minelittlepony/unicopia/ClientHooks.java @@ -56,14 +56,26 @@ class ClientHooks { } @SubscribeEvent - public static void onRenderHud(RenderGameOverlayEvent.Post event) { + public static void onRenderHud(RenderGameOverlayEvent.Pre event) { if (event.getType() != ElementType.ALL) { - return; - } + IPlayer player = UClient.instance().getIPlayer(); + if (player != null && Minecraft.getMinecraft().world != null) { + UHud.instance.repositionElements(player, event.getResolution(), event.getType(), true); + } + } + } + + @SubscribeEvent + public static void onRenderHud(RenderGameOverlayEvent.Post event) { IPlayer player = UClient.instance().getIPlayer(); + if (player != null && Minecraft.getMinecraft().world != null) { - UHud.instance.renderHud(player, event.getResolution()); + if (event.getType() == ElementType.ALL) { + UHud.instance.renderHud(player, event.getResolution()); + } else { + UHud.instance.repositionElements(player, event.getResolution(), event.getType(), false); + } } } diff --git a/src/main/java/com/minelittlepony/unicopia/hud/FlightExperienceBar.java b/src/main/java/com/minelittlepony/unicopia/hud/FlightExperienceBar.java index a309109b..a0976736 100644 --- a/src/main/java/com/minelittlepony/unicopia/hud/FlightExperienceBar.java +++ b/src/main/java/com/minelittlepony/unicopia/hud/FlightExperienceBar.java @@ -3,6 +3,7 @@ package com.minelittlepony.unicopia.hud; import com.minelittlepony.unicopia.player.IPlayer; import net.minecraft.client.gui.Gui; +import net.minecraft.client.renderer.GlStateManager; import net.minecraft.util.ResourceLocation; class FlightExperienceBar implements IHudElement { @@ -12,7 +13,7 @@ class FlightExperienceBar implements IHudElement { @Override public boolean shouldRender(IPlayer player) { return player.getPlayerSpecies().canFly() - && player.getGravity().isFlying(); + && !player.getOwner().capabilities.isCreativeMode; } @Override @@ -21,22 +22,33 @@ class FlightExperienceBar implements IHudElement { float length = context.player.getGravity().getFlightDuration(); context.mc.getTextureManager().bindTexture(TEXTURE); - int x = (context.width - 184) / 2; + int x = (context.width - 183) / 2; int y = context.height - 29; - int xpFill = (int)Math.floor(xp * 184); - int xpBuff = (int)Math.floor((184 - xpFill) * length); + int xpFill = (int)Math.floor(xp * 183); + int xpBuff = (int)Math.floor((183 - xpFill) * length); - Gui.drawModalRectWithCustomSizedTexture(x, y, 0, 0, 256, 5, 256, 256); - Gui.drawModalRectWithCustomSizedTexture(x, y, 0, 5, xpFill, 5, 256, 256); + int baseV = 0; + if (context.player.getGravity().isExperienceCritical()) { - Gui.drawModalRectWithCustomSizedTexture(x + xpFill, y, xpFill, 10, xpBuff, 5, 256, 256); + int tickCount = (int)(context.mc.getRenderPartialTicks() * 10); - // context.fonts.drawStringWithShadow("Flight experience: " + context.player.getFlightExperience(), 0, 0, 0xFFFFFF); + baseV += (tickCount % 3) * 10; + } + + Gui.drawModalRectWithCustomSizedTexture(x, y, 0, baseV, 256, 5, 256, 256); + Gui.drawModalRectWithCustomSizedTexture(x, y, 0, baseV + 5, xpFill, 5, 256, 256); + + Gui.drawModalRectWithCustomSizedTexture(x + xpFill, y, xpFill, baseV + 10, xpBuff, 5, 256, 256); } + @Override + public void repositionHud(UHud context) { + int offset = 6; + GlStateManager.translate(0, context.begin ? -offset : offset, 0); + } } diff --git a/src/main/java/com/minelittlepony/unicopia/hud/IHudElement.java b/src/main/java/com/minelittlepony/unicopia/hud/IHudElement.java index eb91feda..3db213da 100644 --- a/src/main/java/com/minelittlepony/unicopia/hud/IHudElement.java +++ b/src/main/java/com/minelittlepony/unicopia/hud/IHudElement.java @@ -3,6 +3,9 @@ package com.minelittlepony.unicopia.hud; import com.minelittlepony.unicopia.player.IPlayer; public interface IHudElement { + + void repositionHud(UHud context); + void renderHud(UHud context); boolean shouldRender(IPlayer player); diff --git a/src/main/java/com/minelittlepony/unicopia/hud/UHud.java b/src/main/java/com/minelittlepony/unicopia/hud/UHud.java index 384bf07a..8d0c3ff5 100644 --- a/src/main/java/com/minelittlepony/unicopia/hud/UHud.java +++ b/src/main/java/com/minelittlepony/unicopia/hud/UHud.java @@ -12,6 +12,7 @@ import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.renderer.GlStateManager; +import net.minecraftforge.client.event.RenderGameOverlayEvent.ElementType; public class UHud extends Gui { @@ -29,6 +30,8 @@ public class UHud extends Gui { int height; + boolean begin; + private UHud() { elements.add(new FlightExperienceBar()); } @@ -37,10 +40,44 @@ public class UHud extends Gui { this.width = resolution.getScaledWidth(); this.height = resolution.getScaledHeight(); this.player = player; + this.begin = true; elements.forEach(this::renderElement); } + public void repositionElements(IPlayer player, ScaledResolution resolution, ElementType type, boolean begin) { + this.width = resolution.getScaledWidth(); + this.height = resolution.getScaledHeight(); + this.player = player; + this.begin = begin; + + if (isSurvivalElement(type)) { + elements.forEach(this::positionElement); + } + } + + protected boolean isSurvivalElement(ElementType type) { + switch (type) { + case ARMOR: + case HEALTH: + case FOOD: + case AIR: + case EXPERIENCE: + case HEALTHMOUNT: + case JUMPBAR: + return true; + default: return false; + } + } + + private void positionElement(IHudElement element) { + if (!element.shouldRender(player)) { + return; + } + + element.repositionHud(this); + } + private void renderElement(IHudElement element) { if (!element.shouldRender(player)) { return; diff --git a/src/main/java/com/minelittlepony/unicopia/player/IGravity.java b/src/main/java/com/minelittlepony/unicopia/player/IGravity.java index 947585c7..05be5bd7 100644 --- a/src/main/java/com/minelittlepony/unicopia/player/IGravity.java +++ b/src/main/java/com/minelittlepony/unicopia/player/IGravity.java @@ -7,6 +7,8 @@ public interface IGravity { float getFlightDuration(); + boolean isExperienceCritical(); + void setGraviationConstant(float constant); float getGravitationConstant(); diff --git a/src/main/java/com/minelittlepony/unicopia/player/PlayerGravityDelegate.java b/src/main/java/com/minelittlepony/unicopia/player/PlayerGravityDelegate.java index 13b69f7b..bbd54268 100644 --- a/src/main/java/com/minelittlepony/unicopia/player/PlayerGravityDelegate.java +++ b/src/main/java/com/minelittlepony/unicopia/player/PlayerGravityDelegate.java @@ -1,6 +1,7 @@ package com.minelittlepony.unicopia.player; import com.minelittlepony.unicopia.Race; +import com.minelittlepony.unicopia.init.UParticles; import com.minelittlepony.unicopia.init.USounds; import com.minelittlepony.unicopia.mixin.MixinEntity; import com.minelittlepony.unicopia.spell.IMagicEffect; @@ -26,12 +27,13 @@ class PlayerGravityDelegate implements IUpdatable, IGravity, InbtSerialisable, I private final IPlayer player; - private static final float MAXIMUM_FLIGHT_EXPERIENCE = 500; + private static final float MAXIMUM_FLIGHT_EXPERIENCE = 1500; - public int ticksInAir = 0; + public int ticksNextLevel = 0; public float flightExperience = 0; public boolean isFlying = false; + public boolean isRainbooming = false; private float gravity = 0; @@ -109,6 +111,11 @@ class PlayerGravityDelegate implements IUpdatable, IGravity, InbtSerialisable, I return gravity; } + @Override + public boolean isExperienceCritical() { + return isRainbooming || flightExperience > MAXIMUM_FLIGHT_EXPERIENCE * 0.8; + } + @Override public void onUpdate() { EntityPlayer entity = player.getOwner(); @@ -158,37 +165,80 @@ class PlayerGravityDelegate implements IUpdatable, IGravity, InbtSerialisable, I if (!entity.capabilities.isCreativeMode && !entity.isElytraFlying()) { if (isFlying && !entity.isRiding()) { + if (!isRainbooming && entity.moveForward != 0 && flightExperience < MAXIMUM_FLIGHT_EXPERIENCE) { + flightExperience++; + } + entity.fallDistance = 0; if (player.getPlayerSpecies() != Race.CHANGELING && entity.world.rand.nextInt(100) == 0) { - float exhaustion = (0.3F * ticksInAir) / 70; + float exhaustion = (0.3F * ticksNextLevel) / 70; if (entity.isSprinting()) { exhaustion *= 3.11F; } - exhaustion *= (1 - flightExperience/MAXIMUM_FLIGHT_EXPERIENCE); + exhaustion *= (1 - flightExperience / MAXIMUM_FLIGHT_EXPERIENCE); entity.addExhaustion(exhaustion); } - if (ticksInAir++ >= MAXIMUM_FLIGHT_EXPERIENCE) { - ticksInAir = 0; - addFlightExperience(entity); + if (ticksNextLevel++ >= MAXIMUM_FLIGHT_EXPERIENCE) { + ticksNextLevel = 0; + + entity.addExperience(1); + addFlightExperience(entity, 1); entity.playSound(SoundEvents.ENTITY_GUARDIAN_FLOP, 1, 1); } moveFlying(entity); - if (ticksInAir > 0 && ticksInAir % 12 == 0) { + if (isExperienceCritical()) { + + if (player.getEnergy() <= 0.25F) { + player.addEnergy(2); + } + + if (isRainbooming || (entity.isSneaking() && isRainboom(player))) { + float forward = 0.5F * flightExperience / MAXIMUM_FLIGHT_EXPERIENCE; + + entity.motionX += - forward * MathHelper.sin(entity.rotationYaw * 0.017453292F); + entity.motionZ += forward * MathHelper.cos(entity.rotationYaw * 0.017453292F); + entity.motionY += 0.3; + + if (!isRainbooming || entity.world.rand.nextInt(5) == 0) { + entity.playSound(SoundEvents.ENTITY_LIGHTNING_THUNDER, 1, 1); + } + + player.spawnParticles(UParticles.UNICORN_MAGIC, 20); + + if (flightExperience > 0) { + flightExperience -= 13; + isRainbooming = true; + } else { + isRainbooming = false; + } + } + } + + if (ticksNextLevel > 0 && ticksNextLevel % 30 == 0) { entity.playSound(getWingSound(), 0.5F, 1); } } else { - if (ticksInAir != 0) { + if (ticksNextLevel != 0) { entity.playSound(getWingSound(), 0.4F, 1); } - ticksInAir = 0; - flightExperience *= 0.9991342; + ticksNextLevel = 0; + + if (isExperienceCritical()) { + addFlightExperience(entity, -0.39991342F); + } else { + addFlightExperience(entity, -0.019991342F); + } + + if (flightExperience < 0.02) { + isRainbooming = false; + } } } } @@ -199,7 +249,7 @@ class PlayerGravityDelegate implements IUpdatable, IGravity, InbtSerialisable, I protected void moveFlying(EntityPlayer player) { - float forward = 0.00015F * flightExperience * player.moveForward; + float forward = 0.000015F * flightExperience * player.moveForward; int factor = gravity < 0 ? -1 : 1; boolean sneak = !player.isSneaking(); @@ -288,10 +338,11 @@ class PlayerGravityDelegate implements IUpdatable, IGravity, InbtSerialisable, I return distance > 4 ? SoundEvents.ENTITY_PLAYER_BIG_FALL : SoundEvents.ENTITY_PLAYER_SMALL_FALL; } - private void addFlightExperience(EntityPlayer entity) { - entity.addExperience(1); + private void addFlightExperience(EntityPlayer entity, float factor) { + float maximumGain = MAXIMUM_FLIGHT_EXPERIENCE - flightExperience; + float gainSteps = 20; - flightExperience += (MAXIMUM_FLIGHT_EXPERIENCE - flightExperience) / 20; + flightExperience = Math.max(0, flightExperience + factor * maximumGain / gainSteps); } public void updateFlightStat(EntityPlayer entity, boolean flying) { @@ -304,7 +355,7 @@ class PlayerGravityDelegate implements IUpdatable, IGravity, InbtSerialisable, I isFlying = entity.capabilities.isFlying; if (isFlying) { - ticksInAir = 0; + ticksNextLevel = 0; } } else { @@ -316,7 +367,7 @@ class PlayerGravityDelegate implements IUpdatable, IGravity, InbtSerialisable, I @Override public void writeToNBT(NBTTagCompound compound) { - compound.setInteger("flightDuration", ticksInAir); + compound.setInteger("flightDuration", ticksNextLevel); compound.setFloat("flightExperience", flightExperience); compound.setBoolean("isFlying", isFlying); @@ -327,7 +378,7 @@ class PlayerGravityDelegate implements IUpdatable, IGravity, InbtSerialisable, I @Override public void readFromNBT(NBTTagCompound compound) { - ticksInAir = compound.getInteger("flightDuration"); + ticksNextLevel = compound.getInteger("flightDuration"); flightExperience = compound.getFloat("flightExperience"); isFlying = compound.getBoolean("isFlying"); @@ -350,6 +401,6 @@ class PlayerGravityDelegate implements IUpdatable, IGravity, InbtSerialisable, I @Override public float getFlightDuration() { - return ticksInAir / MAXIMUM_FLIGHT_EXPERIENCE; + return ticksNextLevel / MAXIMUM_FLIGHT_EXPERIENCE; } }