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 com.google.common.base.MoreObjects;
import com.minelittlepony.unicopia.client.render.AccessoryFeatureRenderer;
import com.minelittlepony.unicopia.entity.player.Pony;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.item.HeldItemRenderer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Arm;
import net.minecraft.util.Hand;
public class 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) {
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 {
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.LivingEntity;
import net.minecraft.util.Arm;
import net.minecraft.util.Hand;
import net.minecraft.util.math.*;
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);
matrices.pop();
float equipProgress = 1 - sender.getEquipProgress(tickDelta);
float equipProgress = 1 - sender.getEquipProgress(Hand.MAIN_HAND, tickDelta);
matrices.push();
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) {
Pony pony = Pony.of(player);
float tickDelta = MinecraftClient.getInstance().getTickDelta();
float progress = pony.getAnimationProgress(MinecraftClient.getInstance().getTickDelta());
AnimationInstance animation = pony.getAnimation();
Race ponyRace = MineLPDelegate.getInstance().getPlayerPonyRace(player);
@ -130,6 +131,51 @@ public class PlayerPoser {
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: {
float saw = AnimationUtil.seesaw(progress);
@ -138,14 +184,14 @@ public class PlayerPoser {
if (ponyRace.isEquine()) {
rearUp(matrices, model, saw);
pitch = saw * 2F;
model.head.pitch += saw * 0.5F;
pitch = saw * 2F;
}
if (liftLeftArm) {
rotateArm(model.leftArm, pitch, -yaw, yaw);
} else if (ponyRace.isEquine()) {
model.leftArm.pitch += saw / 4F;
model.leftArm.pitch -= saw / 4F;
model.leftArm.roll -= saw / 4F;
}
@ -164,15 +210,25 @@ public class PlayerPoser {
float pitch = MathHelper.clamp(3F * saw, 1, 2);
float yaw = 0.5F * saw;
if (context == Context.THIRD_PERSON) {
if (ponyRace.isEquine()) {
rearUp(matrices, model, saw);
rearUp(matrices, model, 1);
pitch = saw * 2F;
model.head.pitch += saw * 0.5F;
}
rotateArm(model.leftArm, pitch, -yaw, yaw / 2F);
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);
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.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;
}
@ -324,6 +403,10 @@ public class PlayerPoser {
public boolean canPlay(boolean isPony) {
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> {
@ -335,6 +418,7 @@ public class PlayerPoser {
WAVE_TWO(USounds.ENTITY_PLAYER_WHISTLE, 20),
KICK(USounds.ENTITY_PLAYER_KICK, 5),
CLIMB(20),
HANG(20),
STOMP(5),
WIGGLE_NOSE(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) {
if (getAnimation().isOf(animation) && animationDuration > 0) {
return;
}
setAnimation(new AnimationInstance(animation, recipient), animation.getDuration());
}
public void setAnimation(Animation animation, Animation.Recipient recipient, int duration) {
if (getAnimation().isOf(animation) && animationDuration > 0) {
return;
}
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) {
setAnimation(Animation.ARMS_UP, Recipient.HUMAN);
setAnimation(Animation.HANG, Recipient.ANYONE);
} else if (distanceClimbed > 1.5) {
setAnimation(Animation.CLIMB, Recipient.HUMAN);
}
setAnimation(Animation.CLIMB, Recipient.ANYONE);
}
} else {
distanceClimbed = 0;
@ -484,16 +488,21 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
private void updateAnimations() {
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.getVelocity().length() < 0.08F) {
if (animation.isOf(Animation.ARMS_UP)) {
if (animation.renderBothArms()) {
animationDuration = 2;
}
return;
}
if (animationDuration > 0 && --animationDuration <= 0) {
if (animation.renderBothArms() && distanceClimbed > 0) {
return;
}
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.util.math.MatrixStack;
import net.minecraft.util.Arm;
import net.minecraft.util.Hand;
import net.minecraft.util.math.MathHelper;
@Mixin(HeldItemRenderer.class)
@ -25,13 +26,21 @@ abstract class MixinHeldItemRenderer implements FirstPersonRendererOverrides.Arm
@Shadow
private float prevEquipProgressMainHand;
@Shadow
private float equipProgressOffHand;
@Shadow
private float prevEquipProgressOffHand;
@Override
@Invoker("renderArmHoldingItem")
public abstract void invokeRenderArmHoldingItem(MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, float equipProgress, float swingProgress, Arm arm);
@Override
public float getEquipProgress(float tickDelta) {
return MathHelper.lerp(tickDelta, prevEquipProgressMainHand, equipProgressMainHand);
public float getEquipProgress(Hand hand, float tickDelta) {
return MathHelper.lerp(tickDelta,
hand == Hand.MAIN_HAND ? prevEquipProgressMainHand : prevEquipProgressOffHand,
hand == Hand.MAIN_HAND ? equipProgressMainHand : equipProgressOffHand
);
}
@Inject(