181 lines
7.0 KiB
Java
181 lines
7.0 KiB
Java
/*
|
||
* 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;
|
||
}
|
||
}
|
||
} |