From 4202723731f78288943feb5c0859baba8d3a4f6e Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 29 May 2023 14:13:52 +0100 Subject: [PATCH] Make first/second/gem spell selection less confusing - cast and shoot now both use the slot that's visually selected in the hud - swapping between first/second slot is done only by sneaking - there are now messages in the hud indicating the spell being cast - gems now have a cooldown after being used - holding a gem now changes the selector icon and title to make it clear that spells can be swapped - activating an ability whilst holding a gem changes the message to indicate you're casting the spell from the gem rather than your spell slot - ability titles now reflect what they do when sneaking - equipping a spell from a gem whilst in creative mode no longer consumes the gem's spell --- .../unicopia/ability/Ability.java | 12 ++- .../unicopia/ability/AbilitySlot.java | 11 ++- .../ability/AbstractSpellCastingAbility.java | 70 ++++++++++++++++++ .../ability/PegasusFlightToggleAbility.java | 2 +- .../ability/UnicornCastingAbility.java | 36 +-------- .../ability/UnicornDispellAbility.java | 2 +- .../ability/UnicornProjectileAbility.java | 32 +------- .../ability/UnicornTeleportAbility.java | 13 +++- .../unicopia/client/KeyBindingsHandler.java | 3 +- .../unicopia/client/gui/UHud.java | 26 ++++--- .../SpellbookProfilePageContent.java | 1 - .../entity/player/PlayerCharmTracker.java | 12 ++- .../unicopia/item/EnchantableItem.java | 21 +++--- .../unicopia/item/GemstoneItem.java | 6 +- .../resources/assets/unicopia/lang/en_us.json | 12 ++- .../assets/unicopia/textures/gui/hud.png | Bin 33653 -> 34102 bytes 16 files changed, 164 insertions(+), 95 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/ability/AbstractSpellCastingAbility.java diff --git a/src/main/java/com/minelittlepony/unicopia/ability/Ability.java b/src/main/java/com/minelittlepony/unicopia/ability/Ability.java index 3a5721fe..7bd9dc03 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/Ability.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/Ability.java @@ -91,17 +91,25 @@ public interface Ability { /** * The icon representing this ability on the UI and HUD. */ - default Identifier getIcon(Pony player, boolean swap) { + default Identifier getIcon(Pony player) { Identifier id = Abilities.REGISTRY.getId(this); return new Identifier(id.getNamespace(), "textures/gui/ability/" + id.getPath() + ".png"); } + default Text getName(Pony player) { + return getName(); + } + /** * The display name for this ability. */ default Text getName() { + return Text.translatable(getTranslationKey()); + } + + default String getTranslationKey() { Identifier id = Abilities.REGISTRY.getId(this); - return Text.translatable("ability." + id.getNamespace() + "." + id.getPath().replace('/', '.')); + return "ability." + id.getNamespace() + "." + id.getPath().replace('/', '.'); } /** diff --git a/src/main/java/com/minelittlepony/unicopia/ability/AbilitySlot.java b/src/main/java/com/minelittlepony/unicopia/ability/AbilitySlot.java index 9aefaa1b..5adb408d 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/AbilitySlot.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/AbilitySlot.java @@ -1,21 +1,24 @@ package com.minelittlepony.unicopia.ability; public enum AbilitySlot { + /** + * No slot. Corresponds to abilities that are not equipped. + */ NONE, /** - * The primary ability. Corresponds to the largest ring in the HUD + * The primary ability slot. Corresponds to the largest ring in the HUD */ PRIMARY, /** - * THe secondary ability. Corresponds to the top small ring in the HUD + * The secondary ability slot. Corresponds to the top small ring in the HUD */ SECONDARY, /** - * The tertiary ability. Corresponds to the bottom small ring in the HUD. + * The tertiary ability slot. Corresponds to the bottom small ring in the HUD. */ TERTIARY, /** - * The passive primary ability. Appears in place of the primary ability whilst sneaking. + * The passive primary ability slot. Appears in place of the primary ability whilst sneaking. */ PASSIVE; diff --git a/src/main/java/com/minelittlepony/unicopia/ability/AbstractSpellCastingAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/AbstractSpellCastingAbility.java new file mode 100644 index 00000000..e583eec2 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/ability/AbstractSpellCastingAbility.java @@ -0,0 +1,70 @@ +package com.minelittlepony.unicopia.ability; + +import com.minelittlepony.unicopia.*; +import com.minelittlepony.unicopia.ability.data.Hit; +import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellType; +import com.minelittlepony.unicopia.entity.player.Pony; +import com.minelittlepony.unicopia.particle.MagicParticleEffect; + +import net.minecraft.text.Text; +import net.minecraft.util.ActionResult; +import net.minecraft.util.TypedActionResult; + +abstract class AbstractSpellCastingAbility implements Ability { + + @Override + public int getCooldownTime(Pony player) { + return 0; + } + + @Override + public boolean canUse(Race race) { + return race.canCast(); + } + + @Override + public Text getName(Pony player) { + CustomisedSpellType spell = player.getCharms().getEquippedSpell(player.getCharms().getHand()); + TypedActionResult> gemSpell = player.getCharms().getSpellInHand(false); + var active = !player.getAbilities().getStat(AbilitySlot.PRIMARY).getActiveAbility().isEmpty(); + if (!spell.isEmpty()) { + if (active) { + if (gemSpell.getResult().isAccepted()) { + return Text.translatable(getTranslationKey() + ".with_spell.hand", + gemSpell.getValue().type().getName().copy().formatted(gemSpell.getValue().type().getAffinity().getColor()) + ); + } + + return Text.translatable(getTranslationKey() + ".with_spell.active", + spell.type().getName().copy().formatted(spell.type().getAffinity().getColor()) + ); + } + + return Text.translatable(getTranslationKey() + ".with_spell" + (gemSpell.getResult().isAccepted() ? ".replacing" : ""), + spell.type().getName().copy().formatted(spell.type().getAffinity().getColor()), + gemSpell.getValue().type().getName().copy().formatted(gemSpell.getValue().type().getAffinity().getColor()) + ); + } + return getName(); + } + + @Override + public int getColor(Pony player) { + TypedActionResult> newSpell = player.getCharms().getSpellInHand(false); + + if (newSpell.getResult() != ActionResult.FAIL) { + return newSpell.getValue().type().getColor(); + } + return -1; + } + + @Override + public Hit.Serializer getSerializer() { + return Hit.SERIALIZER; + } + + @Override + public void postApply(Pony player, AbilitySlot slot) { + player.spawnParticles(MagicParticleEffect.UNICORN, 5); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/ability/PegasusFlightToggleAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/PegasusFlightToggleAbility.java index e8643062..5ac0d19e 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/PegasusFlightToggleAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/PegasusFlightToggleAbility.java @@ -39,7 +39,7 @@ public class PegasusFlightToggleAbility implements Ability { } @Override - public Identifier getIcon(Pony player, boolean swap) { + public Identifier getIcon(Pony player) { Identifier id = Abilities.REGISTRY.getId(this); return new Identifier(id.getNamespace(), "textures/gui/ability/" + id.getPath() + (player.getPhysics().isFlying() ? "_land" : "_takeoff") diff --git a/src/main/java/com/minelittlepony/unicopia/ability/UnicornCastingAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/UnicornCastingAbility.java index e87472af..d0c80bac 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/UnicornCastingAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/UnicornCastingAbility.java @@ -33,23 +33,13 @@ import net.minecraft.util.math.random.Random; * 2. If the player is holding a gem, consumes it and casts whatever spell is contained within onto the user. * 3. If the player is holding a amulet, charges it. */ -public class UnicornCastingAbility implements Ability { +public class UnicornCastingAbility extends AbstractSpellCastingAbility { @Override public int getWarmupTime(Pony player) { return 20; } - @Override - public int getCooldownTime(Pony player) { - return 0; - } - - @Override - public boolean canUse(Race race) { - return race.canCast(); - } - @Override @Nullable public Hit tryActivate(Pony player) { @@ -59,11 +49,6 @@ public class UnicornCastingAbility implements Ability { return Hit.of(player.getMagicalReserves().getMana().get() >= getCostEstimate(player)); } - @Override - public Hit.Serializer getSerializer() { - return Hit.SERIALIZER; - } - @Override public double getCostEstimate(Pony player) { TypedActionResult amulet = getAmulet(player); @@ -74,8 +59,7 @@ public class UnicornCastingAbility implements Ability { return Math.min(manaLevel, ((AmuletItem)amulet.getValue().getItem()).getChargeRemainder(amulet.getValue())); } - Hand hand = player.asEntity().isSneaking() ? Hand.OFF_HAND : Hand.MAIN_HAND; - TypedActionResult> spell = player.getCharms().getSpellInHand(hand); + TypedActionResult> spell = player.getCharms().getSpellInHand(false); return !spell.getResult().isAccepted() || spell.getValue().isOn(player) ? 2 : 4; } @@ -87,13 +71,7 @@ public class UnicornCastingAbility implements Ability { return 0x000000; } - Hand hand = player.asEntity().isSneaking() ? Hand.OFF_HAND : Hand.MAIN_HAND; - TypedActionResult> newSpell = player.getCharms().getSpellInHand(hand); - - if (newSpell.getResult() != ActionResult.FAIL) { - return newSpell.getValue().type().getColor(); - } - return -1; + return super.getColor(player); } @Override @@ -118,8 +96,7 @@ public class UnicornCastingAbility implements Ability { } } } else { - Hand hand = player.asEntity().isSneaking() ? Hand.OFF_HAND : Hand.MAIN_HAND; - TypedActionResult> newSpell = player.getCharms().getSpellInHand(hand); + TypedActionResult> newSpell = player.getCharms().getSpellInHand(true); if (newSpell.getResult() != ActionResult.FAIL) { CustomisedSpellType spell = newSpell.getValue(); @@ -178,9 +155,4 @@ public class UnicornCastingAbility implements Ability { player.spawnParticles(MagicParticleEffect.UNICORN, 5); } } - - @Override - public void postApply(Pony player, AbilitySlot slot) { - player.spawnParticles(MagicParticleEffect.UNICORN, 5); - } } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/UnicornDispellAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/UnicornDispellAbility.java index e0299d56..4f1bea80 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/UnicornDispellAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/UnicornDispellAbility.java @@ -43,7 +43,7 @@ public class UnicornDispellAbility implements Ability { } @Override - public Identifier getIcon(Pony player, boolean swap) { + public Identifier getIcon(Pony player) { Identifier id = Abilities.REGISTRY.getId(this); return new Identifier(id.getNamespace(), "textures/gui/ability/" + id.getPath() + (player.getSpecies() == Race.CHANGELING ? "_changeling" : "") + ".png"); } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/UnicornProjectileAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/UnicornProjectileAbility.java index 32261a02..ae02ec26 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/UnicornProjectileAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/UnicornProjectileAbility.java @@ -1,6 +1,5 @@ package com.minelittlepony.unicopia.ability; -import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.ability.data.Hit; import com.minelittlepony.unicopia.ability.magic.spell.HomingSpell; import com.minelittlepony.unicopia.ability.magic.spell.Spell; @@ -11,7 +10,6 @@ import com.minelittlepony.unicopia.particle.MagicParticleEffect; import com.minelittlepony.unicopia.util.TraceHelper; import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; import net.minecraft.util.TypedActionResult; /** @@ -20,30 +18,15 @@ import net.minecraft.util.TypedActionResult; * 1. If the player is holding nothing, casts their equipped offensive spell (currently only vortex - inverse of shield) * 2. If the player is holding a gem, consumes it and casts whatever spell is contained within onto a projectile. */ -public class UnicornProjectileAbility implements Ability { +public class UnicornProjectileAbility extends AbstractSpellCastingAbility { @Override public int getWarmupTime(Pony player) { return 8; } - @Override - public int getCooldownTime(Pony player) { - return 0; - } - - @Override - public boolean canUse(Race race) { - return race.canCast(); - } - @Override public Hit tryActivate(Pony player) { - return Hit.of(player.getCharms().getSpellInHand(Hand.OFF_HAND).getResult() != ActionResult.FAIL); - } - - @Override - public Hit.Serializer getSerializer() { - return Hit.SERIALIZER; + return Hit.of(player.getCharms().getSpellInHand(false).getResult() != ActionResult.FAIL); } @Override @@ -55,8 +38,7 @@ public class UnicornProjectileAbility implements Ability { public boolean onQuickAction(Pony player, ActivationType type) { if (type == ActivationType.DOUBLE_TAP) { if (!player.isClient()) { - Hand hand = player.asEntity().isSneaking() ? Hand.MAIN_HAND : Hand.OFF_HAND; - TypedActionResult> thrown = player.getCharms().getSpellInHand(hand); + TypedActionResult> thrown = player.getCharms().getSpellInHand(true); if (thrown.getResult() != ActionResult.FAIL) { thrown.getValue().create().toThrowable().throwProjectile(player).ifPresent(projectile -> { @@ -73,8 +55,7 @@ public class UnicornProjectileAbility implements Ability { @Override public void apply(Pony player, Hit data) { - Hand hand = player.asEntity().isSneaking() ? Hand.MAIN_HAND : Hand.OFF_HAND; - TypedActionResult> thrown = player.getCharms().getSpellInHand(hand); + TypedActionResult> thrown = player.getCharms().getSpellInHand(true); if (thrown.getResult() != ActionResult.FAIL) { Spell spell = thrown.getValue().create(); @@ -96,9 +77,4 @@ public class UnicornProjectileAbility implements Ability { player.getMagicalReserves().getExhaustion().multiply(3.3F); player.spawnParticles(MagicParticleEffect.UNICORN, 5); } - - @Override - public void postApply(Pony player, AbilitySlot slot) { - player.spawnParticles(MagicParticleEffect.UNICORN, 5); - } } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/UnicornTeleportAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/UnicornTeleportAbility.java index 4c3a33a4..3903d8e9 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/UnicornTeleportAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/UnicornTeleportAbility.java @@ -20,6 +20,7 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.predicate.entity.EntityPredicates; import net.minecraft.sound.SoundCategory; +import net.minecraft.text.Text; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; @@ -31,9 +32,17 @@ import net.minecraft.world.World; public class UnicornTeleportAbility implements Ability { @Override - public Identifier getIcon(Pony player, boolean swap) { + public Identifier getIcon(Pony player) { Identifier id = Abilities.REGISTRY.getId(this); - return new Identifier(id.getNamespace(), "textures/gui/ability/" + id.getPath() + (swap ? "_far" : "_near") + ".png"); + return new Identifier(id.getNamespace(), "textures/gui/ability/" + id.getPath() + (player.asEntity().isSneaking() ? "_far" : "_near") + ".png"); + } + + @Override + public Text getName(Pony player) { + if (player.asEntity().isSneaking()) { + return Text.translatable(getTranslationKey() + ".far"); + } + return getName(); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/client/KeyBindingsHandler.java b/src/main/java/com/minelittlepony/unicopia/client/KeyBindingsHandler.java index 9b9803db..b89dbff8 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/KeyBindingsHandler.java +++ b/src/main/java/com/minelittlepony/unicopia/client/KeyBindingsHandler.java @@ -8,7 +8,6 @@ import java.util.Set; import org.lwjgl.glfw.GLFW; import com.minelittlepony.unicopia.Unicopia; -import com.minelittlepony.unicopia.ability.Ability; import com.minelittlepony.unicopia.ability.AbilityDispatcher; import com.minelittlepony.unicopia.ability.AbilitySlot; import com.minelittlepony.unicopia.ability.ActivationType; @@ -87,7 +86,7 @@ public class KeyBindingsHandler { if (state != PressedState.UNCHANGED) { if (state == PressedState.PRESSED) { - abilities.activate(slot, page).map(Ability::getName).ifPresent(UHud.INSTANCE::setMessage); + abilities.activate(slot, page).map(a -> a.getName(iplayer)).ifPresent(UHud.INSTANCE::setMessage); } else { abilities.clear(slot, ActivationType.NONE, page); } 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 f22e3f58..f57dd946 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java @@ -66,6 +66,10 @@ public class UHud extends DrawableHelper { @Nullable private LoopingSoundInstance partySound; + private boolean prevPointed; + private boolean prevReplacing; + private SpellType focusedType = SpellType.empty(); + public void render(InGameHud hud, MatrixStack matrices, float tickDelta) { if (client.player == null) { @@ -119,23 +123,29 @@ public class UHud extends DrawableHelper { slots.forEach(slot -> slot.renderBackground(matrices, abilities, swap, tickDelta)); if (pony.getObservedSpecies().canCast()) { - - Ability ability = pony.getAbilities().getStat(AbilitySlot.PRIMARY) + AbilitySlot slot = swap ? AbilitySlot.PASSIVE : AbilitySlot.PRIMARY; + Ability ability = pony.getAbilities().getStat(slot) .getAbility(Unicopia.getConfig().hudPage.get()) .orElse(null); if (ability == Abilities.CAST || ability == Abilities.SHOOT) { matrices.push(); matrices.translate(PRIMARY_SLOT_SIZE / 2F, PRIMARY_SLOT_SIZE / 2F, 0); - boolean first = ability == Abilities.CAST; - if (pony.asEntity().isSneaking()) { - first = !first; + boolean first = !pony.asEntity().isSneaking(); + TypedActionResult> inHand = pony.getCharms().getSpellInHand(false); + boolean replacing = inHand.getResult().isAccepted() && pony.getAbilities().getStat(slot).getActiveAbility().isEmpty(); + if (first != prevPointed || replacing != prevReplacing || inHand.getValue().type() != focusedType) { + focusedType = inHand.getValue().type(); + prevPointed = first; + prevReplacing = replacing; + setMessage(ability.getName(pony)); } matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(first ? 37 : 63)); matrices.translate(-23, 0, 0); matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(-26)); matrices.scale(0.8F, 0.8F, 1); - UHud.drawTexture(matrices, 0, 0, 3, 120, 15, 7, 128, 128); + int u = replacing ? 16 : 3; + UHud.drawTexture(matrices, 0, 0, u, 120, 13, 7, 128, 128); matrices.pop(); } } @@ -327,8 +337,6 @@ public class UHud extends DrawableHelper { getZOffset(), Math.min(1, radius)); } - - public void setMessage(Text message) { this.message = message; this.messageTime = 60; @@ -342,7 +350,7 @@ public class UHud extends DrawableHelper { void renderAbilityIcon(MatrixStack matrices, AbilityDispatcher.Stat stat, int x, int y, int u, int v, int frameWidth, int frameHeight) { stat.getAbility(Unicopia.getConfig().hudPage.get()).ifPresent(ability -> { - RenderSystem.setShaderTexture(0, ability.getIcon(Pony.of(client.player), client.options.sneakKey.isPressed())); + RenderSystem.setShaderTexture(0, ability.getIcon(Pony.of(client.player))); drawTexture(matrices, x, y, 0, 0, frameWidth, frameHeight, u, v); RenderSystem.setShaderTexture(0, HUD_TEXTURE); }); diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/SpellbookProfilePageContent.java b/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/SpellbookProfilePageContent.java index 0fadc54e..b01a9169 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/SpellbookProfilePageContent.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/SpellbookProfilePageContent.java @@ -34,7 +34,6 @@ public class SpellbookProfilePageContent extends DrawableHelper implements Spell int x = screen.getX() + bounds.left + bounds.width / 4 - size + 5; int y = screen.getY() + bounds.top + bounds.height / 2 + 3; - screen.addDrawable(new SpellbookScreen.ImageButton(x, y, size, size)) .getStyle() .setIcon(TribeButton.createSprite(pony.getActualSpecies(), 0, 0, size)) diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerCharmTracker.java b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerCharmTracker.java index 2bdd554a..b720364b 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerCharmTracker.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerCharmTracker.java @@ -34,10 +34,18 @@ public class PlayerCharmTracker implements NbtSerialisable { return handSpells[hand.ordinal()] == null ? SpellType.EMPTY_KEY.withTraits() : handSpells[hand.ordinal()]; } - public TypedActionResult> getSpellInHand(Hand hand) { + public Hand getHand() { + return pony.asEntity().isSneaking() ? Hand.OFF_HAND : Hand.MAIN_HAND; + } + + public TypedActionResult> getSpellInHand(boolean consume) { + return getSpellInHand(getHand(), consume); + } + + public TypedActionResult> getSpellInHand(Hand hand, boolean consume) { return Streams.stream(pony.asEntity().getHandItems()) .filter(EnchantableItem::isEnchanted) - .map(stack -> EnchantableItem.consumeSpell(stack, pony.asEntity(), null)) + .map(stack -> EnchantableItem.consumeSpell(stack, pony.asEntity(), null, consume)) .findFirst() .orElse(getEquippedSpell(hand).toAction()); } diff --git a/src/main/java/com/minelittlepony/unicopia/item/EnchantableItem.java b/src/main/java/com/minelittlepony/unicopia/item/EnchantableItem.java index b068fa0d..6ac2b43b 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/EnchantableItem.java +++ b/src/main/java/com/minelittlepony/unicopia/item/EnchantableItem.java @@ -27,31 +27,34 @@ public interface EnchantableItem extends ItemConvertible { return EnchantableItem.getSpellKey(stack).withTraits(SpellTraits.of(stack)); } - static TypedActionResult> consumeSpell(ItemStack stack, PlayerEntity player, @Nullable Predicate> filter) { + static TypedActionResult> consumeSpell(ItemStack stack, PlayerEntity player, @Nullable Predicate> filter, boolean consume) { if (!isEnchanted(stack)) { - return TypedActionResult.pass(null); + return TypedActionResult.pass(SpellType.EMPTY_KEY.withTraits()); } SpellType key = EnchantableItem.getSpellKey(stack); if (key.isEmpty()) { - return TypedActionResult.fail(null); + return TypedActionResult.fail(SpellType.EMPTY_KEY.withTraits()); } CustomisedSpellType result = key.withTraits(SpellTraits.of(stack)); if (filter != null && !filter.test(result)) { - return TypedActionResult.fail(null); + return TypedActionResult.fail(SpellType.EMPTY_KEY.withTraits()); } - if (!player.world.isClient) { + if (!player.world.isClient && consume) { player.swingHand(player.getStackInHand(Hand.OFF_HAND) == stack ? Hand.OFF_HAND : Hand.MAIN_HAND); + player.getItemCooldownManager().set(stack.getItem(), 20); - if (stack.getCount() == 1) { - unenchant(stack); - } else { - player.giveItemStack(unenchant(stack.split(1))); + if (!player.isCreative()) { + if (stack.getCount() == 1) { + unenchant(stack); + } else { + player.giveItemStack(unenchant(stack.split(1))); + } } } diff --git a/src/main/java/com/minelittlepony/unicopia/item/GemstoneItem.java b/src/main/java/com/minelittlepony/unicopia/item/GemstoneItem.java index 97d75a77..d9d127c1 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/GemstoneItem.java +++ b/src/main/java/com/minelittlepony/unicopia/item/GemstoneItem.java @@ -44,7 +44,9 @@ public class GemstoneItem extends Item implements MultiItem, EnchantableItem { return result; } - TypedActionResult> spell = EnchantableItem.consumeSpell(stack, user, ((Predicate>)charms.getEquippedSpell(hand)::equals).negate()); + hand = user.isSneaking() ? Hand.OFF_HAND : Hand.MAIN_HAND; + + TypedActionResult> spell = EnchantableItem.consumeSpell(stack, user, ((Predicate>)charms.getEquippedSpell(hand)::equals).negate(), true); CustomisedSpellType existing = charms.getEquippedSpell(hand); @@ -67,6 +69,8 @@ public class GemstoneItem extends Item implements MultiItem, EnchantableItem { charms.equipSpell(hand, SpellType.EMPTY_KEY.withTraits()); } + + user.getItemCooldownManager().set(this, 20); return TypedActionResult.success(stack, true); } diff --git a/src/main/resources/assets/unicopia/lang/en_us.json b/src/main/resources/assets/unicopia/lang/en_us.json index 8951a396..67cec935 100644 --- a/src/main/resources/assets/unicopia/lang/en_us.json +++ b/src/main/resources/assets/unicopia/lang/en_us.json @@ -326,11 +326,21 @@ "toxicity.severe.name": "Toxic", "toxicity.lethal.name": "Lethal", - "ability.unicopia.shoot": "Throw Magic", + "ability.unicopia.shoot": "Shoot Magic", + "ability.unicopia.shoot.with_spell": "Shoot %s", + "ability.unicopia.shoot.with_spell.active": "Shooting %s", + "ability.unicopia.shoot.with_spell.hand": "Shooting %s from hand", + "ability.unicopia.shoot.with_spell.replacing": "Replace %s with %s", "ability.unicopia.cast": "Cast Spell", + "ability.unicopia.cast.with_spell": "Cast %s", + "ability.unicopia.cast.with_spell.active": "Casting %s", + "ability.unicopia.cast.with_spell.hand": "Casting %s from hand", + "ability.unicopia.cast.with_spell.replacing": "Replace %s with %s", "ability.unicopia.dispell": "Dispell Magic", "ability.unicopia.teleport": "Teleport", + "ability.unicopia.teleport.far": "Teleport (Far)", "ability.unicopia.teleport_group": "Group Teleport", + "ability.unicopia.teleport_group.far": "Group Teleport (Far)", "ability.unicopia.grow": "Nourish Earth", "ability.unicopia.stomp": "Ground Pound", "ability.unicopia.kick": "Crushing Blow", diff --git a/src/main/resources/assets/unicopia/textures/gui/hud.png b/src/main/resources/assets/unicopia/textures/gui/hud.png index 97a2beeb1ce23a51b4cd01d4565b1cbd7ed64113..7070f5ad3a7515d960cfd7d998a61611539e98ab 100644 GIT binary patch delta 17272 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 delta 16854 zcmXV1WmH>Tvko3SNO2491d11j0>#~3ic4`T!HY|A*C54;yKAAiwMcvSrC`!A-@$(E(f=Y`Wu zXn)IX|7~%|;{cjz4@zL*b>KGNd6t+2SUOTPaRi!qzryk? zmd{HDJI)`w!o1hcIa~Bg>U82`gOi~s-RFU;OI)uj`KEb$f2u(!ISxyjjKcVXzl(Ud$zXpy}{t{rKfwh1{Wq88KVx@ zx8NiMQ)$*h)O8C-Fla<2kkOkedHhpSh?)ZL3C~Un>yLf)rJZ*iotBnS`7Ka8FuuBm za@>3@?+@)s2HkYSllf`(ifs)Aj_NC(v8sw41N-XgZ^Sl=94)i<4%IC)A5}$fXB}L+ zZfDBKKhgU&#R@O)S;h*r?QQ=|c9|0MwH!*-F|l4)&@r`~P`*Fv9Ixp(?jFgTEMgef zsWNDA9@s(uq9J^rqN)1sIrc4-3+6R9(X#5da_qf&FY3Tmd4enSDCFKVWpJ0qhreSo z$%FRUI=4DMk0vVfUU|+vm0SE+j^^Z3q{sWHRcm!Oc4kW}NIqyB zd)@uE_UChofZY1)T;~w=+ufA**O;F|uoL3UMSpHA}$Ng>hr%tGLek{xwS#qlS! zr#Y2zu_FU1p^~Y1F4=bPu3-7cA$7K8M34YF$HHQKO%4R@d}ErMC#mhzI*CPbXx!W< z0kw5@YXMi`6&mR;)7sfkq0%`jm3e@=O&xu5>cdtUWtCEL@2e8AuDgK;wi zMCFG>%-#nZj16ultbq({0Vu!KKT>RrwN(vB9$<&jIvlDwK%KHb;N;FH0T@b16|Bs& z_3CxT%tO7HoW_2Il09eitJG$CC^Y&CSq)34_i-Yu0`(7(G>BYV9p3S|Cu9zB)+eKW zpT$J`LxqVr68CvlFpl?*qKmbZp!0nb`X6+9;I~VhuO1aieuai9*yfcqc2iat2Io2D zbys5AyRtjXW6!nZte=t2PerDqQvaFs{JV976 zx1m}yjzFD`1Yr#-DYv$1VY75baQZHZ=wFu<6W64WW&OJ~HzTKOC&B;TWu zLv!X??P@88-v{Z?%36%Msuhwrs|{6~CIV@!s(q6in&Hj6+RH>1>9_ z6KWzpuIlHQ-fB@WV%Lj6bT;0H{4-a~O5PKd=`1^}aletZ?khH@FbU#VB13VV**eKC zi*4r6n*T{QqG@&C3C+2|;pL5H93dPCNWo}{)#96 z-S~5fdtQmuQkwb;KLdhHP`8n^@l7uei{x{!$d~>iVm|~6Cgp7}JM?2(X@Bpn!mI(0uZ{?3^bgZV|lD6WBH0JWoAxU8k17=t3{-w!i~!9LM_ z4GDVLXk;@**BX%5MEG2pSzrA(Jm4!)kGj(g>MfldUN#fY@VP6R_W6E~wqkG41t z#hEECaNFp0{M63{SF4u)axF3a;MT%DC1cPAZ)#Q1$sW_XB_;#W`@@d&!EwDkNE5AO zMX!2@brGJ<4#a|*vRktnwQ3q7{*=TYXds^SN9qm9hSr-Xp{Xtw6`+!YQZSO6iPz_Sn?%%Ou-lq!`X z$?c&s2kP?)jVvS<7@HOZh}2IOx}DJTy78}mO zC0W#SWN`DA{9K8MZTr>FrUnHDV7xnLnD{LCBdp+FM4p;sV!HqMA$Fb?zwa)Ca?$Q+ zbT^phLmQX0cmM$PnYtTX;#hF|+X*dui*0;;@ z0ws3h523hJD32sqe=Kzw7zD8Y(qYS46fejXgu#&5bJUVSNi8{dg-n_vzcjjtfT6~z z$KqMk&h?MwK{C#J3DPys5?|*Oiw%h}8sO=V`d`-^)==R)sK1X{+Ery|!11B^16dDNZu0NxKv zwyXke*qw%KioU-i`5fu)X(myU!+L@Oj=)qV6~Z%18+mOax|m4uh2RA+2_@}_=}!dF z_o)^xGty=Y!Hj#2_4|Lkf@Wf;F^t`a?2Di{JHmo!4eHd@={vCS9iigIv;&4ZXZVJLES|G zRx}95L6!9Hw>1&^vi|z%ON!u`NuL&}PIuH5x{L}a=!J01&YSVCDrN(gv2jP8SRbg+ zwL%%8y!&&8)vdUL4d0C)FuqyPW7p$|*bnJb3+8VLB-a!#U#tgl-kQ7YgrxORX(We@wAzrS_kHOFmiItM|4P<{ z-{VI>`%N{t1;-q(T4UD&f(p*}%a?unWQZYGMUnE@DGHQbF1t+?Ha{0pCv6q=lYh98 z$x?AHwX&)&Sphv(B!;QPn5=DRJ3d9>NMu%j;|Jj$ajD_{jKjeZ!hJIewAG=g1JerL47GlT+45kVw1{j3wwSL*#3+!Kl`|_B?5D9x+wPc~k~v4up^ zbrh@&vV|}8e`_UgnSIMHWHIvNt-nLL6retyP^PN!L`#yc@UgP&`hKVzXt%Dv1}|rB z+FN1~?Ro?DK{I)wKtJG5)|21&82pi~BA#-z+Tf^pEbLhPQM@?SV_m_axDHM)B#jZI zI2n@kF>}0c7>zWe#0S#v>4pNfFK4p4)h*CPhM{j{l6}7fs=c%#$>)Fnd#2_gfpAR< z;X{)xcxVNOv@NXJ0L`JiK@y#k^@%{TpM7_ur0S_^j0r-p7CwbsbEUL30a&iZShP+= zkv*56kr`PRfTOM1X(Naam;4{ zUU0OLyUElAMO}!eV8q~|Gq|!C1>jEV5K$1I2GaNn{N+>UQHM5YXCQeF{R5A#@kmKv z(2(t297hjalQFcSxuf#@jaoC`okk<2_ufZWp69G zb~N?$aVjde$*5PrLHm2fRb|OxYDr;~xHs<;6~{ik=hQ$z?=8O z*V|%BGT?_Dd248>bt_pMFRznzDu@W&op8gKLErN$mw>OPWEj#vWM2fvD}LkGQ9;XW zHn~PVxC`lTTt;e>A9!|F{o7J|B7n9^X7~NA{ag^OM8n4-$qiHn!#X2Iu9m{|14`My zMiX6iQID~qa$T-av<=HLnJAEX5$D2(mkErTM)75mk7CKpc=XU@{0u}ER$>*##i6;c za|6^6(2c_d@dgRSY0J(ZLF4yo4Jv924q{lmHD!T~??~HZq_K*@+>XpQD0?##nkChS z0ohXOD}pWwjJBZkJ5YK!amn8P3eP%_c_+R=LRv#mHvR*5{RCZI zi>!HjONUyOkP8&#KlVlKlD*qLn+k>xQU_+C+m|rcq8v11sWvU4E#m$?7@p`N5Uyd= z11`INeNAK)RpF_7(AbevRpShoEJV0#k9fdKOW8at!snj3E15t*9#D~`STWGy zW5%W_gzSvQ2zw6htP|Nb;I%2i%cAD+RZd9er4D&iW`&yn9trhfI<9>V<#`!8Y#~q= z{Z5VrVa_eJ1MlFZFw&LyIV5u?V`xpTeEg`qQ3_ChC%k=5^`*b`P`=5FQ)SR}b6en7 z@YPQe#}AHXa_&E7g@;QbXK5YHBDZaAYNEIe9QsU(eI!D&7q@ek z4vWa|f@!?Mb2V7){_(qLIvNrY&we&D_dS2yo}Qr&8BZh`C)Ucv$v-4MpG#89*_#Bh zEDzKZTqakz{{-Rr{-u2W@&Q{0e~($sSa)}R(b%~-*sLmjcwg`W|3t(k2Gv+D*z)3_ z)2HYd>Eqr(C83WB&Br;M66@4>as>J%6NN%azJtkSR66;Qki2Vkm}?L00ZUv_(HPt6 z`xjkkaROnG{==y)CYgAQR*jLkd1J{xhd2ss4cyeon|P5^f^)ETe%o7!OQg=Z>=Rm& zJEB|0QP>Y(kui4|ji&M>D0f*NWwyeu`j6a;lax z4)r)rz@$89F?-4Wu;k|X6H5{=8cOjkY(L4VbbkedW*d*p)?H2E<#bg2_SVxOGw5b! z@ALG8I^Aq)rMg^hv-@u5j{@JJz|oTDn zg66^~K+!+)Tzor70{Vl1ftMXb$0CJqZ2^8SM6SOW03yNtp`?=iAK4kO8hFOE; zUH|>+eG{ipo=mO02klPm&>8Lma#QH8@w;O~`#Og?zio)OJSH`;CB zVa7ZE9|kkYJ{!`K^>cKZ$=`}buvd^h(4`DUeLQe>?nL#%qzlxNG9-;nRzl>U#g(NM zYucszY?{P1E(t{GtM(Nnb~)${NQc?uT==|l&7MA9 zvTqc7$=VxqXQdHG(MTg*c;^n_X z`%0;xJk1k*!!=W@C7@54HNHq=EMt>cQR9socCS15_vIjT-~(#`EoG^#%*FoF?mU8@ zDw)~_0opLRuaNO<(7R9Dy#1+Oe&lWM-*M2$$Osk}EfN|9T`z}XNPQ$PfYNyJsr)hI z)0Pup{P|}gF+nV2RP@N@Y8h5g!h)I8xl;*jL+i-tv1<*FnrGfpZrll~pUXm|ataHX z*UX67k^iC_VmJSz1GB zC~!Kx1$h>AZfgvr&Eet|3GPb!)4*@n&k0Cw{)0<44+dWU{9WS1uvKXBaE&~0^O5jP zqja+@e@wHe8QP9=q7n26H>v750;wSAGGz9d`!B;m(vPGBH<>Sg9m7Tl&4ty53hzEL zUtv)oqN`PqeMi*w$ERENpZSo{(H1FA7PI1K*fYcU%lH$bAeCSeY_IT-OHdgafH%HJ zJNsmuuN|Th`(jT(jyYG#FL6b$RM0MkGm7Pk_o3^Qjk=J`;_@r>Dtr$>@FQMGR40=3 zTalg_qzW5NBNTrJmmp4%z;cxA`7J%k*@waf=IY{VJ<*E8+PS&>*(qC$dFtF+gm(uj z*Z}Xjrjlcw$ZChF$G5>F1v5WeR4^YO5J?uIV&5bEmGvTG@9}E3qbJ^}=@%m*kA}4NcPm_k;C(?5El4?c1<$D8EN}s5av4p_o{-_GG+c zYa5;-8XL!4OmhYc5}n^*TscyxMvNx|wvo<~pl-b6V?3qVNXRffj?ze18BaJX%=VPb z7n|&(d5c#|t3?Fq_r>Xx$bmSZ!?B^8QjmbLe;hoBl?HhbnQiDd%E=O{fnp(y#1cf>}=gp!F)>F zD==Bbu9<=p0}m3Mx=*W0$IC$@1ANGXnt22hOlu}w=XM?>gaR+Xt-SN#EK>O;eSoHl3u+yw19iCADn~gWr;U!ZB4!}Zi zSfnGp2reLT>R&NA4nrTwzzV0o|2O|A>s+w(AxMHG;uNI_@=N7UL<)Y++xao=QNhL* zMq~w9_pRPwmWuQE=&1au-CZO-f}UqFDA;P+)0jfYt;8C|ZF>|CB!!9)ApT;jyqb`i zcq5b){uS)uNWl;;QEh~>i>09;=u4h+$x=U=SeP0QNJo;;)g?AsQqFYd+mxl?3%y!@o=Tmh1~DQz(N@9Lk3yO25QDpdyq*`;uCU9|M=F zC0N4Imxg-x0K!#>XbVBBEdO=hpZX@EH~7{m8y`d ze2uHfl7InT9E)5L&KYGmnNpH}q(a7Tqxb?0W#M7dClbEQ4f>Fs0N^DLBsGWw00F<6 z<1FfcEDS*K85uNbC|^hYCq`M@+Qf5aMB{0Wp)D_R z!1@=RnYvyFADS=;g(!=?I$k5;wKDE!ET%Sd5m!iP2sQP~%XW7SBFY!^>nQ z2tXn7&0=8BIeJAmKc?T#xy77hZN!KDxa0H@qD&wK%z&1n)1tGFhky_b99nDMmBmYv z{wYB2bs{e^cyHJpnTR0sp0guW0VTH1L!zhuKxpgL-4PAKu(!t+>`t|owtZ>G`bmL> zmjPncNca8n-f`aA_7h?OVK)~#hs@=TXGA45fTs(z&CDA(htEJr3u>HHs5ixbr_F-AvMSWjQ!(D!I=4z zCbze(R-rl?SUxxCw{{-V&R9lbAV-0lS(Z@)1vL^QG_`@^P9Y+NI6oT z9Cid-06mtpJPWrlPg>xnKf=Ym2-ZLl5Q&!zs_6kpH%Han5CG1~Q)?i!AWz{6YqH5AZnGd zkwk^q^xl332&N_d)I29@>URQ82Hp8(~f&HKg)2mit#THW+z$c(`;_SUN&S7>X!@F4F?&Ptfrj z`Lxj%sDM1N$nHB#NPa`2hnE9O(joTMK9~oo=hYX?w6H0%D&2Y>zy^)vSSjl@yGPngz-M*a0 zDE8IK-#1uKMwIRvETN-_rIxBm#%)FseM#-oO#kbwzzrsV2T6o$7hrnEJ`MQ-_*^_y z6_NA}Pe5b6LA=X<>gUb-9T@OYHPVZ^V|C9H9P8Gq?t#o z007=2D;5gC`(H-ifw3zevRA~BCgUDst;f^Awm$pBpFe-zJ3fA|s*3yHD&5^;jZK~# z;lw5xv|CuD2JrwAOI1K`_vc3lzgWn?7hFp#E9B77P!cMt;n7jx!^6Y$(h}Nzx}$B(Vm66Quq zO4@gJ20=wbDxLIY$1FOizOX4 z09@tTIo=7Vv)`jSZ2rEw9CLK{au?}tk9&D7_RHUHi-|10X?u-BYGec`Fv{u;0Y(aj zCK_0w0&C#x#c|Kt_5)(%RCy0_&~BbTj)^E>mm&=G{TJdi?*vQW@otX0N`w1!*8cU- z{k4fgV6w)8T9=8pff5l8?5dD4v(uxhGw1^~3vA+dU@wUxK^f#@5D0Nns1uIP^8B5n z9pU3uA5l$VEol#-DhK)o1qpj#{z(9ch}@^eal71PmxmeuBXOCfaq+az>h7%DqOP@x z#rnn}9{%Ocrxz&zkMpTgE7u9#VvX^;e`)kdinPUp6=P%i`}g8WP7zofiU6rd7sznH z)Fnhj1Z!A+PDbp(x0-L#pu0+FbwT|DmwnSRj?}1JmY845BJ@Gr04!%#sCI`7I8~YA z4htyJsXP`O-hyM8?{+pEru@a(?w4}0cv!f&1D7K3Wx<02_2%h?FmwO_Yv2wC;JDI^ zt)UWcYcb7xp^Sf<2SQx&a9#6U;yXmVQLSyzs0e@qsQuCeG2{(#Q$>7cLX20^7CLZ) zsxE6P7X@_d{Q1Z4*Y?AjP$yxUuo7ParMcL6#o-b?*!-_%rxn7?kE7EU$QzF@j|h7* zEBP-K%)j1$B?!{MfE5Ye<>uyQh>K4YH4*lTPkbl1Qv|F>>l%QhoMo+u9P&52SHh(> zKS+&EC^w_8N3RGFys(@Q>`dh+OioT};Y7XAB_To8{i1*VMgAt7W*31~tqK5`W$h#b z&ZebtDVzS4S$zdIE|v?BO&e@I9M-xt$3Bt-y_q|#)~OUgytA51d*m3h_*AaNYOKzh zs^VX!2%CKa{~;1IOL6*|{Hfz(e{?Gs1Pf`&6#ASZ#zc_+wOBKsp+v!2C=Nh3~gb56!IO-au5j_+#BtEBmx;=essePT8I)T?zK z7e7T)M?D5fBj@DXvE`24g%Lq(lE5-@Cb{4m)Aa3$$2vV4}Q&}x70@Vu1K8LjwT)8UyW zC?6!XjPTTIP|fK3a8)MK(K;CE(6ji#2XzxHles78_n>>yy~+Rr#acC;9v{e z@T0=G7fFe(LP?FzYrFm9KSx6XK()!(nD`FQ_o;35E1^xEmzAYuwbJf!3FMc4bKv_iv8U|YRKkb5d=Loy3 zS3KmtQ!8nXfgFY)y?Z{Q2=kFtU6Uw=@if}gZQ3DX(Fel9rg(gdL77ieqPJ!NA`|u6 zeQY+vuy84JrvPbJ<$8>KdK{#?;Khf^CWB+9j95({krV<-NjW(*ey8OWm7~awc%p0# zj9BjZHB_7v@gO-Ul`nFHdF&VSUzykqSnhcMAoz6NKzvMS>qFHf*tQg?Lt`M>Zb3KG+9#=&{$(hjnT@bfNeD27I;cBBHGnLFi2oCrA69 z0CG!MeE4DC)P9J(eck~O`|@kT`{n7rbu)r|R;(mWTs9vHOM{dLLmyk9p&-PtL_UMV zk$Uqq^GN~#z;*HzPpVTqljN;V`5WF${g%740bI+a8kWm*bU=DbBztoq%kb-1DqEfN zT06msrIbg`Wi2L{-&&eonr$mAMN^@|Uud_-xI$|gmZI0`^Xb7DAEISfV({q=tD0;f z9|E{n-v*i+{^yU$(OQQ9obF4Nq}~FadY0r-p}>tznOzB%p{6C1n1xE+k&(>uV{?#{ zwCcWP10D#BtSWMjd~@_0Y4RQcJov7DGj-Fm2}vGzFU3!R#bF=<8y=6lB*l*P+zOwM z8YQb`EGpqix94GjSIi`K#s@R-l=R>+?i}t{U_0eZ?S8tP5Ey{OYC&gKZ?^gBLgo!Z zxlxBn9v&ah*G>b8Q#4FjtZk&(1`eIkro-|PTRqpiKW}$lPAYP|evMME;ZqwGnwCNM z8MIOkUnPYGYi`)rMVQz)*Z5Zt6w344Ewbn+kV3uc8BJ9)|COj$0AUsXm5~|NdhiWe zc^1!i8gxuput1;LmWTOKA3)D+PQs>Z{)tZ817B*RowM0_4dadR=c*B`KoBWUr?VHl zNv_;zcb|&4dhBbsT`%aCv6aLVL?8zOoGy+_vIgV}4F$fS2jLE{1S~@vlly#kbBRgs8ofivdE@t~o4ED=rOwhIgMx$X z-tW&A-2w5SVrRWbg034u&Fl_cyT0OM5!w+;q6h#9coV9au?_e<6#b_4v2ENn|KQDbXFJdlK|`;OMFZPkSj9;jh6WfNNt0N4rlI&0tNjAu|@cm_@Rb9B8l>>h*gHzSAz^FbP5TZzJ-TZf3Ne%LB6 zd(##lewT0p_Fe9}zcj~t&5wDKblM4k*uc_Da>nhpTE} zEouzEBxeiNm}%%Zr0PhOAbjM3e54@+GsoN@r$BtV(cnaG+*&Dx>FlDHCeQDnf?2BG z8hxc%eDCpv3mz9t7i8Ic`)s=H)>fNc>Z{*nV%iFQ4Fsqo=ML%wB{DyL{~81ZGD+JF z$p1Z5l+Vogtx_#c2qwvW3b~X|kZ6=58S{`*<;tEXJ%C_4ocK~9ipwtS=#{1JY? z;ApJPh^n}_7$}V}%$yPn4M1fdSExl#{vl4lT&(%g>(7sYOHt5RsnW~7{DD<$um%Pg zIbiAw5J{`@O>9Dfw1XMEzI}EwZTB2P|E zLUw(je;;3%!a%ZxYP}c##?3)UqFtijE!KkUWS2kB@k;XbD&;{9RzFlomLT$#xu-=< z#v=|7kCZw;BcV?)lhEzgNTVXMsyOYmJAae7GNvAo9sqhqcKP2H=~Tki7lX8G+-4`} z&S(-{lViEnC~#xm6KM_bq6R#FlmuloI~A9ep|R=KDAjH|u0%Mk*gbI1@fMb#TI1o- zW5}%In(L$T!k{#D$`Ti(LA-3L8vNXU(L(@vyRds4Sjw*^2i>gB0p5uq_ZNKtRJU>= z-b$JtezXm-aP<5YWYGZnn-C7l)lm3P&g%<7(W|#Y7u?;zL1PjT8&O?eV~P?au^biR zC#(5Vx5@nr1+&d4P@(+7Dun43lY_|k!x$$OIBCl{ez!}w$Z zh;&3O;3H=1S6rTai&YMpzN+Pg{_VVz3$?E-jh~c z^@Z-{3X|iLPV$miQt#xr%o_CQvuG!3xWNcf016crvEi}YOOV)fSjxJ2?6Y*W4td@s zG6Wl*QJ)Tt1A$Zx@_vXBEsQ=~3L$>W>`$j}hJXu|0!$;TTJT4=gIcs&g;oPsm;_9t z56*>UWo6;x)V_&~#Bv!D8=5kEs-Xbw(XU*fLIZu2h74q)!mgHtcA*5weJC)E4<>Fu z7y|ZZVgEr1IBf@^;uqqVE5-Iu$jKe zmveWBJ#hDRvE6&E-Sa4d+?hs00iGGK7FoP?|D}jve5h=3uwPdmYo+qr_7fe2O&jq? z(!iI?dgfFaI4qL0Ns0i--X!A2G&!$@6SU2WpebK*^5AhTHW?NJEOnmK)Z-)aeih7cqPbSA6)c0qG? zK1iTyF%nNnn?JSAEiC-7ONwAMI!$Kya%*3G+O=Pr?fTmqnhw7dVA$Z`Ao77EVBgoy zuL}a4SzC#lnNjB@!vyU4*2jd2q-QV2_GBenr)*vge1f00%OUucPw2TZ7JC6cs1`h51_K^2Z zr2W`^43-zCuC@0dEG{&<9TYp@`|8{H^WWA2xid#bzUuX0cF7 zdD7~ag754|fi$yG>mV{AF`@bFF|lFN$0IIpzlGn-q9J;(d8XSsICKQK zx}IfPHoqk|AvK_MIzBRW3a!d=gYNJF?eik~63GJbqyUJ#h$x|m-H45-j+O_)OIltP zix0<_?Y}UKE$tnNm|nXscP1X244q#%#?$e)EG=D)silxNRtJ~5Z<{3$GH#{i{@8MQY7^RS#l{5(XHP&()I#}}iY;5{q zG}F=Ez*l)zTja->;}GX&H*#1cuyEUTyYyWGrLkAi&_qwx&`vj;`u>>;*m>I=GPrkU zR&rLUyD5m%eFfwC{J7Bz@a{$~ptBSVm1PqF$XA@PjxWO>egXcm zEVlgiDZ29Y7EUAQf3K}g*f+6~EeMBUNdo)+d-$@)$H&?}cEkJ#bG-$F*Fn$cY$A5O z4f0%DzP$g%In!-m+A4Rr}Tvmu1->Op;2&)MIp9iqt=$ zkl2>&(UCzF9CECFE9&N0cAi?TD6>3Y!3kyRt}jV8i8M2P80bgZ(y%8ykHvoxp)#0IwOw(uuBC8*Z$e+E-pmZ z;SI&0w*}xgg67P>7zL5^L{dJ#IR>Z{I_430@pJ@La*Sgj1VQ2h#OnW$laosq&)oUv zKto3UM47>_Mna3z$_@e+I0|vAwI&9pm~LTV@fQj`(9EZWw@q8?&J~N9F;SCr5WX6| znt`-Dddz#arlF$L6=KP%vuK@jeb&bl0w-Rum8Gd^{>6L18`N?gy19@MYUmTd^5`{B z@;*FoSJasVRY_`7P#r(7A&nirgI1`Aqhstx*9f*4|mI6|Nx#G1o? zH}(_-24+~E_#97_7OVKd>1nzos238;yxeR~14L}L9EorEFU9rDg5h=wtXV2M^~C+@ z=L%E<>FQoAve#8SsZG` z(qSdME~o2BYP6VIb|RahM`=GK(Iu1QDq9z_DgnM$RSd zzf9ZlKG|xdx#2K_lXmkMH|o;<@CYf~%h&DtaoS_&vOavQJo>N)pa)s!;s=NA`oaNq zv(prm!)lbIIB&Pmh_iUcHi(SKaYZM`o$0^*V8Zw?h{7#1lf6V*sw3 z!x6ySCC?dK-U4RH>P5Jo|Ie-M-G7^lgC@J~i@x#RARW&`MiBY5o9oSAOL6T- z30KujTwGjUl*XobCtiI|+ID&19@V4R0~$`@pYlEk);h7;a7`Zva6)D!nHT-`omLAW`al)W7P;qn^rW(JfW=lWKf zMf-kCxBDXMzopn!W?jtcR;*)%h9 z#(NelBIP@M=671v<<(5ks-A)?Cpa;VS@%0P#0KSltmjNsXiG{;QfM;xeBm)(TUNGP zv3?h~KB}LFqKu9;%q=1k1_wvSzJHp!PyK5@q7~Teb4f=K4B^`J!EUw2^RybxVDqL& z%T41K;b;nWS;=m2d8Q4UoPV{=cBV+QOw;vpcj~nouBy=i5urYLX!22h)zQ??dvYMD zfHEV_1XV8g)p@#X0hi%YiXPRU=vM0Sv`puK*9jElgUZOQkRF9M1-E;SOx1CJ1IkKb@R&QGE z7ry;7IP}M*7J~+C+5LJj{k5|4s7q`b@M#1N1kE7xmD&`-9zX?_rQ7HA%!<`I_@6eW z;es>*z;U?|-O|#Mgp2|ikiwR_wZmc9@KKpR_H7QK*D+CCD%;%};C}7AJiveg4P&gE_s@hB%wQ3X!UpcUP5?y zF2q>=rSFf()elQuW6y=(Nr$yjZr1QO1RS9U zA2LeYY&<-!=tkxZJEfj$^?=>q~Bzw1&4s(jI3onu;X(d3UPohJSYJrB_;Jx<@mfcyWaN=>G5FEyynGyA!#AgUH=RsOr1;hEG;jR%dURZY#r_b+A;H&;jz-hz^TYA5wz! z59+YWVg*bSAB(6X-$&JR>JMS^f0zqFkk<@iF!?Nzg$WvA@dx%&c6i0;FHOITzXUIN zihq7QZplv_fB#7qGrWSH4+04qih&YuW!mKR!LRUG%^{VRg6O};mxh`{9K*DQ&Bqs2 zj`8+#J@%JUYyBRtnfJuk@Vys+BEXI-A-nfytHLtnG_XNq@3rdzcu!D;%M(2o-F*bP z1@Nq-8++;V-@pCIO2o+@jgtM;o# zGoc!%oB(E_)<%ld=zq8z4Tqv!^yO~rmKY;kRe=Rpr&3#V1=-aI-)HWA*Cttfz;1wI z9499cFk{f8t#JQ)5;{4l$nU&53IrDvsHvF|g&O7_e7>`fpYN`fuuC!5bBH@$X`%kz z;e9Haa|w5YwilFMG&9TPk|b!2cLib`CG@w$NS3Vaxn-3n#2>Nl!7r9FveWN zFb;=d_zlkaKUS;NN?ThSEtktGlVpYrZ!nZfrEKxekRcsIh71`poFx7~E|->Zyd>NH P00000NkvXXu0mjfRmvA3