Add disintegrate animation, plus misc tweaks to disintegration
This commit is contained in:
@@ -692,6 +692,7 @@ public class ClientProxy extends CommonProxy {
|
||||
LayerTiledOverlay.initialiseLayers(LayerStone::new);
|
||||
LayerTiledOverlay.initialiseLayers(LayerFrost::new);
|
||||
LayerTiledOverlay.initialiseLayers(LayerSummonAnimation::new);
|
||||
LayerTiledOverlay.initialiseLayers(LayerDisintegrateAnimation::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.spell.Disintegration;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.renderer.entity.RenderLivingBase;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraftforge.client.event.RenderLivingEvent;
|
||||
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
|
||||
/**
|
||||
* Layer used to render the appear/disappear animation for summoned creatures.
|
||||
*
|
||||
* @author Electroblob
|
||||
* @since Wizardry 4.3
|
||||
*/
|
||||
@EventBusSubscriber
|
||||
public class LayerDisintegrateAnimation<T extends EntityLivingBase> extends LayerTiledOverlay<T> {
|
||||
|
||||
private static final int ANIMATION_TICKS = 19; // One less than the max death time
|
||||
|
||||
private static final ResourceLocation[] TEXTURES = new ResourceLocation[ANIMATION_TICKS];
|
||||
|
||||
static {
|
||||
for(int i=0; i<ANIMATION_TICKS; i++){
|
||||
TEXTURES[i] = new ResourceLocation(Wizardry.MODID, "textures/entity/disintegrate_overlay/disintegrate_overlay_" + i + ".png");
|
||||
}
|
||||
}
|
||||
|
||||
public LayerDisintegrateAnimation(RenderLivingBase<?> renderer){
|
||||
super(renderer, 32, 32);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldRender(T entity, float partialTicks){
|
||||
return entity.getEntityData().hasKey(Disintegration.NBT_KEY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getTexture(T entity, float partialTicks){
|
||||
return TEXTURES[MathHelper.clamp(entity.ticksExisted - entity.getEntityData().getInteger(Disintegration.NBT_KEY), 0, ANIMATION_TICKS - 1)];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doRenderLayer(T entity, float limbSwing, float limbSwingAmount, float partialTicks,
|
||||
float ageInTicks, float netHeadYaw, float headPitch, float scale){
|
||||
GlStateManager.disableLighting();
|
||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f);
|
||||
super.doRenderLayer(entity, limbSwing, limbSwingAmount, partialTicks, ageInTicks, netHeadYaw, headPitch, scale);
|
||||
GlStateManager.enableLighting();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderLivingEvent(RenderLivingEvent.Pre<EntityLivingBase> event){
|
||||
if(event.getEntity().getEntityData().hasKey(Disintegration.NBT_KEY)){
|
||||
event.getEntity().deathTime = 0;
|
||||
event.getEntity().setInvisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderLivingEvent(RenderLivingEvent.Post<EntityLivingBase> event){
|
||||
if(event.getEntity().getEntityData().hasKey(Disintegration.NBT_KEY)) event.getEntity().setInvisible(false);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -39,9 +39,9 @@ public class EntityEmber extends EntityMagicProjectile {
|
||||
@Override
|
||||
protected void onImpact(RayTraceResult result){
|
||||
|
||||
if(result.entityHit != null){
|
||||
result.entityHit.setFire(Spells.disintegration.getProperty(Spell.BURN_DURATION).intValue());
|
||||
}
|
||||
// if(result.entityHit != null){
|
||||
// result.entityHit.setFire(Spells.disintegration.getProperty(Spell.BURN_DURATION).intValue());
|
||||
// }
|
||||
|
||||
if(result.typeOfHit == RayTraceResult.Type.BLOCK){
|
||||
this.inGround = true;
|
||||
@@ -60,7 +60,7 @@ public class EntityEmber extends EntityMagicProjectile {
|
||||
|
||||
super.applyEntityCollision(entity);
|
||||
|
||||
if(entity instanceof EntityLivingBase){
|
||||
if(entity instanceof EntityLivingBase && ((EntityLivingBase)entity).getHealth() > 0){
|
||||
entity.setFire(Spells.disintegration.getProperty(Spell.BURN_DURATION).intValue());
|
||||
}
|
||||
}
|
||||
@@ -77,6 +77,7 @@ public class EntityEmber extends EntityMagicProjectile {
|
||||
}
|
||||
|
||||
world.getEntitiesInAABBexcluding(thrower, this.getEntityBoundingBox(), e -> e instanceof EntityLivingBase)
|
||||
.stream().filter(e -> !(e instanceof EntityLivingBase) || ((EntityLivingBase)e).getHealth() > 0)
|
||||
.forEach(e -> e.setFire(Spells.disintegration.getProperty(Spell.BURN_DURATION).intValue()));
|
||||
|
||||
// Copied from ParticleLava
|
||||
|
||||
@@ -25,6 +25,8 @@ public class Disintegration extends SpellRay {
|
||||
public static final String EMBER_COUNT = "ember_count";
|
||||
public static final String EMBER_LIFETIME = "ember_lifetime";
|
||||
|
||||
public static final String NBT_KEY = "disintegrating";
|
||||
|
||||
public Disintegration(){
|
||||
super("disintegration", false, SpellActions.POINT);
|
||||
addProperties(DAMAGE, BURN_DURATION, EMBER_LIFETIME, EMBER_COUNT);
|
||||
@@ -43,7 +45,7 @@ public class Disintegration extends SpellRay {
|
||||
MagicDamage.causeDirectMagicDamage(caster, DamageType.FIRE),
|
||||
getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY));
|
||||
|
||||
if(!world.isRemote && target instanceof EntityLivingBase && ((EntityLivingBase)target).getHealth() <= 0){
|
||||
if(target instanceof EntityLivingBase && ((EntityLivingBase)target).getHealth() <= 0){
|
||||
spawnEmbers(world, caster, target, getProperty(EMBER_COUNT).intValue());
|
||||
}
|
||||
}
|
||||
@@ -53,17 +55,28 @@ public class Disintegration extends SpellRay {
|
||||
|
||||
public static void spawnEmbers(World world, EntityLivingBase caster, Entity target, int count){
|
||||
|
||||
for(int i = 0; i < count; i++){
|
||||
EntityEmber ember = new EntityEmber(world, caster);
|
||||
double x = (world.rand.nextDouble() - 0.5) * target.width;
|
||||
double y = world.rand.nextDouble() * target.height;
|
||||
double z = (world.rand.nextDouble() - 0.5) * target.width;
|
||||
ember.setPosition(target.posX + x, target.posY + y, target.posZ + z);
|
||||
float speed = 0.2f;
|
||||
ember.motionX = x * speed;
|
||||
ember.motionY = y * 0.5f * speed;
|
||||
ember.motionZ = z * speed;
|
||||
world.spawnEntity(ember);
|
||||
target.extinguish();
|
||||
|
||||
if(world.isRemote){ // FIXME: Various syncing issues here!
|
||||
// Set NBT client-side, it's only for rendering
|
||||
// Normally dying entities are ignored but we're fiddling with them here so double-check
|
||||
if(!target.getEntityData().hasKey(NBT_KEY)){
|
||||
target.getEntityData().setInteger(NBT_KEY, target.ticksExisted);
|
||||
}
|
||||
}else{
|
||||
for(int i = 0; i < count; i++){
|
||||
EntityEmber ember = new EntityEmber(world, caster);
|
||||
double x = (world.rand.nextDouble() - 0.5) * target.width;
|
||||
double y = world.rand.nextDouble() * target.height;
|
||||
double z = (world.rand.nextDouble() - 0.5) * target.width;
|
||||
ember.setPosition(target.posX + x, target.posY + y, target.posZ + z);
|
||||
ember.ticksExisted = world.rand.nextInt(20);
|
||||
float speed = 0.2f;
|
||||
ember.motionX = x * speed;
|
||||
ember.motionY = y * 0.5f * speed;
|
||||
ember.motionZ = z * speed;
|
||||
world.spawnEntity(ember);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -80,15 +80,17 @@ public final class RayTracer {
|
||||
|
||||
/**
|
||||
* Helper method for use with {@link RayTracer#rayTrace(World, Vec3d, Vec3d, float, boolean, boolean, boolean, Class, Predicate)}
|
||||
* which returns a {@link Predicate} that returns true for the given entity, plus any entities that have zero health
|
||||
* or less (i.e. are in the process of dying). This is a commonly used filter in spells.
|
||||
* which returns a {@link Predicate} that returns true for the given entity, plus any entities that are in the
|
||||
* process of dying. This is a commonly used filter in spells.
|
||||
*
|
||||
* @param entity The entity that the returned predicate should return true for.
|
||||
* @return A {@link Predicate} that returns true for the given entity and any entities that are in the process of
|
||||
* dying, false for all other entities.
|
||||
*/
|
||||
public static Predicate<Entity> ignoreEntityFilter(Entity entity){
|
||||
return e -> e == entity || (e instanceof EntityLivingBase && ((EntityLivingBase)e).getHealth() <= 0);
|
||||
// Use deathTime > 0 so we still hit stuff that has *just* died, otherwise SpellRay#onEntityHit doesn't get
|
||||
// called on the client side when the entity is killed
|
||||
return e -> e == entity || (e instanceof EntityLivingBase && ((EntityLivingBase)e).deathTime > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user