2019-03-23 20:49:34 +01:00
|
|
|
package com.minelittlepony.client.model;
|
|
|
|
|
2019-05-28 10:26:26 +02:00
|
|
|
import com.minelittlepony.client.model.armour.ModelPonyArmour;
|
|
|
|
import com.minelittlepony.client.model.armour.ArmourWrapper;
|
2019-03-23 20:49:34 +01:00
|
|
|
import com.minelittlepony.client.model.components.PonySnout;
|
|
|
|
import com.minelittlepony.client.model.components.PonyTail;
|
|
|
|
import com.minelittlepony.client.pony.PonyData;
|
|
|
|
import com.minelittlepony.client.transform.PonyTransformation;
|
|
|
|
import com.minelittlepony.client.util.render.AbstractRenderer;
|
|
|
|
import com.minelittlepony.client.util.render.PonyRenderer;
|
|
|
|
import com.minelittlepony.client.util.render.plane.PlaneRenderer;
|
2019-03-23 20:58:50 +01:00
|
|
|
import com.minelittlepony.model.BodyPart;
|
|
|
|
import com.minelittlepony.model.IPart;
|
|
|
|
import com.minelittlepony.model.armour.IEquestrianArmour;
|
|
|
|
import com.minelittlepony.pony.IPony;
|
|
|
|
import com.minelittlepony.pony.IPonyData;
|
|
|
|
import com.minelittlepony.pony.meta.Size;
|
2018-10-23 10:06:12 +02:00
|
|
|
import com.minelittlepony.util.math.MathUtil;
|
2018-04-24 14:55:32 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
import net.minecraft.client.model.Cuboid;
|
|
|
|
import net.minecraft.client.render.entity.model.BipedEntityModel;
|
2015-08-02 00:36:33 +02:00
|
|
|
import net.minecraft.entity.Entity;
|
2019-05-27 17:59:15 +02:00
|
|
|
import net.minecraft.entity.LivingEntity;
|
|
|
|
import net.minecraft.util.AbsoluteHand;
|
2016-05-04 03:23:57 +02:00
|
|
|
import net.minecraft.util.math.MathHelper;
|
2019-05-27 17:59:15 +02:00
|
|
|
import net.minecraft.util.math.Vec3d;
|
2015-08-02 00:36:33 +02:00
|
|
|
|
2019-01-06 17:07:42 +01:00
|
|
|
import java.util.UUID;
|
2016-11-25 05:40:19 +01:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
import static com.mojang.blaze3d.platform.GlStateManager.*;
|
2016-11-25 05:40:19 +01:00
|
|
|
|
2016-11-25 05:40:19 +01:00
|
|
|
/**
|
2018-04-29 14:22:26 +02:00
|
|
|
* Foundation class for all types of ponies.
|
2016-11-25 05:40:19 +01:00
|
|
|
*/
|
2019-05-27 17:59:15 +02:00
|
|
|
public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPonyModel<T> {
|
2015-12-09 04:14:42 +01:00
|
|
|
|
2018-08-10 08:32:09 +02:00
|
|
|
public boolean isSleeping;
|
|
|
|
public boolean isFlying;
|
|
|
|
public boolean isElytraFlying;
|
|
|
|
public boolean isSwimming;
|
2019-03-22 21:09:06 +01:00
|
|
|
public boolean isCrouching;
|
2018-09-19 23:22:59 +02:00
|
|
|
public boolean isRidingInteractive;
|
2018-08-10 08:32:09 +02:00
|
|
|
public boolean headGear;
|
2015-12-09 04:14:42 +01:00
|
|
|
|
2018-04-26 16:01:31 +02:00
|
|
|
/**
|
2019-03-22 21:09:06 +01:00
|
|
|
* Associated pony data.
|
2018-04-26 16:01:31 +02:00
|
|
|
*/
|
2019-04-14 22:06:25 +02:00
|
|
|
private IPonyData metadata = new PonyData();
|
2018-04-27 09:48:55 +02:00
|
|
|
|
2018-04-26 16:01:31 +02:00
|
|
|
/**
|
|
|
|
* Vertical pitch whilst flying.
|
|
|
|
*/
|
2016-06-15 03:37:41 +02:00
|
|
|
public float motionPitch;
|
2018-04-27 09:48:55 +02:00
|
|
|
|
2018-04-26 16:01:31 +02:00
|
|
|
/**
|
|
|
|
* Flag indicating that this model is performing a rainboom (flight).
|
|
|
|
*/
|
2018-05-10 18:24:27 +02:00
|
|
|
protected boolean rainboom;
|
2018-04-27 09:48:55 +02:00
|
|
|
|
2018-10-23 10:06:12 +02:00
|
|
|
protected double motionLerp;
|
|
|
|
|
2018-04-29 14:22:26 +02:00
|
|
|
public PlaneRenderer upperTorso;
|
|
|
|
public PlaneRenderer neck;
|
|
|
|
|
2019-03-23 20:49:34 +01:00
|
|
|
public IPart tail;
|
2018-04-29 14:22:26 +02:00
|
|
|
public PonySnout snout;
|
|
|
|
|
2019-01-06 17:07:42 +01:00
|
|
|
public UUID interpolatorId;
|
|
|
|
|
2016-01-19 06:34:07 +01:00
|
|
|
public AbstractPonyModel(boolean arms) {
|
|
|
|
super(0, arms);
|
2015-08-02 00:36:33 +02:00
|
|
|
}
|
|
|
|
|
2018-04-29 14:22:26 +02:00
|
|
|
@Override
|
2019-03-23 20:49:34 +01:00
|
|
|
public IEquestrianArmour<?> createArmour() {
|
2019-05-28 10:26:26 +02:00
|
|
|
return new ArmourWrapper<>(new ModelPonyArmour<>(), new ModelPonyArmour<>());
|
2018-04-29 14:22:26 +02:00
|
|
|
}
|
|
|
|
|
2018-05-10 18:24:27 +02:00
|
|
|
/**
|
|
|
|
* Checks flying and speed conditions and sets rainboom to true if we're a species with wings and is going faaast.
|
|
|
|
*/
|
2019-05-27 17:59:15 +02:00
|
|
|
private void checkRainboom(T entity, float swing) {
|
|
|
|
Vec3d motion = entity.getVelocity();
|
|
|
|
double zMotion = Math.sqrt(motion.x * motion.x + motion.z * motion.z);
|
2018-10-23 10:06:12 +02:00
|
|
|
|
2018-08-22 14:49:29 +02:00
|
|
|
rainboom = (isFlying() && canFly()) || isElytraFlying();
|
2018-10-23 10:06:12 +02:00
|
|
|
rainboom &= zMotion > 0.4F;
|
|
|
|
|
|
|
|
motionLerp = MathUtil.clampLimit(zMotion * 30, 1);
|
2018-06-03 16:38:03 +02:00
|
|
|
}
|
|
|
|
|
2019-05-28 01:50:45 +02:00
|
|
|
@Override
|
2019-05-27 17:59:15 +02:00
|
|
|
public void updateLivingState(T entity, IPony pony) {
|
|
|
|
isChild = entity.isBaby();
|
|
|
|
isSneaking = entity.isSneaking();
|
2019-03-22 21:09:06 +01:00
|
|
|
isCrouching = pony.isCrouching(entity);
|
2019-05-27 17:59:15 +02:00
|
|
|
isSleeping = entity.isSleeping();
|
2018-10-27 10:19:34 +02:00
|
|
|
isFlying = pony.isFlying(entity);
|
2019-05-27 17:59:15 +02:00
|
|
|
isElytraFlying = entity.isFallFlying();
|
2018-06-21 23:49:11 +02:00
|
|
|
isSwimming = pony.isSwimming(entity);
|
|
|
|
headGear = pony.isWearingHeadgear(entity);
|
2018-09-19 23:22:59 +02:00
|
|
|
isRidingInteractive = pony.isRidingInteractive(entity);
|
2019-05-27 17:59:15 +02:00
|
|
|
interpolatorId = entity.getUuid();
|
2018-06-21 23:49:11 +02:00
|
|
|
}
|
|
|
|
|
2018-05-01 12:38:13 +02:00
|
|
|
/**
|
|
|
|
* Sets the model's various rotation angles.
|
|
|
|
*
|
|
|
|
* @param move Entity motion parameter - i.e. velocity in no specific direction used in bipeds to calculate step amount.
|
|
|
|
* @param swing Degree to which each 'limb' swings.
|
2018-06-03 16:38:03 +02:00
|
|
|
* @param ticks Total whole and partial ticks since the entity's existance. Used in animations together with {@code swing} and {@code move}.
|
2018-05-01 12:38:13 +02:00
|
|
|
* @param headYaw Horizontal head motion in radians.
|
|
|
|
* @param headPitch Vertical head motion in radians.
|
|
|
|
* @param scale Scaling factor used to render this model. Determined by the return value of {@link RenderLivingBase.prepareScale}. Usually {@code 0.0625F}.
|
|
|
|
* @param entity The entity we're being called for.
|
|
|
|
*/
|
2018-04-29 14:22:26 +02:00
|
|
|
@Override
|
2019-05-27 17:59:15 +02:00
|
|
|
public void setAngles(T entity, float move, float swing, float ticks, float headYaw, float headPitch, float scale) {
|
2018-05-10 18:24:27 +02:00
|
|
|
checkRainboom(entity, swing);
|
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
super.setAngles(entity, move, swing, ticks, headYaw, headPitch, scale);
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
float headRotateAngleY = isSleeping() ? (Math.abs(entity.getUuid().getMostSignificantBits()) % 2.8F) - 1.9F : headYaw / 57.29578F;
|
2018-08-17 22:46:28 +02:00
|
|
|
float headRotateAngleX = isSleeping() ? 0.1f : headPitch / 57.29578F;
|
2018-04-29 14:22:26 +02:00
|
|
|
|
|
|
|
headRotateAngleX = Math.min(headRotateAngleX, (float) (0.5f - Math.toRadians(motionPitch)));
|
|
|
|
headRotateAngleX = Math.max(headRotateAngleX, (float) (-1.25f - Math.toRadians(motionPitch)));
|
|
|
|
|
|
|
|
updateHeadRotation(headRotateAngleX, headRotateAngleY);
|
|
|
|
|
2018-06-03 16:38:03 +02:00
|
|
|
shakeBody(move, swing, getWobbleAmount(), ticks);
|
|
|
|
rotateLegs(move, swing, ticks, entity);
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2018-08-17 22:46:28 +02:00
|
|
|
if (!isSwimming() && !rainboom) {
|
2018-05-10 18:24:27 +02:00
|
|
|
holdItem(swing);
|
|
|
|
}
|
2018-05-01 12:38:13 +02:00
|
|
|
swingItem(entity);
|
2018-04-29 14:22:26 +02:00
|
|
|
|
|
|
|
if (isCrouching()) {
|
2018-12-09 22:02:04 +01:00
|
|
|
ponyCrouch();
|
2018-04-29 14:22:26 +02:00
|
|
|
} else if (isRiding) {
|
2018-12-09 22:02:04 +01:00
|
|
|
ponyRide();
|
2018-04-29 14:22:26 +02:00
|
|
|
} else {
|
2018-08-18 00:24:58 +02:00
|
|
|
adjustBody(BODY_ROT_X_NOTSNEAK, BODY_RP_Y_NOTSNEAK, BODY_RP_Z_NOTSNEAK);
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
rightLeg.rotationPointY = FRONT_LEG_RP_Y_NOTSNEAK;
|
|
|
|
leftLeg.rotationPointY = FRONT_LEG_RP_Y_NOTSNEAK;
|
2018-05-01 12:38:13 +02:00
|
|
|
swingArms(ticks);
|
2018-04-29 14:22:26 +02:00
|
|
|
setHead(0, 0, 0);
|
|
|
|
}
|
|
|
|
|
2018-12-09 22:02:04 +01:00
|
|
|
if (isSleeping) {
|
|
|
|
ponySleep();
|
|
|
|
}
|
2018-04-29 14:22:26 +02:00
|
|
|
|
|
|
|
animateWears();
|
|
|
|
|
2018-05-01 16:46:59 +02:00
|
|
|
snout.setGender(metadata.getGender());
|
2018-04-29 14:22:26 +02:00
|
|
|
}
|
|
|
|
|
2018-12-09 22:02:04 +01:00
|
|
|
@Override
|
2018-09-09 19:39:28 +02:00
|
|
|
public float getWobbleAmount() {
|
2018-06-03 16:38:03 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
if (getSwingAmount() <= 0) {
|
2018-06-02 20:05:22 +02:00
|
|
|
return 0;
|
|
|
|
}
|
2018-06-03 16:38:03 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
return MathHelper.sin(MathHelper.sqrt(getSwingAmount()) * PI * 2) * 0.04F;
|
2018-06-02 20:05:22 +02:00
|
|
|
}
|
|
|
|
|
2018-12-09 22:02:04 +01:00
|
|
|
/**
|
|
|
|
* Aligns legs to a sneaky position.
|
|
|
|
*/
|
|
|
|
protected void ponyCrouch() {
|
|
|
|
adjustBody(BODY_ROT_X_SNEAK, BODY_RP_Y_SNEAK, BODY_RP_Z_SNEAK);
|
|
|
|
setHead(0, 6, -2);
|
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
rightArm.pitch -= LEG_ROT_X_SNEAK_ADJ;
|
|
|
|
leftArm.pitch -= LEG_ROT_X_SNEAK_ADJ;
|
2018-12-09 22:02:04 +01:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
leftLeg.rotationPointY = FRONT_LEG_RP_Y_SNEAK;
|
|
|
|
rightLeg.rotationPointY = FRONT_LEG_RP_Y_SNEAK;
|
2018-12-09 22:02:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
protected void ponySleep() {
|
2019-05-27 17:59:15 +02:00
|
|
|
rightArm.pitch = ROTATE_270;
|
|
|
|
leftArm.pitch = ROTATE_270;
|
2018-12-09 22:02:04 +01:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
rightLeg.pitch = ROTATE_90;
|
|
|
|
leftLeg.pitch = ROTATE_90;
|
2018-12-09 22:02:04 +01:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
setHead(1, 2, isSneaking ? -1 : 1);
|
2018-12-09 22:02:04 +01:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
AbstractRenderer.shiftRotationPoint(rightArm, 0, 2, 6);
|
|
|
|
AbstractRenderer.shiftRotationPoint(leftArm, 0, 2, 6);
|
|
|
|
AbstractRenderer.shiftRotationPoint(rightLeg, 0, 2, -8);
|
|
|
|
AbstractRenderer.shiftRotationPoint(leftLeg, 0, 2, -8);
|
2018-12-09 22:02:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
protected void ponyRide() {
|
2018-09-19 23:22:59 +02:00
|
|
|
if (isRidingInteractive) {
|
|
|
|
adjustBodyComponents(BODY_ROT_X_RIDING * 2, BODY_RP_Y_RIDING, BODY_RP_Z_RIDING);
|
|
|
|
adjustNeck(BODY_ROT_X_NOTSNEAK * 2, BODY_RP_Y_NOTSNEAK, BODY_RP_Z_NOTSNEAK - 4);
|
|
|
|
setHead(0, -2, -5);
|
|
|
|
} else {
|
|
|
|
adjustBodyComponents(BODY_ROT_X_RIDING, BODY_RP_Y_RIDING, BODY_RP_Z_RIDING);
|
|
|
|
adjustNeck(BODY_ROT_X_NOTSNEAK, BODY_RP_Y_NOTSNEAK, BODY_RP_Z_NOTSNEAK);
|
|
|
|
setHead(0, 0, 0);
|
|
|
|
}
|
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
leftLeg.rotationPointZ = 15;
|
|
|
|
leftLeg.rotationPointY = 9;
|
|
|
|
leftLeg.pitch = -PI / 4;
|
|
|
|
leftLeg.yaw = -PI / 5;
|
2018-12-09 22:02:04 +01:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
rightLeg.rotationPointZ = 15;
|
|
|
|
rightLeg.rotationPointY = 9;
|
|
|
|
rightLeg.pitch = -PI / 4;
|
|
|
|
rightLeg.yaw = PI / 5;
|
2018-12-09 22:02:04 +01:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
leftArm.roll = -PI * 0.06f;
|
|
|
|
rightArm.roll = PI * 0.06f;
|
2018-09-19 23:22:59 +02:00
|
|
|
|
2018-12-09 22:02:04 +01:00
|
|
|
if (isRidingInteractive) {
|
2019-05-27 17:59:15 +02:00
|
|
|
leftLeg.yaw = PI / 15;
|
|
|
|
leftLeg.pitch = PI / 9;
|
2018-12-09 22:02:04 +01:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
leftLeg.rotationPointZ = 10;
|
|
|
|
leftLeg.rotationPointY = 7;
|
2018-12-09 22:02:04 +01:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
rightLeg.yaw = -PI / 15;
|
|
|
|
rightLeg.pitch = PI / 9;
|
2018-12-09 22:02:04 +01:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
rightLeg.rotationPointZ = 10;
|
|
|
|
rightLeg.rotationPointY = 7;
|
2018-12-09 22:02:04 +01:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
leftArm.pitch = PI / 6;
|
|
|
|
rightArm.pitch = PI / 6;
|
2018-12-09 22:02:04 +01:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
leftArm.roll *= 2;
|
|
|
|
rightArm.roll *= 2;
|
2018-12-09 22:02:04 +01:00
|
|
|
}
|
2018-04-29 14:22:26 +02:00
|
|
|
}
|
|
|
|
|
2018-05-01 12:38:13 +02:00
|
|
|
/**
|
|
|
|
* Sets the model's various rotation angles.
|
|
|
|
*
|
|
|
|
* @param move Entity motion parameter - i.e. velocity in no specific direction used in bipeds to calculate step amount.
|
|
|
|
* @param swing Degree to which each 'limb' swings.
|
|
|
|
* @param bodySwing Horizontal (Y) body rotation.
|
|
|
|
* @param ticks Total whole and partial ticks since the entity's existance. Used in animations together with {@code swing} and {@code move}.
|
|
|
|
*/
|
2018-06-03 16:38:03 +02:00
|
|
|
protected void shakeBody(float move, float swing, float bodySwing, float ticks) {
|
2019-01-06 17:07:42 +01:00
|
|
|
tail.setRotationAndAngles(isSwimming() || rainboom, interpolatorId, move, swing, bodySwing * 5, ticks);
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
upperTorso.yaw = bodySwing;
|
|
|
|
body.yaw = bodySwing;
|
|
|
|
neck.yaw = bodySwing;
|
2018-04-29 14:22:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private void animateWears() {
|
2019-05-27 17:59:15 +02:00
|
|
|
leftArmOverlay.copyRotation(leftArm);
|
|
|
|
rightArmOverlay.copyRotation(rightArm);
|
|
|
|
leftLegOverlay.copyRotation(leftLeg);
|
|
|
|
rightLegOverlay.copyRotation(rightLeg);
|
|
|
|
bodyOverlay.copyRotation(body);
|
2018-04-29 14:22:26 +02:00
|
|
|
}
|
|
|
|
|
2018-05-26 22:50:30 +02:00
|
|
|
@Override
|
2019-05-27 17:59:15 +02:00
|
|
|
public Cuboid getHead() {
|
|
|
|
return head;
|
2018-05-26 22:50:30 +02:00
|
|
|
}
|
|
|
|
|
2019-03-22 21:09:06 +01:00
|
|
|
@Override
|
|
|
|
public void setPitch(float pitch) {
|
|
|
|
motionPitch = pitch;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public float getPitch() {
|
|
|
|
return motionPitch;
|
|
|
|
}
|
|
|
|
|
2018-04-29 14:22:26 +02:00
|
|
|
/**
|
2018-05-01 12:38:13 +02:00
|
|
|
* Sets the head rotation point.
|
2018-04-29 14:22:26 +02:00
|
|
|
*/
|
|
|
|
protected void setHead(float posX, float posY, float posZ) {
|
2019-05-27 17:59:15 +02:00
|
|
|
head.setRotationPoint(posX, posY, posZ);
|
|
|
|
headwear.setRotationPoint(posX, posY, posZ);
|
2018-04-29 14:22:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Called to update the head rotation.
|
|
|
|
*
|
2018-05-01 12:38:13 +02:00
|
|
|
* @param x New rotation X
|
|
|
|
* @param y New rotation Y
|
2018-04-29 14:22:26 +02:00
|
|
|
*/
|
|
|
|
protected void updateHeadRotation(float x, float y) {
|
2019-05-27 17:59:15 +02:00
|
|
|
headwear.yaw = head.yaw = y;
|
|
|
|
headwear.pitch = head.pitch = x;
|
2018-04-29 14:22:26 +02:00
|
|
|
}
|
|
|
|
|
2018-05-01 12:38:13 +02:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* Used to set the legs rotation based on walking/crouching animations.
|
|
|
|
*
|
|
|
|
* Takes the same parameters as {@link AbstractPonyModel.setRotationAndAngles}
|
|
|
|
*
|
|
|
|
*/
|
2019-05-27 17:59:15 +02:00
|
|
|
protected void rotateLegs(float move, float swing, float ticks, T entity) {
|
2018-06-29 18:36:03 +02:00
|
|
|
if (isSwimming()) {
|
|
|
|
rotateLegsSwimming(move, swing, ticks, entity);
|
2018-07-30 05:49:45 +02:00
|
|
|
} else if (isGoingFast()) {
|
2018-05-01 12:38:13 +02:00
|
|
|
rotateLegsInFlight(move, swing, ticks, entity);
|
2018-04-29 14:22:26 +02:00
|
|
|
} else {
|
2018-05-01 12:38:13 +02:00
|
|
|
rotateLegsOnGround(move, swing, ticks, entity);
|
2018-04-29 14:22:26 +02:00
|
|
|
}
|
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
float sin = MathHelper.sin(body.yaw) * 5;
|
|
|
|
float cos = MathHelper.cos(body.yaw) * 5;
|
2018-06-03 16:38:03 +02:00
|
|
|
|
|
|
|
float spread = getLegSpread();
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
rightArm.rotationPointZ = spread + sin;
|
|
|
|
leftArm.rotationPointZ = spread - sin;
|
2018-06-03 16:38:03 +02:00
|
|
|
|
2018-10-28 15:26:00 +01:00
|
|
|
float legRPX = cos - getLegOutset() - 0.001F;
|
2018-06-03 16:38:03 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
legRPX = metadata.getInterpolator(entity.getUuid()).interpolate("legOffset", legRPX, 3);
|
2018-06-11 19:25:02 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
rightArm.rotationPointX = -legRPX;
|
|
|
|
rightLeg.rotationPointX = -legRPX;
|
2018-06-03 16:38:03 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
leftArm.rotationPointX = legRPX;
|
|
|
|
leftLeg.rotationPointX = legRPX;
|
2018-06-03 16:38:03 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
rightArm.yaw += body.yaw;
|
|
|
|
leftArm.yaw += body.yaw;
|
2018-06-03 16:38:03 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
rightArm.rotationPointY = leftArm.rotationPointY = 8;
|
|
|
|
rightLeg.rotationPointZ = leftLeg.rotationPointZ = 10;
|
2018-04-29 14:22:26 +02:00
|
|
|
}
|
|
|
|
|
2018-06-29 18:36:03 +02:00
|
|
|
/**
|
|
|
|
* Rotates legs in quopy fashion whilst swimming.
|
|
|
|
*
|
|
|
|
* @param move Entity motion parameter - i.e. velocity in no specific direction used in bipeds to calculate step amount.
|
|
|
|
* @param swing Degree to which each 'limb' swings.
|
|
|
|
* @param ticks Total whole and partial ticks since the entity's existance. Used in animations together with {@code swing} and {@code move}.
|
|
|
|
* @param entity The entity we're being called for.
|
|
|
|
*
|
|
|
|
*/
|
2019-05-27 17:59:15 +02:00
|
|
|
protected void rotateLegsSwimming(float move, float swing, float ticks, T entity) {
|
2018-06-29 18:36:03 +02:00
|
|
|
|
2018-10-23 10:06:12 +02:00
|
|
|
float legLeft = (ROTATE_90 + MathHelper.sin((move / 3) + 2 * PI/3) / 2) * (float)motionLerp;
|
2018-06-29 18:36:03 +02:00
|
|
|
|
2018-10-23 10:06:12 +02:00
|
|
|
float left = (ROTATE_90 + MathHelper.sin((move / 3) + 2 * PI) / 2) * (float)motionLerp;
|
|
|
|
float right = (ROTATE_90 + MathHelper.sin(move / 3) / 2) * (float)motionLerp;
|
2018-06-29 18:36:03 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
leftArm.pitch = -left;
|
|
|
|
leftArm.yaw = -left/2;
|
|
|
|
leftArm.roll = left/2;
|
2018-06-29 18:36:03 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
rightArm.pitch = -right;
|
|
|
|
rightArm.yaw = right/2;
|
|
|
|
rightArm.roll = -right/2;
|
2018-06-29 18:36:03 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
leftLeg.pitch = legLeft;
|
|
|
|
rightLeg.pitch = right;
|
2018-06-29 18:36:03 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
leftLeg.yaw = 0;
|
|
|
|
rightLeg.yaw = 0;
|
2018-06-29 18:36:03 +02:00
|
|
|
}
|
2018-06-03 16:38:03 +02:00
|
|
|
|
2018-05-01 12:38:13 +02:00
|
|
|
/**
|
|
|
|
* Rotates legs in quopy fashion whilst flying.
|
|
|
|
*
|
|
|
|
* @param move Entity motion parameter - i.e. velocity in no specific direction used in bipeds to calculate step amount.
|
|
|
|
* @param swing Degree to which each 'limb' swings.
|
|
|
|
* @param ticks Total whole and partial ticks since the entity's existance. Used in animations together with {@code swing} and {@code move}.
|
|
|
|
* @param entity The entity we're being called for.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
protected void rotateLegsInFlight(float move, float swing, float ticks, Entity entity) {
|
2018-05-10 18:24:27 +02:00
|
|
|
float armX = rainboom ? ROTATE_270 : MathHelper.sin(-swing / 2);
|
|
|
|
float legX = rainboom ? ROTATE_90 : MathHelper.sin(swing / 2);
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
leftArm.pitch = armX;
|
|
|
|
rightArm.pitch = armX;
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
leftLeg.pitch = legX;
|
|
|
|
rightLeg.pitch = legX;
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
leftArm.yaw = -0.2F;
|
|
|
|
leftLeg.yaw = 0.2F;
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
rightArm.yaw = 0.2F;
|
|
|
|
rightLeg.yaw = -0.2F;
|
2018-10-21 17:15:42 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
rightArm.roll = 0;
|
|
|
|
leftArm.roll = 0;
|
2018-04-29 14:22:26 +02:00
|
|
|
}
|
|
|
|
|
2018-05-01 12:38:13 +02:00
|
|
|
/**
|
|
|
|
* Rotates legs in quopy fashion for walking.
|
|
|
|
*
|
|
|
|
* @param move Entity motion parameter - i.e. velocity in no specific direction used in bipeds to calculate step amount.
|
|
|
|
* @param swing Degree to which each 'limb' swings.
|
|
|
|
* @param ticks Total whole and partial ticks since the entity's existance. Used in animations together with {@code swing} and {@code move}.
|
|
|
|
* @param entity The entity we're being called for.
|
|
|
|
*
|
|
|
|
*/
|
2019-05-27 17:59:15 +02:00
|
|
|
protected void rotateLegsOnGround(float move, float swing, float ticks, T entity) {
|
2018-05-01 12:38:13 +02:00
|
|
|
float angle = PI * (float) Math.pow(swing, 16);
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2018-05-01 12:38:13 +02:00
|
|
|
float baseRotation = move * 0.6662F; // magic number ahoy
|
|
|
|
float scale = swing / 4;
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
leftArm.pitch = MathHelper.cos(baseRotation + angle) * scale;
|
|
|
|
rightArm.pitch = MathHelper.cos(baseRotation + PI + angle / 2) * scale;
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
leftLeg.pitch = MathHelper.cos(baseRotation + PI - (angle * 0.4f)) * scale;
|
|
|
|
rightLeg.pitch = MathHelper.cos(baseRotation + angle / 5) * scale;
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
leftArm.yaw = 0;
|
|
|
|
rightArm.yaw = 0;
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
leftLeg.yaw = 0;
|
|
|
|
rightLeg.yaw = 0;
|
2018-10-21 17:15:42 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
rightArm.roll = 0;
|
|
|
|
leftArm.roll = 0;
|
2018-04-29 14:22:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
protected float getLegOutset() {
|
2018-12-09 22:02:04 +01:00
|
|
|
if (isSleeping()) {
|
|
|
|
return 3.6f;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isCrouching()) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-04-29 23:06:34 +02:00
|
|
|
return 5;
|
2018-04-29 14:22:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
protected float getLegSpread() {
|
|
|
|
return rainboom ? 2 : 1;
|
|
|
|
}
|
|
|
|
|
2018-05-01 12:38:13 +02:00
|
|
|
/**
|
|
|
|
* Adjusts legs as if holding an item. Delegates to the correct arm/leg/limb as neccessary.
|
|
|
|
*
|
|
|
|
* @param swing
|
|
|
|
*/
|
2018-04-29 14:22:26 +02:00
|
|
|
protected void holdItem(float swing) {
|
|
|
|
boolean both = leftArmPose == ArmPose.ITEM && rightArmPose == ArmPose.ITEM;
|
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
alignArmForAction(leftArm, leftArmPose, rightArmPose, both, swing, 1);
|
|
|
|
alignArmForAction(rightArm, rightArmPose, leftArmPose, both, swing, -1);
|
2018-04-29 14:22:26 +02:00
|
|
|
}
|
|
|
|
|
2019-04-14 22:06:25 +02:00
|
|
|
@Override
|
2019-05-27 17:59:15 +02:00
|
|
|
public Cuboid getBodyPart(BodyPart part) {
|
2019-04-14 22:06:25 +02:00
|
|
|
switch (part) {
|
|
|
|
default:
|
2019-05-27 17:59:15 +02:00
|
|
|
case HEAD: return head;
|
2019-04-14 22:06:25 +02:00
|
|
|
case NECK: return neck;
|
|
|
|
case TAIL:
|
|
|
|
case LEGS:
|
2019-05-27 17:59:15 +02:00
|
|
|
case BODY: return body;
|
2019-04-14 22:06:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-01 12:38:13 +02:00
|
|
|
/**
|
|
|
|
* Aligns an arm for the appropriate arm pose
|
|
|
|
*
|
|
|
|
* @param arm The arm model to align
|
|
|
|
* @param pose The post to align to
|
|
|
|
* @param both True if we have something in both hands
|
|
|
|
* @param swing Degree to which each 'limb' swings.
|
|
|
|
*/
|
2019-05-27 17:59:15 +02:00
|
|
|
protected void alignArmForAction(Cuboid arm, ArmPose pose, ArmPose complement, boolean both, float swing, float reflect) {
|
2018-04-29 14:22:26 +02:00
|
|
|
switch (pose) {
|
|
|
|
case ITEM:
|
|
|
|
float swag = 1;
|
2018-08-17 22:46:28 +02:00
|
|
|
if (!isFlying() && both) {
|
2018-04-29 14:22:26 +02:00
|
|
|
swag -= (float)Math.pow(swing, 2);
|
|
|
|
}
|
|
|
|
float mult = 1 - swag/2;
|
2019-05-27 17:59:15 +02:00
|
|
|
arm.pitch = arm.pitch * mult - (PI / 10) * swag;
|
|
|
|
arm.roll = -reflect * (PI / 15);
|
2018-08-17 22:46:28 +02:00
|
|
|
if (isCrouching()) {
|
2018-06-03 16:38:03 +02:00
|
|
|
arm.rotationPointX -= reflect * 2;
|
|
|
|
}
|
2018-04-29 14:22:26 +02:00
|
|
|
case EMPTY:
|
2019-05-27 17:59:15 +02:00
|
|
|
arm.yaw = 0;
|
2018-04-29 14:22:26 +02:00
|
|
|
break;
|
|
|
|
case BLOCK:
|
2019-05-27 17:59:15 +02:00
|
|
|
arm.pitch = (arm.pitch / 2 - 0.9424779F) - 0.3F;
|
|
|
|
arm.yaw = reflect * PI / 9;
|
2018-08-22 15:15:48 +02:00
|
|
|
if (complement == pose) {
|
2019-05-27 17:59:15 +02:00
|
|
|
arm.yaw -= reflect * PI / 18;
|
2018-08-22 15:15:48 +02:00
|
|
|
}
|
2018-06-03 17:30:53 +02:00
|
|
|
arm.rotationPointX += reflect;
|
|
|
|
arm.rotationPointZ += 3;
|
2018-08-17 22:46:28 +02:00
|
|
|
if (isCrouching()) {
|
2018-06-03 17:30:53 +02:00
|
|
|
arm.rotationPointY += 4;
|
2018-06-03 16:38:03 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case BOW_AND_ARROW:
|
|
|
|
aimBow(arm, swing);
|
2018-04-29 14:22:26 +02:00
|
|
|
break;
|
2019-06-02 16:36:21 +02:00
|
|
|
case CROSSBOW_HOLD:
|
|
|
|
aimBow(arm, swing);
|
|
|
|
|
|
|
|
arm.pitch = head.pitch - ROTATE_90;
|
|
|
|
arm.yaw = head.yaw + 0.06F;
|
|
|
|
break;
|
|
|
|
case CROSSBOW_CHARGE:
|
|
|
|
aimBow(arm, swing);
|
|
|
|
|
|
|
|
arm.pitch = -0.8F;
|
|
|
|
arm.yaw = head.yaw + 0.06F;
|
|
|
|
break;
|
|
|
|
case THROW_SPEAR:
|
|
|
|
arm.pitch = ROTATE_90 * 2;
|
|
|
|
break;
|
2018-04-29 14:22:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
protected void aimBow(Cuboid arm, float ticks) {
|
|
|
|
arm.pitch = ROTATE_270 + head.pitch + (MathHelper.sin(ticks * 0.067F) * 0.05F);
|
|
|
|
arm.yaw = head.yaw - 0.06F;
|
|
|
|
arm.roll = MathHelper.cos(ticks * 0.09F) * 0.05F + 0.05F;
|
2018-12-09 22:02:04 +01:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
if (isSneaking) {
|
2018-06-03 16:38:03 +02:00
|
|
|
arm.rotationPointY += 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-05-01 12:38:13 +02:00
|
|
|
/**
|
|
|
|
* Animates arm swinging. Delegates to the correct arm/leg/limb as neccessary.
|
|
|
|
*
|
|
|
|
* @param entity The entity we are being called for.
|
|
|
|
*/
|
2019-05-27 17:59:15 +02:00
|
|
|
protected void swingItem(T entity) {
|
|
|
|
if (getSwingAmount() > 0 && !isSleeping()) {
|
|
|
|
AbsoluteHand mainSide = getPreferedHand(entity);
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
swingArm(getArm(mainSide));
|
2018-04-29 14:22:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-01 12:38:13 +02:00
|
|
|
/**
|
|
|
|
* Animates arm swinging.
|
|
|
|
*
|
|
|
|
* @param arm The arm to swing
|
|
|
|
*/
|
2019-05-27 17:59:15 +02:00
|
|
|
protected void swingArm(Cuboid arm) {
|
|
|
|
float swing = 1 - (float)Math.pow(1 - getSwingAmount(), 3);
|
2018-04-29 14:22:26 +02:00
|
|
|
|
|
|
|
float deltaX = MathHelper.sin(swing * PI);
|
2019-05-27 17:59:15 +02:00
|
|
|
float deltaZ = MathHelper.sin(getSwingAmount() * PI);
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
float deltaAim = deltaZ * (0.7F - head.pitch) * 0.75F;
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
arm.pitch -= deltaAim + deltaX * 1.2F;
|
|
|
|
arm.yaw += body.yaw * 2;
|
|
|
|
arm.roll = -deltaZ * 0.4F;
|
2018-04-29 14:22:26 +02:00
|
|
|
}
|
|
|
|
|
2018-05-01 12:38:13 +02:00
|
|
|
/**
|
|
|
|
* Animates the walking animation.
|
|
|
|
*
|
|
|
|
* @param ticks Total whole and partial ticks since the entity's existance. Used in animations together with {@code swing} and {@code move}.
|
|
|
|
*/
|
|
|
|
protected void swingArms(float ticks) {
|
2018-12-09 22:02:04 +01:00
|
|
|
if (isSleeping()) {
|
|
|
|
return;
|
|
|
|
}
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2018-05-01 12:38:13 +02:00
|
|
|
float cos = MathHelper.cos(ticks * 0.09F) * 0.05F + 0.05F;
|
|
|
|
float sin = MathHelper.sin(ticks * 0.067F) * 0.05F;
|
2018-04-29 14:22:26 +02:00
|
|
|
|
|
|
|
if (rightArmPose != ArmPose.EMPTY) {
|
2019-05-27 17:59:15 +02:00
|
|
|
rightArm.roll += cos;
|
|
|
|
rightArm.pitch += sin;
|
2018-04-29 14:22:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (leftArmPose != ArmPose.EMPTY) {
|
2019-05-27 17:59:15 +02:00
|
|
|
leftArm.roll += cos;
|
|
|
|
leftArm.pitch += sin;
|
2018-04-29 14:22:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void adjustBody(float rotateAngleX, float rotationPointY, float rotationPointZ) {
|
|
|
|
adjustBodyComponents(rotateAngleX, rotationPointY, rotationPointZ);
|
|
|
|
adjustNeck(rotateAngleX, rotationPointY, rotationPointZ);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void adjustBodyComponents(float rotateAngleX, float rotationPointY, float rotationPointZ) {
|
2019-05-27 17:59:15 +02:00
|
|
|
body.pitch = rotateAngleX;
|
|
|
|
body.rotationPointY = rotationPointY;
|
|
|
|
body.rotationPointZ = rotationPointZ;
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
upperTorso.pitch = rotateAngleX;
|
2018-04-29 14:22:26 +02:00
|
|
|
upperTorso.rotationPointY = rotationPointY;
|
|
|
|
upperTorso.rotationPointZ = rotationPointZ;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void adjustNeck(float rotateAngleX, float rotationPointY, float rotationPointZ) {
|
|
|
|
neck.setRotationPoint(NECK_ROT_X + rotateAngleX, rotationPointY, rotationPointZ);
|
|
|
|
}
|
|
|
|
|
2018-09-07 21:16:07 +02:00
|
|
|
@Override
|
2016-11-25 05:40:19 +01:00
|
|
|
public void init(float yOffset, float stretch) {
|
2019-05-27 17:59:15 +02:00
|
|
|
cuboidList.clear();
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2018-06-21 23:49:11 +02:00
|
|
|
initHead(yOffset, stretch);
|
|
|
|
initBody(yOffset, stretch);
|
|
|
|
initLegs(yOffset, stretch);
|
|
|
|
initTail(yOffset, stretch);
|
2018-04-29 14:22:26 +02:00
|
|
|
}
|
|
|
|
|
2018-06-21 23:49:11 +02:00
|
|
|
protected void initHead(float yOffset, float stretch) {
|
2019-05-27 17:59:15 +02:00
|
|
|
head = new PonyRenderer(this, 0, 0)
|
2018-06-21 23:49:11 +02:00
|
|
|
.offset(HEAD_CENTRE_X, HEAD_CENTRE_Y, HEAD_CENTRE_Z)
|
2018-04-29 14:22:26 +02:00
|
|
|
.around(HEAD_RP_X, HEAD_RP_Y + yOffset, HEAD_RP_Z - 2)
|
2018-08-24 13:54:24 +02:00
|
|
|
.box(-4, -4, -4, 8, 8, 8, stretch);
|
2019-05-27 17:59:15 +02:00
|
|
|
initEars(((PonyRenderer)head), yOffset, stretch);
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
headwear = new PonyRenderer(this, 32, 0)
|
2018-06-21 23:49:11 +02:00
|
|
|
.offset(HEAD_CENTRE_X, HEAD_CENTRE_Y, HEAD_CENTRE_Z)
|
2018-04-29 14:22:26 +02:00
|
|
|
.around(HEAD_RP_X, HEAD_RP_Y + yOffset, HEAD_RP_Z - 2)
|
2018-10-20 14:12:12 +02:00
|
|
|
.box(-4, -4, -4, 8, 8, 8, stretch + 0.7504F);
|
2018-06-29 19:14:11 +02:00
|
|
|
|
|
|
|
snout = new PonySnout(this);
|
|
|
|
snout.init(yOffset, stretch);
|
2018-04-29 14:22:26 +02:00
|
|
|
}
|
|
|
|
|
2018-08-24 13:54:24 +02:00
|
|
|
protected void initEars(PonyRenderer head, float yOffset, float stretch) {
|
|
|
|
head.tex(12, 16).box(-4, -6, 1, 2, 2, 2, stretch) // right ear
|
|
|
|
.flip().box( 2, -6, 1, 2, 2, 2, stretch); // left ear
|
|
|
|
}
|
|
|
|
|
2018-06-21 23:49:11 +02:00
|
|
|
protected void initTail(float yOffset, float stretch) {
|
|
|
|
tail = new PonyTail(this);
|
|
|
|
tail.init(yOffset, stretch);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-04-29 14:22:26 +02:00
|
|
|
/**
|
|
|
|
* Creates the main torso and neck.
|
|
|
|
*/
|
2018-06-21 23:49:11 +02:00
|
|
|
protected void initBody(float yOffset, float stretch) {
|
|
|
|
if (textureHeight == 64) {
|
2019-05-27 17:59:15 +02:00
|
|
|
bodyOverlay.boxes.clear();
|
|
|
|
cuboidList.add(bodyOverlay);
|
2018-06-21 23:49:11 +02:00
|
|
|
}
|
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
body = new PonyRenderer(this, 16, 16)
|
2018-06-21 23:49:11 +02:00
|
|
|
.around(HEAD_RP_X, HEAD_RP_Y + yOffset, HEAD_RP_Z)
|
|
|
|
.box(-4, 4, -2, 8, 8, 4, stretch);
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
bodyOverlay.addBox(-4, 4, -2, 8, 8, 4, stretch + 0.25F);
|
|
|
|
bodyOverlay.setRotationPoint(HEAD_RP_X, HEAD_RP_Y + yOffset, HEAD_RP_Z);
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2018-06-21 23:49:11 +02:00
|
|
|
upperTorso = new PlaneRenderer(this, 24, 0);
|
2018-04-29 14:22:26 +02:00
|
|
|
upperTorso.offset(BODY_CENTRE_X, BODY_CENTRE_Y, BODY_CENTRE_Z)
|
|
|
|
.around(HEAD_RP_X, HEAD_RP_Y + yOffset, HEAD_RP_Z)
|
2018-09-05 10:17:22 +02:00
|
|
|
.tex(24, 0) .east( 4, -4, -4, 8, 8, stretch)
|
|
|
|
.tex(4, 0) .east( 4, -4, 4, 8, 4, stretch)
|
|
|
|
.tex(56, 0) .bottom(-4, 4, -4, 8, 8, stretch)
|
2018-10-31 19:47:50 +01:00
|
|
|
.tex(36, 16) .north(-4, -4, 8, 8, 4, stretch)
|
|
|
|
.north(-4, 0, 8, 8, 4, stretch)
|
2018-09-05 10:17:22 +02:00
|
|
|
.bottom(-4, 4, 4, 8, 4, stretch)
|
|
|
|
.flipZ().tex(32, 20).top(-4, -4, -4, 8, 12, stretch)
|
|
|
|
.tex(24, 0).west(-4, -4, -4, 8, 8, stretch)
|
|
|
|
.tex(4, 0) .west(-4, -4, 4, 8, 4, stretch)
|
2018-04-29 14:22:26 +02:00
|
|
|
// Tail stub
|
|
|
|
.child(0)
|
2018-09-05 10:17:22 +02:00
|
|
|
.tex(32, 0).top(-1, 2, 2, 2, 6, stretch)
|
|
|
|
.bottom(-1, 4, 2, 2, 6, stretch)
|
|
|
|
.east( 1, 2, 2, 2, 6, stretch)
|
|
|
|
.south(-1, 2, 8, 2, 2, stretch)
|
|
|
|
.flipZ().west(-1, 2, 2, 2, 6, stretch)
|
2018-06-21 23:49:11 +02:00
|
|
|
.rotate(0.5F, 0, 0);
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2018-06-21 23:49:11 +02:00
|
|
|
neck = new PlaneRenderer(this, 0, 16)
|
|
|
|
.at(NECK_CENTRE_X, NECK_CENTRE_Y, NECK_CENTRE_Z)
|
|
|
|
.rotate(NECK_ROT_X, 0, 0).around(HEAD_RP_X, HEAD_RP_Y + yOffset, HEAD_RP_Z)
|
2018-09-05 10:17:22 +02:00
|
|
|
.north(0, 0, 0, 4, 4, stretch)
|
|
|
|
.south(0, 0, 4, 4, 4, stretch)
|
|
|
|
.east(4, 0, 0, 4, 4, stretch)
|
|
|
|
.west(0, 0, 0, 4, 4, stretch);
|
2018-04-29 14:22:26 +02:00
|
|
|
}
|
|
|
|
|
2018-06-21 23:49:11 +02:00
|
|
|
protected void preInitLegs() {
|
2019-05-27 17:59:15 +02:00
|
|
|
leftArm = new Cuboid(this, 32, 48);
|
|
|
|
rightArm = new Cuboid(this, 40, 16);
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
leftLeg = new Cuboid(this, 16, 48);
|
|
|
|
rightLeg = new Cuboid(this, 0, 16);
|
2018-04-29 14:22:26 +02:00
|
|
|
}
|
|
|
|
|
2018-06-21 23:49:11 +02:00
|
|
|
protected void preInitLegwear() {
|
2019-05-27 17:59:15 +02:00
|
|
|
leftArmOverlay.boxes.clear();
|
|
|
|
cuboidList.add(leftArmOverlay);
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
rightArmOverlay.boxes.clear();
|
|
|
|
cuboidList.add(rightArmOverlay);
|
|
|
|
|
|
|
|
leftLegOverlay.boxes.clear();
|
|
|
|
cuboidList.add(leftLegOverlay);
|
|
|
|
leftLegOverlay.setTextureOffset(0, 48);
|
|
|
|
|
|
|
|
rightLegOverlay.boxes.clear();
|
|
|
|
cuboidList.add(rightLegOverlay);
|
|
|
|
rightLegOverlay.setTextureOffset(0, 32);
|
2018-04-29 14:22:26 +02:00
|
|
|
}
|
|
|
|
|
2018-06-21 23:49:11 +02:00
|
|
|
protected void initLegs(float yOffset, float stretch) {
|
|
|
|
preInitLegs();
|
|
|
|
preInitLegwear();
|
|
|
|
|
2018-08-15 17:14:40 +02:00
|
|
|
int armLength = getArmLength();
|
2018-04-29 14:22:26 +02:00
|
|
|
int armWidth = getArmWidth();
|
|
|
|
int armDepth = getArmDepth();
|
|
|
|
|
|
|
|
float rarmX = getLegRotationX();
|
|
|
|
float rarmY = getArmRotationY();
|
|
|
|
|
2018-04-29 18:00:26 +02:00
|
|
|
float armX = THIRDP_ARM_CENTRE_X;
|
2018-06-22 17:58:18 +02:00
|
|
|
float armY = THIRDP_ARM_CENTRE_Y;
|
2018-04-29 18:00:26 +02:00
|
|
|
float armZ = BODY_CENTRE_Z / 2 - 1 - armDepth;
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
leftArm .addBox(armX, armY, armZ, armWidth, armLength, armDepth, stretch);
|
|
|
|
rightArm.addBox(armX - armWidth, armY, armZ, armWidth, armLength, armDepth, stretch);
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
leftLeg .addBox(armX, armY, armZ, armWidth, armLength, armDepth, stretch);
|
|
|
|
rightLeg.addBox(armX - armWidth, armY, armZ, armWidth, armLength, armDepth, stretch);
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
leftArm .setRotationPoint( rarmX, yOffset + rarmY, 0);
|
|
|
|
rightArm.setRotationPoint(-rarmX, yOffset + rarmY, 0);
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
leftLeg .setRotationPoint( rarmX, yOffset, 0);
|
|
|
|
rightLeg.setRotationPoint(-rarmX, yOffset, 0);
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
leftArmOverlay.addBox(armX, armY, armZ, armWidth, armLength, armDepth, stretch + 0.25f);
|
|
|
|
leftArmOverlay.setRotationPoint(rarmX, yOffset + rarmY, 0);
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
rightArmOverlay.addBox(armX - armWidth, armY, armZ, armWidth, armLength, armDepth, stretch + 0.25f);
|
|
|
|
rightArmOverlay.setRotationPoint(-rarmX, yOffset + rarmY, 0);
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
leftArmOverlay.addBox(armX, armY, armZ, armWidth, armLength, armDepth, stretch + 0.25f);
|
|
|
|
rightLegOverlay.setRotationPoint(rarmX, yOffset, 0);
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
rightLegOverlay.addBox(armX - armWidth, armY, armZ, armWidth, armLength, armDepth, stretch + 0.25f);
|
|
|
|
rightLegOverlay.setRotationPoint(-rarmX, yOffset, 0);
|
2018-04-29 14:22:26 +02:00
|
|
|
}
|
2015-08-02 00:36:33 +02:00
|
|
|
|
2018-06-21 23:49:11 +02:00
|
|
|
protected int getArmWidth() {
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected int getArmDepth() {
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
|
2018-08-15 17:14:40 +02:00
|
|
|
protected int getArmLength() {
|
|
|
|
return 12;
|
|
|
|
}
|
|
|
|
|
2018-06-21 23:49:11 +02:00
|
|
|
protected float getLegRotationX() {
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected float getArmRotationY() {
|
|
|
|
return 8;
|
|
|
|
}
|
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
public ArmPose getArmPoseForSide(AbsoluteHand side) {
|
|
|
|
return side == AbsoluteHand.RIGHT ? rightArmPose : leftArmPose;
|
2018-04-27 20:37:54 +02:00
|
|
|
}
|
|
|
|
|
2018-04-28 18:13:35 +02:00
|
|
|
@Override
|
2018-05-10 18:24:27 +02:00
|
|
|
public IPonyData getMetadata() {
|
|
|
|
return metadata;
|
2015-08-02 00:36:33 +02:00
|
|
|
}
|
2018-04-27 09:48:55 +02:00
|
|
|
|
2019-04-14 22:06:25 +02:00
|
|
|
@Override
|
|
|
|
public void apply(IPonyData meta) {
|
|
|
|
metadata = meta;
|
|
|
|
}
|
|
|
|
|
2018-05-10 18:24:27 +02:00
|
|
|
@Override
|
|
|
|
public boolean isCrouching() {
|
2019-03-22 21:09:06 +01:00
|
|
|
return isCrouching;
|
2018-04-26 16:01:31 +02:00
|
|
|
}
|
2015-08-02 00:36:33 +02:00
|
|
|
|
2018-05-10 18:24:27 +02:00
|
|
|
@Override
|
|
|
|
public boolean isGoingFast() {
|
|
|
|
return rainboom;
|
|
|
|
}
|
|
|
|
|
2018-06-21 19:28:22 +02:00
|
|
|
@Override
|
|
|
|
public boolean hasHeadGear() {
|
|
|
|
return headGear;
|
|
|
|
}
|
|
|
|
|
2018-04-28 18:13:35 +02:00
|
|
|
@Override
|
|
|
|
public boolean isFlying() {
|
2018-05-10 18:34:55 +02:00
|
|
|
return isFlying && canFly();
|
2018-04-28 18:13:35 +02:00
|
|
|
}
|
|
|
|
|
2018-07-30 05:49:45 +02:00
|
|
|
@Override
|
|
|
|
public boolean isElytraFlying() {
|
|
|
|
return isElytraFlying;
|
|
|
|
}
|
|
|
|
|
2018-06-22 00:42:13 +02:00
|
|
|
@Override
|
|
|
|
public boolean isSleeping() {
|
|
|
|
return isSleeping;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isRiding() {
|
|
|
|
return isRiding;
|
|
|
|
}
|
|
|
|
|
2018-06-03 22:23:32 +02:00
|
|
|
@Override
|
|
|
|
public boolean isSwimming() {
|
|
|
|
return isSwimming;
|
|
|
|
}
|
|
|
|
|
2018-04-28 18:13:35 +02:00
|
|
|
@Override
|
2018-04-26 16:01:31 +02:00
|
|
|
public boolean isChild() {
|
2019-03-23 20:49:34 +01:00
|
|
|
return getSize() == Size.FOAL;
|
2018-04-26 16:01:31 +02:00
|
|
|
}
|
|
|
|
|
2018-05-26 22:47:38 +02:00
|
|
|
@Override
|
2019-03-23 20:49:34 +01:00
|
|
|
public Size getSize() {
|
|
|
|
return isChild ? Size.FOAL : getMetadata().getSize();
|
2018-05-26 22:47:38 +02:00
|
|
|
}
|
|
|
|
|
2018-04-28 18:13:35 +02:00
|
|
|
@Override
|
|
|
|
public float getSwingAmount() {
|
2019-05-27 17:59:15 +02:00
|
|
|
return handSwingProgress;
|
2018-04-28 18:13:35 +02:00
|
|
|
}
|
|
|
|
|
2018-07-01 17:33:30 +02:00
|
|
|
@Override
|
2018-07-08 12:21:57 +02:00
|
|
|
public float getRiderYOffset() {
|
2018-07-22 17:20:14 +02:00
|
|
|
|
2018-07-08 12:21:57 +02:00
|
|
|
if (isChild()) {
|
2018-07-22 17:20:14 +02:00
|
|
|
return 0.25F;
|
2018-07-08 12:21:57 +02:00
|
|
|
}
|
|
|
|
|
2018-07-28 19:01:12 +02:00
|
|
|
switch (getSize()) {
|
2018-07-08 12:21:57 +02:00
|
|
|
case NORMAL: return 0.4F;
|
2018-07-22 17:20:14 +02:00
|
|
|
case FOAL:
|
2018-07-08 12:21:57 +02:00
|
|
|
case TALL:
|
2018-10-20 19:09:58 +02:00
|
|
|
case BULKY:
|
2018-07-22 17:20:14 +02:00
|
|
|
default: return 0.25F;
|
2018-07-08 12:21:57 +02:00
|
|
|
}
|
2018-07-01 17:33:30 +02:00
|
|
|
}
|
|
|
|
|
2018-09-05 13:56:07 +02:00
|
|
|
@Override
|
|
|
|
public float getModelHeight() {
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
2018-05-01 12:38:13 +02:00
|
|
|
/**
|
|
|
|
* Sets the model's various rotation angles.
|
|
|
|
*
|
|
|
|
* @param entity The entity we're being called for.
|
|
|
|
* @param move Entity motion parameter - i.e. velocity in no specific direction used in bipeds to calculate step amount.
|
|
|
|
* @param swing Degree to which each 'limb' swings.
|
|
|
|
* @param ticks Total whole and partial ticks since the entity's existance. Used in animations together with {@code swing} and {@code move}.
|
|
|
|
* @param headYaw Horizontal head motion in radians.
|
|
|
|
* @param headPitch Vertical head motion in radians.
|
|
|
|
* @param scale Scaling factor used to render this model. Determined by the return value of {@link RenderLivingBase.prepareScale}. Usually {@code 0.0625F}.
|
|
|
|
*/
|
2018-04-29 14:22:26 +02:00
|
|
|
@Override
|
2019-05-27 17:59:15 +02:00
|
|
|
public void render(T entity, float move, float swing, float ticks, float headYaw, float headPitch, float scale) {
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2018-10-29 14:16:42 +01:00
|
|
|
pushMatrix();
|
2019-05-29 12:49:17 +02:00
|
|
|
transform(BodyPart.BODY);
|
|
|
|
renderBody(entity, move, swing, ticks, headYaw, headPitch, scale);
|
2018-10-29 14:16:42 +01:00
|
|
|
popMatrix();
|
2018-04-29 14:22:26 +02:00
|
|
|
|
|
|
|
pushMatrix();
|
|
|
|
transform(BodyPart.NECK);
|
2018-06-03 22:23:32 +02:00
|
|
|
renderNeck(scale);
|
2018-04-29 14:22:26 +02:00
|
|
|
popMatrix();
|
|
|
|
|
|
|
|
pushMatrix();
|
2019-05-29 12:49:17 +02:00
|
|
|
transform(BodyPart.HEAD);
|
|
|
|
renderHead(entity, move, swing, ticks, headYaw, headPitch, scale);
|
2018-04-29 14:22:26 +02:00
|
|
|
popMatrix();
|
|
|
|
|
|
|
|
pushMatrix();
|
|
|
|
transform(BodyPart.LEGS);
|
2018-06-03 22:23:32 +02:00
|
|
|
renderLegs(scale);
|
2018-04-29 14:22:26 +02:00
|
|
|
popMatrix();
|
2018-08-24 13:54:24 +02:00
|
|
|
|
2019-05-29 12:49:17 +02:00
|
|
|
pushMatrix();
|
2019-05-29 13:07:27 +02:00
|
|
|
transform(BodyPart.HEAD);
|
2019-05-29 12:49:17 +02:00
|
|
|
renderHelmet(scale);
|
|
|
|
popMatrix();
|
|
|
|
|
|
|
|
if (textureHeight == 64) {
|
|
|
|
pushMatrix();
|
|
|
|
transform(BodyPart.LEGS);
|
|
|
|
renderSleeves(scale);
|
|
|
|
popMatrix();
|
|
|
|
}
|
|
|
|
|
2018-04-29 14:22:26 +02:00
|
|
|
}
|
|
|
|
|
2018-05-01 12:38:13 +02:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* Called to render the head.
|
|
|
|
*
|
|
|
|
* Takes the same parameters as {@link AbstractPonyModel.setRotationAndAngles}
|
|
|
|
*
|
|
|
|
*/
|
2019-05-27 17:59:15 +02:00
|
|
|
protected void renderHead(T entity, float move, float swing, float ticks, float headYaw, float headPitch, float scale) {
|
|
|
|
head.render(scale);
|
2019-05-29 12:49:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
protected void renderHelmet(float scale) {
|
|
|
|
headwear.render(scale);
|
2018-04-29 14:22:26 +02:00
|
|
|
}
|
|
|
|
|
2018-06-03 22:23:32 +02:00
|
|
|
protected void renderNeck(float scale) {
|
2019-05-27 17:59:15 +02:00
|
|
|
scalef(0.9F, 0.9F, 0.9F);
|
2018-04-29 14:22:26 +02:00
|
|
|
neck.render(scale);
|
|
|
|
}
|
|
|
|
|
2018-05-01 12:38:13 +02:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* Called to render the head.
|
|
|
|
*
|
|
|
|
* Takes the same parameters as {@link AbstractPonyModel.setRotationAndAngles}
|
|
|
|
*
|
|
|
|
*/
|
2019-05-27 17:59:15 +02:00
|
|
|
protected void renderBody(T entity, float move, float swing, float ticks, float headYaw, float headPitch, float scale) {
|
|
|
|
body.render(scale);
|
2019-05-29 12:49:17 +02:00
|
|
|
|
2018-04-29 14:22:26 +02:00
|
|
|
upperTorso.render(scale);
|
2019-05-27 17:59:15 +02:00
|
|
|
body.applyTransform(scale);
|
|
|
|
tail.renderPart(scale, entity.getUuid());
|
2018-04-29 14:22:26 +02:00
|
|
|
}
|
|
|
|
|
2018-06-03 22:23:32 +02:00
|
|
|
protected void renderLegs(float scale) {
|
2019-05-29 12:49:17 +02:00
|
|
|
if (!isSneaking) {
|
|
|
|
body.applyTransform(scale);
|
|
|
|
}
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2019-05-27 17:59:15 +02:00
|
|
|
leftArm.render(scale);
|
|
|
|
rightArm.render(scale);
|
|
|
|
leftLeg.render(scale);
|
|
|
|
rightLeg.render(scale);
|
2019-05-29 12:49:17 +02:00
|
|
|
}
|
2018-04-29 14:22:26 +02:00
|
|
|
|
2019-05-29 12:49:17 +02:00
|
|
|
protected void renderSleeves(float scale) {
|
|
|
|
leftArmOverlay.render(scale);
|
|
|
|
rightArmOverlay.render(scale);
|
|
|
|
leftLegOverlay.render(scale);
|
|
|
|
rightArmOverlay.render(scale);
|
|
|
|
bodyOverlay.render(scale);
|
2018-04-25 16:40:47 +02:00
|
|
|
}
|
2015-12-14 09:29:10 +01:00
|
|
|
|
2018-04-29 11:56:26 +02:00
|
|
|
@Override
|
2015-12-14 09:29:10 +01:00
|
|
|
public void transform(BodyPart part) {
|
2018-08-17 22:46:28 +02:00
|
|
|
if (isSleeping()) {
|
2019-03-24 18:55:15 +01:00
|
|
|
rotatef(90, 1, 0, 0);
|
|
|
|
rotatef(180, 0, 1, 0);
|
2015-12-14 09:29:10 +01:00
|
|
|
}
|
|
|
|
|
2018-04-29 20:18:57 +02:00
|
|
|
if (part == BodyPart.HEAD) {
|
2019-03-24 18:55:15 +01:00
|
|
|
rotatef(motionPitch, 1, 0, 0);
|
2018-04-29 20:18:57 +02:00
|
|
|
}
|
|
|
|
|
2019-03-23 20:49:34 +01:00
|
|
|
PonyTransformation.forSize(getSize()).transform(this, part);
|
2015-12-14 09:29:10 +01:00
|
|
|
}
|
|
|
|
|
2018-04-25 21:29:49 +02:00
|
|
|
/**
|
|
|
|
* Copies this model's attributes from some other.
|
|
|
|
*/
|
2015-12-14 09:29:10 +01:00
|
|
|
@Override
|
2019-05-27 17:59:15 +02:00
|
|
|
public void setAttributes(BipedEntityModel<T> model) {
|
|
|
|
super.setAttributes(model);
|
|
|
|
|
2015-12-16 05:29:47 +01:00
|
|
|
if (model instanceof AbstractPonyModel) {
|
2019-05-27 17:59:15 +02:00
|
|
|
AbstractPonyModel<T> pony = (AbstractPonyModel<T>) model;
|
2018-04-25 21:29:49 +02:00
|
|
|
isFlying = pony.isFlying;
|
2019-03-22 21:09:06 +01:00
|
|
|
isCrouching = pony.isCrouching;
|
2018-07-30 05:49:45 +02:00
|
|
|
isElytraFlying = pony.isElytraFlying;
|
|
|
|
isSwimming = pony.isSwimming;
|
2018-04-25 21:29:49 +02:00
|
|
|
isSleeping = pony.isSleeping;
|
2018-08-18 15:13:08 +02:00
|
|
|
headGear = pony.headGear;
|
2018-04-25 21:29:49 +02:00
|
|
|
metadata = pony.metadata;
|
|
|
|
motionPitch = pony.motionPitch;
|
2018-04-26 16:01:31 +02:00
|
|
|
rainboom = pony.rainboom;
|
2015-12-14 09:29:10 +01:00
|
|
|
}
|
|
|
|
}
|
2015-08-02 00:36:33 +02:00
|
|
|
}
|