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
|
||||
public double getCostEstimate(Pony player) {
|
||||
double distance = MineLPDelegate.getInstance().getPlayerPonyRace(player.asEntity()).isHuman() ? 6 : -6;
|
||||
|
||||
return TraceHelper.findBlock(player.asEntity(), distance, 1)
|
||||
return TraceHelper.findBlock(player.asEntity(), getKickDirection(player) * 6, 1)
|
||||
.filter(pos -> TreeType.at(pos, player.asWorld()) != TreeType.NONE)
|
||||
.isPresent() ? 3 : 1;
|
||||
}
|
||||
|
@ -121,7 +119,7 @@ public class EarthPonyKickAbility implements Ability<Pos> {
|
|||
}
|
||||
|
||||
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) {
|
||||
|
|
|
@ -38,7 +38,7 @@ public class PegasusRainboomAbility implements Ability<Hit> {
|
|||
@Nullable
|
||||
@Override
|
||||
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
|
||||
|
@ -54,7 +54,7 @@ public class PegasusRainboomAbility implements Ability<Hit> {
|
|||
@Override
|
||||
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.subtractEnergyCost(4);
|
||||
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.OFFHAND));
|
||||
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(GlassesGear::new);
|
||||
}
|
||||
|
@ -80,27 +82,14 @@ public class Main extends MineLPDelegate implements ClientModInitializer {
|
|||
}
|
||||
|
||||
private static Race toUnicopiaRace(com.minelittlepony.api.pony.meta.Race race) {
|
||||
switch (race) {
|
||||
case ALICORN:
|
||||
return Race.ALICORN;
|
||||
case CHANGELING:
|
||||
case CHANGEDLING:
|
||||
return Race.CHANGELING;
|
||||
case ZEBRA:
|
||||
case EARTH:
|
||||
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;
|
||||
}
|
||||
return switch (race) {
|
||||
case ALICORN -> Race.ALICORN;
|
||||
case CHANGELING, CHANGEDLING -> Race.CHANGELING;
|
||||
case ZEBRA, EARTH -> Race.EARTH;
|
||||
case GRYPHON, HIPPOGRIFF, PEGASUS -> Race.PEGASUS;
|
||||
case BATPONY -> Race.BAT;
|
||||
case SEAPONY, UNICORN, KIRIN -> Race.UNICORN;
|
||||
default -> 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