diff --git a/src/main/java/com/atsuishio/superbwarfare/event/LivingEventHandler.java b/src/main/java/com/atsuishio/superbwarfare/event/LivingEventHandler.java index 57ae2a3fc..f46a144f6 100644 --- a/src/main/java/com/atsuishio/superbwarfare/event/LivingEventHandler.java +++ b/src/main/java/com/atsuishio/superbwarfare/event/LivingEventHandler.java @@ -487,8 +487,16 @@ public class LivingEventHandler { if (!(stack.getItem() instanceof GunItem)) return; var data = GunData.from(stack); + float damage = event.getAmount(); + + for (Perk.Type type : Perk.Type.values()) { + var instance = data.perk.getInstance(type); + if (instance != null) { + damage = instance.perk().getModifiedDamage(damage, data, instance, event.getEntity(), source); + } + } + if (DamageTypeTool.isGunDamage(source) || source.is(ModDamageTypes.PROJECTILE_BOOM)) { - handleKillClipDamage(stack, event); handleVorpalWeaponDamage(stack, event); } @@ -522,6 +530,8 @@ public class LivingEventHandler { if (DamageTypeTool.isHeadshotDamage(source)) { handleHeadSeekerDamage(stack, event); } + + event.setAmount(damage); } private static void handleGunPerksWhenDeath(LivingDeathEvent event) { @@ -548,14 +558,10 @@ public class LivingEventHandler { for (Perk.Type type : Perk.Type.values()) { var instance = data.perk.getInstance(type); if (instance != null) { - instance.perk().onKill(data, instance, attacker, event.getEntity(), source); + instance.perk().onKill(data, instance, event.getEntity(), source); } } - if (DamageTypeTool.isGunDamage(source) || source.is(ModDamageTypes.PROJECTILE_BOOM)) { - handleClipPerks(stack); - } - if (DamageTypeTool.isGunDamage(source)) { handleKillingTallyAddCount(stack); handleSubsistence(stack, attacker); @@ -566,30 +572,11 @@ public class LivingEventHandler { } } - private static void handleClipPerks(ItemStack stack) { - var data = GunData.from(stack); - int killClipLevel = data.perk.getLevel(ModPerks.KILL_CLIP); - if (killClipLevel != 0) { - data.perk.getTag(ModPerks.KILL_CLIP).putInt("KillClipReloadTime", 80); - } - data.save(); - } - - private static void handleKillClipDamage(ItemStack stack, LivingIncomingDamageEvent event) { - var data = GunData.from(stack); - final var tag = data.perk.getTag(ModPerks.KILL_CLIP); - if (tag.getInt("KillClipTime") > 0) { - int level = data.perk.getLevel(ModPerks.KILL_CLIP); - if (level == 0) return; - - event.setAmount(event.getAmount() * (1.2f + 0.05f * level)); - } - } - private static void handleGutshotStraightDamage(ItemStack stack, LivingIncomingDamageEvent event) { - var data = GunData.from(stack); - int level = data.perk.getLevel(ModPerks.GUTSHOT_STRAIGHT); - if (level == 0) return; + int level = GunData.from(stack).perk.getLevel(ModPerks.GUTSHOT_STRAIGHT); + if (level == 0) { + return; + } event.setAmount(event.getAmount() * (1.15f + 0.05f * level)); } diff --git a/src/main/java/com/atsuishio/superbwarfare/event/ReloadEventHandler.java b/src/main/java/com/atsuishio/superbwarfare/event/ReloadEventHandler.java index ece746439..84e813263 100644 --- a/src/main/java/com/atsuishio/superbwarfare/event/ReloadEventHandler.java +++ b/src/main/java/com/atsuishio/superbwarfare/event/ReloadEventHandler.java @@ -31,7 +31,6 @@ public class ReloadEventHandler { } } - handleKillClipPre(stack); handleKillingTallyPre(stack); handleDesperadoPre(stack); } @@ -56,33 +55,9 @@ public class ReloadEventHandler { } } - handleKillClipPost(stack); handleDesperadoPost(stack); } - private static void handleKillClipPre(ItemStack stack) { - var data = GunData.from(stack); - final var tag = data.tag(); - int time = GunsTool.getPerkIntTag(tag, "KillClipReloadTime"); - if (time > 0) { - GunsTool.setPerkIntTag(tag, "KillClipReloadTime", 0); - GunsTool.setPerkBooleanTag(tag, "KillClip", true); - } else { - GunsTool.setPerkBooleanTag(tag, "KillClip", false); - } - data.save(); - } - - private static void handleKillClipPost(ItemStack stack) { - var data = GunData.from(stack); - final var tag = data.tag(); - if (!GunsTool.getPerkBooleanTag(tag, "KillClip")) return; - - int level = data.perk.getLevel(ModPerks.KILL_CLIP); - GunsTool.setPerkIntTag(tag, "KillClipTime", 90 + 10 * level); - data.save(); - } - private static void handleKillingTallyPre(ItemStack stack) { var data = GunData.from(stack); final var tag = data.tag(); diff --git a/src/main/java/com/atsuishio/superbwarfare/init/ModPerks.java b/src/main/java/com/atsuishio/superbwarfare/init/ModPerks.java index 7161a4e0c..f0d592a80 100644 --- a/src/main/java/com/atsuishio/superbwarfare/init/ModPerks.java +++ b/src/main/java/com/atsuishio/superbwarfare/init/ModPerks.java @@ -3,6 +3,7 @@ package com.atsuishio.superbwarfare.init; import com.atsuishio.superbwarfare.Mod; import com.atsuishio.superbwarfare.perk.AmmoPerk; import com.atsuishio.superbwarfare.perk.Perk; +import com.atsuishio.superbwarfare.perk.damage.KillClip; import com.atsuishio.superbwarfare.perk.functional.HealClip; import net.minecraft.resources.ResourceKey; import net.minecraft.world.effect.MobEffects; @@ -67,7 +68,7 @@ public class ModPerks { */ public static final DeferredRegister DAMAGE_PERKS = DeferredRegister.create(Mod.loc("perk"), Mod.MODID); - public static final DeferredHolder KILL_CLIP = DAMAGE_PERKS.register("kill_clip", () -> new Perk("kill_clip", Perk.Type.DAMAGE)); + public static final DeferredHolder KILL_CLIP = DAMAGE_PERKS.register("kill_clip", KillClip::new); public static final DeferredHolder GUTSHOT_STRAIGHT = DAMAGE_PERKS.register("gutshot_straight", () -> new Perk("gutshot_straight", Perk.Type.DAMAGE)); public static final DeferredHolder KILLING_TALLY = DAMAGE_PERKS.register("killing_tally", () -> new Perk("killing_tally", Perk.Type.DAMAGE)); public static final DeferredHolder HEAD_SEEKER = DAMAGE_PERKS.register("head_seeker", () -> new Perk("head_seeker", Perk.Type.DAMAGE)); diff --git a/src/main/java/com/atsuishio/superbwarfare/item/gun/GunItem.java b/src/main/java/com/atsuishio/superbwarfare/item/gun/GunItem.java index 7f09e5c92..59b6cff32 100644 --- a/src/main/java/com/atsuishio/superbwarfare/item/gun/GunItem.java +++ b/src/main/java/com/atsuishio/superbwarfare/item/gun/GunItem.java @@ -82,7 +82,7 @@ public abstract class GunItem extends Item implements CustomRendererItem { @Override @ParametersAreNonnullByDefault public void inventoryTick(ItemStack stack, Level level, Entity entity, int slot, boolean selected) { - if (!(entity instanceof LivingEntity) || !(stack.getItem() instanceof GunItem gunItem)) return; + if (!(entity instanceof LivingEntity living) || !(stack.getItem() instanceof GunItem gunItem)) return; var data = GunData.from(stack); @@ -93,6 +93,13 @@ public abstract class GunItem extends Item implements CustomRendererItem { } } data.draw.set(false); + + for (Perk.Type type : Perk.Type.values()) { + var instance = data.perk.getInstance(type); + if (instance != null) { + instance.perk().tick(data, instance, living); + } + } handleGunPerks(data); var hasBulletInBarrel = gunItem.hasBulletInBarrel(stack); @@ -113,8 +120,7 @@ public abstract class GunItem extends Item implements CustomRendererItem { data.ammo.set(magazine + (hasBulletInBarrel ? 1 : 0)); } - //冷却 - + // 冷却 double cooldown = 0; if (entity.wasInPowderSnow) { cooldown = 0.15; @@ -195,11 +201,6 @@ public abstract class GunItem extends Item implements CustomRendererItem { private void handleGunPerks(GunData data) { var perk = data.perk; - perk.reduceCooldown(ModPerks.HEAL_CLIP, "HealClipTime"); - - perk.reduceCooldown(ModPerks.KILL_CLIP, "KillClipReloadTime"); - perk.reduceCooldown(ModPerks.KILL_CLIP, "KillClipTime"); - perk.reduceCooldown(ModPerks.FOURTH_TIMES_CHARM, "FourthTimesCharmTick"); perk.reduceCooldown(ModPerks.HEAD_SEEKER, "HeadSeeker"); diff --git a/src/main/java/com/atsuishio/superbwarfare/item/gun/data/subdata/Perks.java b/src/main/java/com/atsuishio/superbwarfare/item/gun/data/subdata/Perks.java index 149fe9b31..4dc295f72 100644 --- a/src/main/java/com/atsuishio/superbwarfare/item/gun/data/subdata/Perks.java +++ b/src/main/java/com/atsuishio/superbwarfare/item/gun/data/subdata/Perks.java @@ -12,6 +12,7 @@ import javax.annotation.Nullable; import java.util.ArrayList; public final class Perks { + private final CompoundTag perks; public Perks(GunData gun) { diff --git a/src/main/java/com/atsuishio/superbwarfare/perk/Perk.java b/src/main/java/com/atsuishio/superbwarfare/perk/Perk.java index 53dd95dda..ed29bf3a6 100644 --- a/src/main/java/com/atsuishio/superbwarfare/perk/Perk.java +++ b/src/main/java/com/atsuishio/superbwarfare/perk/Perk.java @@ -6,24 +6,17 @@ import com.atsuishio.superbwarfare.item.gun.data.GunData; import net.minecraft.ChatFormatting; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.neoforged.neoforge.registries.DeferredHolder; import org.jetbrains.annotations.Nullable; -import java.util.function.BiFunction; - public class Perk { + public final String descriptionId; public final String name; public final Type type; public int level = 1; - public BiFunction tick; - public BiFunction preReload; - public BiFunction postReload; - public BiFunction onKill; - public Perk(String descriptionId, Type type) { this.descriptionId = descriptionId; this.type = type; @@ -58,21 +51,25 @@ public class Perk { return result.get(); } - public void tick(GunData data, PerkInstance instance, @Nullable Player player) { + public void tick(GunData data, PerkInstance instance, @Nullable LivingEntity living) { } - public void preReload(GunData data, PerkInstance instance, @Nullable Player player) { + public void preReload(GunData data, PerkInstance instance, @Nullable LivingEntity living) { } - public void postReload(GunData data, PerkInstance instance, @Nullable Player player) { + public void postReload(GunData data, PerkInstance instance, @Nullable LivingEntity living) { } - public void onKill(GunData data, PerkInstance instance, @Nullable Player player, LivingEntity target, DamageSource source) { + public void onKill(GunData data, PerkInstance instance, LivingEntity target, DamageSource source) { } public void onShoot() { } + public float getModifiedDamage(float damage, GunData data, PerkInstance instance, @Nullable LivingEntity target, DamageSource source) { + return damage; + } + public enum Type { AMMO("Ammo", ChatFormatting.YELLOW), FUNCTIONAL("Functional", ChatFormatting.GREEN), diff --git a/src/main/java/com/atsuishio/superbwarfare/perk/damage/KillClip.java b/src/main/java/com/atsuishio/superbwarfare/perk/damage/KillClip.java new file mode 100644 index 000000000..2a3b46808 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/perk/damage/KillClip.java @@ -0,0 +1,71 @@ +package com.atsuishio.superbwarfare.perk.damage; + +import com.atsuishio.superbwarfare.init.ModDamageTypes; +import com.atsuishio.superbwarfare.item.gun.data.GunData; +import com.atsuishio.superbwarfare.perk.Perk; +import com.atsuishio.superbwarfare.perk.PerkInstance; +import com.atsuishio.superbwarfare.tools.DamageTypeTool; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.LivingEntity; +import org.jetbrains.annotations.Nullable; + +public class KillClip extends Perk { + + public KillClip() { + super("kill_clip", Perk.Type.DAMAGE); + } + + @Override + public void tick(GunData data, PerkInstance instance, @Nullable LivingEntity living) { + super.tick(data, instance, living); + data.perk.reduceCooldown(this, "KillClipReloadTime"); + data.perk.reduceCooldown(this, "KillClipTime"); + } + + @Override + public void preReload(GunData data, PerkInstance instance, @Nullable LivingEntity living) { + super.preReload(data, instance, living); + + int time = data.perk.getTag(this).getInt("KillClipReloadTime"); + if (time > 0) { + data.perk.getTag(this).remove("KillClipReloadTime"); + data.perk.getTag(this).putBoolean("KillClip", true); + } else { + data.perk.getTag(this).remove("KillClip"); + } + } + + @Override + public void postReload(GunData data, PerkInstance instance, @Nullable LivingEntity living) { + super.postReload(data, instance, living); + + if (!data.perk.getTag(this).getBoolean("KillClip")) { + return; + } + + int level = instance.level(); + data.perk.getTag(this).putInt("KillClipTime", 90 + 10 * level); + } + + @Override + public void onKill(GunData data, PerkInstance instance, LivingEntity target, DamageSource source) { + super.onKill(data, instance, target, source); + + if (DamageTypeTool.isGunDamage(source) || source.is(ModDamageTypes.PROJECTILE_BOOM)) { + int killClipLevel = instance.level(); + if (killClipLevel != 0) { + data.perk.getTag(this).putInt("KillClipReloadTime", 80); + } + } + } + + @Override + public float getModifiedDamage(float damage, GunData data, PerkInstance instance, @Nullable LivingEntity target, DamageSource source) { + if (DamageTypeTool.isGunDamage(source) || source.is(ModDamageTypes.PROJECTILE_BOOM)) { + if (data.perk.getTag(this).getInt("KillClipTime") > 0) { + return damage * (1.2f + 0.05f * instance.level()); + } + } + return super.getModifiedDamage(damage, data, instance, target, source); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/perk/functional/HealClip.java b/src/main/java/com/atsuishio/superbwarfare/perk/functional/HealClip.java index 84dcd4c4d..15d77f55a 100644 --- a/src/main/java/com/atsuishio/superbwarfare/perk/functional/HealClip.java +++ b/src/main/java/com/atsuishio/superbwarfare/perk/functional/HealClip.java @@ -8,7 +8,6 @@ import com.atsuishio.superbwarfare.tools.DamageTypeTool; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.Nullable; import java.util.List; @@ -20,8 +19,14 @@ public class HealClip extends Perk { } @Override - public void onKill(GunData data, PerkInstance instance, @Nullable Player player, LivingEntity target, DamageSource source) { - super.onKill(data, instance, player, target, source); + public void tick(GunData data, PerkInstance instance, @Nullable LivingEntity living) { + super.tick(data, instance, living); + data.perk.reduceCooldown(this, "HealClipTime"); + } + + @Override + public void onKill(GunData data, PerkInstance instance, LivingEntity target, DamageSource source) { + super.onKill(data, instance, target, source); if (DamageTypeTool.isGunDamage(source) || source.is(ModDamageTypes.PROJECTILE_BOOM)) { int healClipLevel = instance.level(); @@ -32,26 +37,25 @@ public class HealClip extends Perk { } @Override - public void preReload(GunData data, PerkInstance instance, @Nullable Player player) { - super.preReload(data, instance, player); + public void preReload(GunData data, PerkInstance instance, @Nullable LivingEntity living) { + super.preReload(data, instance, living); - ItemStack stack = data.stack; int time = data.perk.getTag(this).getInt("HealClipTime"); if (time > 0) { - data.perk.getTag(this).putInt("HealClipTime", 0); + data.perk.getTag(this).remove("HealClipTime"); data.perk.getTag(this).putBoolean("HealClip", true); } else { - data.perk.getTag(this).putBoolean("HealClip", false); + data.perk.getTag(this).remove("HealClip"); } } @Override - public void postReload(GunData data, PerkInstance instance, @Nullable Player player) { - super.postReload(data, instance, player); + public void postReload(GunData data, PerkInstance instance, @Nullable LivingEntity living) { + super.postReload(data, instance, living); - if (player == null) return; + if (living == null) return; - if (!data.perk.getTag(this).getBoolean("HealClip")) { + if (!data.perk.getTag(this).contains("HealClip")) { return; } @@ -60,9 +64,9 @@ public class HealClip extends Perk { healClipLevel = 1; } - player.heal(12.0f * (0.8f + 0.2f * healClipLevel)); - List players = player.level().getEntitiesOfClass(Player.class, player.getBoundingBox().inflate(5)) - .stream().filter(p -> p.isAlliedTo(player)).toList(); + living.heal(12.0f * (0.8f + 0.2f * healClipLevel)); + List players = living.level().getEntitiesOfClass(Player.class, living.getBoundingBox().inflate(5)) + .stream().filter(p -> p.isAlliedTo(living)).toList(); int finalHealClipLevel = healClipLevel; players.forEach(p -> p.heal(6.0f * (0.8f + 0.2f * finalHealClipLevel))); }