mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-02-01 11:36:43 +01:00
Make the seapony transformation into an ability granted if you're wearing the necklace
This commit is contained in:
parent
5dbff11d7a
commit
e0826bf1e3
6 changed files with 148 additions and 11 deletions
|
@ -27,6 +27,7 @@ import net.minecraft.registry.RegistryKey;
|
||||||
public record Race (Supplier<Composite> compositeSupplier, Availability availability, boolean canCast, FlightType flightType, boolean canUseEarth, boolean isNocturnal, boolean canHang) implements Affine {
|
public record Race (Supplier<Composite> compositeSupplier, Availability availability, boolean canCast, FlightType flightType, boolean canUseEarth, boolean isNocturnal, boolean canHang) implements Affine {
|
||||||
public static final String DEFAULT_ID = "unicopia:unset";
|
public static final String DEFAULT_ID = "unicopia:unset";
|
||||||
public static final Registry<Race> REGISTRY = RegistryUtils.createDefaulted(Unicopia.id("race"), DEFAULT_ID);
|
public static final Registry<Race> REGISTRY = RegistryUtils.createDefaulted(Unicopia.id("race"), DEFAULT_ID);
|
||||||
|
public static final Registry<Race> COMMAND_REGISTRY = RegistryUtils.createDefaulted(Unicopia.id("race/grantable"), DEFAULT_ID);
|
||||||
public static final RegistryKey<? extends Registry<Race>> REGISTRY_KEY = REGISTRY.getKey();
|
public static final RegistryKey<? extends Registry<Race>> REGISTRY_KEY = REGISTRY.getKey();
|
||||||
private static final DynamicCommandExceptionType UNKNOWN_RACE_EXCEPTION = new DynamicCommandExceptionType(id -> Text.translatable("race.unknown", id));
|
private static final DynamicCommandExceptionType UNKNOWN_RACE_EXCEPTION = new DynamicCommandExceptionType(id -> Text.translatable("race.unknown", id));
|
||||||
|
|
||||||
|
@ -35,11 +36,15 @@ public record Race (Supplier<Composite> compositeSupplier, Availability availabi
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Race register(Identifier id, Availability availability, boolean magic, FlightType flight, boolean earth, boolean nocturnal, boolean canHang) {
|
public static Race register(Identifier id, Availability availability, boolean magic, FlightType flight, boolean earth, boolean nocturnal, boolean canHang) {
|
||||||
return Registry.register(REGISTRY, id, new Race(Suppliers.memoize(() -> new Composite(REGISTRY.get(id), null)), availability, magic, flight, earth, nocturnal, canHang));
|
Race race = Registry.register(REGISTRY, id, new Race(Suppliers.memoize(() -> new Composite(REGISTRY.get(id), null, null)), availability, magic, flight, earth, nocturnal, canHang));
|
||||||
|
if (availability.isGrantable()) {
|
||||||
|
Registry.register(COMMAND_REGISTRY, id, race);
|
||||||
|
}
|
||||||
|
return race;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static RegistryKeyArgumentType<Race> argument() {
|
public static RegistryKeyArgumentType<Race> argument() {
|
||||||
return RegistryKeyArgumentType.registryKey(REGISTRY_KEY);
|
return RegistryKeyArgumentType.registryKey(COMMAND_REGISTRY.getKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -64,8 +69,8 @@ public record Race (Supplier<Composite> compositeSupplier, Availability availabi
|
||||||
return compositeSupplier.get();
|
return compositeSupplier.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Composite composite(@Nullable Race pseudo) {
|
public Composite composite(@Nullable Race pseudo, @Nullable Race potential) {
|
||||||
return pseudo == null ? composite() : new Composite(this, pseudo);
|
return pseudo == null && potential == null ? composite() : new Composite(this, pseudo, potential);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -147,6 +152,10 @@ public record Race (Supplier<Composite> compositeSupplier, Availability availabi
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Race or(Race other) {
|
||||||
|
return isEquine() ? this : other;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return getId().hashCode();
|
return getId().hashCode();
|
||||||
|
@ -194,7 +203,7 @@ public record Race (Supplier<Composite> compositeSupplier, Availability availabi
|
||||||
return REGISTRY.stream().filter(r -> r.isPermitted(player)).collect(Collectors.toSet());
|
return REGISTRY.stream().filter(r -> r.isPermitted(player)).collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
public record Composite (Race physical, @Nullable Race pseudo) {
|
public record Composite (Race physical, @Nullable Race pseudo, @Nullable Race potential) {
|
||||||
public Race collapsed() {
|
public Race collapsed() {
|
||||||
return pseudo == null ? physical : pseudo;
|
return pseudo == null ? physical : pseudo;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,9 @@ public interface Abilities {
|
||||||
.toList();
|
.toList();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// all races
|
||||||
|
Ability<?> CHANGE_FORM = register(new ChangeFormAbility(), "change_form", AbilitySlot.PRIMARY);
|
||||||
|
|
||||||
// unicorn / alicorn
|
// unicorn / alicorn
|
||||||
Ability<?> CAST = register(new UnicornCastingAbility(), "cast", AbilitySlot.PRIMARY);
|
Ability<?> CAST = register(new UnicornCastingAbility(), "cast", AbilitySlot.PRIMARY);
|
||||||
Ability<?> SHOOT = register(new UnicornProjectileAbility(), "shoot", AbilitySlot.PRIMARY);
|
Ability<?> SHOOT = register(new UnicornProjectileAbility(), "shoot", AbilitySlot.PRIMARY);
|
||||||
|
|
|
@ -179,6 +179,10 @@ public class AbilityDispatcher implements Tickable, NbtSerialisable {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cooldown > 100 && player.asEntity().isCreative()) {
|
||||||
|
cooldown = Math.max(10, cooldown - 100);
|
||||||
|
}
|
||||||
|
|
||||||
if (cooldown > 0 && cooldown-- > 0) {
|
if (cooldown > 0 && cooldown-- > 0) {
|
||||||
ability.coolDown(player, slot);
|
ability.coolDown(player, slot);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
package com.minelittlepony.unicopia.ability;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.Race;
|
||||||
|
import com.minelittlepony.unicopia.USounds;
|
||||||
|
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||||
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
|
|
||||||
|
import net.minecraft.particle.ParticleTypes;
|
||||||
|
import net.minecraft.sound.SoundCategory;
|
||||||
|
import net.minecraft.sound.SoundEvents;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
public class ChangeFormAbility implements Ability<Hit> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getWarmupTime(Pony player) {
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCooldownTime(Pony player) {
|
||||||
|
return 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canUse(Race.Composite race) {
|
||||||
|
return race.potential() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canUse(Race race) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Identifier getIcon(Pony player) {
|
||||||
|
Race potential = player.getCompositeRace().potential();
|
||||||
|
if (potential == null) {
|
||||||
|
return Ability.super.getIcon(player);
|
||||||
|
}
|
||||||
|
return getId().withPath(p -> "textures/gui/ability/" + p + "_" + potential.getId().getPath() + ".png");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Optional<Hit> prepare(Pony player) {
|
||||||
|
return Hit.of(canUse(player.getCompositeRace()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Hit.Serializer<Hit> getSerializer() {
|
||||||
|
return Hit.SERIALIZER;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getCostEstimate(Pony player) {
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Pony player, Hit data) {
|
||||||
|
if (prepare(player).isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
player.subtractEnergyCost(5);
|
||||||
|
|
||||||
|
Race.Composite composite = player.getCompositeRace();
|
||||||
|
Race actualRace = player.getSpecies();
|
||||||
|
player.setSpecies(composite.potential());
|
||||||
|
player.setSuppressedRace(actualRace.availability().isGrantable() ? actualRace : Race.UNSET);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void warmUp(Pony player, AbilitySlot slot) {
|
||||||
|
player.getMagicalReserves().getExertion().addPercent(6);
|
||||||
|
|
||||||
|
if (player.getAbilities().getStat(slot).getWarmup() % 5 == 0) {
|
||||||
|
player.asWorld().playSound(null, player.getOrigin(), SoundEvents.BLOCK_BUBBLE_COLUMN_WHIRLPOOL_INSIDE, SoundCategory.PLAYERS);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.asWorld().random.nextInt(5) == 0) {
|
||||||
|
player.asWorld().playSound(null, player.getOrigin(), USounds.Vanilla.BLOCK_BUBBLE_COLUMN_BUBBLE_POP, SoundCategory.PLAYERS);
|
||||||
|
}
|
||||||
|
|
||||||
|
player.spawnParticles(ParticleTypes.BUBBLE_COLUMN_UP, 15);
|
||||||
|
player.spawnParticles(ParticleTypes.BUBBLE_POP, 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void coolDown(Pony player, AbilitySlot slot) {
|
||||||
|
}
|
||||||
|
}
|
|
@ -60,8 +60,7 @@ public class EarthPonyKickAbility implements Ability<Pos> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Identifier getIcon(Pony player) {
|
public Identifier getIcon(Pony player) {
|
||||||
Identifier id = Abilities.REGISTRY.getId(this);
|
return getId().withPath(p -> "textures/gui/ability/" + p
|
||||||
return new Identifier(id.getNamespace(), "textures/gui/ability/" + id.getPath()
|
|
||||||
+ "_" + player.getObservedSpecies().getId().getPath()
|
+ "_" + player.getObservedSpecies().getId().getPath()
|
||||||
+ "_" + (getKickDirection(player) > 0 ? "forward" : "backward")
|
+ "_" + (getKickDirection(player) > 0 ? "forward" : "backward")
|
||||||
+ ".png");
|
+ ".png");
|
||||||
|
|
|
@ -66,6 +66,7 @@ import net.minecraft.world.GameRules;
|
||||||
|
|
||||||
public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, UpdateCallback {
|
public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, UpdateCallback {
|
||||||
private static final TrackedData<String> RACE = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.STRING);
|
private static final TrackedData<String> RACE = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.STRING);
|
||||||
|
private static final TrackedData<String> SUPPRESSED_RACE = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.STRING);
|
||||||
|
|
||||||
static final TrackedData<Float> ENERGY = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.FLOAT);
|
static final TrackedData<Float> ENERGY = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.FLOAT);
|
||||||
static final TrackedData<Float> EXHAUSTION = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.FLOAT);
|
static final TrackedData<Float> EXHAUSTION = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.FLOAT);
|
||||||
|
@ -120,6 +121,7 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
|
||||||
this.mana = addTicker(new ManaContainer(this));
|
this.mana = addTicker(new ManaContainer(this));
|
||||||
|
|
||||||
player.getDataTracker().startTracking(RACE, Race.DEFAULT_ID);
|
player.getDataTracker().startTracking(RACE, Race.DEFAULT_ID);
|
||||||
|
player.getDataTracker().startTracking(SUPPRESSED_RACE, Race.DEFAULT_ID);
|
||||||
|
|
||||||
addTicker(this::updateAnimations);
|
addTicker(this::updateAnimations);
|
||||||
addTicker(this::updateBatPonyAbilities);
|
addTicker(this::updateBatPonyAbilities);
|
||||||
|
@ -223,8 +225,13 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
|
||||||
@Override
|
@Override
|
||||||
public void setSpecies(Race race) {
|
public void setSpecies(Race race) {
|
||||||
race = race.validate(entity);
|
race = race.validate(entity);
|
||||||
|
Race current = getSpecies();
|
||||||
|
entity.getDataTracker().set(RACE, Race.REGISTRY.getId(race.validate(entity)).toString());
|
||||||
|
if (race != current) {
|
||||||
|
clearSuppressedRace();
|
||||||
|
}
|
||||||
|
|
||||||
ticksInSun = 0;
|
ticksInSun = 0;
|
||||||
entity.getDataTracker().set(RACE, Race.REGISTRY.getId(race).toString());
|
|
||||||
|
|
||||||
gravity.updateFlightState();
|
gravity.updateFlightState();
|
||||||
entity.sendAbilitiesUpdate();
|
entity.sendAbilitiesUpdate();
|
||||||
|
@ -232,6 +239,18 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
|
||||||
UCriteria.PLAYER_CHANGE_RACE.trigger(entity);
|
UCriteria.PLAYER_CHANGE_RACE.trigger(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSuppressedRace(Race race) {
|
||||||
|
entity.getDataTracker().set(SUPPRESSED_RACE, Race.REGISTRY.getId(race.validate(entity)).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearSuppressedRace() {
|
||||||
|
setSuppressedRace(Race.UNSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Race getSuppressedRace() {
|
||||||
|
return Race.fromName(entity.getDataTracker().get(SUPPRESSED_RACE), Race.UNSET);
|
||||||
|
}
|
||||||
|
|
||||||
public TraitDiscovery getDiscoveries() {
|
public TraitDiscovery getDiscoveries() {
|
||||||
return discoveries;
|
return discoveries;
|
||||||
}
|
}
|
||||||
|
@ -354,17 +373,19 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
|
||||||
@Override
|
@Override
|
||||||
public boolean beforeUpdate() {
|
public boolean beforeUpdate() {
|
||||||
if (compositeRace.includes(Race.UNSET) || entity.age % 2 == 0) {
|
if (compositeRace.includes(Race.UNSET) || entity.age % 2 == 0) {
|
||||||
|
Race intrinsicRace = getSpecies();
|
||||||
|
Race suppressedRace = getSuppressedRace();
|
||||||
compositeRace = getSpellSlot()
|
compositeRace = getSpellSlot()
|
||||||
.get(SpellPredicate.IS_MIMIC, true)
|
.get(SpellPredicate.IS_MIMIC, true)
|
||||||
.map(AbstractDisguiseSpell::getDisguise)
|
.map(AbstractDisguiseSpell::getDisguise)
|
||||||
.map(EntityAppearance::getAppearance)
|
.map(EntityAppearance::getAppearance)
|
||||||
.flatMap(Pony::of)
|
.flatMap(Pony::of)
|
||||||
.map(Pony::getSpecies)
|
.map(Pony::getSpecies)
|
||||||
.orElseGet(this::getSpecies).composite(
|
.orElse(intrinsicRace).composite(
|
||||||
AmuletSelectors.UNICORN_AMULET.test(entity) ? Race.UNICORN
|
AmuletSelectors.UNICORN_AMULET.test(entity) ? Race.UNICORN
|
||||||
: AmuletSelectors.ALICORN_AMULET.test(entity) ? Race.ALICORN
|
: AmuletSelectors.ALICORN_AMULET.test(entity) ? Race.ALICORN
|
||||||
: AmuletSelectors.PEARL_NECKLACE.test(entity) ? Race.SEAPONY
|
: null,
|
||||||
: null
|
AmuletSelectors.PEARL_NECKLACE.test(entity) ? suppressedRace.or(Race.SEAPONY) : null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -794,6 +815,7 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
|
||||||
public void toSyncronisedNbt(NbtCompound compound) {
|
public void toSyncronisedNbt(NbtCompound compound) {
|
||||||
super.toSyncronisedNbt(compound);
|
super.toSyncronisedNbt(compound);
|
||||||
compound.putString("playerSpecies", Race.REGISTRY.getId(getSpecies()).toString());
|
compound.putString("playerSpecies", Race.REGISTRY.getId(getSpecies()).toString());
|
||||||
|
compound.putString("suppressedSpecies", Race.REGISTRY.getId(getSuppressedRace()).toString());
|
||||||
compound.putFloat("magicExhaustion", magicExhaustion);
|
compound.putFloat("magicExhaustion", magicExhaustion);
|
||||||
compound.putInt("ticksInSun", ticksInSun);
|
compound.putInt("ticksInSun", ticksInSun);
|
||||||
compound.putBoolean("hasShades", hasShades);
|
compound.putBoolean("hasShades", hasShades);
|
||||||
|
@ -819,6 +841,7 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
|
||||||
public void fromSynchronizedNbt(NbtCompound compound) {
|
public void fromSynchronizedNbt(NbtCompound compound) {
|
||||||
super.fromSynchronizedNbt(compound);
|
super.fromSynchronizedNbt(compound);
|
||||||
setSpecies(Race.fromName(compound.getString("playerSpecies"), Race.HUMAN));
|
setSpecies(Race.fromName(compound.getString("playerSpecies"), Race.HUMAN));
|
||||||
|
setSuppressedRace(Race.fromName(compound.getString("suppressedSpecies"), Race.UNSET));
|
||||||
powers.fromNBT(compound.getCompound("powers"));
|
powers.fromNBT(compound.getCompound("powers"));
|
||||||
gravity.fromNBT(compound.getCompound("gravity"));
|
gravity.fromNBT(compound.getCompound("gravity"));
|
||||||
charms.fromNBT(compound.getCompound("charms"));
|
charms.fromNBT(compound.getCompound("charms"));
|
||||||
|
|
Loading…
Reference in a new issue