Skip to content

Commit 5ffd831

Browse files
committed
gnomad animation
1 parent 1f85b96 commit 5ffd831

6 files changed

Lines changed: 204 additions & 26 deletions

File tree

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package birsy.clinker.client;
2+
3+
import net.minecraft.util.Mth;
4+
5+
public class AnimationUtilities {
6+
public static float nSin(float time) {
7+
return Mth.sin(time * Mth.PI);
8+
}
9+
}
Lines changed: 178 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,202 @@
11
package birsy.clinker.client.entity.gnomad.basic;
22

3+
import birsy.clinker.client.entity.gnomad.mogul.GnomadMogulAnimator;
4+
import birsy.clinker.client.entity.gnomad.mogul.GnomadMogulSkeleton;
5+
import birsy.clinker.common.world.entity.gnomad.mogul.GnomadMogulEntity;
36
import birsy.clinker.common.world.entity.gnomad.testing.SquadTestingThrowerEntity;
7+
import foundry.veil.api.client.necromancer.animation.Animation;
48
import foundry.veil.api.client.necromancer.animation.Animator;
59
import net.minecraft.core.Direction;
610
import net.minecraft.util.Mth;
711

12+
import static net.minecraft.core.Direction.Axis.*;
13+
import static birsy.clinker.client.AnimationUtilities.*;
14+
15+
816
public class GnomadAnimator extends Animator<SquadTestingThrowerEntity, GnomadSkeleton> {
17+
public final AnimationEntry<?, ?> idleAnim, walkAnim, strafeAnim;
918
protected GnomadAnimator(SquadTestingThrowerEntity parent, GnomadSkeleton skeleton) {
1019
super(parent, skeleton);
20+
this.idleAnim = this.addAnimation(IdleAnimation.INSTANCE, 0);
21+
this.walkAnim = this.addAnimation(WalkAnimation.INSTANCE, 1);
22+
this.strafeAnim = this.addAnimation(StrafeAnimation.INSTANCE, 2);
1123
}
1224

1325
@Override
1426
public void animate() {
1527
super.animate();
1628
SquadTestingThrowerEntity entity = this.parent;
1729

18-
float bodyYaw = Mth.wrapDegrees(180 - entity.yBodyRot);
19-
float headYaw = Mth.wrapDegrees(180 - entity.yHeadRot);
20-
float netHeadYaw = Mth.degreesDifference(bodyYaw, headYaw);
21-
netHeadYaw = Mth.clamp(netHeadYaw, -80, 80);
22-
float headPitch = -entity.getViewXRot(1.0F);
23-
skeleton.root.rotateDeg(bodyYaw, Direction.Axis.Y);
24-
skeleton.neck.rotateDeg(netHeadYaw, Direction.Axis.Y);
25-
skeleton.head.rotateDeg(headPitch, Direction.Axis.X);
30+
this.idleAnim.setMixFactor(1.0F);
31+
this.idleAnim.setTime(entity.tickCount);
32+
33+
float moveTime = entity.getCumulativeLocomotionAmount() * 1.5F;
34+
35+
float walkFac = Mth.clamp(12 * entity.getForwardLocomotionAmount(1.0F), -2.0F, 2.0F);
36+
this.walkAnim.setMixFactor(walkFac);
37+
this.walkAnim.setTime(moveTime);
38+
39+
float strafeFac = Mth.clamp(12 * entity.getStrafeLocomotionAmount(1.0F), -2.0F, 2.0F);
40+
this.strafeAnim.setMixFactor(strafeFac);
41+
this.strafeAnim.setTime(moveTime);
42+
43+
// flinch
44+
if (entity.hurtDuration > 0) {
45+
float flinchTime = entity.tickCount * 0.9F;
46+
float flinchFactor = (float) entity.hurtTime / entity.hurtDuration;
47+
skeleton.root.rotateDeg(Mth.sin(flinchTime) * 8 * flinchFactor, Direction.Axis.X);
48+
skeleton.root.rotateDeg(Mth.cos(flinchTime) * 8 * flinchFactor, Direction.Axis.Z);
49+
50+
skeleton.head.rotateDeg(Mth.sin(flinchTime - 1) * 8 * flinchFactor, Direction.Axis.X);
51+
skeleton.head.rotateDeg(Mth.cos(flinchTime - 1) * 8 * flinchFactor, Direction.Axis.Z);
52+
53+
skeleton.rightArm.rotateDeg(Mth.sin(flinchTime - 1) * 15 * flinchFactor, Direction.Axis.X);
54+
skeleton.rightArm.rotateDeg(Mth.cos(flinchTime - 1) * 15 * flinchFactor, Direction.Axis.Z);
55+
skeleton.leftArm.rotateDeg(Mth.sin(flinchTime - 1) * 15 * flinchFactor, Direction.Axis.X);
56+
skeleton.leftArm.rotateDeg(Mth.cos(flinchTime - 1) * -15 * flinchFactor, Direction.Axis.Z);
57+
58+
skeleton.leftLeg.rotateDeg(Mth.sin(flinchTime - 1) * 15 * flinchFactor, Direction.Axis.X);
59+
skeleton.leftLeg.rotateDeg(Mth.cos(flinchTime - 1) * -15 * flinchFactor, Direction.Axis.Z);
60+
skeleton.rightLeg.rotateDeg(Mth.sin(flinchTime - 1) * 15 * flinchFactor, Direction.Axis.X);
61+
skeleton.rightLeg.rotateDeg(Mth.cos(flinchTime - 1) * 15 * flinchFactor, Direction.Axis.Z);
62+
}
63+
}
64+
65+
private static class IdleAnimation extends Animation<SquadTestingThrowerEntity, GnomadSkeleton> {
66+
protected static IdleAnimation INSTANCE = new IdleAnimation();
67+
68+
public void apply(SquadTestingThrowerEntity entity, GnomadSkeleton skeleton, float mixFactor, float time) {
69+
float bodyYaw = Mth.wrapDegrees(180 - entity.yBodyRot);
70+
float headYaw = Mth.wrapDegrees(180 - entity.yHeadRot);
71+
float netHeadYaw = Mth.degreesDifference(bodyYaw, headYaw);
72+
netHeadYaw = Mth.clamp(netHeadYaw, -80, 80);
73+
float headPitch = -entity.getViewXRot(1.0F);
74+
skeleton.root.rotateDeg(bodyYaw, Y);
75+
skeleton.neck.rotateDeg(netHeadYaw, Y);
76+
skeleton.head.rotateDeg(headPitch, X);
77+
78+
float torsoRotation = -5;
79+
skeleton.torso.rotateDeg(torsoRotation, X);
80+
skeleton.torso.rotation.conjugate(skeleton.skirt.rotation);
81+
82+
skeleton.rightArm.rotateDeg(-torsoRotation, X);
83+
skeleton.leftArm.rotateDeg(-torsoRotation, X);
84+
skeleton.rightArm.rotateDeg(5, Z);
85+
skeleton.leftArm.rotateDeg(-5, Z);
86+
87+
float neckRotation = 10;
88+
skeleton.neck.rotateDeg(-torsoRotation + neckRotation, X);
89+
skeleton.headJoint.rotateDeg(-neckRotation, X);
90+
91+
float speed = 1.0F / 40.0F;
92+
float degree = 1.0F;
93+
94+
skeleton.rightArm.rotateDeg(nSin(time * speed * 1.0F) * 1 * mixFactor * degree, Z);
95+
skeleton.rightArm.rotateDeg(nSin(time * speed * 0.9F) * 1 * mixFactor * degree, X);
96+
97+
skeleton.leftArm.rotateDeg(nSin(time * speed * 0.85F) * 1 * mixFactor * degree, Z);
98+
skeleton.leftArm.rotateDeg(nSin(time * speed * 0.95F) * 1 * mixFactor * degree, X);
99+
100+
skeleton.torso.offsetY(nSin(time * speed * 0.7F) * 0.2F * mixFactor * degree);
101+
102+
skeleton.nose.rotateDeg(nSin(time * speed * 0.85F) * 1 * mixFactor * degree, Z);
103+
skeleton.nose.rotateDeg(nSin(time * speed * 0.95F) * 1 * mixFactor * degree, X);
104+
105+
skeleton.neck.rotateDeg(nSin(time * speed * 0.6F) * 1 * mixFactor * degree, Z);
106+
skeleton.neck.rotateDeg(nSin(time * speed * 0.5F) * 1 * mixFactor * degree, X);
107+
}
108+
}
109+
110+
private static class WalkAnimation extends Animation<SquadTestingThrowerEntity, GnomadSkeleton> {
111+
protected static WalkAnimation INSTANCE = new WalkAnimation();
112+
113+
@Override
114+
public boolean running(SquadTestingThrowerEntity entity, GnomadSkeleton skeleton, float mixFactor, float time) {
115+
return mixFactor != 0;
116+
}
117+
118+
@Override
119+
public void apply(SquadTestingThrowerEntity entity, GnomadSkeleton skeleton, float mixFactor, float time) {
120+
float degree = 1.0F;
121+
float sign = Mth.sign(mixFactor);
122+
mixFactor = Mth.abs(mixFactor);
123+
124+
// bounce mix factor decreases with speed...
125+
float bounceMixFactor = mixFactor;
126+
if (mixFactor > 1.0F) bounceMixFactor = Mth.clampedMap(bounceMixFactor, 1.0F, 3.0F, mixFactor, 0);
127+
// squared mix factor really emphasizes movements when running
128+
float squaredMixFactor = mixFactor * mixFactor;
129+
130+
skeleton.root.offsetY(Math.abs(nSin(time + 0.5F)) * 1.0F * bounceMixFactor * degree);
131+
skeleton.root.offsetX(nSin(time * 2) * 0.5F * bounceMixFactor * sign * degree);
26132

27-
float torsoRotation = -5;
28-
skeleton.torso.rotateDeg(torsoRotation, Direction.Axis.X);
29-
skeleton.torso.rotation.conjugate(skeleton.skirt.rotation);
133+
skeleton.root.rotateDeg(nSin(time) * 1 * bounceMixFactor * sign * degree, Z);
30134

31-
skeleton.rightArm.rotateDeg(-torsoRotation, Direction.Axis.X);
32-
skeleton.leftArm.rotateDeg(-torsoRotation, Direction.Axis.X);
33-
skeleton.rightArm.rotateDeg(5, Direction.Axis.Z);
34-
skeleton.leftArm.rotateDeg(-5, Direction.Axis.Z);
135+
skeleton.rightLeg.offsetZ(nSin(time) * -2 * mixFactor * sign * degree);
136+
skeleton.rightLeg.offsetY(nSin(time + 0.5F) * 1 * mixFactor * degree);
137+
skeleton.rightLeg.rotateDeg(nSin(time) * 15 * mixFactor * sign * degree, X);
35138

36-
float neckRotation = 10;
37-
skeleton.neck.rotateDeg(-torsoRotation + neckRotation, Direction.Axis.X);
38-
skeleton.headJoint.rotateDeg(-neckRotation, Direction.Axis.X);
139+
skeleton.leftLeg.offsetZ(-nSin(time) * -2 * mixFactor * sign * degree);
140+
skeleton.leftLeg.offsetY(-nSin(time + 0.5F) * 1 * mixFactor * degree);
141+
skeleton.leftLeg.rotateDeg(-nSin(time) * 15 * mixFactor * sign * degree, X);
39142

143+
skeleton.rightArm.rotateDeg(nSin(time + 0.2F) * -12 * squaredMixFactor * sign * degree, X);
144+
skeleton.leftArm.rotateDeg(-nSin(time + 0.2F) * -12 * squaredMixFactor * sign * degree, X);
40145

146+
skeleton.rightArm.offsetY(nSin(time * 2 + 0.2F) * 0.1F * bounceMixFactor * degree);
147+
skeleton.leftArm .offsetY(nSin(time * 2 + 0.2F) * 0.1F * bounceMixFactor * degree);
148+
149+
skeleton.neck.offsetY(nSin(time * 2 + 0.15F) * 0.15F * bounceMixFactor * degree);
150+
skeleton.head.offsetY(nSin(time * 2 + 0.30F) * 0.1F * bounceMixFactor * degree);
151+
152+
skeleton.bag.offsetY(nSin(time * 2 + 0.4F) * 0.1F * bounceMixFactor * degree);
153+
154+
float torsoAngle = -3.0F * squaredMixFactor * degree * sign;
155+
skeleton.torso.rotateDeg(torsoAngle, X);
156+
skeleton.skirt.rotateDeg(-torsoAngle, X);
157+
}
41158
}
159+
160+
private static class StrafeAnimation extends Animation<SquadTestingThrowerEntity, GnomadSkeleton> {
161+
protected static StrafeAnimation INSTANCE = new StrafeAnimation();
162+
163+
@Override
164+
public boolean running(SquadTestingThrowerEntity entity, GnomadSkeleton skeleton, float mixFactor, float time) {
165+
return mixFactor != 0;
166+
}
167+
168+
@Override
169+
public void apply(SquadTestingThrowerEntity entity, GnomadSkeleton skeleton, float mixFactor, float time) {
170+
float degree = 1.0F;
171+
float sign = Mth.sign(mixFactor);
172+
mixFactor = Mth.abs(mixFactor);
173+
174+
float bounceMixFactor = mixFactor;
175+
if (mixFactor > 1.0F) bounceMixFactor = Mth.clampedMap(bounceMixFactor, 1.0F, 3.0F, mixFactor, 0);
176+
177+
skeleton.root.rotateDeg(-2 * mixFactor * sign * degree, Z);
178+
skeleton.neck.rotateDeg(2 * mixFactor * sign * degree, Z);
179+
skeleton.bag.rotateDeg(2 * mixFactor * sign * degree, Z);
180+
181+
skeleton.root.offsetY(Math.abs(nSin(time + 0.5F)) * 0.5F * bounceMixFactor * degree);
182+
skeleton.root.rotateDeg(nSin(time) * 1 * bounceMixFactor * sign * degree, Z);
183+
184+
skeleton.rightLeg.offsetX(nSin(time) * 1 * mixFactor * sign * degree);
185+
skeleton.rightLeg.offsetY(nSin(time + 0.5F) * 1 * mixFactor * degree);
186+
skeleton.rightLeg.rotateDeg(nSin(time) * 10 * mixFactor * sign * degree, Z);
187+
188+
skeleton.leftLeg.offsetX(-nSin(time) * 1 * mixFactor * sign * degree);
189+
skeleton.leftLeg.offsetY(-nSin(time + 0.5F) * 1 * mixFactor * degree);
190+
skeleton.leftLeg.rotateDeg(-nSin(time) * 10 * mixFactor * sign * degree, Z);
191+
192+
float armSwingMixFactor = mixFactor * mixFactor;
193+
skeleton.rightArm.rotateDeg(nSin(time + 0.2F) * -10 * armSwingMixFactor * sign * degree, X);
194+
skeleton.leftArm.rotateDeg(-nSin(time + 0.2F) * -10 * armSwingMixFactor * sign * degree, X);
195+
196+
skeleton.neck.offsetY(nSin(time * 2 + 0.15F) * 0.10F * bounceMixFactor * degree);
197+
skeleton.head.offsetY(nSin(time * 2 + 0.30F) * 0.05F * bounceMixFactor * degree);
198+
skeleton.bag.offsetY(nSin(time * 2 + 0.4F) * 0.1F * bounceMixFactor * degree);
199+
}
200+
}
201+
42202
}

