重制部分功能perk

This commit is contained in:
17146 2025-05-07 13:09:14 +08:00 committed by Light_Quanta
parent 30c114af35
commit 90e76d7c92
No known key found for this signature in database
GPG key ID: 11A39A1B8C890959
7 changed files with 172 additions and 102 deletions

View file

@ -7,7 +7,6 @@ import com.atsuishio.superbwarfare.config.server.MiscConfig;
import com.atsuishio.superbwarfare.config.server.VehicleConfig; import com.atsuishio.superbwarfare.config.server.VehicleConfig;
import com.atsuishio.superbwarfare.entity.ICustomKnockback; import com.atsuishio.superbwarfare.entity.ICustomKnockback;
import com.atsuishio.superbwarfare.entity.TargetEntity; import com.atsuishio.superbwarfare.entity.TargetEntity;
import com.atsuishio.superbwarfare.entity.projectile.ProjectileEntity;
import com.atsuishio.superbwarfare.entity.vehicle.LaserTowerEntity; import com.atsuishio.superbwarfare.entity.vehicle.LaserTowerEntity;
import com.atsuishio.superbwarfare.entity.vehicle.base.ArmedVehicleEntity; import com.atsuishio.superbwarfare.entity.vehicle.base.ArmedVehicleEntity;
import com.atsuishio.superbwarfare.entity.vehicle.base.ContainerMobileVehicleEntity; import com.atsuishio.superbwarfare.entity.vehicle.base.ContainerMobileVehicleEntity;
@ -496,22 +495,11 @@ public class LivingEventHandler {
if (instance != null) { if (instance != null) {
instance.perk().onHit(damage, data, instance, event.getEntity(), source); instance.perk().onHit(damage, data, instance, event.getEntity(), source);
damage = instance.perk().getModifiedDamage(damage, data, instance, event.getEntity(), source); damage = instance.perk().getModifiedDamage(damage, data, instance, event.getEntity(), source);
if (instance.perk().shouldCancelHurtEvent(damage, data, instance, event.getEntity(), source)) {
event.setCanceled(true);
return;
} }
} }
if (source.getDirectEntity() instanceof ProjectileEntity projectile) {
if (data.perk.getLevel(ModPerks.FOURTH_TIMES_CHARM) > 0) {
float bypassArmorRate = projectile.getBypassArmorRate();
if (bypassArmorRate >= 1.0f && source.is(ModDamageTypes.GUN_FIRE_HEADSHOT_ABSOLUTE)) {
handleFourthTimesCharm(stack);
} else if (source.is(ModDamageTypes.GUN_FIRE_HEADSHOT)) {
handleFourthTimesCharm(stack);
}
}
if (!projectile.isZoom()) {
handleFieldDoctor(stack, event, attacker);
}
} }
event.setAmount(damage); event.setAmount(damage);
@ -544,67 +532,6 @@ public class LivingEventHandler {
instance.perk().onKill(data, instance, event.getEntity(), source); instance.perk().onKill(data, instance, event.getEntity(), source);
} }
} }
if (DamageTypeTool.isGunDamage(source)) {
handleSubsistence(stack, attacker);
}
}
private static void handleFourthTimesCharm(ItemStack stack) {
var data = GunData.from(stack);
int level = data.perk.getLevel(ModPerks.FOURTH_TIMES_CHARM);
if (level == 0) return;
final var tag = data.perk.getTag(ModPerks.FOURTH_TIMES_CHARM);
int fourthTimesCharmTick = tag.getInt("FourthTimesCharmTick");
if (fourthTimesCharmTick <= 0) {
tag.putInt("FourthTimesCharmTick", 40 + 10 * level);
tag.putInt("FourthTimesCharmCount", 1);
} else {
int count = tag.getInt("FourthTimesCharmCount");
if (count < 4) {
tag.putInt("FourthTimesCharmCount", Math.min(4, count + 1));
}
}
data.save();
}
private static void handleSubsistence(ItemStack stack, Player player) {
var data = GunData.from(stack);
int level = data.perk.getLevel(ModPerks.SUBSISTENCE);
if (level == 0) return;
float rate = level * 0.1f + (stack.is(ModTags.Items.SMG) || stack.is(ModTags.Items.RIFLE) ? 0.07f : 0f);
int mag = data.magazine();
int ammo = data.ammo.get();
int ammoReload = (int) Math.min(mag, mag * rate);
int ammoNeed = Math.min(mag - ammo, ammoReload);
boolean flag = player.isCreative() || InventoryTool.hasCreativeAmmoBox(player);
int ammoFinal = Math.min(data.countBackupAmmo(player), ammoNeed);
if (flag) {
ammoFinal = ammoNeed;
} else {
data.consumeBackupAmmo(player, ammoFinal);
}
data.ammo.set(Math.min(mag, ammo + ammoFinal));
data.save();
}
private static void handleFieldDoctor(ItemStack stack, LivingIncomingDamageEvent event, Player player) {
var data = GunData.from(stack);
int level = data.perk.getLevel(ModPerks.FIELD_DOCTOR);
if (level == 0) return;
if (event.getEntity().isAlliedTo(player)) {
event.getEntity().heal(event.getAmount() * Math.min(1.0f, 0.25f + 0.05f * level));
event.setCanceled(true);
}
} }
@SubscribeEvent @SubscribeEvent

