Implemented pony wearables as saddlebags and (soon)

This commit is contained in:
Sollace 2018-06-05 20:18:57 +02:00
parent ad77b48e59
commit 42081b38d4
12 changed files with 170 additions and 41 deletions

View file

@ -3,6 +3,7 @@ package com.minelittlepony.model.capabilities;
import com.minelittlepony.model.BodyPart;
import com.minelittlepony.model.armour.PonyArmor;
import com.minelittlepony.pony.data.IPonyData;
import com.minelittlepony.pony.data.PonyWearable;
public interface IModel {
@ -59,4 +60,8 @@ public interface IModel {
boolean isChild();
float getSwingAmount();
default boolean isWearing(PonyWearable wearable) {
return getMetadata().isWearing(wearable);
}
}

View file

@ -1,5 +1,10 @@
package com.minelittlepony.model.capabilities;
import static com.minelittlepony.model.PonyModelConstants.LEFT_WING_ROTATE_ANGLE_Z_SNEAK;
import static com.minelittlepony.model.PonyModelConstants.ROTATE_270;
import net.minecraft.util.math.MathHelper;
public interface IModelPegasus extends IModel {
/**
* Returns true if the wings are spread.
@ -7,4 +12,16 @@ public interface IModelPegasus extends IModel {
default boolean wingsAreOpen() {
return isSwimming() || isFlying() || isCrouching();
}
default float getWingRotationFactor(float ticks) {
if (isSwimming()) {
return (MathHelper.sin(ticks * 0.136f) / 2) + ROTATE_270;
}
if (isFlying()) {
return MathHelper.sin(ticks * 0.536f) + ROTATE_270 + 0.4f;
}
return LEFT_WING_ROTATE_ANGLE_Z_SNEAK;
}
}

View file

@ -7,6 +7,7 @@ import static com.minelittlepony.model.PonyModelConstants.*;
import com.minelittlepony.model.AbstractPonyModel;
import com.minelittlepony.model.capabilities.IModelPart;
import com.minelittlepony.model.capabilities.IModelPegasus;
import com.minelittlepony.pony.data.PonyWearable;
public class PegasusWings implements IModelPart {
@ -15,11 +16,14 @@ public class PegasusWings implements IModelPart {
private final ModelWing leftWing;
private final ModelWing rightWing;
private final ModelWing legacyWing;
public <T extends AbstractPonyModel & IModelPegasus> PegasusWings(T model, float yOffset, float stretch) {
pegasus = model;
leftWing = new ModelWing(model, false, 4f, yOffset, stretch, 32);
rightWing = new ModelWing(model, true, -6f, yOffset, stretch, 16);
leftWing = new ModelWing(model, false, 4, yOffset, stretch, 32);
rightWing = new ModelWing(model, true, -6, yOffset, stretch, 16);
legacyWing = new ModelWing(model, true, -6, yOffset, stretch, 32);
}
@ -28,6 +32,14 @@ public class PegasusWings implements IModelPart {
}
public ModelWing getLeft() {
return leftWing;
}
public ModelWing getRight() {
return pegasus.isWearing(PonyWearable.SADDLE_BAGS) ? legacyWing : rightWing;
}
@Override
public void setRotationAndAngles(boolean rainboom, float move, float swing, float bodySwing, float ticks) {
float flap = 0;
@ -44,31 +56,21 @@ public class PegasusWings implements IModelPart {
flap = MathHelper.cos(mve + pi) * srt;
}
leftWing.rotateWalking(flap);
rightWing.rotateWalking(-flap);
getLeft().rotateWalking(flap);
getRight().rotateWalking(-flap);
if (pegasus.wingsAreOpen()) {
float flapAngle = getWingRotationFactor(ticks);
leftWing.rotateFlying(flapAngle);
rightWing.rotateFlying(-flapAngle);
float flapAngle = pegasus.getWingRotationFactor(ticks);
getLeft().rotateFlying(flapAngle);
getRight().rotateFlying(-flapAngle);
}
}
public float getWingRotationFactor(float ticks) {
if (pegasus.isSwimming()) {
return (MathHelper.sin(ticks * 0.136f) / 2) + ROTATE_270;
}
if (pegasus.isFlying()) {
return MathHelper.sin(ticks * 0.536f) + ROTATE_270 + 0.4f;
}
return LEFT_WING_ROTATE_ANGLE_Z_SNEAK;
}
@Override
public void renderPart(float scale) {
boolean standing = pegasus.wingsAreOpen();
leftWing.render(standing, scale);
rightWing.render(standing, scale);
getLeft().render(standing, scale);
getRight().render(standing, scale);
}
}

View file

@ -3,7 +3,6 @@ package com.minelittlepony.model.components;
import static com.minelittlepony.model.PonyModelConstants.*;
import com.minelittlepony.model.AbstractPonyModel;
import com.minelittlepony.model.capabilities.IModel;
import com.minelittlepony.model.capabilities.IModelPart;
import com.minelittlepony.render.plane.PlaneRenderer;
@ -17,11 +16,9 @@ public class SaddleBags implements IModelPart {
private PlaneRenderer strap;
private IModel model;
private boolean hangLow = false;
public SaddleBags(AbstractPonyModel model) {
this.model = model;
leftBag = new PlaneRenderer(model, 56, 19);
rightBag = new PlaneRenderer(model, 56, 19);
strap = new PlaneRenderer(model, 56, 19);
@ -69,7 +66,7 @@ public class SaddleBags implements IModelPart {
float pi = PI * (float) Math.pow(swing, 16);
float mve = move * 0.6662f;
float srt = swing / 4;
float srt = swing / 6;
bodySwing = MathHelper.cos(mve + pi) * srt;
@ -80,9 +77,13 @@ public class SaddleBags implements IModelPart {
rightBag.rotateAngleZ = -bodySwing;
}
public void sethangingLow(boolean veryLow) {
hangLow = veryLow;
}
@Override
public void renderPart(float scale) {
if (model.canFly()) {
if (hangLow) {
GlStateManager.pushMatrix();
GlStateManager.translate(0, 0.3F, 0);
}
@ -91,7 +92,7 @@ public class SaddleBags implements IModelPart {
rightBag.render(scale);
strap.render(scale);
if (model.canFly()) {
if (hangLow) {
GlStateManager.popMatrix();
}
}

View file

@ -25,6 +25,7 @@ public class ModelAlicorn extends ModelUnicorn implements IModelPegasus {
if (canFly()) {
wings.setRotationAndAngles(rainboom, move, swing, 0, ticks);
saddlebags.sethangingLow(wingsAreOpen());
}
}

View file

@ -1,14 +1,17 @@
package com.minelittlepony.model.player;
import com.minelittlepony.model.AbstractPonyModel;
import com.minelittlepony.model.components.SaddleBags;
import com.minelittlepony.pony.data.PonyWearable;
import com.minelittlepony.render.PonyRenderer;
import net.minecraft.entity.Entity;
public class ModelEarthPony extends AbstractPonyModel {
private final boolean smallArms;
public SaddleBags saddlebags;
public PonyRenderer bipedCape;
public ModelEarthPony(boolean smallArms) {
@ -25,6 +28,34 @@ public class ModelEarthPony extends AbstractPonyModel {
}
}
@Override
protected void shakeBody(float move, float swing, float bodySwing, float ticks) {
super.shakeBody(move, swing, bodySwing, ticks);
saddlebags.setRotationAndAngles(rainboom, move, swing, bodySwing, ticks);
}
@Override
protected void renderBody(Entity entity, float move, float swing, float ticks, float headYaw, float headPitch, float scale) {
super.renderBody(entity, move, swing, ticks, headYaw, headPitch, scale);
if (isWearing(PonyWearable.SADDLE_BAGS)) {
saddlebags.renderPart(scale);
}
}
@Override
protected void initTextures() {
super.initTextures();
saddlebags = new SaddleBags(this);
}
@Override
protected void initPositions(float yOffset, float stretch) {
super.initPositions(yOffset, stretch);
saddlebags.init(yOffset, stretch);
}
protected float getLegOutset() {
if (smallArms) {
if (isSleeping) return 2.6f;

View file

@ -23,6 +23,7 @@ public class ModelPegasus extends ModelEarthPony implements IModelPegasus {
public void setRotationAngles(float move, float swing, float ticks, float headYaw, float headPitch, float scale, Entity entity) {
super.setRotationAngles(move, swing, ticks, headYaw, headPitch, scale, entity);
wings.setRotationAndAngles(rainboom, move, swing, 0, ticks);
saddlebags.sethangingLow(wingsAreOpen());
}
@Override

View file

@ -1,19 +1,21 @@
package com.minelittlepony.model.ponies;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.monster.EntityZombieVillager;
import net.minecraft.entity.passive.EntityVillager;
import static com.minelittlepony.model.PonyModelConstants.*;
import com.minelittlepony.model.components.SaddleBags;
import com.minelittlepony.model.player.ModelAlicorn;
import com.minelittlepony.pony.data.PonyWearable;
import com.minelittlepony.render.plane.PlaneRenderer;
public class ModelVillagerPony extends ModelAlicorn {
public PlaneRenderer apron, trinket;
public SaddleBags saddlebags;
private int profession;
public ModelVillagerPony() {
super(false);
@ -22,26 +24,33 @@ public class ModelVillagerPony extends ModelAlicorn {
@Override
protected void shakeBody(float move, float swing, float bodySwing, float ticks) {
super.shakeBody(move, swing, bodySwing, ticks);
saddlebags.setRotationAndAngles(rainboom, move, swing, bodySwing, ticks);
apron.rotateAngleY = bodySwing;
trinket.rotateAngleY = bodySwing;
}
@Override
public void setLivingAnimations(EntityLivingBase entity, float limbSwing, float limbSwingAmount, float partialTickTime) {
profession = getProfession(entity);
}
@Override
protected void renderBody(Entity entity, float move, float swing, float ticks, float headYaw, float headPitch, float scale) {
super.renderBody(entity, move, swing, ticks, headYaw, headPitch, scale);
int profession = getProfession(entity);
if (profession > -1) {
if (profession < 2) {
saddlebags.renderPart(scale);
} else if (profession == 2) {
if (profession == 2) {
trinket.render(scale);
} else if (profession > 2) {
apron.render(scale);
}
}
@Override
public boolean isWearing(PonyWearable wearable) {
if (wearable == PonyWearable.SADDLE_BAGS) {
return profession > -1 && profession < 2;
}
return super.isWearing(wearable);
}
protected int getProfession(Entity entity) {

View file

@ -35,4 +35,6 @@ public interface IPonyData extends IMetadataSection {
* Returns true if and only if this metadata represents a pony that can cast magic.
*/
boolean hasMagic();
boolean isWearing(PonyWearable wearable);
}

View file

@ -19,12 +19,16 @@ public class PonyData implements IPonyData {
private final PonySize size;
private final int glowColor;
private final boolean[] wearables;
public PonyData() {
race = PonyRace.HUMAN;
tailSize = TailLengths.FULL;
gender = PonyGender.MARE;
size = PonySize.NORMAL;
glowColor = 0x4444aa;
wearables = new boolean[PonyWearable.values().length];
}
private PonyData(BufferedImage image) {
@ -33,6 +37,8 @@ public class PonyData implements IPonyData {
size = TriggerPixels.SIZE.readValue(image);
gender = TriggerPixels.GENDER.readValue(image);
glowColor = TriggerPixels.GLOW.readColor(image);
wearables = TriggerPixels.WEARABLES.readFlags(image);
}
@Override
@ -65,6 +71,11 @@ public class PonyData implements IPonyData {
return race != null && race.hasHorn() && glowColor != 0;
}
@Override
public boolean isWearing(PonyWearable wearable) {
return wearables[wearable.ordinal()];
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
@ -72,6 +83,7 @@ public class PonyData implements IPonyData {
.add("tailSize", tailSize)
.add("gender", gender)
.add("size", size)
.add("wearables", PonyWearable.flags(wearables))
.add("glowColor", "#" + Integer.toHexString(glowColor))
.toString();
}

View file

@ -0,0 +1,30 @@
package com.minelittlepony.pony.data;
import java.util.ArrayList;
import java.util.List;
public enum PonyWearable implements ITriggerPixelMapped<PonyWearable> {
NONE(0),
SADDLE_BAGS(0xff0000),
HAT(0x00ff00);
private int triggerValue;
PonyWearable(int pixel) {
triggerValue = pixel;
}
@Override
public int getTriggerPixel() {
return triggerValue;
}
public static PonyWearable[] flags(boolean[] flags) {
List<PonyWearable> wears = new ArrayList<PonyWearable>();
PonyWearable[] values = values();
for (int i = 1; i < values.length; i++) {
if (flags[i]) wears.add(values[i]);
}
return wears.toArray(new PonyWearable[wears.size()]);
}
}

View file

@ -11,8 +11,9 @@ public enum TriggerPixels {
RACE(PonyRace.HUMAN, Channel.ALL, 0, 0),
TAIL(TailLengths.FULL, Channel.ALL, 1, 0),
GENDER(PonyGender.MARE, Channel.ALL, 2, 0),
SIZE(PonySize.NORMAL, Channel.ALL, 3, 0),
GLOW(null, Channel.RAW, 0, 1);
SIZE(PonySize.LARGE, Channel.ALL, 3, 0),
GLOW(null, Channel.RAW, 0, 1),
WEARABLES(PonyWearable.NONE, Channel.RAW, 1, 1);
private int x;
private int y;
@ -46,6 +47,23 @@ public enum TriggerPixels {
return ITriggerPixelMapped.getByTriggerPixel((T)def, readColor(image));
}
public <T extends Enum<T> & ITriggerPixelMapped<T>> boolean[] readFlags(BufferedImage image) {
boolean[] out = new boolean[def.getClass().getEnumConstants().length];
readFlags(out, image);
return out;
}
public <T extends Enum<T> & ITriggerPixelMapped<T>> void readFlags(boolean[] out, BufferedImage image) {
readFlag(out, Channel.RED, image);
readFlag(out, Channel.GREEN, image);
readFlag(out, Channel.BLUE, image);
}
private <T extends Enum<T> & ITriggerPixelMapped<T>> void readFlag(boolean[] out, Channel channel, BufferedImage image) {
T value = ITriggerPixelMapped.getByTriggerPixel((T)def, channel.readValue(x, y, image));
if (value != def) out[value.ordinal()] = true;
}
enum Channel {
RAW(-1, 0),
ALL(0xffffff, 0),