diff --git a/src/main/java/com/atsuishio/superbwarfare/client/screens/KillMessageOverlay.java b/src/main/java/com/atsuishio/superbwarfare/client/screens/KillMessageOverlay.java index 9777256d7..1293c2bc8 100644 --- a/src/main/java/com/atsuishio/superbwarfare/client/screens/KillMessageOverlay.java +++ b/src/main/java/com/atsuishio/superbwarfare/client/screens/KillMessageOverlay.java @@ -1,15 +1,15 @@ package com.atsuishio.superbwarfare.client.screens; -import com.atsuishio.superbwarfare.config.client.KillMessageConfig; -import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.systems.RenderSystem; import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.config.client.KillMessageConfig; import com.atsuishio.superbwarfare.event.KillMessageHandler; import com.atsuishio.superbwarfare.init.ModDamageTypes; import com.atsuishio.superbwarfare.init.ModItems; import com.atsuishio.superbwarfare.item.gun.GunItem; import com.atsuishio.superbwarfare.tools.DamageTypeTool; import com.atsuishio.superbwarfare.tools.PlayerKillRecord; +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.core.registries.Registries; @@ -42,6 +42,7 @@ public class KillMessageOverlay { private static final ResourceLocation SHOCK = ModUtils.loc("textures/screens/damage_types/shock.png"); private static final ResourceLocation BLOOD_CRYSTAL = ModUtils.loc("textures/screens/damage_types/blood_crystal.png"); private static final ResourceLocation BURN = ModUtils.loc("textures/screens/damage_types/burn.png"); + private static final ResourceLocation DRONE = ModUtils.loc("textures/screens/damage_types/drone.png"); private static final ResourceLocation WORLD_PEACE_STAFF = ModUtils.loc("textures/gun_icon/compat/world_peace_staff.png"); @@ -272,7 +273,9 @@ public class KillMessageOverlay { icon = SHOCK; } else if (record.damageType == ModDamageTypes.BURN || record.damageType == DamageTypes.IN_FIRE || record.damageType == DamageTypes.ON_FIRE || record.damageType == DamageTypes.LAVA) { icon = BURN; - } else { + } else if (record.damageType == ModDamageTypes.DRONE_HIT) { + icon = DRONE; + }else { icon = GENERIC; } } diff --git a/src/main/java/com/atsuishio/superbwarfare/entity/DroneEntity.java b/src/main/java/com/atsuishio/superbwarfare/entity/DroneEntity.java index 7d90480aa..185ef7228 100644 --- a/src/main/java/com/atsuishio/superbwarfare/entity/DroneEntity.java +++ b/src/main/java/com/atsuishio/superbwarfare/entity/DroneEntity.java @@ -9,6 +9,7 @@ import com.atsuishio.superbwarfare.init.ModSounds; import com.atsuishio.superbwarfare.item.Monitor; import com.atsuishio.superbwarfare.tools.CustomExplosion; import com.atsuishio.superbwarfare.tools.EntityFindUtil; +import com.atsuishio.superbwarfare.tools.ParticleTool; import com.atsuishio.superbwarfare.tools.SoundTool; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; @@ -33,12 +34,16 @@ import net.minecraft.world.damagesource.DamageTypes; import net.minecraft.world.entity.*; import net.minecraft.world.entity.ai.attributes.AttributeSupplier; import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Explosion; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; +import net.minecraft.world.phys.shapes.BooleanOp; +import net.minecraft.world.phys.shapes.Shapes; import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.network.NetworkHooks; import net.minecraftforge.network.PlayMessages; @@ -48,6 +53,7 @@ import software.bernie.geckolib.core.animatable.instance.AnimatableInstanceCache import software.bernie.geckolib.core.animation.AnimatableManager; import software.bernie.geckolib.util.GeckoLibUtil; +import java.util.Comparator; import java.util.Objects; import java.util.UUID; @@ -214,9 +220,9 @@ public class DroneEntity extends LivingEntity implements GeoEntity { this.entityData.set(MOVE_Y, Mth.lerp(0.5f, this.entityData.get(MOVE_Y), 0)); this.setDeltaMovement(new Vec3( - this.getDeltaMovement().x + -this.entityData.get(MOVE_Z) * 0.1f * this.getLookAngle().x, + this.getDeltaMovement().x + -this.entityData.get(MOVE_Z) * 0.07f * this.getLookAngle().x, this.getDeltaMovement().y + (this.onGround() ? 0.059 : 0) + -this.entityData.get(MOVE_Y) * 0.05f, - this.getDeltaMovement().z + -this.entityData.get(MOVE_Z) * 0.1f * this.getLookAngle().z + this.getDeltaMovement().z + -this.entityData.get(MOVE_Z) * 0.07f * this.getLookAngle().z )); this.move = this.getPersistentData().getBoolean("left") @@ -229,7 +235,7 @@ public class DroneEntity extends LivingEntity implements GeoEntity { Vec3 vec = this.getDeltaMovement(); if (this.getDeltaMovement().horizontalDistanceSqr() < 0.75) { if (this.move) { - this.setDeltaMovement(vec.multiply(1.04, 0.99, 1.04)); + this.setDeltaMovement(vec.multiply(1.035, 0.99, 1.035)); } } @@ -242,9 +248,23 @@ public class DroneEntity extends LivingEntity implements GeoEntity { if (stack.getOrCreateTag().getBoolean("Using") && controller instanceof ServerPlayer serverPlayer) { SoundTool.playLocalSound(serverPlayer, ModSounds.DRONE_SOUND.get(), 100, 1); } - controller.setYRot(controller.getYRot() - 5 * this.entityData.get(ROT_X) * Mth.abs(this.entityData.get(MOVE_Z))); } + + float f = 0.7f; + AABB aabb = AABB.ofSize(this.getEyePosition(), f, 0.3, f); + var level = this.level(); + final Vec3 center = new Vec3(this.getX(), this.getY(), this.getZ()); + for (Entity target : level.getEntitiesOfClass(Entity.class, aabb, e -> true).stream().sorted(Comparator.comparingDouble(e -> e.distanceToSqr(center))).toList()) { + if (this != target && target != null) { + target.hurt(ModDamageTypes.causeDroneHitDamage(this.level().registryAccess(), this, controller), 1); + target.invulnerableTime = 0; + if (target instanceof Mob mobEntity) { + mobEntity.setTarget(this); + } + this.hurt(new DamageSource(level().registryAccess().registryOrThrow(Registries.DAMAGE_TYPE).getHolderOrThrow(DamageTypes.EXPLOSION), Objects.requireNonNullElse(controller, this)), 1); + } + } } if (this.getPersistentData().getBoolean("firing")) { @@ -387,29 +407,58 @@ public class DroneEntity extends LivingEntity implements GeoEntity { this.setDeltaMovement(vec3.multiply(0.9, 0.8, 0.9)); } - - double x0 = this.getX() - this.xOld; - double y0 = this.getY() - this.yOld; - double z0 = this.getZ() - this.zOld; - - lastTickSpeed = Math.sqrt(x0 * x0 + y0 * y0 + z0 * z0); - - - if (controller != null) { - controller.displayClientMessage(Component.literal( new java.text.DecimalFormat("##.####").format(Mth.abs((float) (this.getDeltaMovement().length() - lastTickSpeed)))), false); + lastTickSpeed = this.getDeltaMovement().length(); + crash(controller); + float f = 0.7f; + AABB aabb = AABB.ofSize(this.getEyePosition(), f, 0.3, f); + var level = this.level(); + final Vec3 center = new Vec3(this.getX(), this.getY(), this.getZ()); + for (Entity target : level.getEntitiesOfClass(Entity.class, aabb, e -> true).stream().sorted(Comparator.comparingDouble(e -> e.distanceToSqr(center))).toList()) { + if (this != target && target != null) { + hitEntityCrash(controller, target); + } } - if (Mth.abs((float) (this.getDeltaMovement().length() - lastTickSpeed)) > 1.0) { - this.hurt(new DamageSource(level().registryAccess().registryOrThrow(Registries.DAMAGE_TYPE).getHolderOrThrow(DamageTypes.EXPLOSION), controller), 10000); + } + + public void crash(Player controller) { + if (isHit() && lastTickSpeed > 0.3) { + this.hurt(new DamageSource(level().registryAccess().registryOrThrow(Registries.DAMAGE_TYPE).getHolderOrThrow(DamageTypes.EXPLOSION), Objects.requireNonNullElse(controller, this)), (float) ((this.entityData.get(KAMIKAZE) ? 6 : 2) * lastTickSpeed)); } } + public void hitEntityCrash(Player controller, Entity target) { + if (lastTickSpeed > 0.2) { + if (this.entityData.get(KAMIKAZE) && 6 * lastTickSpeed > this.getHealth()) { + target.hurt(ModDamageTypes.causeCustomExplosionDamage(this.level().registryAccess(), this, controller), 600); + } + target.hurt(ModDamageTypes.causeDroneHitDamage(this.level().registryAccess(), this, controller), (float) (5 * lastTickSpeed)); + if (target instanceof Mob mobEntity) { + mobEntity.setTarget(this); + } + this.hurt(new DamageSource(level().registryAccess().registryOrThrow(Registries.DAMAGE_TYPE).getHolderOrThrow(DamageTypes.EXPLOSION), Objects.requireNonNullElse(controller, this)), (float) ((this.entityData.get(KAMIKAZE) ? 6 : 0.5) * lastTickSpeed)); + } + } + + public boolean isHit() { + float f = 0.7f; + AABB aabb = AABB.ofSize(this.getEyePosition(), f, 0.3, f); + return BlockPos.betweenClosedStream(aabb).anyMatch((block) -> { + BlockState blockstate = this.level().getBlockState(block); + return !blockstate.isAir() && blockstate.isSuffocating(this.level(), block) && Shapes.joinIsNotEmpty(blockstate.getCollisionShape(this.level(), block).move(block.getX(), block.getY(), block.getZ()), Shapes.create(aabb), BooleanOp.AND); + }); + } + + @Override + public boolean canBeCollidedWith() { + return super.canBeCollidedWith(); + } + @Override public void die(DamageSource source) { super.die(source); String id = this.entityData.get(CONTROLLER); - UUID uuid; try { uuid = UUID.fromString(id); @@ -431,28 +480,29 @@ public class DroneEntity extends LivingEntity implements GeoEntity { kamikazeExplosion(source.getEntity()); } + ItemStack stack = new ItemStack(ModItems.RGO_GRENADE.get(),this.entityData.get(AMMO)); + + if (this.level() instanceof ServerLevel level) { + ItemEntity itemEntity = new ItemEntity(level, this.getX(), this.getY(), this.getZ(), stack); + itemEntity.setPickUpDelay(10); + level.addFreshEntity(itemEntity); + } + if (level() instanceof ServerLevel) { level().explode(null, this.getX(), this.getY(), this.getZ(), 0, Level.ExplosionInteraction.NONE); } this.discard(); - } + private void kamikazeExplosion(Entity source) { - - CustomExplosion explosionCore = new CustomExplosion(this.level(), this, - ModDamageTypes.causeProjectileBoomDamage(this.level().registryAccess(), source, source), 1000, - this.getX(), this.getY(), this.getZ(), 4f, ExplosionDestroyConfig.EXPLOSION_DESTROY.get() ? Explosion.BlockInteraction.DESTROY : Explosion.BlockInteraction.KEEP).setDamageMultiplier(1); - explosionCore.explode(); - net.minecraftforge.event.ForgeEventFactory.onExplosionStart(this.level(), explosionCore); - explosionCore.finalizeExplosion(false); - CustomExplosion explosion = new CustomExplosion(this.level(), this, - ModDamageTypes.causeProjectileBoomDamage(this.level().registryAccess(), source, source), 150, - this.getX(), this.getY(), this.getZ(), 12.5f, ExplosionDestroyConfig.EXPLOSION_DESTROY.get() ? Explosion.BlockInteraction.DESTROY : Explosion.BlockInteraction.KEEP).setDamageMultiplier(1); + ModDamageTypes.causeProjectileBoomDamage(this.level().registryAccess(), source, source), 125, + this.getX(), this.getY(), this.getZ(), 7.5f, ExplosionDestroyConfig.EXPLOSION_DESTROY.get() ? Explosion.BlockInteraction.DESTROY : Explosion.BlockInteraction.KEEP).setDamageMultiplier(1); explosion.explode(); net.minecraftforge.event.ForgeEventFactory.onExplosionStart(this.level(), explosion); explosion.finalizeExplosion(false); + ParticleTool.spawnMediumExplosionParticles(this.level(), this.position()); } @Override @@ -479,17 +529,11 @@ public class DroneEntity extends LivingEntity implements GeoEntity { public void registerControllers(AnimatableManager.ControllerRegistrar data) { } - @Override - protected void pushEntities() { - } - @Override public HumanoidArm getMainArm() { return HumanoidArm.RIGHT; } - - @Override public AnimatableInstanceCache getAnimatableInstanceCache() { return this.cache; diff --git a/src/main/java/com/atsuishio/superbwarfare/init/ModDamageTypes.java b/src/main/java/com/atsuishio/superbwarfare/init/ModDamageTypes.java index 1e1bcb21b..8a18118ce 100644 --- a/src/main/java/com/atsuishio/superbwarfare/init/ModDamageTypes.java +++ b/src/main/java/com/atsuishio/superbwarfare/init/ModDamageTypes.java @@ -27,6 +27,7 @@ public class ModDamageTypes { public static final ResourceKey PROJECTILE_BOOM = ResourceKey.create(Registries.DAMAGE_TYPE, new ResourceLocation(ModUtils.MODID, "projectile_boom")); public static final ResourceKey CANNON_FIRE = ResourceKey.create(Registries.DAMAGE_TYPE, new ResourceLocation(ModUtils.MODID, "cannon_fire")); public static final ResourceKey CUSTOM_EXPLOSION = ResourceKey.create(Registries.DAMAGE_TYPE, new ResourceLocation(ModUtils.MODID, "custom_explosion")); + public static final ResourceKey DRONE_HIT = ResourceKey.create(Registries.DAMAGE_TYPE, new ResourceLocation(ModUtils.MODID, "drone_hit")); public static DamageSource causeGunFireDamage(RegistryAccess registryAccess, @Nullable Entity directEntity, @Nullable Entity attacker) { return new DamageMessages(registryAccess.registry(Registries.DAMAGE_TYPE).get().getHolderOrThrow(GUN_FIRE), directEntity, attacker); @@ -68,6 +69,10 @@ public class ModDamageTypes { return new DamageMessages(registryAccess.registry(Registries.DAMAGE_TYPE).get().getHolderOrThrow(CUSTOM_EXPLOSION), directEntity, attacker); } + public static DamageSource causeDroneHitDamage(RegistryAccess registryAccess, @Nullable Entity directEntity, @Nullable Entity attacker) { + return new DamageMessages(registryAccess.registry(Registries.DAMAGE_TYPE).get().getHolderOrThrow(DRONE_HIT), directEntity, attacker); + } + private static class DamageMessages extends DamageSource { public DamageMessages(Holder.Reference typeReference) { super(typeReference); diff --git a/src/main/java/com/atsuishio/superbwarfare/init/ModEntities.java b/src/main/java/com/atsuishio/superbwarfare/init/ModEntities.java index a4a0c2401..d9bf20a5a 100644 --- a/src/main/java/com/atsuishio/superbwarfare/init/ModEntities.java +++ b/src/main/java/com/atsuishio/superbwarfare/init/ModEntities.java @@ -36,7 +36,7 @@ public class ModEntities { EntityType.Builder.of(Mle1934Entity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(true).setTrackingRange(512).setUpdateInterval(3).setCustomClientFactory(Mle1934Entity::new).fireImmune().sized(4.5f, 2.8f)); public static final RegistryObject> DRONE = register("drone", - EntityType.Builder.of(DroneEntity::new, MobCategory.CREATURE).setShouldReceiveVelocityUpdates(true).setTrackingRange(512).setUpdateInterval(3).setCustomClientFactory(DroneEntity::new).sized(0.7f, 0.175f)); + EntityType.Builder.of(DroneEntity::new, MobCategory.CREATURE).setShouldReceiveVelocityUpdates(true).setTrackingRange(512).setUpdateInterval(3).setCustomClientFactory(DroneEntity::new).sized(0.6f, 0.2f)); public static final RegistryObject> TASER_BULLET_PROJECTILE = register("projectile_taser_bullet_projectile", EntityType.Builder.of(TaserBulletProjectileEntity::new, MobCategory.MISC).setCustomClientFactory(TaserBulletProjectileEntity::new).setShouldReceiveVelocityUpdates(true).setTrackingRange(64) diff --git a/src/main/java/com/atsuishio/superbwarfare/item/Monitor.java b/src/main/java/com/atsuishio/superbwarfare/item/Monitor.java index ca7b51b7e..360adfa44 100644 --- a/src/main/java/com/atsuishio/superbwarfare/item/Monitor.java +++ b/src/main/java/com/atsuishio/superbwarfare/item/Monitor.java @@ -1,10 +1,10 @@ package com.atsuishio.superbwarfare.item; +import com.atsuishio.superbwarfare.entity.DroneEntity; import com.atsuishio.superbwarfare.tools.EntityFindUtil; import com.atsuishio.superbwarfare.tools.ItemNBTTool; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.Multimap; -import com.atsuishio.superbwarfare.entity.DroneEntity; import net.minecraft.ChatFormatting; import net.minecraft.client.CameraType; import net.minecraft.client.Minecraft; diff --git a/src/main/resources/assets/superbwarfare/lang/en_us.json b/src/main/resources/assets/superbwarfare/lang/en_us.json index 4488e5116..a2083f070 100644 --- a/src/main/resources/assets/superbwarfare/lang/en_us.json +++ b/src/main/resources/assets/superbwarfare/lang/en_us.json @@ -314,6 +314,9 @@ "death.attack.burn": "%1$s被烧糊了", "death.attack.burn.entity": "%1$s被%2$s烧成了焦炭", "death.attack.burn.item": "%1$s被%2$s烧成了焦炭", + "death.attack.drone_hit": "%1$s被无人机叶片切碎了", + "death.attack.drone_hit.entity": "%1$s被%2$s用无人机叶片切碎了", + "death.attack.drone_hit.item": "%1$s被%2$s用无人机叶片切碎了", "gui.superbwarfare.mortar_gui.button_set": "Confirm", diff --git a/src/main/resources/assets/superbwarfare/lang/zh_cn.json b/src/main/resources/assets/superbwarfare/lang/zh_cn.json index 8b213b51a..b0ea511d2 100644 --- a/src/main/resources/assets/superbwarfare/lang/zh_cn.json +++ b/src/main/resources/assets/superbwarfare/lang/zh_cn.json @@ -314,6 +314,9 @@ "death.attack.burn": "%1$s被烧糊了", "death.attack.burn.entity": "%1$s被%2$s烧成了焦炭", "death.attack.burn.item": "%1$s被%2$s烧成了焦炭", + "death.attack.drone_hit": "%1$s被无人机叶片切碎了", + "death.attack.drone_hit.entity": "%1$s被%2$s用无人机叶片切碎了", + "death.attack.drone_hit.item": "%1$s被%2$s用无人机叶片切碎了", "gui.superbwarfare.mortar_gui.button_set": "确认", diff --git a/src/main/resources/assets/superbwarfare/textures/screens/damage_types/drone.png b/src/main/resources/assets/superbwarfare/textures/screens/damage_types/drone.png new file mode 100644 index 000000000..2c9721c55 Binary files /dev/null and b/src/main/resources/assets/superbwarfare/textures/screens/damage_types/drone.png differ diff --git a/src/main/resources/data/superbwarfare/damage_type/drone_hit.json b/src/main/resources/data/superbwarfare/damage_type/drone_hit.json new file mode 100644 index 000000000..5a7afc08c --- /dev/null +++ b/src/main/resources/data/superbwarfare/damage_type/drone_hit.json @@ -0,0 +1,5 @@ +{ + "exhaustion": 0, + "message_id": "drone_hit", + "scaling": "never" +} \ No newline at end of file