重构弹匣类perk

This commit is contained in:
17146 2025-05-07 11:44:03 +08:00 committed by Light_Quanta
parent 32263ee5ff
commit d4deb03eaf
No known key found for this signature in database
GPG key ID: 11A39A1B8C890959
8 changed files with 127 additions and 90 deletions

View file

@ -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));
}

View file

@ -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();

View file

@ -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<Perk> DAMAGE_PERKS = DeferredRegister.create(Mod.loc("perk"), Mod.MODID);
public static final DeferredHolder<Perk, Perk> KILL_CLIP = DAMAGE_PERKS.register("kill_clip", () -> new Perk("kill_clip", Perk.Type.DAMAGE));
public static final DeferredHolder<Perk, Perk> KILL_CLIP = DAMAGE_PERKS.register("kill_clip", KillClip::new);
public static final DeferredHolder<Perk, Perk> GUTSHOT_STRAIGHT = DAMAGE_PERKS.register("gutshot_straight", () -> new Perk("gutshot_straight", Perk.Type.DAMAGE));
public static final DeferredHolder<Perk, Perk> KILLING_TALLY = DAMAGE_PERKS.register("killing_tally", () -> new Perk("killing_tally", Perk.Type.DAMAGE));
public static final DeferredHolder<Perk, Perk> HEAD_SEEKER = DAMAGE_PERKS.register("head_seeker", () -> new Perk("head_seeker", Perk.Type.DAMAGE));

View file

@ -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);
@ -114,7 +121,6 @@ public abstract class GunItem extends Item implements CustomRendererItem {
}
// 冷却
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");

View file

@ -12,6 +12,7 @@ import javax.annotation.Nullable;
import java.util.ArrayList;
public final class Perks {
private final CompoundTag perks;
public Perks(GunData gun) {

View file

@ -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<GunData, PerkInstance, Void> tick;
public BiFunction<GunData, PerkInstance, Void> preReload;
public BiFunction<GunData, PerkInstance, Void> postReload;
public BiFunction<GunData, PerkInstance, Void> 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),

View file

@ -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);
}
}

View file

@ -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<Player> 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<Player> 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)));
}