View file

@ -4,7 +4,10 @@ import com.atsuishio.superbwarfare.Mod;
import com.atsuishio.superbwarfare.perk.AmmoPerk; import com.atsuishio.superbwarfare.perk.AmmoPerk;
import com.atsuishio.superbwarfare.perk.Perk; import com.atsuishio.superbwarfare.perk.Perk;
import com.atsuishio.superbwarfare.perk.damage.*; import com.atsuishio.superbwarfare.perk.damage.*;
import com.atsuishio.superbwarfare.perk.functional.FieldDoctor;
import com.atsuishio.superbwarfare.perk.functional.FourthTimesCharm;
import com.atsuishio.superbwarfare.perk.functional.HealClip; import com.atsuishio.superbwarfare.perk.functional.HealClip;
import com.atsuishio.superbwarfare.perk.functional.Subsistence;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.world.effect.MobEffects; import net.minecraft.world.effect.MobEffects;
import net.neoforged.bus.api.IEventBus; import net.neoforged.bus.api.IEventBus;
@ -55,9 +58,9 @@ public class ModPerks {
public static final DeferredRegister<Perk> FUNC_PERKS = DeferredRegister.create(Mod.loc("perk"), Mod.MODID); public static final DeferredRegister<Perk> FUNC_PERKS = DeferredRegister.create(Mod.loc("perk"), Mod.MODID);
public static final DeferredHolder<Perk, Perk> HEAL_CLIP = FUNC_PERKS.register("heal_clip", HealClip::new); public static final DeferredHolder<Perk, Perk> HEAL_CLIP = FUNC_PERKS.register("heal_clip", HealClip::new);
public static final DeferredHolder<Perk, Perk> FOURTH_TIMES_CHARM = FUNC_PERKS.register("fourth_times_charm", () -> new Perk("fourth_times_charm", Perk.Type.FUNCTIONAL)); public static final DeferredHolder<Perk, Perk> FOURTH_TIMES_CHARM = FUNC_PERKS.register("fourth_times_charm", FourthTimesCharm::new);
public static final DeferredHolder<Perk, Perk> SUBSISTENCE = FUNC_PERKS.register("subsistence", () -> new Perk("subsistence", Perk.Type.FUNCTIONAL)); public static final DeferredHolder<Perk, Perk> SUBSISTENCE = FUNC_PERKS.register("subsistence", Subsistence::new);
public static final DeferredHolder<Perk, Perk> FIELD_DOCTOR = FUNC_PERKS.register("field_doctor", () -> new Perk("field_doctor", Perk.Type.FUNCTIONAL)); public static final DeferredHolder<Perk, Perk> FIELD_DOCTOR = FUNC_PERKS.register("field_doctor", FieldDoctor::new);
public static final DeferredHolder<Perk, Perk> REGENERATION = FUNC_PERKS.register("regeneration", () -> new Perk("regeneration", Perk.Type.FUNCTIONAL)); public static final DeferredHolder<Perk, Perk> REGENERATION = FUNC_PERKS.register("regeneration", () -> new Perk("regeneration", Perk.Type.FUNCTIONAL));
public static final DeferredHolder<Perk, Perk> TURBO_CHARGER = FUNC_PERKS.register("turbo_charger", () -> new Perk("turbo_charger", Perk.Type.FUNCTIONAL)); public static final DeferredHolder<Perk, Perk> TURBO_CHARGER = FUNC_PERKS.register("turbo_charger", () -> new Perk("turbo_charger", Perk.Type.FUNCTIONAL));
public static final DeferredHolder<Perk, Perk> POWERFUL_ATTRACTION = FUNC_PERKS.register("powerful_attraction", () -> new Perk("powerful_attraction", Perk.Type.FUNCTIONAL)); public static final DeferredHolder<Perk, Perk> POWERFUL_ATTRACTION = FUNC_PERKS.register("powerful_attraction", () -> new Perk("powerful_attraction", Perk.Type.FUNCTIONAL));

View file

@ -100,7 +100,6 @@ public abstract class GunItem extends Item implements CustomRendererItem {
instance.perk().tick(data, instance, living); instance.perk().tick(data, instance, living);
} }
} }
handleGunPerks(data);
var hasBulletInBarrel = gunItem.hasBulletInBarrel(stack); var hasBulletInBarrel = gunItem.hasBulletInBarrel(stack);
var ammoCount = data.ammo.get(); var ammoCount = data.ammo.get();
@ -197,28 +196,6 @@ public abstract class GunItem extends Item implements CustomRendererItem {
return false; return false;
} }
private void handleGunPerks(GunData data) {
var perk = data.perk;
perk.reduceCooldown(ModPerks.FOURTH_TIMES_CHARM, "FourthTimesCharmTick");
if (perk.getLevel(ModPerks.FOURTH_TIMES_CHARM) > 0) {
var tag = data.perk.getTag(ModPerks.FOURTH_TIMES_CHARM);
int count = perk.getTag(ModPerks.FOURTH_TIMES_CHARM).getInt("FourthTimesCharmCount");
if (count >= 4) {
tag.remove("FourthTimesCharmTick");
tag.remove("FourthTimesCharmCount");
int mag = data.magazine();
data.ammo.set(Math.min(mag, data.ammo.get() + 2));
}
}
data.save();
}
public boolean canApplyPerk(Perk perk) { public boolean canApplyPerk(Perk perk) {
return true; return true;
} }

