From f8fa6c880a0ae1aa61762fe283ea1ca7348e7ea1 Mon Sep 17 00:00:00 2001 From: SammySemicolon <69329424+SammySemicolon@users.noreply.github.com> Date: Wed, 6 Dec 2023 00:44:13 +0100 Subject: [PATCH] More work on the staff --- .../entity/HexProjectileEntityRenderer.java | 9 +- .../common/entity/HexProjectileEntity.java | 34 ++++-- .../entity/spirit/SpiritItemEntity.java | 2 +- .../curiosities/weapons/MagicStaveItem.java | 114 +++++++++++++++--- .../common/entity/EntityRegistry.java | 2 +- .../HexBoltHitEnemyParticleEffect.java | 13 +- src/main/resources/assets/malum/sounds.json | 4 +- 7 files changed, 142 insertions(+), 36 deletions(-) diff --git a/src/main/java/com/sammy/malum/client/renderer/entity/HexProjectileEntityRenderer.java b/src/main/java/com/sammy/malum/client/renderer/entity/HexProjectileEntityRenderer.java index 604c0ff02..6f0a53a6e 100644 --- a/src/main/java/com/sammy/malum/client/renderer/entity/HexProjectileEntityRenderer.java +++ b/src/main/java/com/sammy/malum/client/renderer/entity/HexProjectileEntityRenderer.java @@ -36,16 +36,15 @@ public HexProjectileEntityRenderer(EntityRendererProvider.Context context) { this.shadowStrength = 0; } - private static final ResourceLocation SAW = malumPath("textures/particle/saw.png"); - private static final RenderType ADDITIVE_SAW = LodestoneRenderTypeRegistry.ADDITIVE_TEXTURE.apply(SAW); - private static final RenderType LUMITRANSPARENT_SAW = LodestoneRenderTypeRegistry.TRANSPARENT_TEXTURE.apply(SAW, ShaderUniformHandler.LUMITRANSPARENT); - private static final ResourceLocation LIGHT_TRAIL = malumPath("textures/vfx/concentrated_trail.png"); private static final RenderType TRAIL_TYPE = LodestoneRenderTypeRegistry.ADDITIVE_TEXTURE_TRIANGLE.apply(LIGHT_TRAIL); @Override public void render(HexProjectileEntity entity, float entityYaw, float partialTicks, PoseStack poseStack, MultiBufferSource bufferIn, int packedLightIn) { - float effectScalar = entity.fadingAway ? 1 - (entity.age - 70) / 10f : 1; + if (entity.spawnDelay > 0) { + return; + } + float effectScalar = entity.fadingAway ? 1 - (entity.age - HexProjectileEntity.MAX_AGE + 10) / 10f : 1; List spinningTrailPoints = entity.spinningTrailPointBuilder.getTrailPoints(partialTicks); List trailPoints = entity.trailPointBuilder.getTrailPoints(partialTicks); poseStack.pushPose(); diff --git a/src/main/java/com/sammy/malum/common/entity/HexProjectileEntity.java b/src/main/java/com/sammy/malum/common/entity/HexProjectileEntity.java index 15ebf5675..385267748 100644 --- a/src/main/java/com/sammy/malum/common/entity/HexProjectileEntity.java +++ b/src/main/java/com/sammy/malum/common/entity/HexProjectileEntity.java @@ -32,13 +32,16 @@ public class HexProjectileEntity extends ThrowableItemProjectile { + public static final int MAX_AGE = 60; protected static final EntityDataAccessor DATA_FADING_AWAY = SynchedEntityData.defineId(HexProjectileEntity.class, EntityDataSerializers.BOOLEAN); + protected static final EntityDataAccessor DATA_SPAWN_DELAY = SynchedEntityData.defineId(HexProjectileEntity.class, EntityDataSerializers.INT); public final TrailPointBuilder spinningTrailPointBuilder = TrailPointBuilder.create(20); public float spinOffset = (float) (random.nextFloat() * Math.PI * 2); public final TrailPointBuilder trailPointBuilder = TrailPointBuilder.create(12); protected float magicDamage; public int age; + public int spawnDelay; public int soundCooldown = 20 + random.nextInt(100); public boolean fadingAway; @@ -53,14 +56,16 @@ public HexProjectileEntity(Level level, double pX, double pY, double pZ) { noPhysics = false; } - public void setData(Entity owner, float magicDamage) { + public void setData(Entity owner, float magicDamage, int spawnDelay) { setOwner(owner); this.magicDamage = magicDamage; + getEntityData().set(DATA_SPAWN_DELAY, spawnDelay); } @Override protected void defineSynchedData() { this.getEntityData().define(DATA_FADING_AWAY, false); + this.getEntityData().define(DATA_SPAWN_DELAY, 0); super.defineSynchedData(); } @@ -68,7 +73,12 @@ protected void defineSynchedData() { public void onSyncedDataUpdated(EntityDataAccessor pKey) { if (DATA_FADING_AWAY.equals(pKey)) { fadingAway = entityData.get(DATA_FADING_AWAY); - age = 70; + if (fadingAway) { + age = MAX_AGE - 10; + } + } + if (DATA_SPAWN_DELAY.equals(pKey)) { + spawnDelay = entityData.get(DATA_SPAWN_DELAY); } super.onSyncedDataUpdated(pKey); } @@ -81,6 +91,9 @@ public void addAdditionalSaveData(CompoundTag compound) { if (age != 0) { compound.putInt("age", age); } + if (spawnDelay != 0) { + compound.putInt("spawnDelay", spawnDelay); + } if (fadingAway) { compound.putBoolean("fadingAway", true); } @@ -91,6 +104,7 @@ public void readAdditionalSaveData(CompoundTag compound) { super.readAdditionalSaveData(compound); magicDamage = compound.getFloat("magicDamage"); age = compound.getInt("age"); + getEntityData().set(DATA_SPAWN_DELAY, compound.getInt("spawnDelay")); getEntityData().set(DATA_FADING_AWAY, compound.getBoolean("fadingAway")); } @@ -108,7 +122,7 @@ protected boolean canHitEntity(Entity pTarget) { @Override protected void onHitEntity(EntityHitResult result) { - if (fadingAway) { + if (fadingAway || spawnDelay != 0) { return; } if (getOwner() instanceof LivingEntity staveOwner) { @@ -122,7 +136,7 @@ protected void onHitEntity(EntityHitResult result) { if (success && target instanceof LivingEntity livingentity) { ItemStack stave = getItem(); ItemHelper.applyEnchantments(staveOwner, livingentity, stave); - int i = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.FIRE_ASPECT, stave); + int i = stave.getEnchantmentLevel(Enchantments.FIRE_ASPECT); if (i > 0) { livingentity.setSecondsOnFire(i * 4); } @@ -137,6 +151,10 @@ protected void onHitEntity(EntityHitResult result) { @Override public void tick() { + if (spawnDelay > 0) { + spawnDelay--; + return; + } super.tick(); Vec3 motion = getDeltaMovement(); if (!fadingAway) { @@ -160,7 +178,7 @@ public void tick() { trailPointBuilder.tickTrailPoints(); } age++; - if (age >= 80) { + if (age >= MAX_AGE) { remove(RemovalReason.DISCARDED); } if (this.xRotO == 0.0F && this.yRotO == 0.0F) { @@ -169,7 +187,7 @@ public void tick() { xRotO = getXRot(); } if (level().isClientSide && !fadingAway) { - float scalar = age > 70 ? 1f - (age - 70) / 10f : 1f; + float scalar = age > MAX_AGE ? 1f - (age - MAX_AGE + 10) / 10f : 1f; Vec3 norm = motion.normalize().scale(0.05f); var lightSpecs = SpiritLightSpecs.spiritLightSpecs(level(), position(), SpiritTypeRegistry.WICKED_SPIRIT); lightSpecs.getBuilder().multiplyLifetime(1.25f).setMotion(norm); @@ -180,11 +198,13 @@ public void tick() { DirectionalParticleBuilder.create(ParticleRegistry.SAW) .setTransparencyData(GenericParticleData.create(0.9f * scalar, 0.4f * scalar, 0f).setEasing(Easing.SINE_IN_OUT, Easing.SINE_IN).build()) .setSpinData(spinData) - .setScaleData(GenericParticleData.create(0.5f * scalar, 0).setEasing(Easing.SINE_IN_OUT).build()) + .setScaleData(GenericParticleData.create(0.4f * scalar, 0).setEasing(Easing.SINE_IN_OUT).build()) .setColorData(SpiritTypeRegistry.WICKED_SPIRIT.createMainColorData().build()) .setLifetime(Math.min(age * 3, 30)) .setDirection(getDeltaMovement().normalize()) .enableNoClip() + .enableForcedSpawn() + .disableCull() .setSpritePicker(SimpleParticleOptions.ParticleSpritePicker.RANDOM_SPRITE) .addTickActor(behavior) .spawn(level(), position().x, position().y, position().z) diff --git a/src/main/java/com/sammy/malum/common/entity/spirit/SpiritItemEntity.java b/src/main/java/com/sammy/malum/common/entity/spirit/SpiritItemEntity.java index 5f5bd43f1..d46d5932c 100644 --- a/src/main/java/com/sammy/malum/common/entity/spirit/SpiritItemEntity.java +++ b/src/main/java/com/sammy/malum/common/entity/spirit/SpiritItemEntity.java @@ -77,7 +77,7 @@ public void spawnParticles(double x, double y, double z) { public void move() { if (soundCooldown-- == 0) { if (random.nextFloat() < 0.4f) { - level().playSound(null, blockPosition(), SoundRegistry.ARCANE_WHISPERS.get(), SoundSource.NEUTRAL, 0.3f, Mth.nextFloat(random, 1.1f, 2f)); + level().playSound(null, blockPosition(), SoundRegistry.ARCANE_WHISPERS.get(), SoundSource.NEUTRAL, 0.3f, Mth.nextFloat(random, 0.8f, 2f)); } soundCooldown = random.nextInt(40) + 40; } diff --git a/src/main/java/com/sammy/malum/common/item/curiosities/weapons/MagicStaveItem.java b/src/main/java/com/sammy/malum/common/item/curiosities/weapons/MagicStaveItem.java index 075f85e50..1394e9fe7 100644 --- a/src/main/java/com/sammy/malum/common/item/curiosities/weapons/MagicStaveItem.java +++ b/src/main/java/com/sammy/malum/common/item/curiosities/weapons/MagicStaveItem.java @@ -2,17 +2,31 @@ import com.google.common.collect.*; import com.sammy.malum.common.entity.*; +import com.sammy.malum.registry.client.*; import com.sammy.malum.registry.common.*; import com.sammy.malum.registry.common.item.*; import net.minecraft.stats.*; +import net.minecraft.util.*; import net.minecraft.world.*; +import net.minecraft.world.entity.*; import net.minecraft.world.entity.ai.attributes.*; import net.minecraft.world.entity.player.*; import net.minecraft.world.item.*; import net.minecraft.world.item.enchantment.*; import net.minecraft.world.level.*; import net.minecraft.world.phys.*; +import team.lodestar.lodestone.helpers.*; import team.lodestar.lodestone.registry.common.*; +import team.lodestar.lodestone.systems.easing.*; +import team.lodestar.lodestone.systems.particle.*; +import team.lodestar.lodestone.systems.particle.builder.*; +import team.lodestar.lodestone.systems.particle.data.*; +import team.lodestar.lodestone.systems.particle.data.spin.*; +import team.lodestar.lodestone.systems.particle.render_types.*; +import team.lodestar.lodestone.systems.particle.world.*; + +import java.util.*; +import java.util.function.*; public class MagicStaveItem extends MalumStaveItem { @@ -31,26 +45,94 @@ public ImmutableMultimap.Builder createExtraAttrib } @Override - public InteractionResultHolder use(Level pLevel, Player pPlayer, InteractionHand pUsedHand) { - ItemStack stack = pPlayer.getItemInHand(pUsedHand); - Level level = pPlayer.level(); - if (!level.isClientSide && !pPlayer.getCooldowns().isOnCooldown(stack.getItem())) { - float magicDamage = (float) pPlayer.getAttributes().getValue(LodestoneAttributeRegistry.MAGIC_DAMAGE.get()); - int angle = pUsedHand == InteractionHand.MAIN_HAND ? 225 : 90; - Vec3 pos = pPlayer.position().add(pPlayer.getLookAngle().scale(0.5)).add(0.5 * Math.sin(Math.toRadians(angle - pPlayer.yHeadRot)), pPlayer.getBbHeight() * 2 / 3, 0.5 * Math.cos(Math.toRadians(angle - pPlayer.yHeadRot))); + public void onUseTick(Level pLevel, LivingEntity pLivingEntity, ItemStack pStack, int pRemainingUseDuration) { + if (pLevel.isClientSide) { + RandomSource random = pLevel.random; + InteractionHand hand = pLivingEntity.getUsedItemHand(); + Vec3 pos = getProjectileSpawnPos(pLivingEntity, hand, 1.5f, 0.6f); + float pct = Math.min(20, getUseDuration(pStack) - pRemainingUseDuration) / 20f; + final SpinParticleData spinData = SpinParticleData.createRandomDirection(random, 0.25f, 0.5f).setSpinOffset(RandomHelper.randomBetween(random, 0f, 6.28f)).build(); + DirectionalParticleBuilder.create(ParticleRegistry.HEXAGON) + .setTransparencyData(GenericParticleData.create(0.6f * pct, 0f).setEasing(Easing.SINE_IN_OUT, Easing.SINE_IN).build()) + .setSpinData(spinData) + .setScaleData(GenericParticleData.create(0.3f * pct, 0).setEasing(Easing.SINE_IN_OUT).build()) + .setColorData(SpiritTypeRegistry.WICKED_SPIRIT.createMainColorData().build()) + .setLifetime(5) + .setDirection(pLivingEntity.getLookAngle().normalize()) + .setMotion(pLivingEntity.getLookAngle().normalize().scale(0.05f)) + .enableNoClip() + .enableForcedSpawn() + .disableCull() + .setLifeDelay(2) + .setSpritePicker(SimpleParticleOptions.ParticleSpritePicker.RANDOM_SPRITE) + .spawn(pLevel, pos.x, pos.y, pos.z) + .setRenderType(LodestoneWorldParticleRenderType.LUMITRANSPARENT) + .spawn(pLevel, pos.x, pos.y, pos.z); + } + + super.onUseTick(pLevel, pLivingEntity, pStack, pRemainingUseDuration); + } + + @Override + public void releaseUsing(ItemStack pStack, Level pLevel, LivingEntity pLivingEntity, int pTimeCharged) { + if (pTimeCharged <= getUseDuration(pStack) - 20) { + InteractionHand hand = pLivingEntity.getUsedItemHand(); + for (int i = 0; i < 3; i++) { + fireProjectile(pLivingEntity, pStack, pLevel, hand, i); + } + if (pLivingEntity instanceof Player player) { + player.awardStat(Stats.ITEM_USED.get(this)); + if (!player.getAbilities().instabuild) { + pStack.hurtAndBreak(1, player, (p_220009_1_) -> { + p_220009_1_.broadcastBreakEvent(hand); + }); + player.getCooldowns().addCooldown(this, 80); + } + player.swing(hand, true); + } + } + super.releaseUsing(pStack, pLevel, pLivingEntity, pTimeCharged); + } + + @Override + public InteractionResultHolder use(Level pLevel, Player pPlayer, InteractionHand pHand) { + ItemStack itemstack = pPlayer.getItemInHand(pHand); + if (pPlayer.getCooldowns().isOnCooldown(itemstack.getItem())) { + return InteractionResultHolder.fail(itemstack); + } else { + pPlayer.startUsingItem(pHand); + return InteractionResultHolder.consume(itemstack); + } + } + + @Override + public int getUseDuration(ItemStack pStack) { + return 72000; + } + + @Override + public UseAnim getUseAnimation(ItemStack pStack) { + return UseAnim.BOW; + } + + public void fireProjectile(LivingEntity player, ItemStack stack, Level level, InteractionHand hand, int count) { + if (!level.isClientSide) { + float pitchOffset = 3f + count; + int spawnDelay = count * 3; + float velocity = 2.5f + 0.5f * count; + float magicDamage = (float) player.getAttributes().getValue(LodestoneAttributeRegistry.MAGIC_DAMAGE.get()) * 1.5f; + Vec3 pos = getProjectileSpawnPos(player, hand, 0.5f, 0.5f); HexProjectileEntity entity = new HexProjectileEntity(level, pos.x, pos.y, pos.z); - entity.setData(pPlayer, magicDamage); + entity.setData(player, magicDamage, spawnDelay); entity.setItem(stack); - entity.shootFromRotation(pPlayer, pPlayer.getXRot(), pPlayer.getYRot(), 0.0F, 1.75f, 0F); + entity.shootFromRotation(player, player.getXRot(), player.getYRot(), -pitchOffset, velocity, 0F); level.addFreshEntity(entity); - stack.hurtAndBreak(1, pPlayer, (p_220009_1_) -> { - p_220009_1_.broadcastBreakEvent(pUsedHand); - }); - pPlayer.getCooldowns().addCooldown(stack.getItem(), 15); - return InteractionResultHolder.success(stack); } - pPlayer.awardStat(Stats.ITEM_USED.get(stack.getItem())); - return super.use(pLevel, pPlayer, pUsedHand); + } + + public Vec3 getProjectileSpawnPos(LivingEntity player, InteractionHand hand, float distance, float spread) { + int angle = hand == InteractionHand.MAIN_HAND ? 225 : 90; + return player.position().add(player.getLookAngle().scale(distance)).add(spread * Math.sin(Math.toRadians(angle - player.yHeadRot)), player.getBbHeight() * 0.9f, spread * Math.cos(Math.toRadians(angle - player.yHeadRot))); } } diff --git a/src/main/java/com/sammy/malum/registry/common/entity/EntityRegistry.java b/src/main/java/com/sammy/malum/registry/common/entity/EntityRegistry.java index dedd003c0..f0edf182a 100644 --- a/src/main/java/com/sammy/malum/registry/common/entity/EntityRegistry.java +++ b/src/main/java/com/sammy/malum/registry/common/entity/EntityRegistry.java @@ -48,7 +48,7 @@ public class EntityRegistry { .build(MalumMod.malumPath("scythe_boomerang").toString())); public static final RegistryObject> HEX_BOLT = ENTITY_TYPES.register("hex_bolt", - () -> EntityType.Builder.of((e, w) -> new HexProjectileEntity(w), MobCategory.MISC).sized(0.8F, 0.8F).clientTrackingRange(10) + () -> EntityType.Builder.of((e, w) -> new HexProjectileEntity(w), MobCategory.MISC).sized(1F, 1.2F).clientTrackingRange(10) .build(MalumMod.malumPath("hex_bolt").toString())); @Mod.EventBusSubscriber(modid = MalumMod.MALUM, value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD) diff --git a/src/main/java/com/sammy/malum/visual_effects/networked/HexBoltHitEnemyParticleEffect.java b/src/main/java/com/sammy/malum/visual_effects/networked/HexBoltHitEnemyParticleEffect.java index eb0d896f5..5c66dcefe 100644 --- a/src/main/java/com/sammy/malum/visual_effects/networked/HexBoltHitEnemyParticleEffect.java +++ b/src/main/java/com/sammy/malum/visual_effects/networked/HexBoltHitEnemyParticleEffect.java @@ -71,23 +71,28 @@ public Supplier get() { Vec3 spawnPosition = pos.add(direction.scale(distance)); direction = direction.reverse(); float lifetimeMultiplier = 0.7f; - if (random.nextFloat() < 0.75f) { + if (random.nextFloat() < 0.8f) { var lightSpecs = spiritLightSpecs(level, spawnPosition, spiritType); lightSpecs.getBuilder() .multiplyLifetime(lifetimeMultiplier) + .disableCull() + .enableForcedSpawn() + .modifyData(WorldParticleBuilder::getScaleData, d -> d.multiplyValue(1.75f)) .setMotion(direction); lightSpecs.getBloomBuilder() .multiplyLifetime(lifetimeMultiplier) .setMotion(direction); lightSpecs.spawnParticles(); } - if (random.nextFloat() < 0.75f) { + if (random.nextFloat() < 0.8f) { var sparks = SparkParticleEffects.spiritMotionSparks(level, spawnPosition, spiritType); sparks.getBuilder() .multiplyLifetime(lifetimeMultiplier) + .disableCull() + .enableForcedSpawn() .setMotion(direction.scale(1.5f)) - .modifyData(SparkParticleBuilder::getScaleData, d -> d.multiplyValue(1.5f)) - .modifyData(SparkParticleBuilder::getLengthData, d -> d.multiplyValue(2.5f)); + .modifyData(SparkParticleBuilder::getScaleData, d -> d.multiplyValue(1.75f)) + .modifyData(SparkParticleBuilder::getLengthData, d -> d.multiplyValue(3f)); sparks.getBloomBuilder() .multiplyLifetime(lifetimeMultiplier) .setMotion(direction.scale(1.5f)); diff --git a/src/main/resources/assets/malum/sounds.json b/src/main/resources/assets/malum/sounds.json index c9dbcd2c4..14f70a78d 100644 --- a/src/main/resources/assets/malum/sounds.json +++ b/src/main/resources/assets/malum/sounds.json @@ -4,8 +4,8 @@ "arcana_entry_opened": { "sounds":["malum:codex/book_entry_open1", "malum:codex/book_entry_open2", "malum:codex/book_entry_open3", "malum:codex/book_entry_open4"], "subtitle": "malum.subtitle.arcana_entry_opened" }, "arcana_entry_closed": { "sounds":["malum:codex/book_entry_close1", "malum:codex/book_entry_close2", "malum:codex/book_entry_close3", "malum:codex/book_entry_close4"], "subtitle": "malum.subtitle.arcana_entry_closed" }, "arcana_page_flipped": { "sounds":["malum:codex/book_page_turn1", "malum:codex/book_page_turn2", "malum:codex/book_page_turn3", "malum:codex/book_page_turn4"], "subtitle": "malum.subtitle.arcana_page_flipped" }, - "arcana_sweetener_normal": { "sounds":["malum:codex/book_swtnr_normal1", "malum:codex/book_swtnr_normal2", "malum:codex/book_swtnr_normal3", "malum:codex/book_swtnr_normal4", "malum:codex/book_swtnr_normal5", "malum:codex/book_swtnr_normal6"]}, - "arcana_sweetener_evil": { "sounds":["malum:codex/book_swtnr_evil1", "malum:codex/book_swtnr_evil2", "malum:codex/book_swtnr_evil3", "malum:codex/book_swtnr_evil4", "malum:codex/book_swtnr_evil5", "malum:codex/book_swtnr_evil6"]}, + "arcana_sweetener_normal": { "sounds":["malum:codex/book_swtnr_normal1", "malum:codex/book_swtnr_normal2", "malum:codex/book_swtnr_normal3", "malum:codex/book_swtnr_normal4", "malum:codex/book_swtnr_normal5", "malum:codex/book_swtnr_normal6", "malum:codex/book_swtnr_normal7", "malum:codex/book_swtnr_normal8", "malum:codex/book_swtnr_normal6"]}, + "arcana_sweetener_evil": { "sounds":["malum:codex/book_swtnr_evil1", "malum:codex/book_swtnr_evil2", "malum:codex/book_swtnr_evil3", "malum:codex/book_swtnr_evil4", "malum:codex/book_swtnr_evil5", "malum:codex/book_swtnr_evil6", "malum:codex/book_swtnr_evil7", "malum:codex/book_swtnr_evil8", "malum:codex/book_swtnr_evil6"]}, "arcana_transition_normal": { "sounds":["malum:codex/book_transition_normal1", "malum:codex/book_transition_normal2"], "subtitle": "malum.subtitle.arcana_transition_normal" }, "arcana_transition_evil": { "sounds":["malum:codex/book_transition_evil1", "malum:codex/book_transition_evil2"], "subtitle": "malum.subtitle.arcana_transition_evil" },