diff --git a/src/main/java/com/minelittlepony/unicopia/InteractionManager.java b/src/main/java/com/minelittlepony/unicopia/InteractionManager.java index 2c108740..cb46a8ea 100644 --- a/src/main/java/com/minelittlepony/unicopia/InteractionManager.java +++ b/src/main/java/com/minelittlepony/unicopia/InteractionManager.java @@ -25,6 +25,7 @@ public class InteractionManager { public static final int SOUND_MINECART = 3; public static final int SOUND_GLIDING = 4; public static final int SOUND_MAGIC_BEAM = 5; + public static final int SOUND_HEART_BEAT = 6; public static final int SCREEN_DISPELL_ABILITY = 0; diff --git a/src/main/java/com/minelittlepony/unicopia/client/ClientInteractionManager.java b/src/main/java/com/minelittlepony/unicopia/client/ClientInteractionManager.java index efc54a86..7881772b 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/ClientInteractionManager.java +++ b/src/main/java/com/minelittlepony/unicopia/client/ClientInteractionManager.java @@ -12,9 +12,7 @@ import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.ability.magic.CasterView; import com.minelittlepony.unicopia.block.data.Ether; import com.minelittlepony.unicopia.client.gui.DismissSpellScreen; -import com.minelittlepony.unicopia.client.sound.LoopedEntityTrackingSoundInstance; -import com.minelittlepony.unicopia.client.sound.LoopingSoundInstance; -import com.minelittlepony.unicopia.client.sound.MotionBasedSoundInstance; +import com.minelittlepony.unicopia.client.sound.*; import com.minelittlepony.unicopia.entity.effect.UEffects; import com.minelittlepony.unicopia.entity.player.PlayerPhysics; import com.minelittlepony.unicopia.entity.player.Pony; @@ -36,6 +34,7 @@ import net.minecraft.entity.passive.BeeEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.vehicle.AbstractMinecartEntity; import net.minecraft.server.world.ServerWorld; +import net.minecraft.sound.SoundCategory; import net.minecraft.sound.SoundEvents; import net.minecraft.util.math.random.Random; import net.minecraft.world.BlockView; @@ -96,6 +95,8 @@ public class ClientInteractionManager extends InteractionManager { soundManager.play(new MotionBasedSoundInstance(USounds.ENTITY_PLAYER_PEGASUS_FLYING, (PlayerEntity)source, Random.create(seed))); } else if (type == SOUND_MAGIC_BEAM) { soundManager.play(new LoopedEntityTrackingSoundInstance(USounds.SPELL_CAST_SHOOT, 0.3F, 1F, source, seed)); + } else if (type == 6) { + soundManager.play(new NonLoopingFadeOutSoundInstance(USounds.ENTITY_PLAYER_HEARTBEAT, SoundCategory.PLAYERS, 0.3F, Random.create(seed), 80L)); } }); } diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java b/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java index f5e971c6..34adb9e3 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java @@ -15,6 +15,7 @@ import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; import com.minelittlepony.unicopia.client.KeyBindingsHandler; import com.minelittlepony.unicopia.client.sound.*; import com.minelittlepony.unicopia.entity.AmuletSelectors; +import com.minelittlepony.unicopia.entity.ItemTracker; import com.minelittlepony.unicopia.entity.behaviour.EntityAppearance; import com.minelittlepony.unicopia.entity.effect.SunBlindnessStatusEffect; import com.minelittlepony.unicopia.entity.effect.UEffects; @@ -308,6 +309,32 @@ public class UHud extends DrawableHelper { matrices.pop(); } + + if (UItems.ALICORN_AMULET.isApplicable(client.player)) { + int color = 0x000000; + + long timer = pony.getArmour().getTicks(UItems.ALICORN_AMULET); + + float radius = (float)timer / (5 * ItemTracker.DAYS); + + int alpha1 = (int)(MathHelper.clamp(radius * 2, 0, 1) * 205) << 24 & -16777216; + int alpha2 = 0; + + int halfWidth = (int)(scaledWidth * radius); + int halfHeight = (int)(scaledHeight * radius); + + fillGradient(matrices, 0, 0, scaledWidth, halfHeight, color | alpha1, color | alpha2); + fillGradient(matrices, 0, scaledHeight - halfHeight, scaledWidth, scaledHeight, color | alpha2, color | alpha1); + + matrices.push(); + matrices.translate(scaledWidth, 0, 0); + matrices.multiply(Vec3f.POSITIVE_Z.getDegreesQuaternion(90)); + + fillGradient(matrices, 0, 0, scaledHeight, halfWidth, color | alpha1, color | alpha2); + fillGradient(matrices, 0, scaledWidth - halfWidth, scaledHeight, scaledWidth, color | alpha2, color | alpha1); + + matrices.pop(); + } } public void setMessage(Text message) { diff --git a/src/main/java/com/minelittlepony/unicopia/client/sound/NonLoopingFadeOutSoundInstance.java b/src/main/java/com/minelittlepony/unicopia/client/sound/NonLoopingFadeOutSoundInstance.java new file mode 100644 index 00000000..c97118ca --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/client/sound/NonLoopingFadeOutSoundInstance.java @@ -0,0 +1,22 @@ +package com.minelittlepony.unicopia.client.sound; + +import net.minecraft.sound.SoundCategory; +import net.minecraft.sound.SoundEvent; +import net.minecraft.util.math.random.Random; + +public class NonLoopingFadeOutSoundInstance extends FadeOutSoundInstance { + + private final long duration; + private long ticks; + + public NonLoopingFadeOutSoundInstance(SoundEvent sound, SoundCategory category, float volume, Random random, long duration) { + super(sound, category, volume, random); + this.duration = duration; + } + + @Override + protected boolean shouldKeepPlaying() { + return ticks++ < duration; + } + +} diff --git a/src/main/java/com/minelittlepony/unicopia/entity/ItemTracker.java b/src/main/java/com/minelittlepony/unicopia/entity/ItemTracker.java index 0ccaeb29..f968a247 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/ItemTracker.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/ItemTracker.java @@ -21,6 +21,15 @@ public class ItemTracker implements NbtSerialisable, Copyable { public static final long HOURS = 1000 * TICKS; public static final long DAYS = 24 * HOURS; + public static String formatTicks(long ticks) { + long days = ticks / DAYS; + ticks %= DAYS; + long hours = ticks / HOURS; + ticks %= HOURS; + long seconds = ticks / SECONDS; + return String.format("%dd, %dh %ds", days, hours, seconds); + } + private final Map items = new HashMap<>(); public static Predicate wearing(Trackable charm, Predicate range) { diff --git a/src/main/java/com/minelittlepony/unicopia/entity/effect/RaceChangeStatusEffect.java b/src/main/java/com/minelittlepony/unicopia/entity/effect/RaceChangeStatusEffect.java index f51af216..02c57f2e 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/effect/RaceChangeStatusEffect.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/effect/RaceChangeStatusEffect.java @@ -7,6 +7,7 @@ import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.entity.Equine; import com.minelittlepony.unicopia.entity.player.MagicReserves; import com.minelittlepony.unicopia.entity.player.Pony; +import com.minelittlepony.unicopia.item.UItems; import com.minelittlepony.unicopia.util.MagicalDamageSource; import net.minecraft.entity.Entity; @@ -39,6 +40,9 @@ public class RaceChangeStatusEffect extends StatusEffect { } public static boolean hasEffect(PlayerEntity player) { + if (UItems.ALICORN_AMULET.isApplicable(player)) { + return true; + } return player.getStatusEffects().stream().anyMatch(effect -> effect.getEffectType() instanceof RaceChangeStatusEffect); } diff --git a/src/main/java/com/minelittlepony/unicopia/item/AlicornAmuletItem.java b/src/main/java/com/minelittlepony/unicopia/item/AlicornAmuletItem.java index 38ad70c3..21424df0 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/AlicornAmuletItem.java +++ b/src/main/java/com/minelittlepony/unicopia/item/AlicornAmuletItem.java @@ -5,6 +5,7 @@ import java.util.*; import org.jetbrains.annotations.Nullable; import com.google.common.collect.ImmutableMultimap; +import com.minelittlepony.unicopia.InteractionManager; import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.entity.*; import com.minelittlepony.unicopia.entity.player.*; @@ -26,10 +27,7 @@ import net.minecraft.particle.ParticleEffect; import net.minecraft.particle.ParticleTypes; import net.minecraft.sound.SoundCategory; import net.minecraft.text.Text; -import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; -import net.minecraft.util.StringHelper; -import net.minecraft.util.TypedActionResult; +import net.minecraft.util.*; import net.minecraft.util.math.MathHelper; import net.minecraft.world.LocalDifficulty; import net.minecraft.world.World; @@ -54,9 +52,9 @@ public class AlicornAmuletItem extends AmuletItem implements ItemTracker.Trackab Pony iplayer = Pony.of(MinecraftClient.getInstance().player); if (iplayer != null) { - long attachedTime = iplayer.getArmour().getTicks(this); - if (attachedTime > 0) { - tooltip.add(Text.translatable(getTranslationKey() + ".lore", StringHelper.formatTicks((int)attachedTime))); + long ticks = iplayer.getArmour().getTicks(this); + if (ticks > 0) { + tooltip.add(Text.literal(ItemTracker.formatTicks(ticks).formatted(Formatting.GRAY))); } } } @@ -123,6 +121,9 @@ public class AlicornAmuletItem extends AmuletItem implements ItemTracker.Trackab } wearer.getMaster().damage(MagicalDamageSource.ALICORN_AMULET, amount); wearer.getMaster().addStatusEffect(new StatusEffectInstance(StatusEffects.NAUSEA, 200, 1)); + if (timeWorn > ItemTracker.HOURS) { + wearer.getMaster().addStatusEffect(new StatusEffectInstance(StatusEffects.WEAKNESS, 200, 3)); + } if (attachedTime > 120) { wearer.getMaster().takeKnockback(1, 1, 1); @@ -130,7 +131,12 @@ public class AlicornAmuletItem extends AmuletItem implements ItemTracker.Trackab } EFFECT_SCALES.keySet().forEach(attribute -> { - wearer.getMaster().getAttributeInstance(attribute).tryRemoveModifier(EFFECT_UUID); + EntityAttributeInstance instance = wearer.getMaster().getAttributeInstance(attribute); + @Nullable + EntityAttributeModifier modifier = instance.getModifier(EFFECT_UUID); + if (modifier != null) { + instance.removeModifier(modifier); + } }); } @@ -154,16 +160,17 @@ public class AlicornAmuletItem extends AmuletItem implements ItemTracker.Trackab } long attachedTicks = living.getArmour().getTicks(this); + boolean poweringUp = attachedTicks < (ItemTracker.DAYS * 4); boolean fullSecond = attachedTicks % ItemTracker.SECONDS == 0; if (entity instanceof PlayerEntity player) { // healing effect - if (player.getHealth() < player.getMaxHealth()) { - player.heal(0.5F); - } else if (player.canConsume(false)) { - player.getHungerManager().add(1, 0); - } else { - player.removeStatusEffect(StatusEffects.NAUSEA); + if (poweringUp) { + if (player.getHealth() < player.getMaxHealth()) { + player.heal(0.5F); + } else if (player.canConsume(false)) { + player.getHungerManager().add(1, 0); + } } Pony pony = (Pony)living; @@ -175,13 +182,32 @@ public class AlicornAmuletItem extends AmuletItem implements ItemTracker.Trackab reserves.getExertion().add(2); } - if (reserves.getEnergy().get() < reserves.getEnergy().getMax()) { - reserves.getEnergy().add(2); + if (fullSecond && world.random.nextInt(12) == 0) { + reserves.getEnergy().add(reserves.getEnergy().getMax() / 10F); + pony.getCorruption().add((int)MathHelper.clamp(attachedTicks / ItemTracker.HOURS, 1, pony.getCorruption().getMax())); } - if (fullSecond && world.random.nextInt(12) == 0) { - player.world.playSound(null, player.getBlockPos(), USounds.ITEM_ALICORN_AMULET_HALLUCINATION, SoundCategory.PLAYERS, 3, 1); - pony.getCorruption().add((int)MathHelper.clamp(attachedTicks / ItemTracker.HOURS, 1, pony.getCorruption().getMax())); + if (attachedTicks % ItemTracker.HOURS < 90 && world.random.nextInt(900) == 0) { + player.world.playSound(null, player.getBlockPos(), USounds.ITEM_ALICORN_AMULET_HALLUCINATION, SoundCategory.AMBIENT, 3, 1); + } else if (attachedTicks < 2 || (attachedTicks % (10 * ItemTracker.SECONDS) < 9 && world.random.nextInt(90) == 0)) { + if (attachedTicks % 5 == 0) { + InteractionManager.INSTANCE.playLoopingSound(player, InteractionManager.SOUND_HEART_BEAT, 0); + } + + reserves.getExertion().add(reserves.getExertion().getMax()); + reserves.getEnergy().add(reserves.getEnergy().getMax() / 2F); + living.getMaster().removeStatusEffect(StatusEffects.WEAKNESS); + living.getMaster().removeStatusEffect(StatusEffects.NAUSEA); + } + + if (!poweringUp) { + if (attachedTicks % 100 == 0) { + player.getHungerManager().addExhaustion(90F); + float healthDrop = MathHelper.clamp(player.getMaxHealth() - player.getHealth(), 2, 5); + player.damage(MagicalDamageSource.ALICORN_AMULET, healthDrop); + } + + return; } }