/**
Copyright (C) <2016> <coolAlias>
This file is part of coolAlias' Zelda Sword Skills Minecraft Mod; as such,
you can redistribute it and/or modify it under the terms of the GNU
General Public License as published by the Free Software Foundation,
either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package zeldaswordskills.client.model;
import net.minecraft.client.model.ModelBase;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import zeldaswordskills.api.client.animation.*;
import zeldaswordskills.api.client.model.*;
import zeldaswordskills.entity.mobs.EntityDekuBaba;
import zeldaswordskills.entity.mobs.EntityDekuBase;
import com.google.common.collect.ImmutableList;
/**
*
* Basic Deku Baba model with prone animation
*
*/
public abstract class ModelDekuBase extends ModelBase
{
protected SmartModelRenderer stem1, stem2, stem3;
protected SmartModelRenderer head_base;
protected SmartModelRenderer tongue_base, tongue_mid, tongue_tip;
protected SmartModelRenderer mouth_base_upper;
protected SmartModelRenderer mouth_upper;
protected SmartModelRenderer mouth_upper_top1;
protected SmartModelRenderer mouth_upper_top2;
protected SmartModelRenderer mouth_base_lower;
protected SmartModelRenderer mouth_lower;
protected SmartModelRenderer mouth_lower_bottom1;
protected SmartModelRenderer mouth_lower_bottom2;
protected SmartModelRenderer stem_base;
protected SmartModelRenderer leaf1_base, leaf1_mid, leaf1_tip;
protected SmartModelRenderer leaf2_base, leaf2_mid, leaf2_tip;
protected SmartModelRenderer leaf3_base, leaf3_mid, leaf3_tip;
protected SmartModelRenderer leaf4_base, leaf4_mid, leaf4_tip;
protected final ImmutableList<IAnimation> DEATH_ANIMATION, PRONE_ANIMATION;
public ModelDekuBase() {
this.textureWidth = 64;
this.textureHeight = 32;
// Stem and Head
// stem1 has a dynamic offset value for the sprouting animation
this.stem1 = new SmartOffsetModelRenderer(this, 56, 0);
this.stem1.setRotationPoint(0.0F, 22.0F, 0.0F);
this.stem1.addBox(-1.0F, -11.0F, -1.0F, 2, 11, 2, 0.0F);
this.stem1.setInitialPose(0, 0, 0); // save original offset values (even though all are currently zero...)
// stem2 has a dynamic rotation point during the death animation, so it needs to use SmartModelRendererPlus
this.stem2 = new SmartModelRendererPlus(this, 56, 0);
this.stem2.setRotationPoint(0.0F, -11.0F, 0.0F);
this.stem2.addBox(-1.0F, -6.0F, -1.0F, 2, 6, 2, 0.0F);
this.stem2.setInitialPose(0, 0, 0); // required to save original rotation point values
this.stem3 = new SmartModelRenderer(this, 56, 0);
this.stem3.setRotationPoint(0.0F, -6.0F, 0.0F);
this.stem3.addBox(-1.0F, -5.0F, -1.0F, 2, 5, 2, 0.0F);
this.head_base = new SmartModelRenderer(this, 56, 9);
this.head_base.setRotationPoint(0.0F, -5.0F, 0.0F);
this.head_base.addBox(-0.5F, -1.0F, -0.5F, 1, 1, 1, 0.0F);
this.stem1.addChild(this.stem2);
this.stem2.addChild(this.stem3);
this.stem3.addChild(this.head_base);
// Tongue
this.tongue_base = new SmartModelRenderer(this, 30, 0);
this.tongue_base.setRotationPoint(0.0F, 0.0F, 0.0F);
this.tongue_base.addBox(-1.5F, -0.5F, -4.0F, 3, 1, 4, 0.0F);
this.tongue_base.setInitialPose(-1.5707963267948966F, 0.0F, 0.0F);
this.tongue_mid = new SmartModelRenderer(this, 34, 0);
this.tongue_mid.setRotationPoint(0.0F, 0.0F, -4.0F);
this.tongue_mid.addBox(-1.0F, -0.5F, -3.0F, 2, 1, 3, 0.0F);
this.tongue_mid.setInitialPose(0.2617993877991494F, 0.0F, 0.0F);
this.tongue_tip = new SmartModelRenderer(this, 36, 0);
this.tongue_tip.setRotationPoint(0.0F, 0.0F, -3.0F);
this.tongue_tip.addBox(-0.5F, -0.5F, -3.0F, 1, 1, 3, 0.0F);
this.tongue_tip.setInitialPose(-0.2617993877991494F, 0.0F, 0.0F);
this.head_base.addChild(this.tongue_base);
this.tongue_base.addChild(this.tongue_mid);
this.tongue_mid.addChild(this.tongue_tip);
// Lower Jaw
this.mouth_base_lower = new SmartModelRenderer(this, 0, 9);
this.mouth_base_lower.setRotationPoint(0.0F, 0.0F, -0.5F);
this.mouth_base_lower.addBox(-3.0F, -0.5F, -4.0F, 6, 1, 4, 0.0F);
this.mouth_base_lower.setInitialPose(-1.0471975511965976F, 0.0F, 0.0F);
this.mouth_lower = new SmartModelRenderer(this, 26, 25);
this.mouth_lower.setRotationPoint(0.0F, 0.0F, -4.0F);
this.mouth_lower.addBox(-3.0F, -0.5F, -6.0F, 6, 1, 6, 0.0F);
this.mouth_lower.setInitialPose(-0.4363323129985824F, 0.0F, 0.0F);
this.mouth_lower_bottom1 = new SmartModelRenderer(this, 0, 18);
this.mouth_lower_bottom1.setRotationPoint(0.0F, 1.0F, 0.0F);
this.mouth_lower_bottom1.addBox(-2.0F, -0.5F, -5.0F, 4, 1, 5, 0.0F);
this.mouth_lower_bottom2 = new SmartModelRenderer(this, 0, 14);
this.mouth_lower_bottom2.setRotationPoint(0.0F, 2.0F, 0.0F);
this.mouth_lower_bottom2.addBox(-1.0F, -0.5F, -3.0F, 2, 1, 3, 0.0F);
this.head_base.addChild(this.mouth_base_lower);
this.mouth_base_lower.addChild(this.mouth_lower);
this.mouth_lower.addChild(this.mouth_lower_bottom1);
this.mouth_lower.addChild(this.mouth_lower_bottom2);
// Upper Jaw
this.mouth_base_upper = new SmartModelRenderer(this, 0, 5);
this.mouth_base_upper.setRotationPoint(0.0F, 0.0F, 0.5F);
this.mouth_base_upper.addBox(-3.0F, -3.0F, -0.5F, 6, 3, 1, 0.0F);
this.mouth_base_upper.setInitialPose(-0.5235987755982988F, 0.0F, 0.0F);
this.mouth_upper = new SmartModelRenderer(this, 0, 24);
this.mouth_upper.setRotationPoint(0.0F, -3.0F, 0.0F);
this.mouth_upper.addBox(-3.0F, -0.5F, -7.0F, 6, 1, 7, 0.0F);
this.mouth_upper.setInitialPose(-1.2217304763960306F, 0.0F, 0.0F);
this.mouth_upper_top1 = new SmartModelRenderer(this, 26, 18);
this.mouth_upper_top1.setRotationPoint(0.0F, -1.0F, 0.0F);
this.mouth_upper_top1.addBox(-3.0F, -0.5F, -6.0F, 6, 1, 6, 0.0F);
this.mouth_upper_top2 = new SmartModelRenderer(this, 26, 13);
this.mouth_upper_top2.setRotationPoint(0.0F, -2.0F, -1.0F);
this.mouth_upper_top2.addBox(-2.0F, -0.5F, -4.0F, 4, 1, 4, 0.0F);
this.head_base.addChild(this.mouth_base_upper);
this.mouth_base_upper.addChild(this.mouth_upper);
this.mouth_upper.addChild(this.mouth_upper_top1);
this.mouth_upper.addChild(this.mouth_upper_top2);
// Plant base + leaves
this.stem_base = new SmartModelRenderer(this, 44, 0);
this.stem_base.setRotationPoint(0.0F, 22.0F, 0.0F);
this.stem_base.addBox(-1.5F, 0.0F, -1.5F, 3, 2, 3, 0.0F);
// First Leaf
this.leaf1_base = new SmartModelRenderer(this, 50, 16);
this.leaf1_base.setRotationPoint(2.0F, 2.0F, 0.0F);
this.leaf1_base.addBox(0.0F, -3.0F, -2.5F, 1, 3, 5, 0.0F);
this.leaf1_base.setInitialPose(0.0F, 0.0F, 0.4363323129985824F);
this.leaf1_mid = new SmartModelRenderer(this, 50, 14);
this.leaf1_mid.setRotationPoint(0.0F, -3.0F, 0.0F);
this.leaf1_mid.addBox(0.0F, -3.0F, -2.0F, 1, 3, 4, 0.0F);
this.leaf1_mid.setInitialPose(0.0F, 0.0F, 0.5235987755982988F);
this.leaf1_tip = new SmartModelRenderer(this, 50, 14);
this.leaf1_tip.setRotationPoint(0.0F, -3.0F, 0.0F);
this.leaf1_tip.addBox(0.0F, -5.0F, -1.5F, 1, 5, 3, 0.0F);
this.leaf1_tip.setInitialPose(0.0F, 0.0F, 0.5235987755982988F);
this.stem_base.addChild(this.leaf1_base);
this.leaf1_base.addChild(this.leaf1_mid);
this.leaf1_mid.addChild(this.leaf1_tip);
// Second Leaf
this.leaf2_base = new SmartModelRenderer(this, 50, 16);
this.leaf2_base.setRotationPoint(-2.0F, 2.0F, 0.0F);
this.leaf2_base.addBox(0.0F, -3.0F, -2.5F, 1, 3, 5, 0.0F);
this.leaf2_base.setInitialPose(0.0F, 3.141592653589793F, -0.4363323129985824F);
this.leaf2_mid = new SmartModelRenderer(this, 50, 14);
this.leaf2_mid.setRotationPoint(0.0F, -3.0F, 0.0F);
this.leaf2_mid.addBox(0.0F, -3.0F, -2.0F, 1, 3, 4, 0.0F);
this.leaf2_mid.setInitialPose(0.0F, 0.0F, 0.5235987755982988F);
this.leaf2_tip = new SmartModelRenderer(this, 50, 14);
this.leaf2_tip.setRotationPoint(0.0F, -3.0F, 0.0F);
this.leaf2_tip.addBox(0.0F, -5.0F, -1.5F, 1, 5, 3, 0.0F);
this.leaf2_tip.setInitialPose(0.0F, 0.0F, 0.5235987755982988F);
this.stem_base.addChild(this.leaf2_base);
this.leaf2_base.addChild(this.leaf2_mid);
this.leaf2_mid.addChild(this.leaf2_tip);
// Third Leaf
this.leaf3_base = new SmartModelRenderer(this, 50, 16);
this.leaf3_base.setRotationPoint(0.0F, 2.0F, 2.0F);
this.leaf3_base.addBox(-2.5F, -3.0F, 0.0F, 5, 3, 1, 0.0F);
this.leaf3_base.setInitialPose(-0.4363323129985824F, 0.0F, 0.0F);
this.leaf3_mid = new SmartModelRenderer(this, 50, 14);
this.leaf3_mid.setRotationPoint(0.0F, -3.0F, 0.0F);
this.leaf3_mid.addBox(-2.0F, -3.0F, 0.0F, 4, 3, 1, 0.0F);
this.leaf3_mid.setInitialPose(-0.5235987755982988F, 0.0F, 0.0F);
this.leaf3_tip = new SmartModelRenderer(this, 50, 14);
this.leaf3_tip.setRotationPoint(0.0F, -3.0F, 0.0F);
this.leaf3_tip.addBox(-1.5F, -5.0F, 0.0F, 3, 5, 1, 0.0F);
this.leaf3_tip.setInitialPose(-0.5235987755982988F, 0.0F, 0.0F);
this.stem_base.addChild(this.leaf3_base);
this.leaf3_base.addChild(this.leaf3_mid);
this.leaf3_mid.addChild(this.leaf3_tip);
// Fourth Leaf
this.leaf4_base = new SmartModelRenderer(this, 50, 16);
this.leaf4_base.setRotationPoint(0.0F, 2.0F, -2.0F);
this.leaf4_base.addBox(-2.5F, -3.0F, 0.0F, 5, 3, 1, 0.0F);
this.leaf4_base.setInitialPose(-0.4363323129985824F, 3.141592653589793F, 0.0F);
this.leaf4_mid = new SmartModelRenderer(this, 50, 14);
this.leaf4_mid.setRotationPoint(0.0F, -3.0F, 0.0F);
this.leaf4_mid.addBox(-2.0F, -3.0F, 0.0F, 4, 3, 1, 0.0F);
this.leaf4_mid.setInitialPose(-0.5235987755982988F, 0.0F, 0.0F);
this.leaf4_tip = new SmartModelRenderer(this, 50, 14);
this.leaf4_tip.setRotationPoint(0.0F, -3.0F, 0.0F);
this.leaf4_tip.addBox(-1.5F, -5.0F, 0.0F, 3, 5, 1, 0.0F);
this.leaf4_tip.setInitialPose(-0.5235987755982988F, 0.0F, 0.0F);
this.stem_base.addChild(this.leaf4_base);
this.leaf4_base.addChild(this.leaf4_mid);
this.leaf4_mid.addChild(this.leaf4_tip);
DEATH_ANIMATION = new ImmutableList.Builder<IAnimation>()
.add(new AnimationTargetPoint(stem2, RotationAxis.X, 16F, 0, 15))
.add(new AnimationTargetPoint(stem2, RotationAxis.Y, -4F, 0, 7).setAllowInversion(false))
.add(new AnimationTargetPoint(stem2, RotationAxis.Y, 11F, 8, 15).setAllowInversion(false))
.add(new AnimationTargetPoint(stem2, RotationAxis.Z, -6F, 0, 15).setAllowInversion(false))
.add(new AnimationTargetAngle(stem2, RotationAxis.Y, 15.0F, 0, 15, true))
.add(new AnimationTargetAngle(stem2, RotationAxis.X, -15.0F, 0, 15, true).setAllowInversion(false))
.add(new AnimationTargetAngle(stem2, RotationAxis.Z, -60.0F, 0, 15, true))
.add(new AnimationTargetAngle(stem3, RotationAxis.X, 40.0F, 0, 15, true).setAllowInversion(false))
.add(new AnimationTargetAngle(head_base, RotationAxis.Z, 20.0F, 0, 8, true))
.add(new AnimationTargetAngle(head_base, RotationAxis.Z, -20.0F, 15, 18, true))
.add(new AnimationTargetAngle(mouth_base_lower, RotationAxis.X, -30.0F, 0, 12, true).setAllowInversion(false))
.add(new AnimationTargetAngle(mouth_base_lower, RotationAxis.X, -60.0F, 12, 15, true).setAllowInversion(false))
.add(new AnimationTargetAngle(mouth_base_upper, RotationAxis.X, -60.0F, 0, 12, true).setAllowInversion(false))
.add(new AnimationTargetAngle(mouth_base_upper, RotationAxis.X, -40.0F, 12, 15, true).setAllowInversion(false))
.add(new AnimationWave.AnimationWaveSin(RotationAxis.Z, 0.25F, 0.85F, 1.0F, tongue_base, tongue_mid, tongue_tip))
.build();
int end = EntityDekuBaba.ACTION_PRONE.duration;
int start = end - 3;
PRONE_ANIMATION = new ImmutableList.Builder<IAnimation>()
.add(new AnimationTargetAngle(stem1, RotationAxis.X, 0.0F, 0, 5, true))
.add(new AnimationTargetAngle(stem1, RotationAxis.X, -15.0F, start, end, true))
.add(new AnimationTargetAngle(stem2, RotationAxis.X, 0.0F, 0, 5, true))
.add(new AnimationTargetAngle(stem2, RotationAxis.X, 20.0F, start, end, true))
.add(new AnimationTargetAngle(stem3, RotationAxis.X, 0.0F, 0, 5, true))
.add(new AnimationTargetAngle(stem3, RotationAxis.X, 30.0F, start, end, true))
.add(new AnimationTargetAngle(head_base, RotationAxis.X, 0.0F, 0, 5, true))
.add(new AnimationTargetAngle(head_base, RotationAxis.X, 60.0F, start, end, true))
.build();
}
/**
* Resets all model parts to their initial pose; this only works if the model is
* composed of {@link SmartModelRenderer SmartModelRenderers} and {@link #setInitialPose}
* was called for each of them during the construction of the model
*/
protected void resetPose() {
for (int i = 0; i < this.boxList.size(); ++i) {
Object o = boxList.get(i);
if (o instanceof SmartModelRenderer) {
((SmartModelRenderer) o).resetPose();
}
}
}
@Override
public void render(Entity entity, float f, float f1, float f2, float f3, float f4, float f5) {
this.stem_base.render(f5);
this.stem1.render(f5);
}
@Override
public final void setLivingAnimations(EntityLivingBase entity, float par2, float par3, float partialTick) {
resetPose();
applyAnimations((EntityDekuBase) entity, par2, par3, partialTick);
}
/**
* Called from {@link #setLivingAnimations(EntityLivingBase, float, float, float) setLivingAnimations} after resetting the pose
*/
protected abstract void applyAnimations(EntityDekuBase entity, float par2, float par3, float partialTick);
/**
* Returns true if a death animation was applied
*/
protected boolean applyDeathAnimation(EntityDekuBase entity, float par2, float par3, float partialTick) {
ImmutableList<IAnimation> animation = getDeathAnimation(entity);
if (animation != null) {
IAnimation.Helper.applyAnimation(animation, entity.deathTime, partialTick, 1.0F, 1.0F, 0.0F, entity.custom_death < 0);
}
return animation != null;
}
/**
* Return custom death animation, if any, based on the baba's {@link EntityDekuBase#custom_death} type
*/
protected ImmutableList<IAnimation> getDeathAnimation(EntityDekuBase entity) {
return entity.custom_death == 0 ? null : DEATH_ANIMATION;
}
}