diff --git a/src/client/java/com/virus5600/defensive_measures/model/entity/CannonTurretModel.java b/src/client/java/com/virus5600/defensive_measures/model/entity/CannonTurretModel.java index 9e8e287..c4fe1ce 100644 --- a/src/client/java/com/virus5600/defensive_measures/model/entity/CannonTurretModel.java +++ b/src/client/java/com/virus5600/defensive_measures/model/entity/CannonTurretModel.java @@ -17,9 +17,9 @@ @Environment(EnvType.CLIENT) public class CannonTurretModel extends GeoModel { - /////////////////////// - // INTERFACE METHODS // - /////////////////////// + ///////////////////////// + /// INTERFACE METHODS /// + ///////////////////////// @Override public Identifier getModelResource(CannonTurretEntity cannonTurretEntity, @Nullable GeoRenderer geoRenderer) { @@ -62,9 +62,4 @@ public void setCustomAnimations(CannonTurretEntity animatable, long instanceId, base.get().setRotZ(0); } } - - /* - * TODO: Consult Discord Servers for potential issue why this is thrown specifically when placed on Lightning Rods: - * [09:11:45] [Netty Server IO #1/ERROR] (Minecraft) Error sending packet clientbound/minecraft:set_entity_data - */ } diff --git a/src/client/java/com/virus5600/defensive_measures/model/projectiles/CannonballModel.java b/src/client/java/com/virus5600/defensive_measures/model/projectiles/CannonballModel.java new file mode 100644 index 0000000..d8383e3 --- /dev/null +++ b/src/client/java/com/virus5600/defensive_measures/model/projectiles/CannonballModel.java @@ -0,0 +1,35 @@ +package com.virus5600.defensive_measures.model.projectiles; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.util.Identifier; + +import org.jetbrains.annotations.Nullable; + +import software.bernie.geckolib.model.GeoModel; +import software.bernie.geckolib.renderer.GeoRenderer; + +import com.virus5600.defensive_measures.DefensiveMeasures; +import com.virus5600.defensive_measures.entity.projectiles.CannonballEntity; + +@Environment(EnvType.CLIENT) +public class CannonballModel extends GeoModel { + ///////////////////////// + /// INTERFACE METHODS /// + ///////////////////////// + + @Override + public Identifier getModelResource(CannonballEntity cannonballEntity, @Nullable GeoRenderer geoRenderer) { + return Identifier.of(DefensiveMeasures.MOD_ID, "geo/projectiles/cannonball.geo.json"); + } + + @Override + public Identifier getTextureResource(CannonballEntity cannonballEntity, @Nullable GeoRenderer geoRenderer) { + return Identifier.of(DefensiveMeasures.MOD_ID, "textures/entity/cannon_turret/cannonball.png"); + } + + @Override + public Identifier getAnimationResource(CannonballEntity animatable) { + return null; + } +} diff --git a/src/client/java/com/virus5600/defensive_measures/renderer/ModEntityRenderer.java b/src/client/java/com/virus5600/defensive_measures/renderer/ModEntityRenderer.java index 07dd322..dcada41 100644 --- a/src/client/java/com/virus5600/defensive_measures/renderer/ModEntityRenderer.java +++ b/src/client/java/com/virus5600/defensive_measures/renderer/ModEntityRenderer.java @@ -3,6 +3,7 @@ import com.virus5600.defensive_measures.DefensiveMeasures; import com.virus5600.defensive_measures.entity.ModEntities; import com.virus5600.defensive_measures.renderer.entity.CannonTurretRenderer; +import com.virus5600.defensive_measures.renderer.projectiles.CannonballRenderer; import net.fabricmc.fabric.api.client.rendering.v1.EntityRendererRegistry; public class ModEntityRenderer { @@ -15,5 +16,12 @@ public static void registerEntityRenderers() { // v1.0.0 EntityRendererRegistry.register(ModEntities.CANNON_TURRET, CannonTurretRenderer::new); + + ///////////////// + // PROJECTILES // + ///////////////// + + // v1.0.0 + EntityRendererRegistry.register(ModEntities.CANNONBALL, CannonballRenderer::new); } } diff --git a/src/client/java/com/virus5600/defensive_measures/renderer/projectiles/CannonballRenderer.java b/src/client/java/com/virus5600/defensive_measures/renderer/projectiles/CannonballRenderer.java new file mode 100644 index 0000000..e79bff8 --- /dev/null +++ b/src/client/java/com/virus5600/defensive_measures/renderer/projectiles/CannonballRenderer.java @@ -0,0 +1,22 @@ +package com.virus5600.defensive_measures.renderer.projectiles; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import net.minecraft.client.render.entity.EntityRendererFactory.Context; +import software.bernie.geckolib.renderer.GeoEntityRenderer; + +import com.virus5600.defensive_measures.entity.projectiles.CannonballEntity; +import com.virus5600.defensive_measures.model.projectiles.CannonballModel; + +@Environment(EnvType.CLIENT) +public class CannonballRenderer extends GeoEntityRenderer { + public CannonballRenderer(Context ctx) { + super(ctx, new CannonballModel()); + } + + @Override + protected float getDeathMaxRotation(CannonballEntity animatable, float partialTick) { + return 0.0f; + } +} diff --git a/src/main/java/com/virus5600/defensive_measures/entity/ModEntities.java b/src/main/java/com/virus5600/defensive_measures/entity/ModEntities.java index 7c004c2..4e33776 100644 --- a/src/main/java/com/virus5600/defensive_measures/entity/ModEntities.java +++ b/src/main/java/com/virus5600/defensive_measures/entity/ModEntities.java @@ -2,30 +2,25 @@ import com.virus5600.defensive_measures.DefensiveMeasures; -import com.virus5600.defensive_measures.entity.turrets.CannonTurretEntity; +import com.virus5600.defensive_measures.entity.projectiles.*; +import com.virus5600.defensive_measures.entity.turrets.*; +import com.virus5600.defensive_measures.util.RegistryUtil; import net.fabricmc.fabric.api.object.builder.v1.entity.FabricDefaultAttributeRegistry; import net.minecraft.entity.EntityType; import net.minecraft.entity.EntityType.Builder; import net.minecraft.entity.SpawnGroup; -import net.minecraft.registry.Registries; -import net.minecraft.registry.Registry; -import net.minecraft.registry.RegistryKey; -import net.minecraft.registry.RegistryKeys; -import net.minecraft.util.Identifier; public class ModEntities { // TURRETS // // v1.0.0 - public static final EntityType CANNON_TURRET = Registry.register( - Registries.ENTITY_TYPE, - Identifier.of(DefensiveMeasures.MOD_ID, "cannon_turret"), + public static final EntityType CANNON_TURRET = RegistryUtil.registerEntity( + "cannon_turret", Builder .create(CannonTurretEntity::new, SpawnGroup.MISC) .dimensions(1F, 1F) .eyeHeight(0.51F) - .build(RegistryKey.of(RegistryKeys.ENTITY_TYPE, Identifier.of(DefensiveMeasures.MOD_ID, "cannon_turret"))) ); // public static final EntityType BALLISTA = Registry.register( @@ -48,14 +43,15 @@ public class ModEntities { // PROJECTILES // // v1.0.0 -// public static final EntityType CANNONBALL = Registry.register( -// Registries.ENTITY_TYPE, -// Identifier.of(DefensiveMeasures.MOD_ID, "cannonball"), -// Builder -// .create(CannonballEntity::new, SpawnGroup.MISC) -// .dimensions(EntityDimensions.fixed(0.125f, 0.125f)) -// .build() -// ); + public static final EntityType CANNONBALL = RegistryUtil.registerEntity( + "cannonball", + Builder + .create(CannonballEntity::new, SpawnGroup.MISC) + .dropsNothing() + .dimensions(0.125f, 0.125f) + .maxTrackingRange(4) + .trackingTickInterval(10) + ); // public static final EntityType BALLISTA_ARROW = Registry.register( // Registries.ENTITY_TYPE, diff --git a/src/main/java/com/virus5600/defensive_measures/entity/projectiles/CannonballEntity.java b/src/main/java/com/virus5600/defensive_measures/entity/projectiles/CannonballEntity.java new file mode 100644 index 0000000..5578869 --- /dev/null +++ b/src/main/java/com/virus5600/defensive_measures/entity/projectiles/CannonballEntity.java @@ -0,0 +1,188 @@ +package com.virus5600.defensive_measures.entity.projectiles; + +import net.minecraft.entity.EntityType; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.damage.DamageSource; +import net.minecraft.entity.projectile.ExplosiveProjectileEntity; +import net.minecraft.particle.ParticleEffect; +import net.minecraft.particle.ParticleTypes; +import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.sound.SoundEvent; +import net.minecraft.sound.SoundEvents; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.hit.EntityHitResult; +import net.minecraft.util.hit.HitResult; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.World; +import net.minecraft.world.explosion.ExplosionBehavior; + +import software.bernie.geckolib.animatable.GeoEntity; +import software.bernie.geckolib.animatable.instance.AnimatableInstanceCache; +import software.bernie.geckolib.animation.AnimatableManager.ControllerRegistrar; +import software.bernie.geckolib.util.GeckoLibUtil; + +import com.virus5600.defensive_measures.entity.ModEntities; + +public class CannonballEntity extends ExplosiveProjectileEntity implements GeoEntity { + private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this); + private LivingEntity shooter; + + //////////////////// + /// CONSTRUCTORS /// + //////////////////// + public CannonballEntity(EntityType entityType, World world) { + super(entityType, world); + this.setFireTicks(0); + this.setOnFire(false); + this.setNoGravity(false); + } + + public CannonballEntity(World world, LivingEntity owner) { + this(ModEntities.CANNONBALL, world); + this.setOwner(owner); + } + + public CannonballEntity(LivingEntity owner, double directionX, double directionY, double directionZ, World world) { + this(world, owner); + this.setVelocity(directionX, directionY, directionZ); + } + + /////////////// + /// METHODS /// + /////////////// + // PROTECTED + @Override + protected void onBlockHit(BlockHitResult blockHitResult) { + super.onBlockHit(blockHitResult); + + if (!this.getWorld().isClient) { + this.doDamage(); + } + } + + @Override + protected void onEntityHit(EntityHitResult entityHitResult) { + if (!this.getWorld().isClient) { + this.doDamage(); + } + } + + @Override + protected boolean isBurning() { + return false; + } + + @Override + protected ParticleEffect getParticleType() { + return ParticleTypes.CLOUD; + } + + @Override + protected void onCollision(HitResult hitResult) { + super.onCollision(hitResult); + if (!this.getWorld().isClient) { + this.doDamage(); + } + } + + protected RegistryEntry.Reference getHitSound() { + return SoundEvents.ENTITY_GENERIC_EXPLODE; + } + + // PUBLIC + private double radius = 0; + public void doDamage() { + // Create damage source + DamageSource dmgSrc = this.getDamageSources().explosion( + this, + this.getOwner() == null ? this : this.getOwner() + ); + + // Create explosion + this.getWorld() + .createExplosion( + this, + dmgSrc, + new ExplosionBehavior(), + this.getX(), + this.getBodyY(0.0625), + this.getZ(), + 1.25F, + false, + World.ExplosionSourceType.NONE + ); + + // Damage entities within a 4 block radius + double maxEffectiveDmgRad = 2; + double maxDmgRad = 4; + double dmgReduction = 3.75; + double baseDmg = 10; + + for (radius = 0; radius < maxDmgRad; radius += 0.25) { + if (radius < maxEffectiveDmgRad) radius += 0.75; + + double x1 = MathHelper.floor(this.getX() - radius - 1.0D); + double x2 = MathHelper.floor(this.getX() + radius + 1.0D); + double y1 = MathHelper.floor(this.getY() - radius - 1.0D); + double y2 = MathHelper.floor(this.getY() + radius + 1.0D); + double z1 = MathHelper.floor(this.getZ() - radius - 1.0D); + double z3 = MathHelper.floor(this.getZ() + radius + 1.0D); + + this.getWorld() + .getOtherEntities( + this, + new Box(x1, y1, z1, x2, y2, z3) + ) + .forEach(entity -> { + float dmg = (float) baseDmg; + + if (radius > maxEffectiveDmgRad) { + dmg -= (float) (dmgReduction * (radius - maxEffectiveDmgRad)); + } + + if (entity instanceof LivingEntity) { + entity.damage( + (ServerWorld) this.getWorld(), + dmgSrc, + dmg + ); + } + }); + } + + this.discard(); + } + + @Override + public void tick() { + super.tick(); + + double acceleration = 0.08; + if (!this.hasNoGravity()) { + this.setVelocity( + this.getVelocity() + .add( + 0, + -acceleration / 4.0, + 0 + ) + ); + } + } + + ///////////////////////////////// + /// INTERFACE IMPLEMENTATIONS /// + ///////////////////////////////// + + // GeoEntity // + @Override + public void registerControllers(final ControllerRegistrar controllers) { + } + + @Override + public AnimatableInstanceCache getAnimatableInstanceCache() { + return this.geoCache; + } +} diff --git a/src/main/java/com/virus5600/defensive_measures/entity/turrets/CannonTurretEntity.java b/src/main/java/com/virus5600/defensive_measures/entity/turrets/CannonTurretEntity.java index 9412319..29c8497 100644 --- a/src/main/java/com/virus5600/defensive_measures/entity/turrets/CannonTurretEntity.java +++ b/src/main/java/com/virus5600/defensive_measures/entity/turrets/CannonTurretEntity.java @@ -40,6 +40,7 @@ import com.virus5600.defensive_measures.entity.TurretMaterial; import com.virus5600.defensive_measures.entity.ai.goal.ProjectileAttackGoal; import com.virus5600.defensive_measures.entity.ai.goal.TargetOtherTeamGoal; +import com.virus5600.defensive_measures.entity.projectiles.CannonballEntity; import com.virus5600.defensive_measures.item.ModItems; import com.virus5600.defensive_measures.particle.ModParticles; import com.virus5600.defensive_measures.sound.ModSoundEvents; @@ -120,9 +121,7 @@ public void shootAt(LivingEntity target, float pullProgress) { double vz = (target.getZ() - this.getZ()) * 1.0625; double variance = Math.sqrt(vx * vx + vz * vz); float divergence = this.getWorld().getDifficulty().getId() * 2; -// ProjectileEntity projectile = new CannonballEntity(ModEntities.CANNONBALL, this, vx, vy, vz, this.getWorld()); - ProjectileEntity projectile = new ArrowEntity(EntityType.ARROW, this.getWorld()); - projectile.setOwner(this); + ProjectileEntity projectile = new CannonballEntity(this, vx, vy, vz, this.getWorld()); projectile.setPos(this.getX(), this.getY() + 0.5, this.getZ()); projectile.setVelocity(vx, vy + variance * 0.1f, vz, 1.5f, divergence); diff --git a/src/main/java/com/virus5600/defensive_measures/sound/ModSoundEvents.java b/src/main/java/com/virus5600/defensive_measures/sound/ModSoundEvents.java index 507e31d..d839064 100644 --- a/src/main/java/com/virus5600/defensive_measures/sound/ModSoundEvents.java +++ b/src/main/java/com/virus5600/defensive_measures/sound/ModSoundEvents.java @@ -12,7 +12,7 @@ public class ModSoundEvents { // V1.0 public final static SoundEvent TURRET_REMOVED_METAL = ModSoundEvents.registerSoundEvent("turret.remove.metal"); public final static SoundEvent TURRET_REMOVED_WOOD = ModSoundEvents.registerSoundEvent("turret.remove.wood"); - public final static SoundEvent TURRET_REPAIR_METAL = ModSoundEvents.registerSoundEvent("turret.repair.iron"); + public final static SoundEvent TURRET_REPAIR_METAL = ModSoundEvents.registerSoundEvent("turret.repair.metal"); public final static SoundEvent TURRET_REPAIR_WOOD = ModSoundEvents.registerSoundEvent("turret.repair.wood"); public final static SoundEvent TURRET_REPAIR_BOW = ModSoundEvents.registerSoundEvent("turret.repair.bow"); diff --git a/src/main/java/com/virus5600/defensive_measures/util/RegistryUtil.java b/src/main/java/com/virus5600/defensive_measures/util/RegistryUtil.java index 8fd0ab4..a300173 100644 --- a/src/main/java/com/virus5600/defensive_measures/util/RegistryUtil.java +++ b/src/main/java/com/virus5600/defensive_measures/util/RegistryUtil.java @@ -4,6 +4,8 @@ import net.minecraft.block.AbstractBlock; import net.minecraft.block.Block; import net.minecraft.block.Blocks; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; import net.minecraft.item.Item; import net.minecraft.item.Items; import net.minecraft.registry.Registries; @@ -52,4 +54,19 @@ public static Item registerItem(String path, Function facto public static Item registerItem(String path, Function factory) { return Items.register(createItemKey(path), factory); } + + // Entity Registry + private static RegistryKey> createEntityKey(String path) { + return RegistryKey.of(RegistryKeys.ENTITY_TYPE, Identifier.of(DefensiveMeasures.MOD_ID, path)); + } + + public static EntityType registerEntity(String path, EntityType.Builder builder) { + RegistryKey> key = createEntityKey(path); + + return Registry.register( + Registries.ENTITY_TYPE, + key, + builder.build(key) + ); + } } diff --git a/src/main/resources/assets/dm/geo/projectiles/cannonball.geo.json b/src/main/resources/assets/dm/geo/projectiles/cannonball.geo.json new file mode 100644 index 0000000..02f4563 --- /dev/null +++ b/src/main/resources/assets/dm/geo/projectiles/cannonball.geo.json @@ -0,0 +1,27 @@ +{ + "format_version": "1.12.0", + "minecraft:geometry": [ + { + "description": { + "identifier": "geometry.cannonball", + "texture_width": 64, + "texture_height": 64, + "visible_bounds_width": 2, + "visible_bounds_height": 1.5, + "visible_bounds_offset": [0, 0.25, 0] + }, + "bones": [ + { + "name": "body", + "pivot": [0, 3, 0], + "cubes": [ + {"origin": [-2, 1, -2], "size": [4, 4, 4], "uv": [0, 0]}, + {"origin": [-1, 2, -3], "size": [2, 2, 6], "uv": [0, 0]}, + {"origin": [-3, 2, -1], "size": [6, 2, 2], "uv": [0, 2]}, + {"origin": [-1, 0, -1], "size": [2, 6, 2], "uv": [0, 0]} + ] + } + ] + } + ] +} diff --git a/src/main/resources/assets/dm/lang/en_us.json b/src/main/resources/assets/dm/lang/en_us.json index 7a59090..1cfbc6d 100644 --- a/src/main/resources/assets/dm/lang/en_us.json +++ b/src/main/resources/assets/dm/lang/en_us.json @@ -27,7 +27,7 @@ "item.dm.machine_gun_stand" : "MG Stand", "item.dm.mg_turret" : "Place MG Turret", - "itemTooltip.dm.cannon_turret.line1" : "Range: 20 blocks", + "itemTooltip.dm.cannon_turret.line1" : "Range: 16 blocks", "itemTooltip.dm.cannon_turret.line2" : "Damage: 10", "itemTooltip.dm.cannon_turret.line3" : "Reload Time: 2 seconds", @@ -40,7 +40,7 @@ "entity.dm.mg_turret" : "MG Turret", "entity.dm.mg_bullet" : "MG Bullet", - "death.attack.arrowhead" : "%1$s stepepd on an Arrowhead", + "death.attack.arrowhead" : "%1$s stepped on an Arrowhead", "death.attack.arrowhead.player" : "%1$s stepped on a random Arrowhead whilst fighting with %2$s", "subtitles.turret.remove.metal" : "Metallic Turret Removed", diff --git a/src/main/resources/assets/dm/sounds.json b/src/main/resources/assets/dm/sounds.json index 268639d..2754f03 100644 --- a/src/main/resources/assets/dm/sounds.json +++ b/src/main/resources/assets/dm/sounds.json @@ -3,9 +3,7 @@ "sounds": [ "dm:turrets/bullet_impacts/bullet_impact_dirt1", "dm:turrets/bullet_impacts/bullet_impact_dirt2", - "dm:turrets/bullet_impacts/bullet_impact_dirt3", - "dm:turrets/bullet_impacts/bullet_impact_dirt4", - "dm:turrets/bullet_impacts/bullet_impact_dirt5" + "dm:turrets/bullet_impacts/bullet_impact_dirt3" ], "subtitle": "subtitles.generic.impact.bullet.dirt" }, @@ -83,28 +81,29 @@ ], "subtitle": "subtitles.turret.remove.wood" }, - "turret.iron.repair": { + "turret.repair.metal": { "sounds": [ { - "name": "mob/irongolem/repair", - "volume": 0.8 + "name": "dm:turrets/repair/metal_repair1", + "volume": 0.8, + "pitch": 1 }, { - "name": "mob/irongolem/repair", - "pitch": 0.8, - "volume": 0.8 + "name": "dm:turrets/repair/metal_repair2", + "volume": 0.8, + "pitch": 0.8 } ], "subtitle": "subtitles.turret.iron.repair" }, - "turret.bow.repair": { + "turret.repair.bow": { "sounds": [ "block/fletching_table/fletching_table1", "block/fletching_table/fletching_table2" ], "subtitle": "subtitles.turret.bow.repair" }, - "turret.wood.repair": { + "turret.repair.wood": { "sounds": [ "dm:turrets/repair/wood_repair1", "dm:turrets/repair/wood_repair2" @@ -254,4 +253,4 @@ ], "subtitles": "subtitles.anti_air_turret.turret.shoot.end" } -} \ No newline at end of file +} diff --git a/src/main/resources/assets/dm/sounds/turrets/bullet_impacts/bullet_impact_dirt1.ogg b/src/main/resources/assets/dm/sounds/turrets/bullet_impacts/bullet_impact_dirt1.ogg new file mode 100644 index 0000000..b23d6bc Binary files /dev/null and b/src/main/resources/assets/dm/sounds/turrets/bullet_impacts/bullet_impact_dirt1.ogg differ diff --git a/src/main/resources/assets/dm/sounds/turrets/bullet_impacts/bullet_impact_dirt4.ogg b/src/main/resources/assets/dm/sounds/turrets/bullet_impacts/bullet_impact_dirt2.ogg similarity index 100% rename from src/main/resources/assets/dm/sounds/turrets/bullet_impacts/bullet_impact_dirt4.ogg rename to src/main/resources/assets/dm/sounds/turrets/bullet_impacts/bullet_impact_dirt2.ogg diff --git a/src/main/resources/assets/dm/sounds/turrets/bullet_impacts/bullet_impact_dirt3.ogg b/src/main/resources/assets/dm/sounds/turrets/bullet_impacts/bullet_impact_dirt3.ogg index b23d6bc..5860c29 100644 Binary files a/src/main/resources/assets/dm/sounds/turrets/bullet_impacts/bullet_impact_dirt3.ogg and b/src/main/resources/assets/dm/sounds/turrets/bullet_impacts/bullet_impact_dirt3.ogg differ diff --git a/src/main/resources/assets/dm/sounds/turrets/bullet_impacts/bullet_impact_dirt5.ogg b/src/main/resources/assets/dm/sounds/turrets/bullet_impacts/bullet_impact_dirt5.ogg deleted file mode 100644 index 5860c29..0000000 Binary files a/src/main/resources/assets/dm/sounds/turrets/bullet_impacts/bullet_impact_dirt5.ogg and /dev/null differ diff --git a/src/main/resources/assets/dm/sounds/turrets/bullet_impacts/bullet_impact_metal1.ogg b/src/main/resources/assets/dm/sounds/turrets/bullet_impacts/bullet_impact_metal1.ogg new file mode 100644 index 0000000..8285b30 Binary files /dev/null and b/src/main/resources/assets/dm/sounds/turrets/bullet_impacts/bullet_impact_metal1.ogg differ diff --git a/src/main/resources/assets/dm/sounds/turrets/bullet_impacts/bullet_impact_metal2.ogg b/src/main/resources/assets/dm/sounds/turrets/bullet_impacts/bullet_impact_metal2.ogg new file mode 100644 index 0000000..d183d7c Binary files /dev/null and b/src/main/resources/assets/dm/sounds/turrets/bullet_impacts/bullet_impact_metal2.ogg differ diff --git a/src/main/resources/assets/dm/sounds/turrets/bullet_impacts/bullet_impact_wood1.ogg b/src/main/resources/assets/dm/sounds/turrets/bullet_impacts/bullet_impact_wood1.ogg new file mode 100644 index 0000000..a4542d7 Binary files /dev/null and b/src/main/resources/assets/dm/sounds/turrets/bullet_impacts/bullet_impact_wood1.ogg differ diff --git a/src/main/resources/assets/dm/sounds/turrets/bullet_impacts/bullet_impact_wood2.ogg b/src/main/resources/assets/dm/sounds/turrets/bullet_impacts/bullet_impact_wood2.ogg new file mode 100644 index 0000000..009ce2a Binary files /dev/null and b/src/main/resources/assets/dm/sounds/turrets/bullet_impacts/bullet_impact_wood2.ogg differ diff --git a/src/main/resources/assets/dm/sounds/turrets/bullet_impacts/bullet_impact_wood3.ogg b/src/main/resources/assets/dm/sounds/turrets/bullet_impacts/bullet_impact_wood3.ogg new file mode 100644 index 0000000..ce02379 Binary files /dev/null and b/src/main/resources/assets/dm/sounds/turrets/bullet_impacts/bullet_impact_wood3.ogg differ diff --git a/src/main/resources/assets/dm/sounds/turrets/repair/metal_repair1.ogg b/src/main/resources/assets/dm/sounds/turrets/repair/metal_repair1.ogg new file mode 100644 index 0000000..123ea71 Binary files /dev/null and b/src/main/resources/assets/dm/sounds/turrets/repair/metal_repair1.ogg differ diff --git a/src/main/resources/assets/dm/sounds/turrets/repair/metal_repair2.ogg b/src/main/resources/assets/dm/sounds/turrets/repair/metal_repair2.ogg new file mode 100644 index 0000000..7909a13 Binary files /dev/null and b/src/main/resources/assets/dm/sounds/turrets/repair/metal_repair2.ogg differ diff --git a/src/main/resources/assets/dm/textures/entity/cannon_turret/cannonball.png b/src/main/resources/assets/dm/textures/entity/cannon_turret/cannonball.png index 05e8dbb..5925844 100644 Binary files a/src/main/resources/assets/dm/textures/entity/cannon_turret/cannonball.png and b/src/main/resources/assets/dm/textures/entity/cannon_turret/cannonball.png differ