From a1268e8209a08f66e5db970935d661318115a7d7 Mon Sep 17 00:00:00 2001 From: Sollace Date: Fri, 9 Dec 2022 23:55:53 +0000 Subject: [PATCH] Implement proper composition of abilities when wearing the alicorn amulet --- src/main/java/com/minelittlepony/unicopia/Race.java | 13 ++++++++++++- .../minelittlepony/unicopia/ability/Abilities.java | 7 +++---- .../unicopia/ability/AbilityDispatcher.java | 6 +++--- .../unicopia/client/gui/DismissSpellScreen.java | 2 +- .../minelittlepony/unicopia/client/gui/UHud.java | 5 +++-- .../client/gui/spellbook/ProfileTooltip.java | 5 +++-- .../gui/spellbook/SpellbookProfilePageContent.java | 8 +++++++- .../entity/effect/SunBlindnessStatusEffect.java | 2 +- .../unicopia/entity/player/PlayerPhysics.java | 6 +++--- .../minelittlepony/unicopia/entity/player/Pony.java | 11 ++++++++--- .../item/RacePredicatedAliasedBlockItem.java | 2 +- .../minelittlepony/unicopia/item/toxin/Ailment.java | 4 ++-- 12 files changed, 47 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/Race.java b/src/main/java/com/minelittlepony/unicopia/Race.java index 7a7a8815..34d5e6af 100644 --- a/src/main/java/com/minelittlepony/unicopia/Race.java +++ b/src/main/java/com/minelittlepony/unicopia/Race.java @@ -1,6 +1,7 @@ package com.minelittlepony.unicopia; -import java.util.Set; +import java.util.*; +import java.util.function.Predicate; import java.util.stream.Collectors; import org.jetbrains.annotations.Nullable; @@ -197,6 +198,16 @@ public final class Race implements Affine { public static Set allPermitted(PlayerEntity player) { return REGISTRY.stream().filter(r -> r.isPermitted(player)).collect(Collectors.toSet()); } + + public record Composite (Race physical, Race pseudo) { + public boolean includes(Race race) { + return physical == race || pseudo == race; + } + + public boolean any(Predicate test) { + return test.test(physical) || test.test(pseudo); + } + } } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/Abilities.java b/src/main/java/com/minelittlepony/unicopia/ability/Abilities.java index 79cf5348..10c2f57a 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/Abilities.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/Abilities.java @@ -11,17 +11,16 @@ import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.util.Registries; -import net.minecraft.util.Identifier; -import net.minecraft.util.Util; +import net.minecraft.util.*; import net.minecraft.util.registry.Registry; public interface Abilities { Registry> REGISTRY = Registries.createSimple(Unicopia.id("abilities")); Map>> BY_SLOT = new EnumMap<>(AbilitySlot.class); - BiFunction>> BY_SLOT_AND_RACE = Util.memoize((slot, race) -> { + BiFunction>> BY_SLOT_AND_COMPOSITE_RACE = Util.memoize((slot, race) -> { return BY_SLOT.computeIfAbsent(slot, s -> new LinkedHashSet<>()) .stream() - .filter(a -> a.canUse(race)) + .filter(a -> race.any(a::canUse)) .toList(); }); diff --git a/src/main/java/com/minelittlepony/unicopia/ability/AbilityDispatcher.java b/src/main/java/com/minelittlepony/unicopia/ability/AbilityDispatcher.java index a020cb15..a6260430 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/AbilityDispatcher.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/AbilityDispatcher.java @@ -224,7 +224,7 @@ public class AbilityDispatcher implements Tickable, NbtSerialisable { } public Optional> getAbility(long page) { - List> found = Abilities.BY_SLOT_AND_RACE.apply(slot, player.getSpecies()); + List> found = Abilities.BY_SLOT_AND_COMPOSITE_RACE.apply(slot, player.getCompositeRace()); if (found.isEmpty()) { return Optional.empty(); } @@ -233,7 +233,7 @@ public class AbilityDispatcher implements Tickable, NbtSerialisable { } public long getMaxPage() { - return Abilities.BY_SLOT_AND_RACE.apply(slot, player.getSpecies()).size(); + return Abilities.BY_SLOT_AND_COMPOSITE_RACE.apply(slot, player.getCompositeRace()).size(); } protected synchronized Optional> setActiveAbility(@Nullable Ability power) { @@ -249,7 +249,7 @@ public class AbilityDispatcher implements Tickable, NbtSerialisable { protected synchronized Optional> getActiveAbility() { return activeAbility.filter(ability -> { - return (!(ability == null || (triggered && warmup == 0 && cooldown == 0)) && ability.canUse(player.getSpecies())); + return (!(ability == null || (triggered && warmup == 0 && cooldown == 0)) && player.getCompositeRace().any(ability::canUse)); }); } diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java b/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java index c2dc992d..abb4478a 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java @@ -84,7 +84,7 @@ public class DismissSpellScreen extends GameGui { DrawableUtil.drawArc(matrices, 160, 1600, 0, DrawableUtil.TAU, 0x00000020, false); super.render(matrices, mouseX, mouseY, delta); - DrawableUtil.renderRaceIcon(matrices, pony.getSpecies(), 0, 0, 16); + DrawableUtil.renderRaceIcon(matrices, pony.getObservedSpecies(), 0, 0, 16); matrices.pop(); DrawableUtil.drawLine(matrices, mouseX, mouseY - 4, mouseX, mouseY + 4, 0xFFAAFF99); 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 16f80ecb..f5e971c6 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java @@ -14,6 +14,7 @@ import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellTyp 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.behaviour.EntityAppearance; import com.minelittlepony.unicopia.entity.effect.SunBlindnessStatusEffect; import com.minelittlepony.unicopia.entity.effect.UEffects; @@ -125,7 +126,7 @@ public class UHud extends DrawableHelper { matrices.pop(); - if (pony.getActualSpecies().canCast()) { + if (pony.getActualSpecies().canCast() || AmuletSelectors.ALICORN_AMULET.test(pony.getMaster())) { renderSpell(pony.getCharms().getEquippedSpell(Hand.MAIN_HAND), hudX + 15 - xDirection * 13, hudY + 3); renderSpell(pony.getCharms().getEquippedSpell(Hand.OFF_HAND), hudX + 15 - xDirection * 2, hudY - 3); } @@ -217,7 +218,7 @@ public class UHud extends DrawableHelper { ItemStack glasses = GlassesItem.getForEntity(client.player); boolean hasSunglasses = glasses.getItem() == UItems.SUNGLASSES; - if (hasEffect || (!hasSunglasses && pony.getSpecies() == Race.BAT && SunBlindnessStatusEffect.hasSunExposure(client.player))) { + if (hasEffect || (!hasSunglasses && pony.getObservedSpecies() == Race.BAT && SunBlindnessStatusEffect.hasSunExposure(client.player))) { float i = hasEffect ? (client.player.getStatusEffect(UEffects.SUN_BLINDNESS).getDuration() - tickDelta) / SunBlindnessStatusEffect.MAX_DURATION : 0; float pulse = (1 + (float)Math.sin(client.player.age / 108F)) * 0.25F; diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/ProfileTooltip.java b/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/ProfileTooltip.java index 27d27f4a..75017334 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/ProfileTooltip.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/ProfileTooltip.java @@ -11,10 +11,11 @@ public class ProfileTooltip { public static Tooltip get(Pony pony) { return () -> { return List.of( - Text.literal(String.format("Level %d ", pony.getLevel().get() + 1)).append(pony.getSpecies().getDisplayName()).formatted(pony.getSpecies().getAffinity().getColor()), + Text.literal(String.format("Level %d ", pony.getLevel().get() + 1)).append(pony.getActualSpecies().getDisplayName()).formatted(pony.getSpecies().getAffinity().getColor()), Text.literal(String.format("Mana: %d%%", (int)(pony.getMagicalReserves().getMana().getPercentFill() * 100))), + Text.literal(String.format("Corruption: %d%%", (int)(pony.getCorruption().getScaled(100)))), Text.literal(String.format("Experience: %d", (int)(pony.getMagicalReserves().getXp().getPercentFill() * 100))), - Text.literal(String.format("Next level in: %d experience points", 100 - (int)(pony.getMagicalReserves().getXp().getPercentFill() * 100))) + Text.literal(String.format("Next level in: %dxp", 100 - (int)(pony.getMagicalReserves().getXp().getPercentFill() * 100))) ); }; } 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 c56407a2..a3e75028 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 @@ -36,9 +36,15 @@ public class SpellbookProfilePageContent extends DrawableHelper implements Spell screen.addDrawable(new SpellbookScreen.ImageButton(x, y, size, size)) .getStyle() - .setIcon(TribeButton.createSprite(pony.getSpecies(), 0, 0, size)) + .setIcon(TribeButton.createSprite(pony.getActualSpecies(), 0, 0, size)) .setTooltip(ProfileTooltip.get(pony)); + if (pony.getSpecies() != pony.getActualSpecies()) { + int halfSize = size / 2; + screen.addDrawable(new SpellbookScreen.ImageButton(x + halfSize, y + halfSize, halfSize, halfSize)) + .getStyle() + .setIcon(TribeButton.createSprite(pony.getSpecies(), 0, 0, halfSize)); + } float mainAngle = 90 * MathHelper.RADIANS_PER_DEGREE; float offAngle = 60 * MathHelper.RADIANS_PER_DEGREE; diff --git a/src/main/java/com/minelittlepony/unicopia/entity/effect/SunBlindnessStatusEffect.java b/src/main/java/com/minelittlepony/unicopia/entity/effect/SunBlindnessStatusEffect.java index 776812ce..5df140cb 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/effect/SunBlindnessStatusEffect.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/effect/SunBlindnessStatusEffect.java @@ -56,7 +56,7 @@ public class SunBlindnessStatusEffect extends StatusEffect { public static boolean isSunImmune(LivingEntity entity) { return entity.hasStatusEffect(StatusEffects.BLINDNESS) || entity.hasPortalCooldown() - || Pony.of(entity).map(pony -> pony.isSunImmune()).orElse(false); + || Pony.of(entity).filter(Pony::isSunImmune).isPresent(); } public static boolean hasSunExposure(LivingEntity entity) { 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 94eccbf7..6f31ec41 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java @@ -218,7 +218,7 @@ public class PlayerPhysics extends EntityPhysics implements Tickab if ((entity.isOnGround() && entity.isSneaking()) || entity.isTouchingWater() || entity.horizontalCollision - || (entity.verticalCollision && (pony.getSpecies() != Race.BAT || velocity.y < 0))) { + || (entity.verticalCollision && (pony.getObservedSpecies() != Race.BAT || velocity.y < 0))) { if (entity.getAbilities().flying && entity.horizontalCollision) { handleWallCollission(velocity); @@ -251,7 +251,7 @@ public class PlayerPhysics extends EntityPhysics implements Tickab if (type.canFly()) { if (isFlying()) { - if (pony.getSpecies() == Race.BAT && entity.verticalCollision && pony.canHangAt(pony.getOrigin().up(2))) { + if (pony.getObservedSpecies() == Race.BAT && entity.verticalCollision && pony.canHangAt(pony.getOrigin().up(2))) { EntityAttributeInstance attr = entity.getAttributeInstance(UEntityAttributes.ENTITY_GRAVTY_MODIFIER); if (!attr.hasModifier(PlayerAttributes.BAT_HANGING)) { @@ -327,7 +327,7 @@ public class PlayerPhysics extends EntityPhysics implements Tickab if (type.isAvian()) { applyThrust(velocity); - if (pony.getSpecies() != Race.BAT && entity.world.random.nextInt(9000) == 0) { + if (pony.getObservedSpecies() != Race.BAT && entity.world.random.nextInt(9000) == 0) { entity.dropItem(UItems.PEGASUS_FEATHER); entity.playSound(USounds.ENTITY_PLAYER_PEGASUS_MOLT, 0.3F, 1); UCriteria.SHED_FEATHER.trigger(entity); 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 1cdf0701..bbf08279 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java @@ -181,6 +181,11 @@ public class Pony extends Living implements Transmittable, Copieab .orElse(getActualSpecies()); } + public Race.Composite getCompositeRace() { + Race observed = getObservedSpecies(); + return new Race.Composite(observed, AmuletSelectors.ALICORN_AMULET.test(entity) ? Race.ALICORN : observed); + } + public Race getActualSpecies() { return Race.fromName(entity.getDataTracker().get(RACE), Race.HUMAN); } @@ -287,7 +292,7 @@ public class Pony extends Living implements Transmittable, Copieab public void onSpawn() { if (entity.world instanceof ServerWorld sw - && getSpecies() == Race.BAT + && getObservedSpecies() == Race.BAT && sw.getServer().getSaveProperties().getGameMode() != GameMode.ADVENTURE && SunBlindnessStatusEffect.isPositionExposedToSun(sw, getOrigin())) { SpawnLocator.selectSpawnPosition(sw, entity); @@ -371,14 +376,14 @@ public class Pony extends Living implements Transmittable, Copieab if (isHanging()) { ((LivingEntityDuck)entity).setLeaningPitch(0); - if (!isClient() && (getSpecies() != Race.BAT || (ticksHanging++ > 2 && hangingPosition.filter(getOrigin().down()::equals).filter(this::canHangAt).isEmpty()))) { + if (!isClient() && (getObservedSpecies() != Race.BAT || (ticksHanging++ > 2 && hangingPosition.filter(getOrigin().down()::equals).filter(this::canHangAt).isEmpty()))) { stopHanging(); } } else { ticksHanging = 0; } - if (getSpecies() == Race.BAT && !entity.hasPortalCooldown()) { + if (getObservedSpecies() == Race.BAT && !entity.hasPortalCooldown()) { if (SunBlindnessStatusEffect.hasSunExposure(entity)) { if (ticksInSun < 200) { ticksInSun++; diff --git a/src/main/java/com/minelittlepony/unicopia/item/RacePredicatedAliasedBlockItem.java b/src/main/java/com/minelittlepony/unicopia/item/RacePredicatedAliasedBlockItem.java index e4bf9179..f2abdf67 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/RacePredicatedAliasedBlockItem.java +++ b/src/main/java/com/minelittlepony/unicopia/item/RacePredicatedAliasedBlockItem.java @@ -22,7 +22,7 @@ public class RacePredicatedAliasedBlockItem extends AliasedBlockItem { @Override public ActionResult useOnBlock(ItemUsageContext context) { Pony pony = Pony.of(context.getPlayer()); - if (pony == null || !predicate.test(pony.getSpecies())) { + if (pony == null || !predicate.test(pony.getObservedSpecies())) { return ActionResult.FAIL; } diff --git a/src/main/java/com/minelittlepony/unicopia/item/toxin/Ailment.java b/src/main/java/com/minelittlepony/unicopia/item/toxin/Ailment.java index 735b9f55..0433df21 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/toxin/Ailment.java +++ b/src/main/java/com/minelittlepony/unicopia/item/toxin/Ailment.java @@ -37,7 +37,7 @@ public record Ailment ( } public TypedActionResult use(World world, PlayerEntity player, Hand hand) { - if (!Pony.of(player).getSpecies().hasIronGut()) { + if (!Pony.of(player).getObservedSpecies().hasIronGut()) { return TypedActionResult.fail(player.getStackInHand(hand)); } return null; @@ -52,7 +52,7 @@ public record Ailment ( if (map.isEmpty()) { return of(def); } - return entity -> Optional.of(entity instanceof PlayerEntity player ? map.getOrDefault(Pony.of(player).getSpecies(), def) : def); + return entity -> Optional.of(entity instanceof PlayerEntity player ? map.getOrDefault(Pony.of(player).getObservedSpecies(), def) : def); } static Ailment.Set of(Ailment ailment) {