EroticDungeonGame/src/main/java/top/r3944realms/eroticdungeongame/client/model/EDGArmPose.java
2026-01-21 15:50:59 +08:00

181 lines
7.0 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright 2025-2026 R3944Realms
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.r3944realms.eroticdungeongame.client.model;
import net.minecraft.client.model.HumanoidModel;
import net.minecraft.client.model.geom.ModelPart;
import net.minecraft.util.Mth;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.HumanoidArm;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import top.r3944realms.eroticdungeongame.content.item.WhipItem;
public class EDGArmPose {
public static HumanoidModel.ArmPose WHIP;
public static void init() {
WHIP = HumanoidModel.ArmPose.create("edg_whip", false, EDGArmPose::applyWhipPose);
}
private static void applyWhipPose(HumanoidModel<?> model, LivingEntity entity, HumanoidArm arm) {
if (!(entity instanceof Player player)) return;
// 检查是否在使用鞭子
ItemStack useItem = player.getUseItem();
if (!(useItem.getItem() instanceof WhipItem)) return;
// 确定使用的是哪只手
InteractionHand useHand = player.getUsedItemHand();
// 只有当指定的手臂是使用鞭子的手臂时才应用动画
HumanoidArm useArm = useHand == InteractionHand.MAIN_HAND ?
player.getMainArm() :
(player.getMainArm() == HumanoidArm.RIGHT ? HumanoidArm.LEFT : HumanoidArm.RIGHT);
if (arm != useArm) {
// 非使用手臂保持正常姿势
resetToDefaultPose(model, arm);
return;
}
// 计算使用进度
int remainedUseTime = player.getUseItemRemainingTicks();
int maxUseTime = useItem.getUseDuration();
float progress = 1.0f - (float)remainedUseTime / maxUseTime;
// System.out.printf("Using %d times of %d seconds%n", remainedUseTime, maxUseTime);
// 应用鞭子动画
applyWhipAnimation(model, arm, progress);
// 如果是主手,应用身体动画
if (arm == player.getMainArm()) {
applyBodyAnimation(model, progress, useArm);
}
}
private static void resetToDefaultPose(HumanoidModel<?> model, HumanoidArm arm) {
ModelPart armPart = getArmPart(model, arm);
// 设置为默认手持姿势
armPart.xRot = -0.87266463F; // 约 -50度
armPart.yRot = 0.0F;
armPart.zRot = 0.0F;
}
private static ModelPart getArmPart(HumanoidModel<?> model, HumanoidArm arm) {
return arm == HumanoidArm.LEFT ? model.leftArm : model.rightArm;
}
private static void applyWhipAnimation(HumanoidModel<?> model, HumanoidArm arm, float progress) {
ModelPart armPart = getArmPart(model, arm);
boolean isRightArm = arm == HumanoidArm.RIGHT;
// 完全重置旋转
armPart.xRot = 0.0f;
armPart.yRot = 0.0f;
armPart.zRot = 0.0f;
// 根据左右手决定挥舞方向
if (isRightArm) {
applyRightHandWhipAnimation(armPart, progress);
} else {
applyLeftHandWhipAnimation(armPart, progress);
}
}
private static void applyRightHandWhipAnimation(ModelPart arm, float progress) {
// 右手:从右向左挥舞(从上到下)
if (progress < 0.2f) {
// 阶段1准备向后上方拉
float phase = progress / 0.2f;
arm.xRot = Mth.lerp(phase, 0.0f, -2.8f); // 向上抬
arm.yRot = Mth.lerp(phase, 0.0f, 0.3f); // 先向右偏(准备从左向右)
arm.zRot = Mth.lerp(phase, 0.0f, -0.2f); // 手腕外旋
}
else if (progress < 0.5f) {
// 阶段2主要挥舞从上到下从右向左
float phase = (progress - 0.2f) / 0.3f;
float swing = Mth.sin(phase * Mth.PI);
// 手臂从上到下
arm.xRot = -0.4f + swing * 1.2f; // -0.4到0.8
// 手臂从右向左摆动
arm.yRot = 0.3f - swing * 0.6f; // 0.3到-0.3
// 手腕转动
arm.zRot = -0.2f + swing * 0.3f; // -0.2到0.1
}
}
private static void applyLeftHandWhipAnimation(ModelPart arm, float progress) {
// 左手:从左向右挥舞(从上到下)
if (progress < 0.2f) {
// 阶段1准备向后上方拉
float phase = progress / 0.2f;
arm.xRot = Mth.lerp(phase, 0.0f, -2.8f); // 向上抬
arm.yRot = Mth.lerp(phase, 0.0f, -0.3f); // 先向左偏(准备从右向左)
arm.zRot = Mth.lerp(phase, 0.0f, 0.2f); // 手腕外旋
}
else if (progress < 0.5f) {
// 阶段2主要挥舞从上到下从左向右
float phase = (progress - 0.2f) / 0.3f;
float swing = Mth.sin(phase * Mth.PI);
// 手臂从上到下
arm.xRot = -0.4f + swing * 1.2f; // -0.4到0.8
// 手臂从左向右摆动
arm.yRot = -0.3f + swing * 0.6f; // -0.3到0.3
// 手腕转动
arm.zRot = 0.2f - swing * 0.3f; // 0.2到-0.1
}
}
private static <T extends LivingEntity> void applyBodyAnimation(HumanoidModel<T> model, float progress, HumanoidArm useArm) {
boolean isRightHand = useArm == HumanoidArm.RIGHT;
// 身体跟随手臂转动
if (progress < 0.6f) {
float phase = progress / 0.6f;
// 根据使用的手决定身体转动方向
if (isRightHand) {
// 右手使用时,身体先向右转,然后向左转
float bodyRot = Mth.sin(phase * Mth.PI) * 0.3f; // 0到0.3到0
model.body.yRot = bodyRot; // 身体向右转
} else {
// 左手使用时,身体先向左转,然后向右转
float bodyRot = -Mth.sin(phase * Mth.PI) * 0.3f; // 0到-0.3到0
model.body.yRot = bodyRot; // 身体向左转
}
} else {
float phase = (progress - 0.6f) / 0.4f;
model.body.yRot = Mth.lerp(phase, 0.0f, 0.0f); // 回正
}
// 头部跟随身体转动,但幅度较小
model.head.yRot = model.body.yRot * 0.6f;
// 根据挥舞动作,身体会有轻微的前倾
if (progress > 0.3f && progress < 0.7f) {
float phase = (progress - 0.3f) / 0.4f;
float lean = Mth.sin(phase * Mth.PI) * 0.1f;
model.body.xRot = lean; // 轻微前倾
} else {
model.body.xRot = 0.0f;
}
}
}