View file

@ -83,6 +83,10 @@ public class Perk {
public void onChangeSlot(GunData data, PerkInstance instance, @Nullable LivingEntity living) { public void onChangeSlot(GunData data, PerkInstance instance, @Nullable LivingEntity living) {
} }
public boolean shouldCancelHurtEvent(float damage, GunData data, PerkInstance instance, LivingEntity target, DamageSource source) {
return false;
}
public enum Type { public enum Type {
AMMO("Ammo", ChatFormatting.YELLOW), AMMO("Ammo", ChatFormatting.YELLOW),
FUNCTIONAL("Functional", ChatFormatting.GREEN), FUNCTIONAL("Functional", ChatFormatting.GREEN),

View file

@ -0,0 +1,44 @@
package com.atsuishio.superbwarfare.perk.functional;
import com.atsuishio.superbwarfare.entity.projectile.ProjectileEntity;
import com.atsuishio.superbwarfare.item.gun.data.GunData;
import com.atsuishio.superbwarfare.perk.Perk;
import com.atsuishio.superbwarfare.perk.PerkInstance;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.projectile.Projectile;
public class FieldDoctor extends Perk {
public FieldDoctor() {
super("field_doctor", Perk.Type.FUNCTIONAL);
}
@Override
public void onHit(float damage, GunData data, PerkInstance instance, LivingEntity target, DamageSource source) {
if (!trigger(target, source)) {
return;
}
target.heal(damage * Math.min(1.0f, 0.25f + 0.05f * instance.level()));
}
@Override
public boolean shouldCancelHurtEvent(float damage, GunData data, PerkInstance instance, LivingEntity target, DamageSource source) {
return trigger(target, source);
}
public boolean trigger(LivingEntity target, DamageSource source) {
if (source.getDirectEntity() instanceof ProjectileEntity projectile && !projectile.isZoom()) {
Player attacker = null;
if (source.getEntity() instanceof Player player) {
attacker = player;
}
if (source.getDirectEntity() instanceof Projectile p && p.getOwner() instanceof Player player) {
attacker = player;
}
return attacker != null && target != null && target.isAlliedTo(attacker);
}
return false;
}
}

View file

@ -0,0 +1,58 @@
package com.atsuishio.superbwarfare.perk.functional;
import com.atsuishio.superbwarfare.entity.projectile.ProjectileEntity;
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 net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.LivingEntity;
import org.jetbrains.annotations.Nullable;
public class FourthTimesCharm extends Perk {
public FourthTimesCharm() {
super("fourth_times_charm", Perk.Type.FUNCTIONAL);
}
@Override
public void tick(GunData data, PerkInstance instance, @Nullable LivingEntity living) {
data.perk.reduceCooldown(this, "FourthTimesCharmTick");
var tag = data.perk.getTag(this);
int count = tag.getInt("FourthTimesCharmCount");
if (count >= 4) {
tag.remove("FourthTimesCharmTick");
tag.remove("FourthTimesCharmCount");
int mag = data.magazine();
data.ammo.set(Math.min(mag, data.ammo.get() + 2));
}
}
@Override
public void onHit(float damage, GunData data, PerkInstance instance, LivingEntity target, DamageSource source) {
if (source.getDirectEntity() instanceof ProjectileEntity projectile) {
float bypassArmorRate = projectile.getBypassArmorRate();
if (bypassArmorRate >= 1.0f && source.is(ModDamageTypes.GUN_FIRE_HEADSHOT_ABSOLUTE)) {
handleFourthTimesCharm(data, instance);
} else if (source.is(ModDamageTypes.GUN_FIRE_HEADSHOT)) {
handleFourthTimesCharm(data, instance);
}
}
}
public void handleFourthTimesCharm(GunData data, PerkInstance instance) {
int fourthTimesCharmTick = data.perk.getTag(this).getInt("FourthTimesCharmTick");
if (fourthTimesCharmTick <= 0) {
data.perk.getTag(this).putInt("FourthTimesCharmTick", 40 + 10 * instance.level());
data.perk.getTag(this).putInt("FourthTimesCharmCount", 1);
} else {
int count = data.perk.getTag(this).getInt("FourthTimesCharmCount");
if (count < 4) {
data.perk.getTag(this).putInt("FourthTimesCharmCount", Math.min(4, count + 1));
}
}
}
}

View file

@ -0,0 +1,57 @@
package com.atsuishio.superbwarfare.perk.functional;
import com.atsuishio.superbwarfare.init.ModAttachments;
import com.atsuishio.superbwarfare.init.ModTags;
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 com.atsuishio.superbwarfare.tools.InventoryTool;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.projectile.Projectile;
import net.minecraft.world.item.ItemStack;
public class Subsistence extends Perk {
public Subsistence() {
super("subsistence", Perk.Type.FUNCTIONAL);
}
@Override
public void onKill(GunData data, PerkInstance instance, LivingEntity target, DamageSource source) {
Player attacker = null;
if (source.getEntity() instanceof Player player) {
attacker = player;
}
if (source.getDirectEntity() instanceof Projectile p && p.getOwner() instanceof Player player) {
attacker = player;
}
if (DamageTypeTool.isGunDamage(source) && attacker != null) {
ItemStack stack = data.stack;
float rate = instance.level() * (0.1f + (stack.is(ModTags.Items.SMG) || stack.is(ModTags.Items.RIFLE) ? 0.07f : 0f));
var cap = attacker.getData(ModAttachments.PLAYER_VARIABLE).watch();
int mag = data.magazine();
int ammo = data.ammo.get();
int ammoReload = (int) Math.min(mag, mag * rate);
int ammoNeed = Math.min(mag - ammo, ammoReload);
boolean flag = attacker.isCreative() || InventoryTool.hasCreativeAmmoBox(attacker);
int ammoFinal = Math.min(data.countBackupAmmo(attacker), ammoNeed);
if (flag) {
ammoFinal = ammoNeed;
} else {
data.consumeBackupAmmo(attacker, ammoFinal);
}
data.ammo.set(Math.min(mag, ammo + ammoFinal));
cap.sync(attacker);
}
}
}