diff --git a/src/main/java/electroblob/wizardry/block/BlockReceptacle.java b/src/main/java/electroblob/wizardry/block/BlockReceptacle.java index 72983785..7f4dc2f0 100644 --- a/src/main/java/electroblob/wizardry/block/BlockReceptacle.java +++ b/src/main/java/electroblob/wizardry/block/BlockReceptacle.java @@ -40,7 +40,7 @@ public class BlockReceptacle extends BlockTorch implements ITileEntityProvider { private static final double WALL_PARTICLE_OFFSET = 3/16d; - private static final Map PARTICLE_COLOURS; + public static final Map PARTICLE_COLOURS; static { diff --git a/src/main/java/electroblob/wizardry/client/ClientProxy.java b/src/main/java/electroblob/wizardry/client/ClientProxy.java index ddb07c7b..7ab6fc2a 100644 --- a/src/main/java/electroblob/wizardry/client/ClientProxy.java +++ b/src/main/java/electroblob/wizardry/client/ClientProxy.java @@ -746,6 +746,7 @@ public class ClientProxy extends CommonProxy { RenderingRegistry.registerEntityRenderingHandler(EntityWizard.class, RenderWizard::new); RenderingRegistry.registerEntityRenderingHandler(EntityEvilWizard.class, RenderEvilWizard::new); RenderingRegistry.registerEntityRenderingHandler(EntityDecoy.class, RenderDecoy::new); + RenderingRegistry.registerEntityRenderingHandler(EntityRemnant.class, RenderRemnant::new); // Throwables RenderingRegistry.registerEntityRenderingHandler(EntitySparkBomb.class, diff --git a/src/main/java/electroblob/wizardry/client/model/ModelRemnant.java b/src/main/java/electroblob/wizardry/client/model/ModelRemnant.java new file mode 100644 index 00000000..ec9d74d2 --- /dev/null +++ b/src/main/java/electroblob/wizardry/client/model/ModelRemnant.java @@ -0,0 +1,48 @@ +package electroblob.wizardry.client.model; + +import net.minecraft.client.model.ModelBase; +import net.minecraft.client.model.ModelRenderer; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.entity.Entity; +import net.minecraft.util.math.MathHelper; + +/** Based on ModelEnderCrystal */ +public class ModelRemnant extends ModelBase { + + private final ModelRenderer cube = new ModelRenderer(this, "cube"); + + public ModelRemnant(){ + this.cube.setTextureOffset(0, 0).addBox(-4.0F, -4.0F, -4.0F, 8, 8, 8); + } + + @Override + public void render(Entity entity, float rotationSpeed, float expandFraction, float age, float netHeadYaw, float headPitch, float scale){ + + GlStateManager.pushMatrix(); + +// GlStateManager.scale(2.0F, 2.0F, 2.0F); +// GlStateManager.translate(0.0F, -0.5F, 0.0F); + + GlStateManager.disableCull(); + + GlStateManager.translate(0.0F, entity.height/2, 0.0F); + + float s = expandFraction + MathHelper.sin(age * 0.1f) * 0.06f; + + GlStateManager.scale(s, s, s); + + 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); + this.cube.render(scale); + + GlStateManager.scale(0.875F, 0.875F, 0.875F); + GlStateManager.rotate(60.0F, 0.7071F, 0.0F, 0.7071F); + GlStateManager.rotate(age * rotationSpeed, 0.0F, 1.0F, 0.0F); + this.cube.render(scale); + + GlStateManager.enableCull(); + + GlStateManager.popMatrix(); + } +} diff --git a/src/main/java/electroblob/wizardry/client/renderer/RenderRemnant.java b/src/main/java/electroblob/wizardry/client/renderer/RenderRemnant.java new file mode 100644 index 00000000..4275c41a --- /dev/null +++ b/src/main/java/electroblob/wizardry/client/renderer/RenderRemnant.java @@ -0,0 +1,75 @@ +package electroblob.wizardry.client.renderer; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.client.model.ModelRemnant; +import electroblob.wizardry.entity.living.EntityRemnant; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.entity.Render; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.MathHelper; + +import javax.annotation.Nullable; + +public class RenderRemnant extends Render { + + private static final ResourceLocation TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/entity/remnant.png"); + + private final ModelRemnant model; + + public RenderRemnant(RenderManager manager){ + super(manager); + model = new ModelRemnant(); + } + + @Override + public void doRender(EntityRemnant entity, double x, double y, double z, float entityYaw, float partialTicks){ + + float age = (float)entity.ticksExisted + partialTicks; + GlStateManager.pushMatrix(); + GlStateManager.translate((float)x, (float)y, (float)z); + this.bindTexture(TEXTURE); +// float whatIsThis = MathHelper.sin(age * 0.2F) / 2.0F + 0.5F; +// whatIsThis = whatIsThis * whatIsThis + whatIsThis; + + if(this.renderOutlines){ + GlStateManager.enableColorMaterial(); + GlStateManager.enableOutlineMode(this.getTeamColor(entity)); + } + + float expansion = 0.9f; + + if(entity.deathTime > 0){ + float f = (entity.deathTime + partialTicks) * 0.25f; + f = 1 - (1 / (f + 1)); + expansion -= f * 0.75f; + + }else if(entity.hurtTime > 0){ + float f = (entity.hurtTime - partialTicks) / entity.maxHurtTime; + // Neat bit of maths borrowed from the camera tilt effect when hurt + f = MathHelper.sin(f * f * f * f * (float)Math.PI); + expansion += f * 0.2f; + } + +// if(entity.isAttacking()) s -= 0.4f; + float rotationSpeed = entity.isAttacking() ? 10 : 3; + + this.model.render(entity, rotationSpeed, expansion, age, 0, 0, 0.0625f); + + if(this.renderOutlines){ + GlStateManager.disableOutlineMode(); + GlStateManager.disableColorMaterial(); + } + + GlStateManager.popMatrix(); + + super.doRender(entity, x, y, z, entityYaw, partialTicks); + } + + @Nullable + @Override + protected ResourceLocation getEntityTexture(EntityRemnant entity){ + return TEXTURE; + } + +} diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityRemnant.java b/src/main/java/electroblob/wizardry/entity/living/EntityRemnant.java new file mode 100644 index 00000000..35efc0ee --- /dev/null +++ b/src/main/java/electroblob/wizardry/entity/living/EntityRemnant.java @@ -0,0 +1,332 @@ +package electroblob.wizardry.entity.living; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.block.BlockReceptacle; +import electroblob.wizardry.constants.Element; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.util.ParticleBuilder; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.IEntityLivingData; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.*; +import net.minecraft.entity.monster.EntityMob; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTUtil; +import net.minecraft.network.datasync.DataParameter; +import net.minecraft.network.datasync.DataSerializers; +import net.minecraft.network.datasync.EntityDataManager; +import net.minecraft.util.DamageSource; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.DifficultyInstance; +import net.minecraft.world.World; + +import javax.annotation.Nullable; + +public class EntityRemnant extends EntityMob { + + /** Data parameter for the remnant's element. */ + private static final DataParameter ELEMENT = EntityDataManager.createKey(EntityRemnant.class, DataSerializers.VARINT); + /** Data parameter that tracks whether the remnant is currently attacking (charging). */ + private static final DataParameter ATTACKING = EntityDataManager.createKey(EntityRemnant.class, DataSerializers.BOOLEAN); + + private ResourceLocation lootTable; + + @Nullable + private BlockPos boundOrigin; + + public EntityRemnant(World world){ + super(world); + this.setSize(0.8f, 0.8f); + this.isImmuneToFire = true; + this.moveHelper = new EntityRemnant.AIMoveControl(this); + this.experienceValue = 8; + } + + @Override + protected void entityInit(){ + super.entityInit(); + this.dataManager.register(ELEMENT, 1); // Default to fire + this.dataManager.register(ATTACKING, false); // Default to fire + } + + @Override + protected void initEntityAI(){ + super.initEntityAI(); + this.tasks.addTask(0, new EntityAISwimming(this)); + this.tasks.addTask(4, new EntityRemnant.AIChargeAttack()); + this.tasks.addTask(8, new EntityRemnant.AIMoveRandom()); + this.tasks.addTask(9, new EntityAIWatchClosest(this, EntityPlayer.class, 3.0F, 1.0F)); + this.tasks.addTask(10, new EntityAIWatchClosest(this, EntityLiving.class, 8.0F)); + this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true, EntityRemnant.class)); + this.targetTasks.addTask(3, new EntityAINearestAttackableTarget<>(this, EntityPlayer.class, true)); + } + + @Override + protected void applyEntityAttributes(){ + super.applyEntityAttributes(); + this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(16); + this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(4); + } + + @Nullable + @Override + public IEntityLivingData onInitialSpawn(DifficultyInstance difficulty, @Nullable IEntityLivingData livingdata){ + this.setElement(Element.values()[1 + rand.nextInt(Element.values().length - 1)]); // Exclude MAGIC + this.setBoundOrigin(new BlockPos(this)); + return super.onInitialSpawn(difficulty, livingdata); + } + + public Element getElement(){ + return Element.values()[this.dataManager.get(ELEMENT)]; + } + + public void setElement(Element element){ + this.dataManager.set(ELEMENT, element.ordinal()); + this.lootTable = new ResourceLocation(Wizardry.MODID, "entities/remnant/" + element.getName()); + } + + public boolean isAttacking(){ + return this.dataManager.get(ATTACKING); + } + + public void setAttacking(boolean attacking){ + this.dataManager.set(ATTACKING, attacking); + } + + @Nullable + public BlockPos getBoundOrigin(){ + return this.boundOrigin; + } + + public void setBoundOrigin(@Nullable BlockPos boundOriginIn){ + this.boundOrigin = boundOriginIn; + } + + @Override + protected boolean isValidLightLevel(){ + return true; + } + + @Override + public void onUpdate(){ + + // Use the same trick as EntityVex to fly through stuff + this.noClip = true; + super.onUpdate(); + this.noClip = false; + + this.setNoGravity(true); + + if(world.isRemote){ + + Vec3d centre = this.getPositionVector().add(0, height/2, 0); + + int[] colours = BlockReceptacle.PARTICLE_COLOURS.get(this.getElement()); + + if(rand.nextInt(10) == 0){ + ParticleBuilder.create(ParticleBuilder.Type.FLASH).entity(this).pos(0, height/2, 0).scale(width).time(48).clr(colours[0]).spawn(world); + } + + double r = width/3; + + double x = r * (rand.nextDouble() * 2 - 1); + double y = r * (rand.nextDouble() * 2 - 1); + double z = r * (rand.nextDouble() * 2 - 1); + + if(this.deathTime > 0){ + // Spew out particles on death + for(int i = 0; i < 8; i++){ + ParticleBuilder.create(ParticleBuilder.Type.DUST, rand, centre.x + x, centre.y + y, centre.z + z, 0.1, true) + .time(12).clr(colours[1]).fade(colours[2]).spawn(world); + } + }else{ + ParticleBuilder.create(ParticleBuilder.Type.DUST).pos(centre.x + x, centre.y + y, centre.z + z) + .vel(x * -0.03, 0.02, z * -0.03).time(24 + rand.nextInt(8)).clr(colours[1]).fade(colours[2]).spawn(world); + } + } + + } + + @Override + protected SoundEvent getAmbientSound(){ + return WizardrySounds.ENTITY_REMNANT_AMBIENT; + } + + @Override + protected SoundEvent getDeathSound(){ + return WizardrySounds.ENTITY_REMNANT_DEATH; + } + + @Override + protected SoundEvent getHurtSound(DamageSource source){ + return WizardrySounds.ENTITY_REMNANT_HURT; + } + + @Nullable + @Override + protected ResourceLocation getLootTable(){ + return lootTable; + } + + @Override + public void readEntityFromNBT(NBTTagCompound nbt){ + super.readEntityFromNBT(nbt); + this.setElement(Element.values()[nbt.getInteger("Element")]); + if(nbt.hasKey("BoundOrigin")) boundOrigin = NBTUtil.getPosFromTag(nbt.getCompoundTag("BoundOrigin")); + } + + @Override + public void writeEntityToNBT(NBTTagCompound nbt){ + super.writeEntityToNBT(nbt); + nbt.setInteger("Element", this.getElement().ordinal()); + if(boundOrigin != null) nbt.setTag("BoundOrigin", NBTUtil.createPosTag(boundOrigin)); + } + + // AI classes (copied from EntityVex) + + class AIChargeAttack extends EntityAIBase { + + public AIChargeAttack(){ + this.setMutexBits(1); + } + + @Override + public boolean shouldExecute(){ + if(EntityRemnant.this.getAttackTarget() != null && !EntityRemnant.this.getMoveHelper().isUpdating() && EntityRemnant.this.rand.nextInt(7) == 0){ + return EntityRemnant.this.getDistanceSq(EntityRemnant.this.getAttackTarget()) > 4.0D; + }else{ + return false; + } + } + + @Override + public boolean shouldContinueExecuting(){ + return EntityRemnant.this.getMoveHelper().isUpdating() && EntityRemnant.this.isAttacking() && EntityRemnant.this.getAttackTarget() != null && EntityRemnant.this.getAttackTarget().isEntityAlive(); + } + + @Override + public void startExecuting(){ + EntityLivingBase entitylivingbase = EntityRemnant.this.getAttackTarget(); + Vec3d vec3d = entitylivingbase.getPositionEyes(1.0F); + EntityRemnant.this.moveHelper.setMoveTo(vec3d.x, vec3d.y, vec3d.z, 1.0D); + EntityRemnant.this.setAttacking(true); +// EntityRemnant.this.playSound(SoundEvents.ENTITY_VEX_CHARGE, 1.0F, 1.0F); + } + + @Override + public void resetTask(){ + EntityRemnant.this.setAttacking(false); + } + + @Override + public void updateTask(){ + + EntityLivingBase entitylivingbase = EntityRemnant.this.getAttackTarget(); + + if(EntityRemnant.this.getEntityBoundingBox().intersects(entitylivingbase.getEntityBoundingBox())){ + EntityRemnant.this.attackEntityAsMob(entitylivingbase); + EntityRemnant.this.setAttacking(false); + }else{ + double d0 = EntityRemnant.this.getDistanceSq(entitylivingbase); + + if(d0 < 9.0D){ + Vec3d vec3d = entitylivingbase.getPositionEyes(1.0F); + EntityRemnant.this.moveHelper.setMoveTo(vec3d.x, vec3d.y, vec3d.z, 1.0D); + } + } + } + } + + class AIMoveControl extends EntityMoveHelper { + + public AIMoveControl(EntityRemnant host){ + super(host); + } + + @Override + public void onUpdateMoveHelper(){ + + if(this.action == EntityMoveHelper.Action.MOVE_TO){ + + double d0 = this.posX - EntityRemnant.this.posX; + double d1 = this.posY - EntityRemnant.this.posY; + double d2 = this.posZ - EntityRemnant.this.posZ; + double d3 = d0 * d0 + d1 * d1 + d2 * d2; + + d3 = MathHelper.sqrt(d3); + + if(d3 < EntityRemnant.this.getEntityBoundingBox().getAverageEdgeLength()){ + + this.action = EntityMoveHelper.Action.WAIT; + EntityRemnant.this.motionX *= 0.5D; + EntityRemnant.this.motionY *= 0.5D; + EntityRemnant.this.motionZ *= 0.5D; + + }else{ + + EntityRemnant.this.motionX += d0 / d3 * 0.05D * this.speed; + EntityRemnant.this.motionY += d1 / d3 * 0.05D * this.speed; + EntityRemnant.this.motionZ += d2 / d3 * 0.05D * this.speed; + + if(EntityRemnant.this.getAttackTarget() == null){ + EntityRemnant.this.rotationYaw = -((float)MathHelper.atan2(EntityRemnant.this.motionX, EntityRemnant.this.motionZ)) * (180F / (float)Math.PI); + }else{ + double d4 = EntityRemnant.this.getAttackTarget().posX - EntityRemnant.this.posX; + double d5 = EntityRemnant.this.getAttackTarget().posZ - EntityRemnant.this.posZ; + EntityRemnant.this.rotationYaw = -((float)MathHelper.atan2(d4, d5)) * (180F / (float)Math.PI); + } + + EntityRemnant.this.renderYawOffset = EntityRemnant.this.rotationYaw; + } + } + } + } + + class AIMoveRandom extends EntityAIBase { + + public AIMoveRandom(){ + this.setMutexBits(1); + } + + @Override + public boolean shouldExecute(){ + return !EntityRemnant.this.getMoveHelper().isUpdating() && EntityRemnant.this.rand.nextInt(7) == 0; + } + + @Override + public boolean shouldContinueExecuting(){ + return false; + } + + @Override + public void updateTask(){ + + BlockPos blockpos = EntityRemnant.this.getBoundOrigin(); + + if(blockpos == null){ + blockpos = new BlockPos(EntityRemnant.this); + } + + for(int i = 0; i < 3; ++i){ + BlockPos blockpos1 = blockpos.add(EntityRemnant.this.rand.nextInt(15) - 7, EntityRemnant.this.rand.nextInt(11) - 5, EntityRemnant.this.rand.nextInt(15) - 7); + + if(EntityRemnant.this.world.isAirBlock(blockpos1)){ + EntityRemnant.this.moveHelper.setMoveTo((double)blockpos1.getX() + 0.5D, (double)blockpos1.getY() + 0.5D, (double)blockpos1.getZ() + 0.5D, 0.25D); + + if(EntityRemnant.this.getAttackTarget() == null){ + EntityRemnant.this.getLookHelper().setLookPosition((double)blockpos1.getX() + 0.5D, (double)blockpos1.getY() + 0.5D, (double)blockpos1.getZ() + 0.5D, 180.0F, 20.0F); + } + + break; + } + } + } + } + +} diff --git a/src/main/java/electroblob/wizardry/registry/WizardryEntities.java b/src/main/java/electroblob/wizardry/registry/WizardryEntities.java index 8324e692..b2c70894 100644 --- a/src/main/java/electroblob/wizardry/registry/WizardryEntities.java +++ b/src/main/java/electroblob/wizardry/registry/WizardryEntities.java @@ -103,6 +103,7 @@ public class WizardryEntities { .spawn(EnumCreatureType.MONSTER, Wizardry.settings.evilWizardSpawnRate, 1, 1, ForgeRegistries.BIOMES.getValuesCollection().stream() .filter(b -> !Arrays.asList(Wizardry.settings.mobSpawnBiomeBlacklist).contains(b.getRegistryName())) .collect(Collectors.toSet())).build()); + registry.register(createEntry(EntityRemnant.class, "remnant", TrackingType.LIVING).egg(0xe4c7cd, 0x9d2cf3).build()); // Directed projectiles registry.register(createEntry(EntityMagicMissile.class, "magic_missile", TrackingType.PROJECTILE).build()); diff --git a/src/main/java/electroblob/wizardry/registry/WizardrySounds.java b/src/main/java/electroblob/wizardry/registry/WizardrySounds.java index 9f2538c4..adf6eba4 100644 --- a/src/main/java/electroblob/wizardry/registry/WizardrySounds.java +++ b/src/main/java/electroblob/wizardry/registry/WizardrySounds.java @@ -75,6 +75,9 @@ public final class WizardrySounds { public static final SoundEvent ENTITY_PHOENIX_FLAP = createSound("entity.phoenix.flap"); public static final SoundEvent ENTITY_PHOENIX_HURT = createSound("entity.phoenix.hurt"); public static final SoundEvent ENTITY_PHOENIX_DEATH = createSound("entity.phoenix.death"); + public static final SoundEvent ENTITY_REMNANT_AMBIENT = createSound("entity.remnant.ambient"); + public static final SoundEvent ENTITY_REMNANT_HURT = createSound("entity.remnant.hurt"); + public static final SoundEvent ENTITY_REMNANT_DEATH = createSound("entity.remnant.death"); public static final SoundEvent ENTITY_SHADOW_WRAITH_AMBIENT = createSound("entity.shadow_wraith.ambient"); public static final SoundEvent ENTITY_SHADOW_WRAITH_NOISE = createSound("entity.shadow_wraith.noise"); public static final SoundEvent ENTITY_SHADOW_WRAITH_HURT = createSound("entity.shadow_wraith.hurt"); @@ -207,6 +210,9 @@ public final class WizardrySounds { event.getRegistry().register(ENTITY_PHOENIX_FLAP); event.getRegistry().register(ENTITY_PHOENIX_HURT); event.getRegistry().register(ENTITY_PHOENIX_DEATH); + event.getRegistry().register(ENTITY_REMNANT_AMBIENT); + event.getRegistry().register(ENTITY_REMNANT_HURT); + event.getRegistry().register(ENTITY_REMNANT_DEATH); event.getRegistry().register(ENTITY_SHADOW_WRAITH_AMBIENT); event.getRegistry().register(ENTITY_SHADOW_WRAITH_NOISE); event.getRegistry().register(ENTITY_SHADOW_WRAITH_HURT); diff --git a/src/main/resources/assets/ebwizardry/lang/en_gb.lang b/src/main/resources/assets/ebwizardry/lang/en_gb.lang index 086a6d18..d8982789 100644 --- a/src/main/resources/assets/ebwizardry/lang/en_gb.lang +++ b/src/main/resources/assets/ebwizardry/lang/en_gb.lang @@ -445,6 +445,7 @@ entity.ebwizardry\:storm_elemental.name=Storm Elemental entity.ebwizardry\:evil_wizard.name=Wizard entity.ebwizardry\:decoy.name=Decoy entity.ebwizardry\:vex_minion.name=Vex +entity.ebwizardry\:remnant.name=Remnant entity.ebwizardry\:magic_missile.name=Magic entity.ebwizardry\:arc.name=Magic diff --git a/src/main/resources/assets/ebwizardry/lang/en_us.lang b/src/main/resources/assets/ebwizardry/lang/en_us.lang index 5fa24eb1..5c21e185 100644 --- a/src/main/resources/assets/ebwizardry/lang/en_us.lang +++ b/src/main/resources/assets/ebwizardry/lang/en_us.lang @@ -445,6 +445,7 @@ entity.ebwizardry\:storm_elemental.name=Storm Elemental entity.ebwizardry\:evil_wizard.name=Wizard entity.ebwizardry\:decoy.name=Decoy entity.ebwizardry\:vex_minion.name=Vex +entity.ebwizardry\:remnant.name=Remnant entity.ebwizardry\:magic_missile.name=Magic entity.ebwizardry\:arc.name=Magic diff --git a/src/main/resources/assets/ebwizardry/loot_tables/entities/remnant/earth.json b/src/main/resources/assets/ebwizardry/loot_tables/entities/remnant/earth.json new file mode 100644 index 00000000..ceee3c72 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/loot_tables/entities/remnant/earth.json @@ -0,0 +1,28 @@ +{ + "pools": [ + { + "name": "spectral_dust", + "rolls": 1, + "entries": [ + { + "type": "item", + "name": "ebwizardry:spectral_dust", + "weight": 1, + "functions": [ + { + "function": "set_count", + "count": { + "min": 0, + "max": 1 + } + }, + { + "function": "minecraft:set_data", + "data": 5 + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/loot_tables/entities/remnant/fire.json b/src/main/resources/assets/ebwizardry/loot_tables/entities/remnant/fire.json new file mode 100644 index 00000000..30f1446d --- /dev/null +++ b/src/main/resources/assets/ebwizardry/loot_tables/entities/remnant/fire.json @@ -0,0 +1,28 @@ +{ + "pools": [ + { + "name": "spectral_dust", + "rolls": 1, + "entries": [ + { + "type": "item", + "name": "ebwizardry:spectral_dust", + "weight": 1, + "functions": [ + { + "function": "set_count", + "count": { + "min": 0, + "max": 1 + } + }, + { + "function": "minecraft:set_data", + "data": 1 + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/loot_tables/entities/remnant/healing.json b/src/main/resources/assets/ebwizardry/loot_tables/entities/remnant/healing.json new file mode 100644 index 00000000..876cb55b --- /dev/null +++ b/src/main/resources/assets/ebwizardry/loot_tables/entities/remnant/healing.json @@ -0,0 +1,28 @@ +{ + "pools": [ + { + "name": "spectral_dust", + "rolls": 1, + "entries": [ + { + "type": "item", + "name": "ebwizardry:spectral_dust", + "weight": 1, + "functions": [ + { + "function": "set_count", + "count": { + "min": 0, + "max": 1 + } + }, + { + "function": "minecraft:set_data", + "data": 7 + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/loot_tables/entities/remnant/ice.json b/src/main/resources/assets/ebwizardry/loot_tables/entities/remnant/ice.json new file mode 100644 index 00000000..61a1d59f --- /dev/null +++ b/src/main/resources/assets/ebwizardry/loot_tables/entities/remnant/ice.json @@ -0,0 +1,28 @@ +{ + "pools": [ + { + "name": "spectral_dust", + "rolls": 1, + "entries": [ + { + "type": "item", + "name": "ebwizardry:spectral_dust", + "weight": 1, + "functions": [ + { + "function": "set_count", + "count": { + "min": 0, + "max": 1 + } + }, + { + "function": "minecraft:set_data", + "data": 2 + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/loot_tables/entities/remnant/lightning.json b/src/main/resources/assets/ebwizardry/loot_tables/entities/remnant/lightning.json new file mode 100644 index 00000000..6a4d5dec --- /dev/null +++ b/src/main/resources/assets/ebwizardry/loot_tables/entities/remnant/lightning.json @@ -0,0 +1,28 @@ +{ + "pools": [ + { + "name": "spectral_dust", + "rolls": 1, + "entries": [ + { + "type": "item", + "name": "ebwizardry:spectral_dust", + "weight": 1, + "functions": [ + { + "function": "set_count", + "count": { + "min": 0, + "max": 1 + } + }, + { + "function": "minecraft:set_data", + "data": 3 + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/loot_tables/entities/remnant/necromancy.json b/src/main/resources/assets/ebwizardry/loot_tables/entities/remnant/necromancy.json new file mode 100644 index 00000000..0064048f --- /dev/null +++ b/src/main/resources/assets/ebwizardry/loot_tables/entities/remnant/necromancy.json @@ -0,0 +1,28 @@ +{ + "pools": [ + { + "name": "spectral_dust", + "rolls": 1, + "entries": [ + { + "type": "item", + "name": "ebwizardry:spectral_dust", + "weight": 1, + "functions": [ + { + "function": "set_count", + "count": { + "min": 0, + "max": 1 + } + }, + { + "function": "minecraft:set_data", + "data": 4 + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/loot_tables/entities/remnant/sorcery.json b/src/main/resources/assets/ebwizardry/loot_tables/entities/remnant/sorcery.json new file mode 100644 index 00000000..8c9f9e8d --- /dev/null +++ b/src/main/resources/assets/ebwizardry/loot_tables/entities/remnant/sorcery.json @@ -0,0 +1,28 @@ +{ + "pools": [ + { + "name": "spectral_dust", + "rolls": 1, + "entries": [ + { + "type": "item", + "name": "ebwizardry:spectral_dust", + "weight": 1, + "functions": [ + { + "function": "set_count", + "count": { + "min": 0, + "max": 1 + } + }, + { + "function": "minecraft:set_data", + "data": 6 + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/sounds.json b/src/main/resources/assets/ebwizardry/sounds.json index 1078a058..16307596 100644 --- a/src/main/resources/assets/ebwizardry/sounds.json +++ b/src/main/resources/assets/ebwizardry/sounds.json @@ -51,6 +51,9 @@ "entity.phoenix.flap": {"category": "hostile", "sounds": ["mob/enderdragon/wings1", "mob/enderdragon/wings2", "mob/enderdragon/wings3", "mob/enderdragon/wings4", "mob/enderdragon/wings5", "mob/enderdragon/wings6"]}, "entity.phoenix.hurt": {"category": "hostile", "sounds": ["mob/blaze/hit1", "mob/blaze/hit2", "mob/blaze/hit3", "mob/blaze/hit4"]}, "entity.phoenix.death": {"category": "hostile", "sounds": ["mob/blaze/death"]}, + "entity.remnant.ambient": {"category": "hostile", "sounds": ["ebwizardry:remnant_hiss"]}, + "entity.remnant.hurt": {"category": "hostile", "sounds": ["ebwizardry:remnant_hurt"]}, + "entity.remnant.death": {"category": "hostile", "sounds": ["ebwizardry:remnant_death"]}, "entity.shadow_wraith.ambient": {"category": "hostile", "sounds": ["mob/blaze/breathe1", "mob/blaze/breathe2", "mob/blaze/breathe3", "mob/blaze/breathe4"]}, "entity.shadow_wraith.noise": {"category": "hostile", "sounds": ["portal/portal"]}, "entity.shadow_wraith.hurt": {"category": "hostile", "sounds": ["mob/blaze/hit1", "mob/blaze/hit2", "mob/blaze/hit3", "mob/blaze/hit4"]}, diff --git a/src/main/resources/assets/ebwizardry/sounds/remnant_death.ogg b/src/main/resources/assets/ebwizardry/sounds/remnant_death.ogg new file mode 100644 index 00000000..4607b82b Binary files /dev/null and b/src/main/resources/assets/ebwizardry/sounds/remnant_death.ogg differ diff --git a/src/main/resources/assets/ebwizardry/sounds/remnant_hiss.ogg b/src/main/resources/assets/ebwizardry/sounds/remnant_hiss.ogg new file mode 100644 index 00000000..8d81d0d7 Binary files /dev/null and b/src/main/resources/assets/ebwizardry/sounds/remnant_hiss.ogg differ diff --git a/src/main/resources/assets/ebwizardry/sounds/remnant_hurt.ogg b/src/main/resources/assets/ebwizardry/sounds/remnant_hurt.ogg new file mode 100644 index 00000000..da59842f Binary files /dev/null and b/src/main/resources/assets/ebwizardry/sounds/remnant_hurt.ogg differ diff --git a/src/main/resources/assets/ebwizardry/textures/entity/remnant.png b/src/main/resources/assets/ebwizardry/textures/entity/remnant.png new file mode 100644 index 00000000..f4429150 Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/entity/remnant.png differ