diff --git a/src/main/java/electroblob/wizardry/client/ClientProxy.java b/src/main/java/electroblob/wizardry/client/ClientProxy.java index 5a9812c7..8683ed84 100644 --- a/src/main/java/electroblob/wizardry/client/ClientProxy.java +++ b/src/main/java/electroblob/wizardry/client/ClientProxy.java @@ -816,6 +816,7 @@ public class ClientProxy extends CommonProxy { RenderingRegistry.registerEntityRenderingHandler(EntityZombieSpawner.class, RenderZombieSpawner::new); RenderingRegistry.registerEntityRenderingHandler(EntityRadiantTotem.class, RenderRadiantTotem::new); RenderingRegistry.registerEntityRenderingHandler(EntityBoulder.class, RenderBoulder::new); + RenderingRegistry.registerEntityRenderingHandler(EntityWitheringTotem.class, RenderWitheringTotem::new); //RenderingRegistry.registerEntityRenderingHandler(EntityContainmentField.class, RenderContainmentField::new); // Stuff that doesn't render diff --git a/src/main/java/electroblob/wizardry/client/renderer/entity/RenderWitheringTotem.java b/src/main/java/electroblob/wizardry/client/renderer/entity/RenderWitheringTotem.java new file mode 100644 index 00000000..b5398be0 --- /dev/null +++ b/src/main/java/electroblob/wizardry/client/renderer/entity/RenderWitheringTotem.java @@ -0,0 +1,159 @@ +package electroblob.wizardry.client.renderer.entity; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.client.DrawingUtils; +import electroblob.wizardry.entity.construct.EntityWitheringTotem; +import electroblob.wizardry.util.GeometryUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.entity.Render; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.Vec3d; +import org.lwjgl.opengl.GL11; + +import javax.annotation.Nullable; + +public class RenderWitheringTotem extends Render { + + private static final ResourceLocation FLARE_TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/entity/totem/flare.png"); + private static final ResourceLocation[] CUBE_TEXTURES = new ResourceLocation[14]; + + static { + for(int i = 0; i< CUBE_TEXTURES.length; i++) CUBE_TEXTURES[i] = new ResourceLocation(Wizardry.MODID, "textures/entity/totem/cube_" + i + ".png"); + } + + public RenderWitheringTotem(RenderManager manager){ + super(manager); + } + + @Nullable + @Override + protected ResourceLocation getEntityTexture(EntityWitheringTotem entity){ + return CUBE_TEXTURES[entity.ticksExisted % CUBE_TEXTURES.length]; + } + + @Override + public void doRender(EntityWitheringTotem entity, double x, double y, double z, float entityYaw, float partialTicks){ + + Tessellator tessellator = Tessellator.getInstance(); + + GlStateManager.pushMatrix(); + + GlStateManager.enableBlend(); + GlStateManager.disableLighting(); + OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240, 240); + GlStateManager.depthMask(false); + GlStateManager.disableCull(); + + GlStateManager.translate(x, y + entity.height/2, z); + + float charge = entity.getHealthDrained() / 50f; + + float s = DrawingUtils.smoothScaleFactor(entity.lifetime, entity.ticksExisted, partialTicks, 10, 10); + s *= 1 + charge * 0.3f; // Gets bigger the more health it drains + GlStateManager.scale(s, s, s); + + drawFlare(charge, tessellator); + drawCube(entity, tessellator, partialTicks); + + GlStateManager.disableBlend(); + GlStateManager.enableLighting(); + GlStateManager.depthMask(true); + GlStateManager.enableCull(); + + GlStateManager.popMatrix(); + } + + private void drawFlare(float redness, Tessellator tessellator){ + + BufferBuilder buffer = tessellator.getBuffer(); + + GlStateManager.pushMatrix(); + + int c = DrawingUtils.mix(0xb333e6, 0xff0044, redness); + int r = c >> 16 & 255; + int g = c >> 8 & 255; + int b = c & 255; + + // Makes the colour add to the colour of the texture pixels, rather than the default multiplying + GlStateManager.glTexEnvi(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_ADD); + GlStateManager.color(r/255f, g/255f, b/255f); // Gets redder the more health it drains + GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + + bindTexture(FLARE_TEXTURE); + + // This counteracts the reverse rotation behaviour when in front f5 view. + // Fun fact: this is a bug with vanilla too! Look at a snowball in front f5 view, for example. + float yaw = Minecraft.getMinecraft().gameSettings.thirdPersonView == 2 + ? Minecraft.getMinecraft().getRenderManager().playerViewX + : -Minecraft.getMinecraft().getRenderManager().playerViewX; + GlStateManager.rotate(180.0F - Minecraft.getMinecraft().getRenderManager().playerViewY, 0.0F, 1.0F, 0.0F); + GlStateManager.rotate(yaw, 1.0F, 0.0F, 0.0F); + + buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); + + float radius = 0.5f; + + buffer.pos(-radius, radius, 0).tex(0, 0).endVertex(); + buffer.pos( radius, radius, 0).tex(1, 0).endVertex(); + buffer.pos( radius, -radius, 0).tex(1, 1).endVertex(); + buffer.pos(-radius, -radius, 0).tex(0, 1).endVertex(); + + tessellator.draw(); + + // Reverses the colour addition change + GlStateManager.glTexEnvi(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_MODULATE); + GlStateManager.color(1, 1, 1, 1); + GlStateManager.popMatrix(); + } + + private void drawCube(EntityWitheringTotem entity, Tessellator tessellator, float partialTicks){ + + BufferBuilder buffer = tessellator.getBuffer(); + + GlStateManager.pushMatrix(); + + float age = entity.ticksExisted + partialTicks; + float rotationSpeed = 2; + + GlStateManager.rotate(age * rotationSpeed/2, 0.0F, 1.0F, 0.0F); + GlStateManager.rotate(60.0F, 0.7071F, 0.0F, 0.7071F); + GlStateManager.rotate(age * rotationSpeed, 0.0F, 1.0F, 0.0F); + + GlStateManager.scale(0.5, 0.5, 0.5); + + GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE); + + bindEntityTexture(entity); + + Vec3d[] vertices = GeometryUtils.getVertices(entity.getEntityBoundingBox().offset(entity.getPositionVector() + .add(0, entity.height/2, 0).scale(-1))); + + buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); + + // Outside + drawFace(buffer, vertices[0], vertices[1], vertices[3], vertices[2], 0.5f, 0, 0.75f, 0.5f); // Bottom + drawFace(buffer, vertices[6], vertices[7], vertices[2], vertices[3], 0.75f, 0.5f, 1, 1); // South + drawFace(buffer, vertices[5], vertices[6], vertices[1], vertices[2], 0, 0.5f, 0.25f, 1); // East + drawFace(buffer, vertices[4], vertices[5], vertices[0], vertices[1], 0.25f, 0.5f, 0.5f, 1); // North + drawFace(buffer, vertices[7], vertices[4], vertices[3], vertices[0], 0.5f, 0.5f, 0.75f, 1); // West + drawFace(buffer, vertices[5], vertices[4], vertices[6], vertices[7], 0.25f, 0, 0.5f, 0.5f); // Top + + tessellator.draw(); + + GlStateManager.popMatrix(); + } + + private static void drawFace(BufferBuilder buffer, Vec3d topLeft, Vec3d topRight, Vec3d bottomLeft, Vec3d bottomRight, float u1, float v1, float u2, float v2){ + buffer.pos(topLeft.x, topLeft.y, topLeft.z).tex(u1, v1).endVertex(); + buffer.pos(topRight.x, topRight.y, topRight.z).tex(u2, v1).endVertex(); + buffer.pos(bottomRight.x, bottomRight.y, bottomRight.z).tex(u2, v2).endVertex(); + buffer.pos(bottomLeft.x, bottomLeft.y, bottomLeft.z).tex(u1, v2).endVertex(); + } + +} diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityWitheringTotem.java b/src/main/java/electroblob/wizardry/entity/construct/EntityWitheringTotem.java new file mode 100644 index 00000000..fca25006 --- /dev/null +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityWitheringTotem.java @@ -0,0 +1,175 @@ +package electroblob.wizardry.entity.construct; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.constants.Constants; +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Spell; +import electroblob.wizardry.spell.WitheringTotem; +import electroblob.wizardry.util.*; +import electroblob.wizardry.util.BlockUtils.SurfaceCriteria; +import electroblob.wizardry.util.MagicDamage.DamageType; +import electroblob.wizardry.util.ParticleBuilder.Type; +import io.netty.buffer.ByteBuf; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.init.MobEffects; +import net.minecraft.network.datasync.DataParameter; +import net.minecraft.network.datasync.DataSerializers; +import net.minecraft.network.datasync.EntityDataManager; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +import java.util.Comparator; +import java.util.List; + +public class EntityWitheringTotem extends EntityScaledConstruct { + + private static final int PERIMETER_PARTICLE_DENSITY = 6; + + private static final DataParameter HEALTH_DRAINED = EntityDataManager.createKey(EntityWitheringTotem.class, DataSerializers.FLOAT); + + public EntityWitheringTotem(World world){ + super(world); + this.setSize(1, 1); // This entity is different in that its area of effect is kind of 'outside' it + } + + @Override + protected void entityInit(){ + dataManager.register(HEALTH_DRAINED, 0f); + } + + public float getHealthDrained(){ + return dataManager.get(HEALTH_DRAINED); + } + + public void addHealthDrained(float health){ + dataManager.set(HEALTH_DRAINED, getHealthDrained() + health); + } + + @Override + protected boolean shouldScaleWidth(){ + return false; + } + + @Override + protected boolean shouldScaleHeight(){ + return false; + } + + @Override + public void onUpdate(){ + + if(world.isRemote && this.ticksExisted == 1){ + Wizardry.proxy.playMovingSound(this, WizardrySounds.ENTITY_WITHERING_TOTEM_AMBIENT, WizardrySounds.SPELLS, 1, 1, true); + } + + super.onUpdate(); + + double radius = Spells.withering_totem.getProperty(Spell.EFFECT_RADIUS).floatValue() * sizeMultiplier; + + if(world.isRemote){ + + ParticleBuilder.create(Type.DUST, rand, posX, posY + 0.2, posZ, 0.3, false) + .vel(0, -0.02 - world.rand.nextFloat() * 0.01, 0).clr(0xf575f5).fade(0x382366).spawn(world); + + for(int i=0; i nearby = EntityUtils.getLivingWithinRadius(radius, posX, posY, posZ, world); + nearby.removeIf(e -> !isValidTarget(e)); + nearby.sort(Comparator.comparingDouble(e -> e.getDistanceSq(this))); + + int targetsRemaining = Spells.withering_totem.getProperty(WitheringTotem.MAX_TARGETS).intValue() + + (int)((damageMultiplier - 1) / Constants.POTENCY_INCREASE_PER_TIER); + + while(!nearby.isEmpty() && targetsRemaining > 0){ + + EntityLivingBase target = nearby.remove(0); + + if(EntityUtils.isLiving(target)){ + + if(target.ticksExisted % target.maxHurtResistantTime == 1){ + + float damage = Spells.withering_totem.getProperty(Spell.DAMAGE).floatValue(); + + if(EntityUtils.attackEntityWithoutKnockback(target, MagicDamage.causeIndirectMagicDamage(this, + getCaster(), DamageType.WITHER), damage)){ + addHealthDrained(damage); + } + } + + targetsRemaining--; + + if(world.isRemote){ + + Vec3d centre = GeometryUtils.getCentre(this); + Vec3d pos = GeometryUtils.getCentre(target); + + ParticleBuilder.create(Type.BEAM).pos(centre).target(target) + .clr(0.1f + 0.2f * world.rand.nextFloat(), 0, 0.3f).spawn(world); + + for(int i = 0; i < 3; i++){ + ParticleBuilder.create(Type.DUST, rand, pos.x, pos.y, pos.z, 0.3, false) + .vel(pos.subtract(centre).normalize().scale(-0.1)).clr(0x0c0024).fade(0x610017).spawn(world); + } + } + } + } + } + + @Override + public void despawn(){ + + double radius = Spells.withering_totem.getProperty(Spell.EFFECT_RADIUS).floatValue() * sizeMultiplier; + + List nearby = EntityUtils.getLivingWithinRadius(radius, posX, posY, posZ, world); + nearby.removeIf(e -> !isValidTarget(e)); + + float damage = Math.min(getHealthDrained() * 0.2f, Spells.withering_totem.getProperty(WitheringTotem.MAX_EXPLOSION_DAMAGE).floatValue()); + + for(EntityLivingBase target : nearby){ + + if(EntityUtils.attackEntityWithoutKnockback(target, MagicDamage.causeIndirectMagicDamage(this, + getCaster(), DamageType.MAGIC), damage)){ + target.addPotionEffect(new PotionEffect(MobEffects.WITHER, Spells.withering_totem.getProperty(Spell.EFFECT_DURATION).intValue(), + Spells.withering_totem.getProperty(Spell.EFFECT_STRENGTH).intValue())); + } + } + + if(world.isRemote) ParticleBuilder.create(Type.SPHERE).pos(GeometryUtils.getCentre(this)).scale((float)radius).clr(0xbe1a53) + .fade(0x210f4a).spawn(world); + + this.playSound(WizardrySounds.ENTITY_WITHERING_TOTEM_EXPLODE, 1, 1); + super.despawn(); + } + + // Usually damage multipliers don't need syncing, but here we're using it for the non-standard purpose of targeting + + @Override + public void writeSpawnData(ByteBuf data){ + super.writeSpawnData(data); + data.writeFloat(damageMultiplier); + } + + @Override + public void readSpawnData(ByteBuf data){ + super.readSpawnData(data); + damageMultiplier = data.readFloat(); + } +} diff --git a/src/main/java/electroblob/wizardry/registry/Spells.java b/src/main/java/electroblob/wizardry/registry/Spells.java index e6327ce9..5dce3c2f 100644 --- a/src/main/java/electroblob/wizardry/registry/Spells.java +++ b/src/main/java/electroblob/wizardry/registry/Spells.java @@ -244,6 +244,7 @@ public final class Spells { public static final Spell mark_sacrifice = placeholder(); public static final Spell stormcloud = placeholder(); + public static final Spell withering_totem = placeholder(); public static final Spell fangs = placeholder(); public static final Spell radiant_totem = placeholder(); @@ -456,6 +457,7 @@ public final class Spells { registry.register(new MarkSacrifice()); registry.register(new Stormcloud()); + registry.register(new WitheringTotem()); registry.register(new Fangs()); registry.register(new RadiantTotem()); diff --git a/src/main/java/electroblob/wizardry/registry/WizardryEntities.java b/src/main/java/electroblob/wizardry/registry/WizardryEntities.java index 6e144a6d..fe7de88e 100644 --- a/src/main/java/electroblob/wizardry/registry/WizardryEntities.java +++ b/src/main/java/electroblob/wizardry/registry/WizardryEntities.java @@ -148,6 +148,7 @@ public class WizardryEntities { registry.register(createEntry(EntityDecay.class, "decay", TrackingType.CONSTRUCT).build()); registry.register(createEntry(EntityZombieSpawner.class, "zombie_spawner", TrackingType.CONSTRUCT).build()); registry.register(createEntry(EntityRadiantTotem.class, "radiant_totem", TrackingType.CONSTRUCT).build()); + registry.register(createEntry(EntityWitheringTotem.class, "withering_totem", TrackingType.CONSTRUCT).build()); // These ones don't render, currently that makes no difference here but we might as well separate them registry.register(createEntry(EntityArrowRain.class, "arrow_rain", TrackingType.CONSTRUCT).build()); diff --git a/src/main/java/electroblob/wizardry/registry/WizardrySounds.java b/src/main/java/electroblob/wizardry/registry/WizardrySounds.java index 5794cc08..4842151a 100644 --- a/src/main/java/electroblob/wizardry/registry/WizardrySounds.java +++ b/src/main/java/electroblob/wizardry/registry/WizardrySounds.java @@ -73,6 +73,8 @@ public final class WizardrySounds { public static final SoundEvent ENTITY_RADIANT_TOTEM_VANISH = createSound("entity.radiant_totem.vanish"); public static final SoundEvent ENTITY_SHIELD_DEFLECT = createSound("entity.shield.deflect"); public static final SoundEvent ENTITY_TORNADO_AMBIENT = createSound("entity.tornado.ambient"); + public static final SoundEvent ENTITY_WITHERING_TOTEM_AMBIENT = createSound("entity.withering_totem.ambient"); + public static final SoundEvent ENTITY_WITHERING_TOTEM_EXPLODE = createSound("entity.withering_totem.explode"); public static final SoundEvent ENTITY_ZOMBIE_SPAWNER_SPAWN = createSound("entity.zombie_spawner.spawn"); public static final SoundEvent ENTITY_EVIL_WIZARD_AMBIENT = createSound("entity.evil_wizard.ambient"); diff --git a/src/main/java/electroblob/wizardry/spell/WitheringTotem.java b/src/main/java/electroblob/wizardry/spell/WitheringTotem.java new file mode 100644 index 00000000..93c69f64 --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/WitheringTotem.java @@ -0,0 +1,25 @@ +package electroblob.wizardry.spell; + +import electroblob.wizardry.entity.construct.EntityWitheringTotem; +import electroblob.wizardry.util.SpellModifiers; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.util.EnumFacing; + +import javax.annotation.Nullable; + +public class WitheringTotem extends SpellConstructRanged { + + public static final String MAX_TARGETS = "max_targets"; + public static final String MAX_EXPLOSION_DAMAGE = "max_explosion_damage"; + + public WitheringTotem(){ + super("withering_totem", EntityWitheringTotem::new, false); + this.addProperties(EFFECT_RADIUS, MAX_TARGETS, DAMAGE, MAX_EXPLOSION_DAMAGE, EFFECT_DURATION, EFFECT_STRENGTH); + this.floor(false); + } + + @Override + protected void addConstructExtras(EntityWitheringTotem construct, EnumFacing side, @Nullable EntityLivingBase caster, SpellModifiers modifiers){ + construct.posY += 1.2; + } +} diff --git a/src/main/resources/assets/ebwizardry/lang/en_gb.lang b/src/main/resources/assets/ebwizardry/lang/en_gb.lang index d57eca84..f1bb201a 100644 --- a/src/main/resources/assets/ebwizardry/lang/en_gb.lang +++ b/src/main/resources/assets/ebwizardry/lang/en_gb.lang @@ -629,6 +629,7 @@ entity.ebwizardry\:stormcloud.name=Stormcloud entity.ebwizardry\:zombie_spawner.name=Zombie Spawner entity.ebwizardry\:boulder.name=Boulder entity.ebwizardry\:radiant_totem.name=Radiant Totem +entity.ebwizardry\:withering_totem.name=Withering Totem itemGroup.ebwizardry=Wizardry itemGroup.ebwizardryspells=Spells @@ -938,6 +939,7 @@ spell.ebwizardry\:water_breathing=Water Breathing spell.ebwizardry\:whirlwind=Whirlwind spell.ebwizardry\:wither=Wither spell.ebwizardry\:wither_skull=Wither Skull +spell.ebwizardry\:withering_totem=Withering Totem spell.ebwizardry\:zombie_apocalypse=Zombie Apocalypse spell.ebwizardry\:agility.desc=Grants the caster faster movement speed and greater jump height for 30 seconds. @@ -1120,6 +1122,7 @@ spell.ebwizardry\:water_breathing.desc=Allows the caster to breathe underwater f spell.ebwizardry\:whirlwind.desc=Causes the target to be blown upwards and away from you at speed. spell.ebwizardry\:wither.desc=Fires a ray of darkness which withers anything it touches. spell.ebwizardry\:wither_skull.desc=Launches a wither skull in the direction you are pointing. +spell.ebwizardry\:withering_totem.desc=Summons a withering totem where you are pointing, which slowly drains health from nearby creatures. After 30 seconds, the totem explodes, releasing a wave of withering energy that deals more damage the more health that was drained. spell.ebwizardry\:zombie_apocalypse.desc=Opening a portal to the underworld is easy. The difficult part is shutting it again when things go wrong... spell.ebwizardry\:invoke_weather.sun=The rain begins to stop... diff --git a/src/main/resources/assets/ebwizardry/lang/en_us.lang b/src/main/resources/assets/ebwizardry/lang/en_us.lang index 4559bc53..a5eac612 100644 --- a/src/main/resources/assets/ebwizardry/lang/en_us.lang +++ b/src/main/resources/assets/ebwizardry/lang/en_us.lang @@ -629,6 +629,7 @@ entity.ebwizardry\:stormcloud.name=Stormcloud entity.ebwizardry\:zombie_spawner.name=Zombie Spawner entity.ebwizardry\:boulder.name=Boulder entity.ebwizardry\:radiant_totem.name=Radiant Totem +entity.ebwizardry\:withering_totem.name=Withering Totem itemGroup.ebwizardry=Wizardry itemGroup.ebwizardryspells=Spells @@ -938,6 +939,7 @@ spell.ebwizardry\:water_breathing=Water Breathing spell.ebwizardry\:whirlwind=Whirlwind spell.ebwizardry\:wither=Wither spell.ebwizardry\:wither_skull=Wither Skull +spell.ebwizardry\:withering_totem=Withering Totem spell.ebwizardry\:zombie_apocalypse=Zombie Apocalypse spell.ebwizardry\:agility.desc=Grants the caster faster movement speed and greater jump height for 30 seconds. @@ -1120,6 +1122,7 @@ spell.ebwizardry\:water_breathing.desc=Allows the caster to breathe underwater f spell.ebwizardry\:whirlwind.desc=Causes the target to be blown upwards and away from you at speed. spell.ebwizardry\:wither.desc=Fires a ray of darkness which withers anything it touches. spell.ebwizardry\:wither_skull.desc=Launches a wither skull in the direction you are pointing. +spell.ebwizardry\:withering_totem.desc=Summons a withering totem where you are pointing, which slowly drains health from nearby creatures. After 30 seconds, the totem explodes, releasing a wave of withering energy that deals more damage the more health that was drained. spell.ebwizardry\:zombie_apocalypse.desc=Opening a portal to the underworld is easy. The difficult part is shutting it again when things go wrong... spell.ebwizardry\:invoke_weather.sun=The rain begins to stop... diff --git a/src/main/resources/assets/ebwizardry/sounds.json b/src/main/resources/assets/ebwizardry/sounds.json index 47ec3571..19ab10ad 100644 --- a/src/main/resources/assets/ebwizardry/sounds.json +++ b/src/main/resources/assets/ebwizardry/sounds.json @@ -46,6 +46,8 @@ "entity.stormcloud.thunder": {"category": "spells", "sounds": ["ambient/weather/thunder1", "ambient/weather/thunder2", "ambient/weather/thunder3"]}, "entity.stormcloud.attack": {"category": "spells", "sounds": ["ebwizardry:arc1", "ebwizardry:arc2", "ebwizardry:arc3"]}, "entity.tornado.ambient": {"category": "spells", "sounds": ["ebwizardry:wind"]}, + "entity.withering_totem.ambient": {"category": "spells", "sounds": ["ebwizardry:dark_aura_loop"]}, + "entity.withering_totem.explode": {"category": "spells", "sounds": ["mob/wither/death"]}, "entity.zombie_spawner.spawn": {"category": "spells", "sounds": ["mob/guardian/elder_death"]}, "entity.evil_wizard.ambient": {"category": "hostile", "sounds": ["mob/evocation_illager/idle1", "mob/evocation_illager/idle2", "mob/evocation_illager/idle3", "mob/evocation_illager/idle4"]}, @@ -341,6 +343,7 @@ "spell.whirlwind": {"category": "spells", "sounds": ["ebwizardry:ice"]}, "spell.wither": {"category": "spells", "sounds": ["mob/wither/hurt1", "mob/wither/hurt2", "mob/wither/hurt3", "mob/wither/hurt4"]}, "spell.wither_skull": {"category": "spells", "sounds": ["mob/wither/shoot"]}, + "spell.withering_totem": {"category": "spells", "sounds": ["ebwizardry:beam_start"]}, "spell.zombie_apocalypse.start": {"category": "spells", "sounds": ["ebwizardry:dark_aura_start"]}, "spell.zombie_apocalypse.loop": {"category": "spells", "sounds": ["ebwizardry:dark_aura_loop"]}, "spell.zombie_apocalypse.end": {"category": "spells", "sounds": ["ebwizardry:dark_aura_end"]}, diff --git a/src/main/resources/assets/ebwizardry/spells/withering_totem.json b/src/main/resources/assets/ebwizardry/spells/withering_totem.json new file mode 100644 index 00000000..d5a7bae4 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/spells/withering_totem.json @@ -0,0 +1,29 @@ +{ + "enabled": { + "book": true, + "scroll": true, + "wands": true, + "npcs": true, + "dispensers": true, + "commands": true, + "treasure": true, + "trades": true, + "looting": true + }, + "tier": "advanced", + "element": "necromancy", + "type": "construct", + "cost": 50, + "chargeup": 20, + "cooldown": 200, + "base_properties": { + "range": 8, + "duration": 600, + "effect_radius": 6, + "max_targets": 1, + "damage": 1, + "max_explosion_damage": 10, + "effect_duration": 120, + "effect_strength": 0 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/textures/spells/withering_totem.png b/src/main/resources/assets/ebwizardry/textures/spells/withering_totem.png new file mode 100644 index 00000000..75ea6800 Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/spells/withering_totem.png differ