src/main/java/birsy/clinker/common/world/entity/GroundLocomotionEntity.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public class GroundLocomotionEntity extends PathfinderMob {
4444
protected GroundLocomotionEntity(EntityType<? extends PathfinderMob> pEntityType, Level pLevel) {
4545
super(pEntityType, pLevel);
4646
this.moveControl = new GroundMoveControl(this);
47-
this.lookControl = new GroundLookAngleControl(this);
47+
this.lookControl = new GroundLookAngleControl(this, 80, 60);
4848
}
4949
@Override
5050
protected void defineSynchedData(SynchedEntityData.Builder builder) {

src/main/java/birsy/clinker/common/world/entity/ai/GroundLookAngleControl.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@
99

1010
public class GroundLookAngleControl extends LookControl {
1111
public final LookTargetController lookTargetController;
12-
13-
public GroundLookAngleControl(GroundLocomotionEntity mob) {
12+
final float pitchLimits, yawLimits;
13+
public GroundLookAngleControl(GroundLocomotionEntity mob, float pitchLimits, float yawLimits) {
1414
super(mob);
1515
this.lookTargetController = new LookTargetController(mob);
16+
this.pitchLimits = pitchLimits;
17+
this.yawLimits = yawLimits;
1618
}
1719

1820
public GroundLocomotionEntity getEntity() {
@@ -25,11 +27,18 @@ public void tick() {
2527
GroundLocomotionEntity me = this.getEntity();
2628
float yaw = this.lookTargetController.getDesiredYaw().orElse(me.getYHeadRot()),
2729
pitch = this.lookTargetController.getDesiredPitch().orElse(me.getXRot());
28-
2930
float lerpFactor = this.lookTargetController.getRotationSpeed();
30-
// me.setYHeadRot(yaw);
31-
// me.setXRot(pitch);
31+
32+
float currentBodyYaw = this.getEntity().getSyncedBodyRotation();
33+
float netYaw = Mth.degreesDifference(currentBodyYaw, yaw);
34+
netYaw = Mth.clamp(netYaw, -yawLimits, yawLimits);
35+
yaw = currentBodyYaw + netYaw;
3236
me.setYHeadRot(Mth.rotLerp(lerpFactor, me.getYHeadRot(), yaw));
37+
38+
float currentBodyPitch = 0.0F;
39+
float netPitch = Mth.degreesDifference(currentBodyPitch, pitch);
40+
netPitch = Mth.clamp(netPitch, -pitchLimits, pitchLimits);
41+
pitch = currentBodyPitch + netPitch;
3342
me.setXRot(Mth.rotLerp(lerpFactor, me.getXRot(), pitch));
3443
}
3544
}

src/main/java/birsy/clinker/common/world/entity/gnomad/gnomind/behaviors/StayNearSquadCenter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ protected boolean checkExtraStartConditions(ServerLevel level, E entity) {
5353
double distToSquadCenterSqr = entity.distanceToSqr(squadCenter);
5454
if (distToSquadCenterSqr <= this.maximumDistanceSqr) return false;
5555

56-
int radius = (int)(Math.sqrt(distToSquadCenterSqr) - this.maximumDistance) + 8;
56+
int radius = (int)(Math.sqrt(distToSquadCenterSqr) - this.maximumDistance) + 12;
5757
Vec3 targetPos = DefaultRandomPos.getPosTowards(entity, radius, 7, squadCenter, Mth.HALF_PI * 0.5);
5858
if (targetPos == null) return false;
5959

src/main/java/birsy/clinker/common/world/entity/gnomad/testing/SquadTestingThrowerEntity.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public BrainActivityGroup<SquadTestingThrowerEntity> getIdleTasks() {
8383
new FirstApplicableBehaviour<>(
8484
new StayNearSquadCenter<SquadTestingThrowerEntity>()
8585
.maximumDistance(10.0F)
86-
.speedModifier(2.0F),
86+
.speedModifier(1.0F),
8787
new OneRandomBehaviour<SquadTestingThrowerEntity>(
8888
new SetRandomWalkTarget<>().speedModifier(0.5F),
8989
new Idle<>().runFor(mob -> mob.getRandom().nextInt(30, 60))

0 commit comments

Comments
 (0)