Add climbing animations in first person mode and fixed changeling's climbing animations not playing. Fixes #164

This commit is contained in:
Sollace 2023-09-29 13:42:37 +01:00
parent 27051ec13f
commit b8a0167ff7
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
5 changed files with 159 additions and 30 deletions

View file

@ -2,15 +2,18 @@ package com.minelittlepony.unicopia.client;
import java.util.Optional; import java.util.Optional;
import com.google.common.base.MoreObjects;
import com.minelittlepony.unicopia.client.render.AccessoryFeatureRenderer; import com.minelittlepony.unicopia.client.render.AccessoryFeatureRenderer;
import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.entity.player.Pony;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.item.HeldItemRenderer; import net.minecraft.client.render.item.HeldItemRenderer;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Arm; import net.minecraft.util.Arm;
import net.minecraft.util.Hand;
public class FirstPersonRendererOverrides { public class FirstPersonRendererOverrides {
public static final FirstPersonRendererOverrides INSTANCE = new FirstPersonRendererOverrides(); public static final FirstPersonRendererOverrides INSTANCE = new FirstPersonRendererOverrides();
@ -21,12 +24,35 @@ public class FirstPersonRendererOverrides {
public boolean beforeRenderHands(ArmRenderer sender, float tickDelta, MatrixStack matrices, VertexConsumerProvider.Immediate vertexConsumers, ClientPlayerEntity player, int light) { public boolean beforeRenderHands(ArmRenderer sender, float tickDelta, MatrixStack matrices, VertexConsumerProvider.Immediate vertexConsumers, ClientPlayerEntity player, int light) {
var root = AccessoryFeatureRenderer.FeatureRoot.of(player); var root = AccessoryFeatureRenderer.FeatureRoot.of(player);
return root != null && root.getAccessories().beforeRenderArms(sender, tickDelta, matrices, vertexConsumers, player, light); boolean cancelled = root != null && root.getAccessories().beforeRenderArms(sender, tickDelta, matrices, vertexConsumers, player, light);
if (cancelled) {
return true;
}
if (Pony.of(player).getAnimation().renderBothArms()) {
float swingProgress = player.getHandSwingProgress(MinecraftClient.getInstance().getTickDelta());
Hand hand = MoreObjects.firstNonNull(player.preferredHand, Hand.MAIN_HAND);
if (player.getMainHandStack().isEmpty()) {
matrices.push();
sender.invokeRenderArmHoldingItem(matrices, vertexConsumers, light, 1 - sender.getEquipProgress(Hand.MAIN_HAND, tickDelta), hand == Hand.MAIN_HAND ? swingProgress : 0, player.getMainArm());
matrices.pop();
}
if (player.getOffHandStack().isEmpty()) {
matrices.push();
sender.invokeRenderArmHoldingItem(matrices, vertexConsumers, light, 1 - sender.getEquipProgress(Hand.OFF_HAND, tickDelta), hand == Hand.OFF_HAND ? swingProgress : 0, player.getMainArm().getOpposite());
matrices.pop();
}
}
return false;
} }
public interface ArmRenderer { public interface ArmRenderer {
void invokeRenderArmHoldingItem(MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, float equipProgress, float swingProgress, Arm arm); void invokeRenderArmHoldingItem(MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, float equipProgress, float swingProgress, Arm arm);
float getEquipProgress(float tickDelta); float getEquipProgress(Hand hand, float tickDelta);
} }
} }

View file

@ -18,6 +18,7 @@ import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.util.Arm; import net.minecraft.util.Arm;
import net.minecraft.util.Hand;
import net.minecraft.util.math.*; import net.minecraft.util.math.*;
public class HeldEntityFeatureRenderer<E extends LivingEntity> implements AccessoryFeatureRenderer.Feature<E> { public class HeldEntityFeatureRenderer<E extends LivingEntity> implements AccessoryFeatureRenderer.Feature<E> {
@ -67,7 +68,7 @@ public class HeldEntityFeatureRenderer<E extends LivingEntity> implements Access
renderCarriedEntity(passenger.asEntity(), matrices, vertexConsumers, light, tickDelta); renderCarriedEntity(passenger.asEntity(), matrices, vertexConsumers, light, tickDelta);
matrices.pop(); matrices.pop();
float equipProgress = 1 - sender.getEquipProgress(tickDelta); float equipProgress = 1 - sender.getEquipProgress(Hand.MAIN_HAND, tickDelta);
matrices.push(); matrices.push();
sender.invokeRenderArmHoldingItem(matrices, vertexConsumers, light, equipProgress, swingProgress, Arm.LEFT); sender.invokeRenderArmHoldingItem(matrices, vertexConsumers, light, equipProgress, swingProgress, Arm.LEFT);

View file

@ -33,6 +33,7 @@ public class PlayerPoser {
public void applyPosing(MatrixStack matrices, PlayerEntity player, BipedEntityModel<?> model, Context context) { public void applyPosing(MatrixStack matrices, PlayerEntity player, BipedEntityModel<?> model, Context context) {
Pony pony = Pony.of(player); Pony pony = Pony.of(player);
float tickDelta = MinecraftClient.getInstance().getTickDelta();
float progress = pony.getAnimationProgress(MinecraftClient.getInstance().getTickDelta()); float progress = pony.getAnimationProgress(MinecraftClient.getInstance().getTickDelta());
AnimationInstance animation = pony.getAnimation(); AnimationInstance animation = pony.getAnimation();
Race ponyRace = MineLPDelegate.getInstance().getPlayerPonyRace(player); Race ponyRace = MineLPDelegate.getInstance().getPlayerPonyRace(player);
@ -130,6 +131,51 @@ public class PlayerPoser {
break; break;
} }
case HANG: {
float saw = MathHelper.sin(player.limbAnimator.getPos());
float pitch = 0.8F * saw;
float basePitch = 3.25F;
if (context == Context.THIRD_PERSON) {
if (ponyRace.isEquine()) {
rearUp(matrices, model, 1);
model.head.pitch += 0.8F;
basePitch = 2.25F;
}
rotateArm(model.leftArm, basePitch - pitch, -0.3F, 0);
rotateArm(model.rightArm, basePitch + pitch, 0.3F, 0);
rotateArm(model.leftLeg, 0, 0.1F, 0);
rotateArm(model.rightLeg, 0, -0.1F, 0);
} else {
pitch *= 0.5F;
float x = ponyRace.isEquine() ? 9 : 10;
float y = ponyRace.isEquine() ? -3 : -1;
float z = ponyRace.isEquine() ? -8 : -6;
float cameraPitch = player.getPitch(tickDelta) * MathHelper.RADIANS_PER_DEGREE;
rotateArm(model.leftArm, 0, 0, -0.4F + pitch);
rotateArm(model.rightArm, 0, 0, 0.4F + pitch);
model.leftArm.pivotX += x;
model.leftArm.pivotY += y;
model.leftArm.pivotZ += z;
model.leftArm.roll -= cameraPitch;
model.rightArm.pivotX -= x;
model.rightArm.pivotY += y;
model.rightArm.pivotZ += z;
model.rightArm.roll += cameraPitch;
}
break;
}
case ARMS_UP: { case ARMS_UP: {
float saw = AnimationUtil.seesaw(progress); float saw = AnimationUtil.seesaw(progress);
@ -138,14 +184,14 @@ public class PlayerPoser {
if (ponyRace.isEquine()) { if (ponyRace.isEquine()) {
rearUp(matrices, model, saw); rearUp(matrices, model, saw);
pitch = saw * 2F;
model.head.pitch += saw * 0.5F; model.head.pitch += saw * 0.5F;
pitch = saw * 2F;
} }
if (liftLeftArm) { if (liftLeftArm) {
rotateArm(model.leftArm, pitch, -yaw, yaw); rotateArm(model.leftArm, pitch, -yaw, yaw);
} else if (ponyRace.isEquine()) { } else if (ponyRace.isEquine()) {
model.leftArm.pitch += saw / 4F; model.leftArm.pitch -= saw / 4F;
model.leftArm.roll -= saw / 4F; model.leftArm.roll -= saw / 4F;
} }
@ -164,15 +210,25 @@ public class PlayerPoser {
float pitch = MathHelper.clamp(3F * saw, 1, 2); float pitch = MathHelper.clamp(3F * saw, 1, 2);
float yaw = 0.5F * saw; float yaw = 0.5F * saw;
if (context == Context.THIRD_PERSON) {
if (ponyRace.isEquine()) { if (ponyRace.isEquine()) {
rearUp(matrices, model, saw); rearUp(matrices, model, 1);
pitch = saw * 2F; pitch = saw * 2F;
model.head.pitch += saw * 0.5F; model.head.pitch += saw * 0.5F;
}
rotateArm(model.leftArm, pitch, -yaw, yaw / 2F); rotateArm(model.leftArm, pitch, -yaw, yaw / 2F);
rotateArm(model.rightLeg, pitch / 2F, yaw, 0); rotateArm(model.rightLeg, pitch / 2F, yaw, 0);
saw = AnimationUtil.seesaw(progress + 0.5F);
yaw = 0.5F * -saw;
rotateArm(model.rightArm, pitch, yaw, -yaw / 2F);
rotateArm(model.leftLeg, pitch / 2F, -yaw, 0);
} else {
rotateArm(model.leftArm, pitch, -yaw, yaw / 2F);
rotateArm(model.rightLeg, pitch / 2F, yaw, 0);
saw = AnimationUtil.seesaw((progress + 0.5F) % 1); saw = AnimationUtil.seesaw((progress + 0.5F) % 1);
pitch = MathHelper.clamp(3F * saw, 1, 2) * (ponyRace.isEquine() ? 2 : 1); pitch = MathHelper.clamp(3F * saw, 1, 2) * (ponyRace.isEquine() ? 2 : 1);
@ -180,6 +236,29 @@ public class PlayerPoser {
rotateArm(model.rightArm, pitch, yaw, -yaw / 2F); rotateArm(model.rightArm, pitch, yaw, -yaw / 2F);
rotateArm(model.leftLeg, pitch / 2F, -yaw, 0); rotateArm(model.leftLeg, pitch / 2F, -yaw, 0);
}
} else {
//saw = MathHelper.sin(progress * 2);
float x = ponyRace.isEquine() ? 9 : 0;
float y = ponyRace.isEquine() ? -3 : 0;
float z = ponyRace.isEquine() ? -8 : -2;
float cameraPitch = player.getPitch(tickDelta) * MathHelper.RADIANS_PER_DEGREE;
pitch = MathHelper.sin((progress * 2) * MathHelper.PI) * 0.6F;
rotateArm(model.leftArm, 0, 0, pitch);
rotateArm(model.rightArm, 0, 0, pitch);
model.leftArm.pivotX += x;
model.leftArm.pivotY += y;
model.leftArm.pivotZ += z;
model.leftArm.roll -= cameraPitch;
model.rightArm.pivotX -= x;
model.rightArm.pivotY += y;
model.rightArm.pivotZ += z;
model.rightArm.roll += cameraPitch;
}
break; break;
} }
@ -324,6 +403,10 @@ public class PlayerPoser {
public boolean canPlay(boolean isPony) { public boolean canPlay(boolean isPony) {
return !isOf(Animation.NONE) && (recipient == Animation.Recipient.ANYONE || isPony == (recipient == Animation.Recipient.PONY)); return !isOf(Animation.NONE) && (recipient == Animation.Recipient.ANYONE || isPony == (recipient == Animation.Recipient.PONY));
} }
public boolean renderBothArms() {
return isOf(Animation.HANG) || isOf(Animation.CLIMB);
}
} }
public enum Animation implements CommandArgumentEnum<Animation> { public enum Animation implements CommandArgumentEnum<Animation> {
@ -335,6 +418,7 @@ public class PlayerPoser {
WAVE_TWO(USounds.ENTITY_PLAYER_WHISTLE, 20), WAVE_TWO(USounds.ENTITY_PLAYER_WHISTLE, 20),
KICK(USounds.ENTITY_PLAYER_KICK, 5), KICK(USounds.ENTITY_PLAYER_KICK, 5),
CLIMB(20), CLIMB(20),
HANG(20),
STOMP(5), STOMP(5),
WIGGLE_NOSE(6), WIGGLE_NOSE(6),
SPREAD_WINGS(6), SPREAD_WINGS(6),

View file

@ -146,10 +146,16 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
} }
public void setAnimation(Animation animation, Animation.Recipient recipient) { public void setAnimation(Animation animation, Animation.Recipient recipient) {
if (getAnimation().isOf(animation) && animationDuration > 0) {
return;
}
setAnimation(new AnimationInstance(animation, recipient), animation.getDuration()); setAnimation(new AnimationInstance(animation, recipient), animation.getDuration());
} }
public void setAnimation(Animation animation, Animation.Recipient recipient, int duration) { public void setAnimation(Animation animation, Animation.Recipient recipient, int duration) {
if (getAnimation().isOf(animation) && animationDuration > 0) {
return;
}
setAnimation(new AnimationInstance(animation, recipient), duration); setAnimation(new AnimationInstance(animation, recipient), duration);
} }
@ -420,12 +426,10 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
} }
} }
if (getAnimation().isOf(Animation.NONE) || (getAnimation().isOf(Animation.NONE) && canhangHere)) {
if (canhangHere) { if (canhangHere) {
setAnimation(Animation.ARMS_UP, Recipient.HUMAN); setAnimation(Animation.HANG, Recipient.ANYONE);
} else if (distanceClimbed > 1.5) { } else if (distanceClimbed > 1.5) {
setAnimation(Animation.CLIMB, Recipient.HUMAN); setAnimation(Animation.CLIMB, Recipient.ANYONE);
}
} }
} else { } else {
distanceClimbed = 0; distanceClimbed = 0;
@ -484,16 +488,21 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
private void updateAnimations() { private void updateAnimations() {
if (distanceClimbed > 0 if (distanceClimbed > 0
&& ((animation.isOf(Animation.CLIMB) && entity.isSneaky()) || (animation.isOf(Animation.ARMS_UP) && isHanging())) && ((animation.isOf(Animation.CLIMB) && entity.isSneaky()) || animation.isOf(Animation.HANG))
&& entity.getClimbingPos().isPresent() && entity.getClimbingPos().isPresent()
&& entity.getVelocity().length() < 0.08F) { && entity.getVelocity().length() < 0.08F) {
if (animation.isOf(Animation.ARMS_UP)) { if (animation.renderBothArms()) {
animationDuration = 2; animationDuration = 2;
} }
return; return;
} }
if (animationDuration > 0 && --animationDuration <= 0) { if (animationDuration > 0 && --animationDuration <= 0) {
if (animation.renderBothArms() && distanceClimbed > 0) {
return;
}
setAnimation(AnimationInstance.NONE); setAnimation(AnimationInstance.NONE);
} }
} }

View file

@ -16,6 +16,7 @@ import net.minecraft.client.render.item.HeldItemRenderer;
import net.minecraft.client.render.item.HeldItemRenderer.HandRenderType; import net.minecraft.client.render.item.HeldItemRenderer.HandRenderType;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.Arm; import net.minecraft.util.Arm;
import net.minecraft.util.Hand;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
@Mixin(HeldItemRenderer.class) @Mixin(HeldItemRenderer.class)
@ -25,13 +26,21 @@ abstract class MixinHeldItemRenderer implements FirstPersonRendererOverrides.Arm
@Shadow @Shadow
private float prevEquipProgressMainHand; private float prevEquipProgressMainHand;
@Shadow
private float equipProgressOffHand;
@Shadow
private float prevEquipProgressOffHand;
@Override @Override
@Invoker("renderArmHoldingItem") @Invoker("renderArmHoldingItem")
public abstract void invokeRenderArmHoldingItem(MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, float equipProgress, float swingProgress, Arm arm); public abstract void invokeRenderArmHoldingItem(MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, float equipProgress, float swingProgress, Arm arm);
@Override @Override
public float getEquipProgress(float tickDelta) { public float getEquipProgress(Hand hand, float tickDelta) {
return MathHelper.lerp(tickDelta, prevEquipProgressMainHand, equipProgressMainHand); return MathHelper.lerp(tickDelta,
hand == Hand.MAIN_HAND ? prevEquipProgressMainHand : prevEquipProgressOffHand,
hand == Hand.MAIN_HAND ? equipProgressMainHand : equipProgressOffHand
);
} }
@Inject( @Inject(