From 047ebfe8aafa5924f5811c74c109e1b0e608c598 Mon Sep 17 00:00:00 2001 From: Bob Date: Sun, 13 Oct 2024 19:49:31 +0200 Subject: [PATCH] better explosion particle effects, flamethrower sound loop --- .../java/com/hbm/config/ClientConfig.java | 3 + .../java/com/hbm/crafting/WeaponRecipes.java | 1 + .../projectile/EntityBulletBaseMK4.java | 7 +- .../standard/EntityProcessorCross.java | 22 +++- .../standard/ExplosionEffectWeapon.java | 28 +++++ .../java/com/hbm/inventory/material/Mats.java | 2 +- .../hbm/items/weapon/sedna/ItemGunBaseNT.java | 9 ++ .../hbm/items/weapon/sedna/factory/Lego.java | 4 +- .../weapon/sedna/factory/Orchestras.java | 113 ++++++++++++++---- .../weapon/sedna/factory/XFactory22lr.java | 42 +++++-- src/main/java/com/hbm/main/ClientProxy.java | 12 +- .../com/hbm/particle/EntityFXRotating.java | 6 + .../hbm/particle/ParticleExplosionSmall.java | 80 +++++++++++++ .../hbm/particle/ParticleFlamethrower.java | 2 +- .../helper/ExplosionSmallCreator.java | 61 ++++++++++ .../hbm/particle/helper/ParticleCreators.java | 15 +++ .../item/weapon/sedna/ItemRenderFlamer.java | 4 +- .../weapon/sedna/ItemRenderWeaponBase.java | 2 +- src/main/resources/assets/hbm/sounds.json | 1 + .../hbm/sounds/weapon/fire/flameLoop.ogg | Bin 0 -> 13920 bytes 20 files changed, 361 insertions(+), 53 deletions(-) create mode 100644 src/main/java/com/hbm/explosion/vanillant/standard/ExplosionEffectWeapon.java create mode 100644 src/main/java/com/hbm/particle/ParticleExplosionSmall.java create mode 100644 src/main/java/com/hbm/particle/helper/ExplosionSmallCreator.java create mode 100644 src/main/java/com/hbm/particle/helper/ParticleCreators.java create mode 100644 src/main/resources/assets/hbm/sounds/weapon/fire/flameLoop.ogg diff --git a/src/main/java/com/hbm/config/ClientConfig.java b/src/main/java/com/hbm/config/ClientConfig.java index 1c852c7c8..8f040e5e5 100644 --- a/src/main/java/com/hbm/config/ClientConfig.java +++ b/src/main/java/com/hbm/config/ClientConfig.java @@ -25,9 +25,12 @@ public class ClientConfig { public static ConfigWrapper GEIGER_OFFSET_HORIZONTAL = new ConfigWrapper(0); public static ConfigWrapper GEIGER_OFFSET_VERTICAL = new ConfigWrapper(0); + public static ConfigWrapper GUN_ANIMS_LEGACY = new ConfigWrapper(false); + private static void initDefaults() { configMap.put("GEIGER_OFFSET_HORIZONTAL", GEIGER_OFFSET_HORIZONTAL); configMap.put("GEIGER_OFFSET_VERTICAL", GEIGER_OFFSET_VERTICAL); + configMap.put("GUN_ANIMS_LEGACY", GUN_ANIMS_LEGACY); } public static void initConfig() { diff --git a/src/main/java/com/hbm/crafting/WeaponRecipes.java b/src/main/java/com/hbm/crafting/WeaponRecipes.java index e62e9633a..d4c0631c7 100644 --- a/src/main/java/com/hbm/crafting/WeaponRecipes.java +++ b/src/main/java/com/hbm/crafting/WeaponRecipes.java @@ -45,6 +45,7 @@ public class WeaponRecipes { CraftingManager.addRecipeAuto(new ItemStack(ModItems.gun_am180, 1), new Object[] { "BBR", "GMS", 'B', DURA.lightBarrel(), 'R', DURA.lightReceiver(), 'M', GUNMETAL.mechanism(), 'G', WOOD.grip(), 'S', WOOD.stock() }); CraftingManager.addRecipeAuto(new ItemStack(ModItems.gun_liberator, 1), new Object[] { "BB ", "BBM", "G G", 'B', DURA.lightBarrel(), 'M', GUNMETAL.mechanism(), 'G', WOOD.grip() }); CraftingManager.addRecipeAuto(new ItemStack(ModItems.gun_congolake, 1), new Object[] { "BM ", "BRS", "G ", 'B', DURA.heavyBarrel(), 'M', GUNMETAL.mechanism(), 'R', DURA.lightReceiver(), 'S', WOOD.stock(), 'G', WOOD.grip() }); + CraftingManager.addRecipeAuto(new ItemStack(ModItems.gun_flamer, 1), new Object[] { " MG", "BBR", " GM", 'M', GUNMETAL.mechanism(), 'G', DURA.grip(), 'B', DURA.heavyBarrel(), 'R', DURA.heavyReceiver() }); //SEDNA Ammo CraftingManager.addRecipeAuto(DictFrame.fromOne(ModItems.ammo_standard, EnumAmmo.STONE, 6), new Object[] { "C", "P", "G", 'C', KEY_COBBLESTONE, 'P', Items.paper, 'G', Items.gunpowder }); diff --git a/src/main/java/com/hbm/entity/projectile/EntityBulletBaseMK4.java b/src/main/java/com/hbm/entity/projectile/EntityBulletBaseMK4.java index f83eeb76d..4f4704bb9 100644 --- a/src/main/java/com/hbm/entity/projectile/EntityBulletBaseMK4.java +++ b/src/main/java/com/hbm/entity/projectile/EntityBulletBaseMK4.java @@ -165,12 +165,15 @@ public class EntityBulletBaseMK4 extends EntityThrowableInterp { if(mop.typeOfHit == mop.typeOfHit.ENTITY) { Entity entity = mop.entityHit; - if(!entity.isEntityAlive()) return; + + if(entity instanceof EntityLivingBase && ((EntityLivingBase) entity).getHealth() <= 0) { + return; + } DamageSource damageCalc = this.config.getDamage(this, getThrower(), false); if(!(entity instanceof EntityLivingBase)) { - entity.attackEntityFrom(damageCalc, this.damage); + EntityDamageUtil.attackEntityFromIgnoreIFrame(entity, damageCalc, this.damage); return; } diff --git a/src/main/java/com/hbm/explosion/vanillant/standard/EntityProcessorCross.java b/src/main/java/com/hbm/explosion/vanillant/standard/EntityProcessorCross.java index 15b1a06b8..a463e016c 100644 --- a/src/main/java/com/hbm/explosion/vanillant/standard/EntityProcessorCross.java +++ b/src/main/java/com/hbm/explosion/vanillant/standard/EntityProcessorCross.java @@ -2,6 +2,7 @@ package com.hbm.explosion.vanillant.standard; import java.util.HashMap; import java.util.List; +import java.util.Map.Entry; import com.hbm.explosion.vanillant.ExplosionVNT; import com.hbm.explosion.vanillant.interfaces.ICustomDamageHandler; @@ -59,6 +60,8 @@ public class EntityProcessorCross implements IEntityProcessor { ForgeDirection dir = ForgeDirection.getOrientation(i); nodes[i] = Vec3.createVectorHelper(x + dir.offsetX * nodeDist, y + dir.offsetY * nodeDist, z + dir.offsetZ * nodeDist); } + + HashMap damageMap = new HashMap(); for(int index = 0; index < list.size(); ++index) { @@ -89,7 +92,8 @@ public class EntityProcessorCross implements IEntityProcessor { double knockback = (1.0D - distanceScaled) * density; - entity.attackEntityFrom(setExplosionSource(explosion.compat), calculateDamage(distanceScaled, density, knockback, size)); + float dmg = calculateDamage(distanceScaled, density, knockback, size); + if(!damageMap.containsKey(entity) || damageMap.get(entity) < dmg) damageMap.put(entity, dmg); double enchKnockback = EnchantmentProtection.func_92092_a(entity, knockback); entity.motionX += deltaX * enchKnockback; @@ -99,14 +103,22 @@ public class EntityProcessorCross implements IEntityProcessor { if(entity instanceof EntityPlayer) { affectedPlayers.put((EntityPlayer) entity, Vec3.createVectorHelper(deltaX * knockback, deltaY * knockback, deltaZ * knockback)); } - - if(damage != null) { - damage.handleAttack(explosion, entity, distanceScaled); - } } } } + for(Entry entry : damageMap.entrySet()) { + + Entity entity = entry.getKey(); + entity.attackEntityFrom(setExplosionSource(explosion.compat), entry.getValue()); + System.out.println(entity + " " + entry.getValue()); + + if(damage != null) { + double distanceScaled = entity.getDistance(x, y, z) / size; + damage.handleAttack(explosion, entity, distanceScaled); + } + } + return affectedPlayers; } diff --git a/src/main/java/com/hbm/explosion/vanillant/standard/ExplosionEffectWeapon.java b/src/main/java/com/hbm/explosion/vanillant/standard/ExplosionEffectWeapon.java new file mode 100644 index 000000000..1443bb3c0 --- /dev/null +++ b/src/main/java/com/hbm/explosion/vanillant/standard/ExplosionEffectWeapon.java @@ -0,0 +1,28 @@ +package com.hbm.explosion.vanillant.standard; + +import com.hbm.explosion.vanillant.ExplosionVNT; +import com.hbm.explosion.vanillant.interfaces.IExplosionSFX; +import com.hbm.particle.helper.ExplosionSmallCreator; + +import net.minecraft.world.World; + +public class ExplosionEffectWeapon implements IExplosionSFX { + + int cloudCount; + float cloudScale; + float cloudSpeedMult; + + public ExplosionEffectWeapon(int cloudCount, float cloudScale, float cloudSpeedMult) { + this.cloudCount = cloudCount; + this.cloudScale = cloudScale; + this.cloudSpeedMult = cloudSpeedMult; + } + + @Override + public void doEffect(ExplosionVNT explosion, World world, double x, double y, double z, float size) { + if(world.isRemote) return; + + world.playSoundEffect(x, y, z, "random.explode", 4.0F, (1.0F + (world.rand.nextFloat() - world.rand.nextFloat()) * 0.2F) * 0.9F); + ExplosionSmallCreator.composeEffect(world, x, y, z, cloudCount, cloudScale, cloudSpeedMult); + } +} diff --git a/src/main/java/com/hbm/inventory/material/Mats.java b/src/main/java/com/hbm/inventory/material/Mats.java index 11864a70c..797295ffc 100644 --- a/src/main/java/com/hbm/inventory/material/Mats.java +++ b/src/main/java/com/hbm/inventory/material/Mats.java @@ -136,7 +136,7 @@ public class Mats { public static final NTMMaterial MAT_STEEL = makeSmeltable(_AS + 0, STEEL, 0xAFAFAF, 0x0F0F0F, 0x4A4A4A).setShapes(DUSTTINY, BOLT, WIRE, INGOT, DUST, PLATE, CASTPLATE, WELDEDPLATE, SHELL, PIPE, BLOCK, HEAVY_COMPONENT, LIGHTBARREL, HEAVYBARREL, LIGHTRECEIVER, GRIP).m(); public static final NTMMaterial MAT_MINGRADE = makeSmeltable(_AS + 1, MINGRADE, 0xFFBA7D, 0xAF1700, 0xE44C0F).setShapes(WIRE, INGOT, DUST, BLOCK).m(); public static final NTMMaterial MAT_ALLOY = makeSmeltable(_AS + 2, ALLOY, 0xFF8330, 0x700000, 0xFF7318).setShapes(WIRE, INGOT, DUST, DENSEWIRE, PLATE, CASTPLATE, BLOCK, HEAVY_COMPONENT).m(); - public static final NTMMaterial MAT_DURA = makeSmeltable(_AS + 3, DURA, 0x183039, 0x030B0B, 0x376373).setShapes(BOLT, INGOT, DUST, PIPE, BLOCK, LIGHTBARREL, HEAVYBARREL, LIGHTRECEIVER, GRIP).m(); + public static final NTMMaterial MAT_DURA = makeSmeltable(_AS + 3, DURA, 0x183039, 0x030B0B, 0x376373).setShapes(BOLT, INGOT, DUST, PIPE, BLOCK, LIGHTBARREL, HEAVYBARREL, LIGHTRECEIVER, HEAVYRECEIVER, GRIP).m(); public static final NTMMaterial MAT_DESH = makeSmeltable(_AS + 12, DESH, 0xFF6D6D, 0x720000, 0xF22929).setShapes(INGOT, DUST, CASTPLATE, BLOCK, HEAVY_COMPONENT).m(); public static final NTMMaterial MAT_STAR = makeSmeltable(_AS + 5, STAR, 0xCCCCEA, 0x11111A, 0xA5A5D3).setShapes(INGOT, DUST, DENSEWIRE, BLOCK).m(); public static final NTMMaterial MAT_FERRO = makeSmeltable(_AS + 7, FERRO, 0xB7B7C9, 0x101022, 0x6B6B8B).setShapes(INGOT).m(); diff --git a/src/main/java/com/hbm/items/weapon/sedna/ItemGunBaseNT.java b/src/main/java/com/hbm/items/weapon/sedna/ItemGunBaseNT.java index 1d1aff580..918a2276e 100644 --- a/src/main/java/com/hbm/items/weapon/sedna/ItemGunBaseNT.java +++ b/src/main/java/com/hbm/items/weapon/sedna/ItemGunBaseNT.java @@ -1,5 +1,6 @@ package com.hbm.items.weapon.sedna; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.BiConsumer; import com.hbm.handler.CasingEjector; @@ -14,6 +15,7 @@ import com.hbm.packet.toclient.AuxParticlePacketNT; import com.hbm.packet.toclient.GunAnimationPacket; import com.hbm.render.anim.HbmAnimations.AnimType; import com.hbm.render.util.RenderScreenOverlay; +import com.hbm.sound.AudioWrapper; import com.hbm.util.EnumUtil; import cpw.mods.fml.common.network.NetworkRegistry.TargetPoint; @@ -56,6 +58,8 @@ public class ItemGunBaseNT extends Item implements IKeybindReceiver, IEquipRecei public static final String KEY_RELOAD = "reload_"; public static final String KEY_LASTANIM = "lastanim_"; public static final String KEY_ANIMTIMER = "animtimer_"; + + public static ConcurrentHashMap loopedSounds = new ConcurrentHashMap(); public static float prevAimingProgress; public static float aimingProgress; @@ -157,6 +161,11 @@ public class ItemGunBaseNT extends Item implements IKeybindReceiver, IEquipRecei for(int i = 0; i < confNo; i++) if(configs[i].getSmokeHandler(stack) != null) { configs[i].getSmokeHandler(stack).accept(stack, ctx[i]); } + + for(int i = 0; i < confNo; i++) { + BiConsumer orchestra = configs[i].getOrchestra(stack); + if(orchestra != null) orchestra.accept(stack, ctx[i]); + } } return; } diff --git a/src/main/java/com/hbm/items/weapon/sedna/factory/Lego.java b/src/main/java/com/hbm/items/weapon/sedna/factory/Lego.java index 7a2e2b362..632048996 100644 --- a/src/main/java/com/hbm/items/weapon/sedna/factory/Lego.java +++ b/src/main/java/com/hbm/items/weapon/sedna/factory/Lego.java @@ -8,7 +8,7 @@ import java.util.function.BiFunction; import com.hbm.entity.projectile.EntityBulletBaseMK4; import com.hbm.explosion.vanillant.ExplosionVNT; import com.hbm.explosion.vanillant.standard.EntityProcessorCrossSmooth; -import com.hbm.explosion.vanillant.standard.ExplosionEffectStandard; +import com.hbm.explosion.vanillant.standard.ExplosionEffectWeapon; import com.hbm.explosion.vanillant.standard.PlayerProcessorStandard; import com.hbm.items.weapon.sedna.BulletConfig; import com.hbm.items.weapon.sedna.GunConfig; @@ -197,7 +197,7 @@ public class Lego { ExplosionVNT vnt = new ExplosionVNT(bullet.worldObj, mop.hitVec.xCoord, mop.hitVec.yCoord, mop.hitVec.zCoord, range); vnt.setEntityProcessor(new EntityProcessorCrossSmooth(1, bullet.damage)); vnt.setPlayerProcessor(new PlayerProcessorStandard()); - vnt.setSFX(new ExplosionEffectStandard()); + vnt.setSFX(new ExplosionEffectWeapon(10, 2.5F, 1F)); vnt.explode(); } diff --git a/src/main/java/com/hbm/items/weapon/sedna/factory/Orchestras.java b/src/main/java/com/hbm/items/weapon/sedna/factory/Orchestras.java index 7a6a5fe5e..d2f167c8e 100644 --- a/src/main/java/com/hbm/items/weapon/sedna/factory/Orchestras.java +++ b/src/main/java/com/hbm/items/weapon/sedna/factory/Orchestras.java @@ -2,13 +2,16 @@ package com.hbm.items.weapon.sedna.factory; import java.util.function.BiConsumer; +import com.hbm.config.ClientConfig; import com.hbm.items.weapon.sedna.ItemGunBaseNT; import com.hbm.items.weapon.sedna.Receiver; import com.hbm.items.weapon.sedna.ItemGunBaseNT.LambdaContext; import com.hbm.items.weapon.sedna.mags.IMagazine; +import com.hbm.main.MainRegistry; import com.hbm.particle.SpentCasing; import com.hbm.particle.helper.CasingCreator; import com.hbm.render.anim.HbmAnimations.AnimType; +import com.hbm.sound.AudioWrapper; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; @@ -20,6 +23,7 @@ public class Orchestras { public static BiConsumer DEBUG_ORCHESTRA = (stack, ctx) -> { EntityPlayer player = ctx.player; + if(player.worldObj.isRemote) return; AnimType type = ItemGunBaseNT.getLastAnim(stack, ctx.configIndex); int timer = ItemGunBaseNT.getAnimTimer(stack, ctx.configIndex); @@ -51,6 +55,7 @@ public class Orchestras { public static BiConsumer ORCHESTRA_PEPPERBOX = (stack, ctx) -> { EntityPlayer player = ctx.player; + if(player.worldObj.isRemote) return; AnimType type = ItemGunBaseNT.getLastAnim(stack, ctx.configIndex); int timer = ItemGunBaseNT.getAnimTimer(stack, ctx.configIndex); @@ -76,6 +81,7 @@ public class Orchestras { public static BiConsumer ORCHESTRA_ATLAS = (stack, ctx) -> { EntityPlayer player = ctx.player; + if(player.worldObj.isRemote) return; AnimType type = ItemGunBaseNT.getLastAnim(stack, ctx.configIndex); int timer = ItemGunBaseNT.getAnimTimer(stack, ctx.configIndex); @@ -103,6 +109,7 @@ public class Orchestras { public static BiConsumer ORCHESTRA_DANI = (stack, ctx) -> { EntityPlayer player = ctx.player; + if(player.worldObj.isRemote) return; AnimType type = ItemGunBaseNT.getLastAnim(stack, ctx.configIndex); int timer = ItemGunBaseNT.getAnimTimer(stack, ctx.configIndex); @@ -130,6 +137,7 @@ public class Orchestras { public static BiConsumer ORCHESTRA_HENRY = (stack, ctx) -> { EntityPlayer player = ctx.player; + if(player.worldObj.isRemote) return; AnimType type = ItemGunBaseNT.getLastAnim(stack, ctx.configIndex); int timer = ItemGunBaseNT.getAnimTimer(stack, ctx.configIndex); boolean aiming = ItemGunBaseNT.getIsAiming(stack); @@ -166,6 +174,7 @@ public class Orchestras { public static BiConsumer ORCHESTRA_GREASEGUN = (stack, ctx) -> { EntityPlayer player = ctx.player; + if(player.worldObj.isRemote) return; AnimType type = ItemGunBaseNT.getLastAnim(stack, ctx.configIndex); int timer = ItemGunBaseNT.getAnimTimer(stack, ctx.configIndex); boolean aiming = ItemGunBaseNT.getIsAiming(stack); @@ -201,6 +210,7 @@ public class Orchestras { public static BiConsumer ORCHESTRA_MARESLEG = (stack, ctx) -> { EntityPlayer player = ctx.player; + if(player.worldObj.isRemote) return; AnimType type = ItemGunBaseNT.getLastAnim(stack, ctx.configIndex); int timer = ItemGunBaseNT.getAnimTimer(stack, ctx.configIndex); boolean aiming = ItemGunBaseNT.getIsAiming(stack); @@ -235,6 +245,7 @@ public class Orchestras { public static BiConsumer ORCHESTRA_FLAREGUN = (stack, ctx) -> { EntityPlayer player = ctx.player; + if(player.worldObj.isRemote) return; AnimType type = ItemGunBaseNT.getLastAnim(stack, ctx.configIndex); int timer = ItemGunBaseNT.getAnimTimer(stack, ctx.configIndex); boolean aiming = ItemGunBaseNT.getIsAiming(stack); @@ -263,6 +274,7 @@ public class Orchestras { public static BiConsumer ORCHESTRA_NOPIP = (stack, ctx) -> { EntityPlayer player = ctx.player; + if(player.worldObj.isRemote) return; AnimType type = ItemGunBaseNT.getLastAnim(stack, ctx.configIndex); int timer = ItemGunBaseNT.getAnimTimer(stack, ctx.configIndex); @@ -294,6 +306,7 @@ public class Orchestras { public static BiConsumer ORCHESTRA_CARBIBE = (stack, ctx) -> { EntityPlayer player = ctx.player; + if(player.worldObj.isRemote) return; AnimType type = ItemGunBaseNT.getLastAnim(stack, ctx.configIndex); int timer = ItemGunBaseNT.getAnimTimer(stack, ctx.configIndex); boolean aiming = ItemGunBaseNT.getIsAiming(stack); @@ -327,38 +340,66 @@ public class Orchestras { public static BiConsumer ORCHESTRA_AM180 = (stack, ctx) -> { EntityPlayer player = ctx.player; + if(player.worldObj.isRemote) return; AnimType type = ItemGunBaseNT.getLastAnim(stack, ctx.configIndex); int timer = ItemGunBaseNT.getAnimTimer(stack, ctx.configIndex); boolean aiming = ItemGunBaseNT.getIsAiming(stack); - if(type == AnimType.CYCLE) { - if(timer == 0) { - SpentCasing casing = ctx.config.getReceivers(stack)[0].getMagazine(stack).getCasing(stack); - CasingCreator.composeEffect(player.worldObj, player, 0.4375, aiming ? 0 : -0.125, aiming ? 0 : -0.25D, 0, -0.06, 0, 0.01, casing.getName()); + if(ClientConfig.GUN_ANIMS_LEGACY.get()) { + if(type == AnimType.CYCLE) { + if(timer == 0) { + SpentCasing casing = ctx.config.getReceivers(stack)[0].getMagazine(stack).getCasing(stack); + CasingCreator.composeEffect(player.worldObj, player, 0.4375, aiming ? 0 : -0.125, aiming ? 0 : -0.25D, 0, -0.06, 0, 0.01, casing.getName()); + } + } + if(type == AnimType.CYCLE_DRY) { + if(timer == 0) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.dryFireClick", 1F, 1F); + if(timer == 6) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.pistolCock", 1F, 0.9F); + } + if(type == AnimType.RELOAD) { + if(timer == 2) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.magRemove", 1F, 1F); + if(timer == 20) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.impact", 0.25F, 1F); + if(timer == 32) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.magInsert", 1F, 1F); + if(timer == 40) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.pistolCock", 1F, 0.9F); + } + if(type == AnimType.JAMMED) { + if(timer == 15) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.pistolCock", 1F, 0.8F); + } + if(type == AnimType.INSPECT) { + if(timer == 2) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.magRemove", 1F, 1F); + if(timer == 35) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.magInsert", 1F, 1F); + } + } else { + if(type == AnimType.CYCLE) { + if(timer == 0) { + SpentCasing casing = ctx.config.getReceivers(stack)[0].getMagazine(stack).getCasing(stack); + CasingCreator.composeEffect(player.worldObj, player, 0.4375, aiming ? 0 : -0.125, aiming ? 0 : -0.25D, 0, -0.06, 0, 0.01, casing.getName()); + } + } + if(type == AnimType.CYCLE_DRY) { + if(timer == 0) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.dryFireClick", 1F, 1F); + if(timer == 6) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.pistolCock", 1F, 0.9F); + } + if(type == AnimType.RELOAD) { + if(timer == 6) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.magRemove", 1F, 1F); + if(timer == 26) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.impact", 0.25F, 1F); + if(timer == 48) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.magInsert", 1F, 1F); + if(timer == 54) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.pistolCock", 1F, 0.9F); + } + if(type == AnimType.JAMMED) { + if(timer == 6) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.pistolCock", 1F, 0.8F); + if(timer == 20) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.pistolCock", 1F, 1.0F); + } + if(type == AnimType.INSPECT) { + if(timer == 6) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.magRemove", 1F, 1F); + if(timer == 53) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.magInsert", 1F, 1F); } - } - if(type == AnimType.CYCLE_DRY) { - if(timer == 0) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.dryFireClick", 1F, 1F); - if(timer == 6) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.pistolCock", 1F, 0.9F); - } - if(type == AnimType.RELOAD) { - if(timer == 6) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.magRemove", 1F, 1F); - if(timer == 26) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.impact", 0.25F, 1F); - if(timer == 48) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.magInsert", 1F, 1F); - if(timer == 54) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.pistolCock", 1F, 0.9F); - } - if(type == AnimType.JAMMED) { - if(timer == 6) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.pistolCock", 1F, 0.8F); - if(timer == 20) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.pistolCock", 1F, 1.0F); - } - if(type == AnimType.INSPECT) { - if(timer == 6) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.magRemove", 1F, 1F); - if(timer == 53) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.magInsert", 1F, 1F); } }; public static BiConsumer ORCHESTRA_LIBERATOR = (stack, ctx) -> { EntityPlayer player = ctx.player; + if(player.worldObj.isRemote) return; AnimType type = ItemGunBaseNT.getLastAnim(stack, ctx.configIndex); int timer = ItemGunBaseNT.getAnimTimer(stack, ctx.configIndex); @@ -401,6 +442,7 @@ public class Orchestras { public static BiConsumer ORCHESTRA_CONGOLAKE = (stack, ctx) -> { EntityPlayer player = ctx.player; + if(player.worldObj.isRemote) return; AnimType type = ItemGunBaseNT.getLastAnim(stack, ctx.configIndex); int timer = ItemGunBaseNT.getAnimTimer(stack, ctx.configIndex); boolean aiming = ItemGunBaseNT.getIsAiming(stack); @@ -426,6 +468,33 @@ public class Orchestras { AnimType type = ItemGunBaseNT.getLastAnim(stack, ctx.configIndex); int timer = ItemGunBaseNT.getAnimTimer(stack, ctx.configIndex); + if(type == AnimType.CYCLE && player.worldObj.isRemote) { + AudioWrapper runningAudio = ItemGunBaseNT.loopedSounds.get(player); + + if(timer < 5) { + //start sound + if(runningAudio == null || !runningAudio.isPlaying()) { + AudioWrapper audio = MainRegistry.proxy.getLoopedSound("hbm:weapon.fire.flameLoop", (float) player.posX, (float) player.posY, (float) player.posZ, 1F, 15F, 1F, 10); + ItemGunBaseNT.loopedSounds.put(player, audio); + audio.startSound(); + } + //keepalive + if(runningAudio != null && runningAudio.isPlaying()) { + runningAudio.keepAlive(); + runningAudio.updatePosition((float) player.posX, (float) player.posY, (float) player.posZ); + } + } else { + //stop sound due to timeout + if(runningAudio != null && runningAudio.isPlaying()) runningAudio.stopSound(); + } + } + //stop sound due to state change + if(type != AnimType.CYCLE && player.worldObj.isRemote) { + AudioWrapper runningAudio = ItemGunBaseNT.loopedSounds.get(player); + if(runningAudio != null && runningAudio.isPlaying()) runningAudio.stopSound(); + } + if(player.worldObj.isRemote) return; + if(type == AnimType.RELOAD) { if(timer == 15) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.openLatch", 1F, 1F); if(timer == 35) player.worldObj.playSoundAtEntity(player, "hbm:weapon.reload.impact", 0.5F, 1F); diff --git a/src/main/java/com/hbm/items/weapon/sedna/factory/XFactory22lr.java b/src/main/java/com/hbm/items/weapon/sedna/factory/XFactory22lr.java index 1bf3fc8a4..6855837d1 100644 --- a/src/main/java/com/hbm/items/weapon/sedna/factory/XFactory22lr.java +++ b/src/main/java/com/hbm/items/weapon/sedna/factory/XFactory22lr.java @@ -3,6 +3,7 @@ package com.hbm.items.weapon.sedna.factory; import java.util.function.BiConsumer; import java.util.function.BiFunction; +import com.hbm.config.ClientConfig; import com.hbm.items.ModItems; import com.hbm.items.weapon.sedna.BulletConfig; import com.hbm.items.weapon.sedna.Crosshair; @@ -58,14 +59,39 @@ public class XFactory22lr { }; @SuppressWarnings("incomplete-switch") public static BiFunction LAMBDA_AM180_ANIMS = (stack, type) -> { - switch(type) { - case EQUIP: return new BusAnimation() - .addBus("EQUIP", new BusAnimationSequence().addPos(45, 0, 0, 0).addPos(0, 0, 0, 500, IType.SIN_FULL)); - case CYCLE: return ResourceManager.am180_anim.get("Fire"); - case CYCLE_DRY: return ResourceManager.am180_anim.get("FireDry"); - case RELOAD: return ResourceManager.am180_anim.get("Reload"); - case JAMMED: return ResourceManager.am180_anim.get("Jammed"); - case INSPECT: return ResourceManager.am180_anim.get("Inspect"); + if(ClientConfig.GUN_ANIMS_LEGACY.get()) { + switch(type) { + case EQUIP: return new BusAnimation() + .addBus("EQUIP", new BusAnimationSequence().addPos(45, 0, 0, 0).addPos(0, 0, 0, 500, IType.SIN_FULL)); + case CYCLE: return new BusAnimation() + .addBus("RECOIL", new BusAnimationSequence().addPos(0, 0, ItemGunBaseNT.getIsAiming(stack) ? -0.125 : -0.25, 15, IType.SIN_DOWN).addPos(0, 0, 0, 35, IType.SIN_FULL)); + case CYCLE_DRY: return new BusAnimation() + .addBus("BOLT", new BusAnimationSequence().addPos(0, 0, 0, 550).addPos(0, 0, -1.5, 100, IType.SIN_UP).addPos(0, 0, 0, 100, IType.SIN_UP)) + .addBus("TURN", new BusAnimationSequence().addPos(0, 0, 0, 300).addPos(0, 0, 15, 250, IType.SIN_FULL).addPos(0, 0, 15, 400).addPos(0, 0, 0, 250, IType.SIN_FULL)); + case RELOAD: + return new BusAnimation() + .addBus("MAGTURN", new BusAnimationSequence().addPos(15, 0, 0, 250, IType.SIN_FULL).addPos(15, 0, 0, 250).addPos(15, 0, 70, 300, IType.SIN_FULL).addPos(15, 0, 0, 0).addPos(15, 0, 0, 750).addPos(0, 0, 0, 250, IType.SIN_FULL)) + .addBus("MAG", new BusAnimationSequence().addPos(0, 0, 0, 250).addPos(2, 0, -4, 250, IType.SIN_FULL).addPos(-10, 2, -4, 300, IType.SIN_UP).addPos(3, -6, -4, 0).addPos(2, 0, -4, 500, IType.SIN_FULL).addPos(0, 0, 0, 250, IType.SIN_FULL)) + .addBus("BOLT", new BusAnimationSequence().addPos(0, 0, 0, 2250).addPos(0, 0, -1.5, 100, IType.SIN_UP).addPos(0, 0, 0, 100, IType.SIN_UP)) + .addBus("TURN", new BusAnimationSequence().addPos(0, 0, 0, 2000).addPos(0, 0, 15, 250, IType.SIN_FULL).addPos(0, 0, 15, 400).addPos(0, 0, 0, 250, IType.SIN_FULL)); + case JAMMED: return new BusAnimation() + .addBus("BOLT", new BusAnimationSequence().addPos(0, 0, 0, 750).addPos(0, 0, -1.5, 100, IType.SIN_UP).addPos(0, 0, 0, 100, IType.SIN_UP)) + .addBus("TURN", new BusAnimationSequence().addPos(0, 0, 0, 500).addPos(0, 0, 45, 250, IType.SIN_FULL).addPos(0, 0, 45, 400).addPos(0, 0, 0, 250, IType.SIN_FULL)); + case INSPECT: return new BusAnimation() + .addBus("MAGTURN", new BusAnimationSequence().addPos(15, 0, 0, 250, IType.SIN_FULL).addPos(15, 0, 0, 1400).addPos(0, 0, 0, 250, IType.SIN_FULL)) + .addBus("MAG", new BusAnimationSequence().addPos(0, 0, 0, 200).addPos(4, -1, -4, 200, IType.SIN_FULL).addPos(4, -1.5, -4, 50).addPos(4, 0, -4, 100).addPos(4, 6, -4, 250, IType.SIN_DOWN).addPos(4, 0, -4, 150, IType.SIN_UP).addPos(4, -1, -4, 100, IType.SIN_DOWN).addPos(4, -1, -4, 250).addPos(0, 0, 0, 250, IType.SIN_FULL)) + .addBus("MAGSPIN", new BusAnimationSequence().addPos(0, 0, 0, 600).addPos(-400, 0, 0, 500, IType.SIN_FULL).addPos(-400, 0, 0, 250).addPos(-360, 0, 0, 250)); + } + } else { + switch(type) { + case EQUIP: return new BusAnimation() + .addBus("EQUIP", new BusAnimationSequence().addPos(45, 0, 0, 0).addPos(0, 0, 0, 500, IType.SIN_FULL)); + case CYCLE: return ResourceManager.am180_anim.get("Fire"); + case CYCLE_DRY: return ResourceManager.am180_anim.get("FireDry"); + case RELOAD: return ResourceManager.am180_anim.get("Reload"); + case JAMMED: return ResourceManager.am180_anim.get("Jammed"); + case INSPECT: return ResourceManager.am180_anim.get("Inspect"); + } } return null; diff --git a/src/main/java/com/hbm/main/ClientProxy.java b/src/main/java/com/hbm/main/ClientProxy.java index b34266158..4732f0370 100644 --- a/src/main/java/com/hbm/main/ClientProxy.java +++ b/src/main/java/com/hbm/main/ClientProxy.java @@ -980,14 +980,6 @@ public class ClientProxy extends ServerProxy { } } - public static HashMap particleCreators = new HashMap(); - - static { - particleCreators.put("explosionLarge", new ExplosionCreator()); - particleCreators.put("casingNT", new CasingCreator()); - particleCreators.put("flamethrower", new FlameCreator()); - } - //mk3, only use this one @Override public void effectNT(NBTTagCompound data) { @@ -1006,8 +998,8 @@ public class ClientProxy extends ServerProxy { double y = data.getDouble("posY"); double z = data.getDouble("posZ"); - if(particleCreators.containsKey(type)) { - particleCreators.get(type).makeParticle(world, player, man, rand, x, y, z, data); + if(ParticleCreators.particleCreators.containsKey(type)) { + ParticleCreators.particleCreators.get(type).makeParticle(world, player, man, rand, x, y, z, data); return; } diff --git a/src/main/java/com/hbm/particle/EntityFXRotating.java b/src/main/java/com/hbm/particle/EntityFXRotating.java index 16dcfd7b4..0c05cd9ca 100644 --- a/src/main/java/com/hbm/particle/EntityFXRotating.java +++ b/src/main/java/com/hbm/particle/EntityFXRotating.java @@ -4,6 +4,7 @@ import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import net.minecraft.client.particle.EntityFX; import net.minecraft.client.renderer.Tessellator; +import net.minecraft.util.Vec3; import net.minecraft.world.World; @SideOnly(Side.CLIENT) @@ -41,6 +42,11 @@ public class EntityFXRotating extends EntityFX { double nX = ((y2 - y1) * (z3 - z1)) - ((z2 - z1) * (y3 - y1)); double nY = ((z2 - z1) * (x3 - x1)) - ((x2 - x1) * (z3 - z1)); double nZ = ((x2 - x1) * (y3 - y1)) - ((y2 - y1) * (x3 - x1)); + + Vec3 vec = Vec3.createVectorHelper(nX, nY, nZ).normalize(); + nX = vec.xCoord; + nY = vec.yCoord; + nZ = vec.zCoord; double cosTh = Math.cos(rotation * Math.PI / 180D); double sinTh = Math.sin(rotation * Math.PI / 180D); diff --git a/src/main/java/com/hbm/particle/ParticleExplosionSmall.java b/src/main/java/com/hbm/particle/ParticleExplosionSmall.java new file mode 100644 index 000000000..18c7158bd --- /dev/null +++ b/src/main/java/com/hbm/particle/ParticleExplosionSmall.java @@ -0,0 +1,80 @@ +package com.hbm.particle; + +import java.awt.Color; + +import com.hbm.main.ModEventHandlerClient; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.util.MathHelper; +import net.minecraft.world.World; + +@SideOnly(Side.CLIENT) +public class ParticleExplosionSmall extends EntityFXRotating { + + public float hue; + + public ParticleExplosionSmall(World world, double x, double y, double z, float scale, float speedMult) { + super(world, x, y, z); + particleIcon = ModEventHandlerClient.particleBase; + this.particleMaxAge = 25 + rand.nextInt(10); + this.particleScale = scale * 0.9F + rand.nextFloat() * 0.2F; + + this.motionX = world.rand.nextGaussian() * speedMult; + this.motionZ = world.rand.nextGaussian() * speedMult; + + this.particleGravity = rand.nextFloat() * -0.01F; + + this.hue = 20F + rand.nextFloat() * 20F; + Color color = Color.getHSBColor(hue / 255F, 1F, 1F); + this.particleRed = color.getRed() / 255F; + this.particleGreen = color.getGreen() / 255F; + this.particleBlue = color.getBlue() / 255F; + + this.noClip = true; + } + + @Override + public void onUpdate() { + this.prevPosX = this.posX; + this.prevPosY = this.posY; + this.prevPosZ = this.posZ; + + this.particleAge++; + + if(this.particleAge >= this.particleMaxAge) { + this.setDead(); + } + + this.motionY -= particleGravity; + this.prevRotationPitch = this.rotationPitch; + + float ageScaled = (float) this.particleAge / (float) this.particleMaxAge; + this.rotationPitch += (1 - ageScaled) * 5 * ((this.getEntityId() % 2) - 0.5); + + this.motionX *= 0.65D; + this.motionZ *= 0.65D; + + this.moveEntity(this.motionX, this.motionY, this.motionZ); + } + + @Override + public void renderParticle(Tessellator tess, float interp, float sX, float sY, float sZ, float dX, float dZ) { + + double ageScaled = (double) (this.particleAge + interp) / (double) this.particleMaxAge; + + Color color = Color.getHSBColor(hue / 255F, Math.max(1F - (float) ageScaled * 2F, 0), MathHelper.clamp_float(1.25F - (float) ageScaled * 2F, hue * 0.01F - 0.1F, 1F)); + this.particleRed = color.getRed() / 255F; + this.particleGreen = color.getGreen() / 255F; + this.particleBlue = color.getBlue() / 255F; + + this.particleAlpha = (float) Math.pow(1 - Math.min(ageScaled, 1), 0.25); + + tess.setColorRGBA_F(this.particleRed, this.particleGreen, this.particleBlue, this.particleAlpha * 0.5F); + tess.setNormal(0.0F, 1.0F, 0.0F); + + double scale = (0.25 + 1 - Math.pow(1 - ageScaled, 4) + (this.particleAge + interp) * 0.02) * this.particleScale; + renderParticleRotated(tess, interp, sX, sY, sZ, dX, dZ, scale); + } +} diff --git a/src/main/java/com/hbm/particle/ParticleFlamethrower.java b/src/main/java/com/hbm/particle/ParticleFlamethrower.java index 3cadf6f22..cc11601ba 100644 --- a/src/main/java/com/hbm/particle/ParticleFlamethrower.java +++ b/src/main/java/com/hbm/particle/ParticleFlamethrower.java @@ -62,7 +62,7 @@ public class ParticleFlamethrower extends EntityFXRotating { tess.setNormal(0.0F, 1.0F, 0.0F); tess.setBrightness(240); - double scale = (ageScaled * 0.75 + 0.5) * particleScale; + double scale = (ageScaled * 1.25 + 0.25) * particleScale; renderParticleRotated(tess, interp, sX, sY, sZ, dX, dZ, scale); } diff --git a/src/main/java/com/hbm/particle/helper/ExplosionSmallCreator.java b/src/main/java/com/hbm/particle/helper/ExplosionSmallCreator.java new file mode 100644 index 000000000..b271f80f6 --- /dev/null +++ b/src/main/java/com/hbm/particle/helper/ExplosionSmallCreator.java @@ -0,0 +1,61 @@ +package com.hbm.particle.helper; + +import java.util.Random; + +import com.hbm.particle.ParticleExplosionSmall; + +import cpw.mods.fml.relauncher.ReflectionHelper; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.particle.EntityBlockDustFX; +import net.minecraft.client.particle.EntityFX; +import net.minecraft.client.renderer.texture.TextureManager; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.World; +import net.minecraftforge.common.util.ForgeDirection; + +public class ExplosionSmallCreator implements IParticleCreator { + + public static void composeEffect(World world, double x, double y, double z, int cloudCount, float cloudScale, float cloudSpeedMult) { + + NBTTagCompound data = new NBTTagCompound(); + data.setString("type", "explosionSmall"); + data.setInteger("cloudCount", cloudCount); + data.setFloat("cloudScale", cloudScale); + data.setFloat("cloudSpeedMult", cloudSpeedMult); + data.setInteger("debris", 15); + IParticleCreator.sendPacket(world, x, y, z, 150, data); + } + + @Override + public void makeParticle(World world, EntityPlayer player, TextureManager texman, Random rand, double x, double y, double z, NBTTagCompound data) { + + int cloudCount = data.getInteger("cloudCount"); + float cloudScale = data.getFloat("cloudScale"); + float cloudSpeedMult = data.getFloat("cloudSpeedMult"); + int debris = data.getInteger("debris"); + + for(int i = 0; i < cloudCount; i++) { + ParticleExplosionSmall particle = new ParticleExplosionSmall(world, x, y, z, cloudScale, cloudSpeedMult); + Minecraft.getMinecraft().effectRenderer.addEffect(particle); + } + + Block b = Blocks.air; + int meta = 0; + + for(ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) { + b = world.getBlock((int) Math.floor(x) + dir.offsetX, (int) Math.floor(y) + dir.offsetY, (int) Math.floor(z) + dir.offsetZ); + meta = world.getBlockMetadata((int) Math.floor(x) + dir.offsetX, (int) Math.floor(y) + dir.offsetY, (int) Math.floor(z) + dir.offsetZ); + if(b != Blocks.air) break; + } + + if(b != Blocks.air) for(int i = 0; i < debris; i++) { + EntityBlockDustFX fx = new EntityBlockDustFX(world, x, y + 0.1, z, world.rand.nextGaussian() * 0.2, 0.5F + world.rand.nextDouble() * 0.7, world.rand.nextGaussian() * 0.2, b, meta); + fx.multipleParticleScaleBy(2); + ReflectionHelper.setPrivateValue(EntityFX.class, fx, 50 + rand.nextInt(20), "particleMaxAge", "field_70547_e"); + Minecraft.getMinecraft().effectRenderer.addEffect(fx); + } + } +} diff --git a/src/main/java/com/hbm/particle/helper/ParticleCreators.java b/src/main/java/com/hbm/particle/helper/ParticleCreators.java new file mode 100644 index 000000000..84df3293b --- /dev/null +++ b/src/main/java/com/hbm/particle/helper/ParticleCreators.java @@ -0,0 +1,15 @@ +package com.hbm.particle.helper; + +import java.util.HashMap; + +public class ParticleCreators { + + public static HashMap particleCreators = new HashMap(); + + static { + particleCreators.put("explosionLarge", new ExplosionCreator()); + particleCreators.put("casingNT", new CasingCreator()); + particleCreators.put("flamethrower", new FlameCreator()); + particleCreators.put("explosionSmall", new ExplosionSmallCreator()); + } +} diff --git a/src/main/java/com/hbm/render/item/weapon/sedna/ItemRenderFlamer.java b/src/main/java/com/hbm/render/item/weapon/sedna/ItemRenderFlamer.java index 2cdf914fb..31b63e608 100644 --- a/src/main/java/com/hbm/render/item/weapon/sedna/ItemRenderFlamer.java +++ b/src/main/java/com/hbm/render/item/weapon/sedna/ItemRenderFlamer.java @@ -72,7 +72,9 @@ public class ItemRenderFlamer extends ItemRenderWeaponBase { @Override public void setupThirdPerson(ItemStack stack) { super.setupThirdPerson(stack); - GL11.glTranslated(0, 1, 3); + double scale = 1.75D; + GL11.glScaled(scale, scale, scale); + GL11.glTranslated(0, -3, 4); } diff --git a/src/main/java/com/hbm/render/item/weapon/sedna/ItemRenderWeaponBase.java b/src/main/java/com/hbm/render/item/weapon/sedna/ItemRenderWeaponBase.java index 7212aa842..926ac4295 100644 --- a/src/main/java/com/hbm/render/item/weapon/sedna/ItemRenderWeaponBase.java +++ b/src/main/java/com/hbm/render/item/weapon/sedna/ItemRenderWeaponBase.java @@ -213,7 +213,7 @@ public abstract class ItemRenderWeaponBase implements IItemRenderer { GL11.glRotatef(15.0F, 0.0F, 0.0F, 1.0F); GL11.glRotatef(12.5F, 0.0F, 1.0F, 0.0F); - GL11.glRotatef(10.0F, 1.0F, 0.0F, 0.0F); + GL11.glRotatef(15.0F, 1.0F, 0.0F, 0.0F); GL11.glTranslated(3.5, 0, 0); diff --git a/src/main/resources/assets/hbm/sounds.json b/src/main/resources/assets/hbm/sounds.json index 543f67a45..39632d3cf 100644 --- a/src/main/resources/assets/hbm/sounds.json +++ b/src/main/resources/assets/hbm/sounds.json @@ -223,6 +223,7 @@ "weapon.switchmode2": {"category": "player", "sounds": [{"name": "weapon/switchmode2", "stream": false}]}, "weapon.fire.blackPowder": {"category": "player", "sounds": [{"name": "weapon/fire/blackPowder", "stream": false}]}, + "weapon.fire.flameLoop": {"category": "player", "sounds": [{"name": "weapon/fire/flameLoop", "stream": false}]}, "weapon.reload.boltClose": {"category": "player", "sounds": ["weapon/reload/boltClose"]}, "weapon.reload.boltOpen": {"category": "player", "sounds": ["weapon/reload/boltOpen"]}, diff --git a/src/main/resources/assets/hbm/sounds/weapon/fire/flameLoop.ogg b/src/main/resources/assets/hbm/sounds/weapon/fire/flameLoop.ogg new file mode 100644 index 0000000000000000000000000000000000000000..8d282277946be93a022f1a85c286cafca2e020f4 GIT binary patch literal 13920 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 literal 0 HcmV?d00001