mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-27 15:17:59 +01:00
Implement bat wings and unicorn horns for ponies that don't normally have them but are those races in the mod
This commit is contained in:
parent
49e74f4c54
commit
5ec332a165
5 changed files with 149 additions and 120 deletions
|
@ -59,9 +59,7 @@ public class EarthPonyKickAbility implements Ability<Pos> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double getCostEstimate(Pony player) {
|
public double getCostEstimate(Pony player) {
|
||||||
double distance = MineLPDelegate.getInstance().getPlayerPonyRace(player.asEntity()).isHuman() ? 6 : -6;
|
return TraceHelper.findBlock(player.asEntity(), getKickDirection(player) * 6, 1)
|
||||||
|
|
||||||
return TraceHelper.findBlock(player.asEntity(), distance, 1)
|
|
||||||
.filter(pos -> TreeType.at(pos, player.asWorld()) != TreeType.NONE)
|
.filter(pos -> TreeType.at(pos, player.asWorld()) != TreeType.NONE)
|
||||||
.isPresent() ? 3 : 1;
|
.isPresent() ? 3 : 1;
|
||||||
}
|
}
|
||||||
|
@ -121,7 +119,7 @@ public class EarthPonyKickAbility implements Ability<Pos> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getKickDirection(Pony player) {
|
private int getKickDirection(Pony player) {
|
||||||
return MineLPDelegate.getInstance().getPlayerPonyRace(player.asEntity()).isHuman() ? 1 : -1;
|
return MineLPDelegate.getInstance().getPlayerPonyRace(player.asEntity()).isEquine() ? -1 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Pos getDefaultKickLocation(Pony player) {
|
private Pos getDefaultKickLocation(Pony player) {
|
||||||
|
|
|
@ -38,7 +38,7 @@ public class PegasusRainboomAbility implements Ability<Hit> {
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public Optional<Hit> prepare(Pony player) {
|
public Optional<Hit> prepare(Pony player) {
|
||||||
return Hit.of(player.canUseSuperMove() && player.getPhysics().isFlying() && !SpellType.RAINBOOM.isOn(player));
|
return Hit.of(player.canUseSuperMove() && player.getPhysics().isFlying() && !player.getMotion().isRainbooming());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -54,7 +54,7 @@ public class PegasusRainboomAbility implements Ability<Hit> {
|
||||||
@Override
|
@Override
|
||||||
public boolean onQuickAction(Pony player, ActivationType type, Optional<Hit> data) {
|
public boolean onQuickAction(Pony player, ActivationType type, Optional<Hit> data) {
|
||||||
|
|
||||||
if (type == ActivationType.TAP && player.getPhysics().isFlying() && player.getMagicalReserves().getMana().get() > 40) {
|
if (type == ActivationType.TAP && !player.getMotion().isRainbooming() && player.getPhysics().isFlying() && player.getMagicalReserves().getMana().get() > 40) {
|
||||||
player.getPhysics().dashForward((float)player.asWorld().random.nextTriangular(2.5F, 0.3F));
|
player.getPhysics().dashForward((float)player.asWorld().random.nextTriangular(2.5F, 0.3F));
|
||||||
player.subtractEnergyCost(4);
|
player.subtractEnergyCost(4);
|
||||||
player.getMagicalReserves().getCharge().add(2);
|
player.getMagicalReserves().getCharge().add(2);
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
package com.minelittlepony.unicopia.client.minelittlepony;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import com.minelittlepony.api.model.*;
|
||||||
|
import com.minelittlepony.api.model.gear.IGear;
|
||||||
|
import com.minelittlepony.client.model.ClientPonyModel;
|
||||||
|
import com.minelittlepony.client.model.ModelType;
|
||||||
|
import com.minelittlepony.client.model.PlayerModelKey;
|
||||||
|
import com.minelittlepony.client.model.entity.race.PegasusModel;
|
||||||
|
import com.minelittlepony.client.model.entity.race.UnicornModel;
|
||||||
|
import com.minelittlepony.client.model.part.UnicornHorn;
|
||||||
|
import com.minelittlepony.mson.api.MsonModel;
|
||||||
|
import com.minelittlepony.unicopia.EquinePredicates;
|
||||||
|
import com.minelittlepony.unicopia.Race;
|
||||||
|
import com.minelittlepony.unicopia.Unicopia;
|
||||||
|
import com.minelittlepony.unicopia.entity.AmuletSelectors;
|
||||||
|
|
||||||
|
import net.minecraft.client.model.ModelPart;
|
||||||
|
import net.minecraft.client.render.VertexConsumer;
|
||||||
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
class BodyPartGear<M extends ClientPonyModel<LivingEntity> & MsonModel & IModel> implements IGear {
|
||||||
|
private static final Identifier ICARUS_WINGS = Unicopia.id("textures/models/wings/icarus_pony.png");
|
||||||
|
private static final Identifier ICARUS_WINGS_CORRUPTED = Unicopia.id("textures/models/wings/icarus_corrupted_pony.png");
|
||||||
|
|
||||||
|
public static final Predicate<LivingEntity> BAT_WINGS_PREDICATE = AmuletSelectors.PEGASUS_AMULET.negate().and(EquinePredicates.PLAYER_BAT);
|
||||||
|
public static final Identifier BAT_WINGS = Unicopia.id("textures/models/wings/bat_pony.png");
|
||||||
|
|
||||||
|
public static final Predicate<LivingEntity> UNICORN_HORN_PREDICATE = AmuletSelectors.ALICORN_AMULET.or(EquinePredicates.raceMatches(Race::canCast));
|
||||||
|
public static final Identifier UNICORN_HORN = Unicopia.id("textures/models/horn/unicorn.png");
|
||||||
|
|
||||||
|
public static final Predicate<LivingEntity> PEGA_WINGS_PREDICATE = AmuletSelectors.PEGASUS_AMULET.or(EquinePredicates.raceMatches(Race::canInteractWithClouds));
|
||||||
|
public static final Identifier PEGASUS_WINGS = Unicopia.id("textures/models/wings/pegasus_pony.png");
|
||||||
|
|
||||||
|
public static BodyPartGear<WingsGearModel> pegasusWings() {
|
||||||
|
return new BodyPartGear<>(BodyPart.BODY, ModelType.PEGASUS, PEGA_WINGS_PREDICATE, WingsGearModel::new, WingsGearModel::getWings, e -> {
|
||||||
|
if (AmuletSelectors.PEGASUS_AMULET.test((LivingEntity)e)) {
|
||||||
|
return e.getWorld().getDimension().ultrawarm() ? ICARUS_WINGS_CORRUPTED : ICARUS_WINGS;
|
||||||
|
}
|
||||||
|
return PEGASUS_WINGS;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BodyPartGear<WingsGearModel> batWings() {
|
||||||
|
return new BodyPartGear<>(BodyPart.BODY, ModelType.BAT_PONY, BAT_WINGS_PREDICATE, WingsGearModel::new, WingsGearModel::getWings, e -> BAT_WINGS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BodyPartGear<HornGearModel> unicornHorn() {
|
||||||
|
return new BodyPartGear<>(BodyPart.HEAD, ModelType.UNICORN, UNICORN_HORN_PREDICATE, HornGearModel::new, HornGearModel::getHorn, e -> UNICORN_HORN);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final M model;
|
||||||
|
private final Predicate<LivingEntity> renderTargetPredicate;
|
||||||
|
private final IPart part;
|
||||||
|
private final Function<Entity, Identifier> textureSupplier;
|
||||||
|
private final BodyPart gearLocation;
|
||||||
|
|
||||||
|
public BodyPartGear(
|
||||||
|
BodyPart gearLocation,
|
||||||
|
PlayerModelKey<LivingEntity, ? super M> modelKey,
|
||||||
|
Predicate<LivingEntity> renderTargetPredicate,
|
||||||
|
MsonModel.Factory<M> modelFactory,
|
||||||
|
Function<M, IPart> partExtractor,
|
||||||
|
Function<Entity, Identifier> textureSupplier) {
|
||||||
|
this.gearLocation = gearLocation;
|
||||||
|
this.model = modelKey.steveKey().createModel(modelFactory);
|
||||||
|
this.part = partExtractor.apply(this.model);
|
||||||
|
this.renderTargetPredicate = renderTargetPredicate;
|
||||||
|
this.textureSupplier = textureSupplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BodyPart getGearLocation() {
|
||||||
|
return gearLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canRender(IModel model, Entity entity) {
|
||||||
|
return entity instanceof LivingEntity l
|
||||||
|
&& MineLPDelegate.getInstance().getRace(entity).isEquine()
|
||||||
|
&& !MineLPDelegate.getInstance().getRace(entity).canFly()
|
||||||
|
&& renderTargetPredicate.test(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends Entity> Identifier getTexture(T entity, Context<T, ?> context) {
|
||||||
|
return textureSupplier.apply(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
|
@Override
|
||||||
|
public void pose(IModel model, Entity entity, boolean rainboom, UUID interpolatorId, float move, float swing, float bodySwing, float ticks) {
|
||||||
|
((ClientPonyModel)model).copyAttributes(this.model);
|
||||||
|
part.setPartAngles(this.model.getAttributes(), move, swing, bodySwing, ticks);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(MatrixStack stack, VertexConsumer consumer, int light, int overlay, float red, float green, float blue, float alpha, UUID interpolatorId) {
|
||||||
|
part.renderPart(stack, consumer, light, overlay, red, green, blue, alpha, model.getAttributes());
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class WingsGearModel extends PegasusModel<LivingEntity> {
|
||||||
|
public WingsGearModel(ModelPart tree) {
|
||||||
|
super(tree, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canFly() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class HornGearModel extends UnicornModel<LivingEntity> {
|
||||||
|
public HornGearModel(ModelPart tree) {
|
||||||
|
super(tree, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canFly() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UnicornHorn getHorn() {
|
||||||
|
return horn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,7 +27,9 @@ public class Main extends MineLPDelegate implements ClientModInitializer {
|
||||||
IGear.register(() -> new BangleGear(TrinketsDelegate.MAINHAND));
|
IGear.register(() -> new BangleGear(TrinketsDelegate.MAINHAND));
|
||||||
IGear.register(() -> new BangleGear(TrinketsDelegate.OFFHAND));
|
IGear.register(() -> new BangleGear(TrinketsDelegate.OFFHAND));
|
||||||
IGear.register(HeldEntityGear::new);
|
IGear.register(HeldEntityGear::new);
|
||||||
IGear.register(WingsGear::new);
|
IGear.register(BodyPartGear::pegasusWings);
|
||||||
|
IGear.register(BodyPartGear::batWings);
|
||||||
|
IGear.register(BodyPartGear::unicornHorn);
|
||||||
IGear.register(AmuletGear::new);
|
IGear.register(AmuletGear::new);
|
||||||
IGear.register(GlassesGear::new);
|
IGear.register(GlassesGear::new);
|
||||||
}
|
}
|
||||||
|
@ -80,27 +82,14 @@ public class Main extends MineLPDelegate implements ClientModInitializer {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Race toUnicopiaRace(com.minelittlepony.api.pony.meta.Race race) {
|
private static Race toUnicopiaRace(com.minelittlepony.api.pony.meta.Race race) {
|
||||||
switch (race) {
|
return switch (race) {
|
||||||
case ALICORN:
|
case ALICORN -> Race.ALICORN;
|
||||||
return Race.ALICORN;
|
case CHANGELING, CHANGEDLING -> Race.CHANGELING;
|
||||||
case CHANGELING:
|
case ZEBRA, EARTH -> Race.EARTH;
|
||||||
case CHANGEDLING:
|
case GRYPHON, HIPPOGRIFF, PEGASUS -> Race.PEGASUS;
|
||||||
return Race.CHANGELING;
|
case BATPONY -> Race.BAT;
|
||||||
case ZEBRA:
|
case SEAPONY, UNICORN, KIRIN -> Race.UNICORN;
|
||||||
case EARTH:
|
default -> Race.HUMAN;
|
||||||
return Race.EARTH;
|
};
|
||||||
case GRYPHON:
|
|
||||||
case HIPPOGRIFF:
|
|
||||||
case PEGASUS:
|
|
||||||
return Race.PEGASUS;
|
|
||||||
case BATPONY:
|
|
||||||
return Race.BAT;
|
|
||||||
case SEAPONY:
|
|
||||||
case UNICORN:
|
|
||||||
case KIRIN:
|
|
||||||
return Race.UNICORN;
|
|
||||||
default:
|
|
||||||
return Race.HUMAN;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,91 +0,0 @@
|
||||||
package com.minelittlepony.unicopia.client.minelittlepony;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import com.minelittlepony.api.model.*;
|
|
||||||
import com.minelittlepony.api.model.gear.IGear;
|
|
||||||
import com.minelittlepony.api.pony.*;
|
|
||||||
import com.minelittlepony.client.model.ClientPonyModel;
|
|
||||||
import com.minelittlepony.client.model.ModelType;
|
|
||||||
import com.minelittlepony.client.model.entity.race.PegasusModel;
|
|
||||||
import com.minelittlepony.unicopia.Race;
|
|
||||||
import com.minelittlepony.unicopia.Unicopia;
|
|
||||||
import com.minelittlepony.unicopia.entity.*;
|
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
|
||||||
|
|
||||||
import net.minecraft.client.model.ModelPart;
|
|
||||||
import net.minecraft.client.render.VertexConsumer;
|
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
|
||||||
import net.minecraft.entity.Entity;
|
|
||||||
import net.minecraft.entity.LivingEntity;
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
|
|
||||||
class WingsGear implements IGear {
|
|
||||||
private static final Identifier ICARUS_WINGS = Unicopia.id("textures/models/wings/icarus_pony.png");
|
|
||||||
private static final Identifier ICARUS_WINGS_CORRUPTED = Unicopia.id("textures/models/wings/icarus_corrupted_pony.png");
|
|
||||||
private static final Identifier PEGASUS_WINGS = Unicopia.id("textures/models/wings/pegasus_pony.png");
|
|
||||||
private static final Identifier BAT_WINGS = Unicopia.id("textures/models/wings/bat_pony.png");
|
|
||||||
|
|
||||||
private final Model model = ModelType.PEGASUS.steveKey().createModel(Model::new);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canRender(IModel model, Entity entity) {
|
|
||||||
return entity instanceof LivingEntity l
|
|
||||||
&& !MineLPDelegate.getInstance().getRace(entity).canFly()
|
|
||||||
&& (AmuletSelectors.PEGASUS_AMULET.test(l) || Equine.of(entity).filter(this::canRender).isPresent());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean canRender(Equine<?> equine) {
|
|
||||||
if (equine instanceof Pony pony) {
|
|
||||||
return pony.getObservedSpecies().canInteractWithClouds();
|
|
||||||
}
|
|
||||||
return equine.getSpecies().canFly();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BodyPart getGearLocation() {
|
|
||||||
return BodyPart.BODY;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T extends Entity> Identifier getTexture(T entity, Context<T, ?> context) {
|
|
||||||
Living<?> living = Living.living(entity);
|
|
||||||
if (living == null) {
|
|
||||||
return DefaultPonySkinHelper.STEVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (AmuletSelectors.PEGASUS_AMULET.test(living.asEntity())) {
|
|
||||||
return entity.getWorld().getDimension().ultrawarm() ? ICARUS_WINGS_CORRUPTED : ICARUS_WINGS;
|
|
||||||
}
|
|
||||||
|
|
||||||
Race race = living instanceof Pony pony ? pony.getObservedSpecies() : living.getSpecies();
|
|
||||||
if (race.canInteractWithClouds()) {
|
|
||||||
return PEGASUS_WINGS;
|
|
||||||
}
|
|
||||||
|
|
||||||
return BAT_WINGS;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
|
||||||
@Override
|
|
||||||
public void pose(IModel model, Entity entity, boolean rainboom, UUID interpolatorId, float move, float swing, float bodySwing, float ticks) {
|
|
||||||
((ClientPonyModel)model).copyAttributes(this.model);
|
|
||||||
this.model.getWings().setPartAngles(this.model.getAttributes(), move, swing, bodySwing, ticks);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void render(MatrixStack stack, VertexConsumer consumer, int light, int overlay, float red, float green, float blue, float alpha, UUID interpolatorId) {
|
|
||||||
model.getWings().renderPart(stack, consumer, light, overlay, red, green, blue, alpha, model.getAttributes());
|
|
||||||
}
|
|
||||||
|
|
||||||
static class Model extends PegasusModel<LivingEntity> {
|
|
||||||
public Model(ModelPart tree) {
|
|
||||||
super(tree, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canFly() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue