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.BodyPart;
import com.minelittlepony.model.armour.PonyArmor; import com.minelittlepony.model.armour.PonyArmor;
import com.minelittlepony.pony.data.IPonyData; import com.minelittlepony.pony.data.IPonyData;
import com.minelittlepony.pony.data.PonyWearable;
public interface IModel { public interface IModel {
@ -59,4 +60,8 @@ public interface IModel {
boolean isChild(); boolean isChild();
float getSwingAmount(); float getSwingAmount();
default boolean isWearing(PonyWearable wearable) {
return getMetadata().isWearing(wearable);
}
} }

View file

@ -1,5 +1,10 @@
package com.minelittlepony.model.capabilities; 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 { public interface IModelPegasus extends IModel {
/** /**
* Returns true if the wings are spread. * Returns true if the wings are spread.
@ -7,4 +12,16 @@ public interface IModelPegasus extends IModel {
default boolean wingsAreOpen() { default boolean wingsAreOpen() {
return isSwimming() || isFlying() || isCrouching(); 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.AbstractPonyModel;
import com.minelittlepony.model.capabilities.IModelPart; import com.minelittlepony.model.capabilities.IModelPart;
import com.minelittlepony.model.capabilities.IModelPegasus; import com.minelittlepony.model.capabilities.IModelPegasus;
import com.minelittlepony.pony.data.PonyWearable;
public class PegasusWings implements IModelPart { public class PegasusWings implements IModelPart {
@ -15,11 +16,14 @@ public class PegasusWings implements IModelPart {
private final ModelWing leftWing; private final ModelWing leftWing;
private final ModelWing rightWing; private final ModelWing rightWing;
private final ModelWing legacyWing;
public <T extends AbstractPonyModel & IModelPegasus> PegasusWings(T model, float yOffset, float stretch) { public <T extends AbstractPonyModel & IModelPegasus> PegasusWings(T model, float yOffset, float stretch) {
pegasus = model; pegasus = model;
leftWing = new ModelWing(model, false, 4f, yOffset, stretch, 32); leftWing = new ModelWing(model, false, 4, yOffset, stretch, 32);
rightWing = new ModelWing(model, true, -6f, yOffset, stretch, 16); 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 @Override
public void setRotationAndAngles(boolean rainboom, float move, float swing, float bodySwing, float ticks) { public void setRotationAndAngles(boolean rainboom, float move, float swing, float bodySwing, float ticks) {
float flap = 0; float flap = 0;
@ -44,31 +56,21 @@ public class PegasusWings implements IModelPart {
flap = MathHelper.cos(mve + pi) * srt; flap = MathHelper.cos(mve + pi) * srt;
} }
leftWing.rotateWalking(flap); getLeft().rotateWalking(flap);
rightWing.rotateWalking(-flap); getRight().rotateWalking(-flap);
if (pegasus.wingsAreOpen()) { if (pegasus.wingsAreOpen()) {
float flapAngle = getWingRotationFactor(ticks); float flapAngle = pegasus.getWingRotationFactor(ticks);
leftWing.rotateFlying(flapAngle); getLeft().rotateFlying(flapAngle);
rightWing.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 @Override
public void renderPart(float scale) { public void renderPart(float scale) {
boolean standing = pegasus.wingsAreOpen(); boolean standing = pegasus.wingsAreOpen();
leftWing.render(standing, scale); getLeft().render(standing, scale);
rightWing.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 static com.minelittlepony.model.PonyModelConstants.*;
import com.minelittlepony.model.AbstractPonyModel; import com.minelittlepony.model.AbstractPonyModel;
import com.minelittlepony.model.capabilities.IModel;
import com.minelittlepony.model.capabilities.IModelPart; import com.minelittlepony.model.capabilities.IModelPart;
import com.minelittlepony.render.plane.PlaneRenderer; import com.minelittlepony.render.plane.PlaneRenderer;
@ -17,11 +16,9 @@ public class SaddleBags implements IModelPart {
private PlaneRenderer strap; private PlaneRenderer strap;
private IModel model; private boolean hangLow = false;
public SaddleBags(AbstractPonyModel model) { public SaddleBags(AbstractPonyModel model) {
this.model = model;
leftBag = new PlaneRenderer(model, 56, 19); leftBag = new PlaneRenderer(model, 56, 19);
rightBag = new PlaneRenderer(model, 56, 19); rightBag = new PlaneRenderer(model, 56, 19);
strap = 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 pi = PI * (float) Math.pow(swing, 16);
float mve = move * 0.6662f; float mve = move * 0.6662f;
float srt = swing / 4; float srt = swing / 6;
bodySwing = MathHelper.cos(mve + pi) * srt; bodySwing = MathHelper.cos(mve + pi) * srt;
@ -80,9 +77,13 @@ public class SaddleBags implements IModelPart {
rightBag.rotateAngleZ = -bodySwing; rightBag.rotateAngleZ = -bodySwing;
} }
public void sethangingLow(boolean veryLow) {
hangLow = veryLow;
}
@Override @Override
public void renderPart(float scale) { public void renderPart(float scale) {
if (model.canFly()) { if (hangLow) {
GlStateManager.pushMatrix(); GlStateManager.pushMatrix();
GlStateManager.translate(0, 0.3F, 0); GlStateManager.translate(0, 0.3F, 0);
} }
@ -91,7 +92,7 @@ public class SaddleBags implements IModelPart {
rightBag.render(scale); rightBag.render(scale);
strap.render(scale); strap.render(scale);
if (model.canFly()) { if (hangLow) {
GlStateManager.popMatrix(); GlStateManager.popMatrix();
} }
} }

View file

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

View file

@ -1,14 +1,17 @@
package com.minelittlepony.model.player; package com.minelittlepony.model.player;
import com.minelittlepony.model.AbstractPonyModel; import com.minelittlepony.model.AbstractPonyModel;
import com.minelittlepony.model.components.SaddleBags;
import com.minelittlepony.pony.data.PonyWearable;
import com.minelittlepony.render.PonyRenderer; import com.minelittlepony.render.PonyRenderer;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
public class ModelEarthPony extends AbstractPonyModel { public class ModelEarthPony extends AbstractPonyModel {
private final boolean smallArms; private final boolean smallArms;
public SaddleBags saddlebags;
public PonyRenderer bipedCape; public PonyRenderer bipedCape;
public ModelEarthPony(boolean smallArms) { 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() { protected float getLegOutset() {
if (smallArms) { if (smallArms) {
if (isSleeping) return 2.6f; 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) { 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); super.setRotationAngles(move, swing, ticks, headYaw, headPitch, scale, entity);
wings.setRotationAndAngles(rainboom, move, swing, 0, ticks); wings.setRotationAndAngles(rainboom, move, swing, 0, ticks);
saddlebags.sethangingLow(wingsAreOpen());
} }
@Override @Override

View file

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

View file

@ -19,12 +19,16 @@ public class PonyData implements IPonyData {
private final PonySize size; private final PonySize size;
private final int glowColor; private final int glowColor;
private final boolean[] wearables;
public PonyData() { public PonyData() {
race = PonyRace.HUMAN; race = PonyRace.HUMAN;
tailSize = TailLengths.FULL; tailSize = TailLengths.FULL;
gender = PonyGender.MARE; gender = PonyGender.MARE;
size = PonySize.NORMAL; size = PonySize.NORMAL;
glowColor = 0x4444aa; glowColor = 0x4444aa;
wearables = new boolean[PonyWearable.values().length];
} }
private PonyData(BufferedImage image) { private PonyData(BufferedImage image) {
@ -33,6 +37,8 @@ public class PonyData implements IPonyData {
size = TriggerPixels.SIZE.readValue(image); size = TriggerPixels.SIZE.readValue(image);
gender = TriggerPixels.GENDER.readValue(image); gender = TriggerPixels.GENDER.readValue(image);
glowColor = TriggerPixels.GLOW.readColor(image); glowColor = TriggerPixels.GLOW.readColor(image);
wearables = TriggerPixels.WEARABLES.readFlags(image);
} }
@Override @Override
@ -65,6 +71,11 @@ public class PonyData implements IPonyData {
return race != null && race.hasHorn() && glowColor != 0; return race != null && race.hasHorn() && glowColor != 0;
} }
@Override
public boolean isWearing(PonyWearable wearable) {
return wearables[wearable.ordinal()];
}
@Override @Override
public String toString() { public String toString() {
return MoreObjects.toStringHelper(this) return MoreObjects.toStringHelper(this)
@ -72,6 +83,7 @@ public class PonyData implements IPonyData {
.add("tailSize", tailSize) .add("tailSize", tailSize)
.add("gender", gender) .add("gender", gender)
.add("size", size) .add("size", size)
.add("wearables", PonyWearable.flags(wearables))
.add("glowColor", "#" + Integer.toHexString(glowColor)) .add("glowColor", "#" + Integer.toHexString(glowColor))
.toString(); .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), RACE(PonyRace.HUMAN, Channel.ALL, 0, 0),
TAIL(TailLengths.FULL, Channel.ALL, 1, 0), TAIL(TailLengths.FULL, Channel.ALL, 1, 0),
GENDER(PonyGender.MARE, Channel.ALL, 2, 0), GENDER(PonyGender.MARE, Channel.ALL, 2, 0),
SIZE(PonySize.NORMAL, Channel.ALL, 3, 0), SIZE(PonySize.LARGE, Channel.ALL, 3, 0),
GLOW(null, Channel.RAW, 0, 1); GLOW(null, Channel.RAW, 0, 1),
WEARABLES(PonyWearable.NONE, Channel.RAW, 1, 1);
private int x; private int x;
private int y; private int y;
@ -46,6 +47,23 @@ public enum TriggerPixels {
return ITriggerPixelMapped.getByTriggerPixel((T)def, readColor(image)); 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 { enum Channel {
RAW(-1, 0), RAW(-1, 0),
ALL(0xffffff, 0), ALL(0xffffff, 0),