superb-warfare/src/main/java/com/atsuishio/superbwarfare/event/GunEventHandler.java
2025-04-02 03:55:43 +08:00

910 lines
42 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.atsuishio.superbwarfare.event;
import com.atsuishio.superbwarfare.Mod;
import com.atsuishio.superbwarfare.capability.ModCapabilities;
import com.atsuishio.superbwarfare.capability.player.PlayerVariable;
import com.atsuishio.superbwarfare.entity.projectile.ProjectileEntity;
import com.atsuishio.superbwarfare.event.events.ReloadEvent;
import com.atsuishio.superbwarfare.init.ModItems;
import com.atsuishio.superbwarfare.init.ModPerks;
import com.atsuishio.superbwarfare.init.ModSounds;
import com.atsuishio.superbwarfare.init.ModTags;
import com.atsuishio.superbwarfare.item.gun.GunItem;
import com.atsuishio.superbwarfare.perk.AmmoPerk;
import com.atsuishio.superbwarfare.perk.Perk;
import com.atsuishio.superbwarfare.perk.PerkHelper;
import com.atsuishio.superbwarfare.tools.*;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.ClipContext;
import net.minecraft.world.phys.Vec3;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.capabilities.Capabilities;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.event.tick.PlayerTickEvent;
import java.util.ArrayList;
@EventBusSubscriber(modid = Mod.MODID)
public class GunEventHandler {
@SubscribeEvent
public static void onPlayerTick(PlayerTickEvent.Post event) {
Player player = event.getEntity();
ItemStack stack = player.getMainHandItem();
var tag = NBTTool.getTag(stack);
if (stack.is(ModTags.Items.GUN)) {
handleGunBolt(player, tag);
handleGunReload(player, tag);
handleGunSingleReload(player, tag);
handleSentinelCharge(player, tag);
}
NBTTool.saveTag(stack, tag);
}
/**
* 拉大栓
*/
private static void handleGunBolt(Player player, final CompoundTag tag) {
ItemStack stack = player.getMainHandItem();
if (stack.is(ModTags.Items.NORMAL_GUN)) {
var data = tag.getCompound("GunData");
if (GunsTool.getGunIntTag(tag, "BoltActionTick") > 0) {
data.putInt("BoltActionTick", GunsTool.getGunIntTag(tag, "BoltActionTick") - 1);
}
if (stack.getItem() == ModItems.MARLIN.get() && GunsTool.getGunIntTag(tag, "BoltActionTick") == 9) {
tag.putBoolean("empty", false);
}
if (GunsTool.getGunIntTag(tag, "BoltActionTick") == 1) {
GunsTool.setGunBooleanTag(tag, "NeedBoltAction", false);
if (stack.is(ModTags.Items.REVOLVER)) {
tag.putBoolean("canImmediatelyShoot", true);
}
}
}
}
/**
* 根据武器的注册名来寻找音效并播放
*/
public static void playGunSounds(Player player) {
ItemStack stack = player.getMainHandItem();
if (!stack.is(ModTags.Items.GUN)) return;
final var tag = NBTTool.getTag(stack);
if (!player.level().isClientSide) {
String origin = stack.getItem().getDescriptionId();
String name = origin.substring(origin.lastIndexOf(".") + 1);
if (stack.getItem() == ModItems.SENTINEL.get()) {
var cap = stack.getCapability(Capabilities.EnergyStorage.ITEM);
if (cap != null && cap.getEnergyStored() > 0) {
float soundRadius = (float) GunsTool.getGunDoubleTag(tag, "SoundRadius");
SoundEvent sound3p = BuiltInRegistries.SOUND_EVENT.get(Mod.loc("sentinel_charge_fire_3p"));
if (sound3p != null) {
player.playSound(sound3p, soundRadius * 0.4f, 1f);
}
SoundEvent soundFar = BuiltInRegistries.SOUND_EVENT.get(Mod.loc("sentinel_charge_far"));
if (soundFar != null) {
player.playSound(soundFar, soundRadius * 0.7f, 1f);
}
SoundEvent soundVeryFar = BuiltInRegistries.SOUND_EVENT.get(Mod.loc("sentinel_charge_veryfar"));
if (soundVeryFar != null) {
player.playSound(soundVeryFar, soundRadius, 1f);
}
return;
}
}
var perk = PerkHelper.getPerkByType(tag, Perk.Type.AMMO);
if (perk == ModPerks.BEAST_BULLET.get()) {
player.playSound(ModSounds.HENG.get(), 4f, 1f);
}
float soundRadius = (float) (GunsTool.getGunDoubleTag(tag, "SoundRadius") * GunsTool.getGunDoubleTag(tag, "CustomSoundRadius", 1));
int barrelType = GunsTool.getAttachmentType(tag, GunsTool.AttachmentType.BARREL);
SoundEvent sound3p = BuiltInRegistries.SOUND_EVENT.get(Mod.loc(name + (barrelType == 2 ? "_fire_3p_s" : "_fire_3p")));
if (sound3p != null) {
player.playSound(sound3p, soundRadius * 0.4f, 1f);
}
SoundEvent soundFar = BuiltInRegistries.SOUND_EVENT.get(Mod.loc(name + (barrelType == 2 ? "_far_s" : "_far")));
if (soundFar != null) {
player.playSound(soundFar, soundRadius * 0.7f, 1f);
}
SoundEvent soundVeryFar = BuiltInRegistries.SOUND_EVENT.get(Mod.loc(name + (barrelType == 2 ? "_veryfar_s" : "_veryfar")));
if (soundVeryFar != null) {
player.playSound(soundVeryFar, soundRadius, 1f);
}
}
}
public static void playGunBoltSounds(Player player) {
ItemStack stack = player.getMainHandItem();
if (!stack.is(ModTags.Items.GUN)) return;
final var tag = NBTTool.getTag(stack);
if (!player.level().isClientSide) {
String origin = stack.getItem().getDescriptionId();
String name = origin.substring(origin.lastIndexOf(".") + 1);
SoundEvent sound1p = BuiltInRegistries.SOUND_EVENT.get(Mod.loc(name + "_bolt"));
if (sound1p != null && player instanceof ServerPlayer serverPlayer) {
SoundTool.playLocalSound(serverPlayer, sound1p, 2f, 1f);
double shooterHeight = player.getEyePosition().distanceTo((Vec3.atLowerCornerOf(player.level().clip(new ClipContext(player.getEyePosition(), player.getEyePosition().add(new Vec3(0, -1, 0).scale(10)),
ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player)).getBlockPos())));
if (stack.is(ModTags.Items.REVOLVER)) return;
Mod.queueServerWork((int) (GunsTool.getGunDoubleTag(tag, "BoltActionTime", 0) / 2 + 1.5 * shooterHeight), () -> {
if (stack.is(ModTags.Items.SHOTGUN)) {
SoundTool.playLocalSound(serverPlayer, ModSounds.SHELL_CASING_SHOTGUN.get(), (float) Math.max(0.75 - 0.12 * shooterHeight, 0), 1);
} else if (stack.is(ModTags.Items.SNIPER_RIFLE)) {
SoundTool.playLocalSound(serverPlayer, ModSounds.SHELL_CASING_50CAL.get(), (float) Math.max(1 - 0.15 * shooterHeight, 0), 1);
} else {
SoundTool.playLocalSound(serverPlayer, ModSounds.SHELL_CASING_NORMAL.get(), (float) Math.max(1.5 - 0.2 * shooterHeight, 0), 1);
}
});
}
}
}
public static void gunShoot(Player player, final CompoundTag tag, double spared) {
ItemStack stack = player.getMainHandItem();
if (!player.level().isClientSide()) {
float headshot = (float) GunsTool.getGunDoubleTag(tag, "Headshot", 0);
float damage = (float) (GunsTool.getGunDoubleTag(tag, "Damage", 0) +
GunsTool.getGunDoubleTag(tag, "ChargedDamage", 0)) * (float) perkDamage(tag);
float velocity = (float) ((GunsTool.getGunDoubleTag(tag, "Velocity", 0) + GunsTool.getGunDoubleTag(tag, "CustomVelocity", 0)) * perkSpeed(tag));
int projectileAmount = GunsTool.getGunIntTag(tag, "ProjectileAmount", 1);
float bypassArmorRate = (float) GunsTool.getGunDoubleTag(tag, "BypassesArmor", 0);
var cap = player.getCapability(ModCapabilities.PLAYER_VARIABLE);
boolean zoom = cap != null && cap.zoom;
var perk = PerkHelper.getPerkByType(tag, Perk.Type.AMMO);
if (perk != null && perk.descriptionId.equals("butterfly_bullet")) {
if (handleButterflyBullet(perk, stack, player)) return;
}
ProjectileEntity projectile = new ProjectileEntity(player.level())
.shooter(player)
.damage(perk instanceof AmmoPerk ammoPerk && ammoPerk.slug ? projectileAmount * damage : damage)
.damage(damage)
.headShot(headshot)
.zoom(zoom);
if (perk instanceof AmmoPerk ammoPerk) {
int level = PerkHelper.getItemPerkLevel(perk, tag);
bypassArmorRate += ammoPerk.bypassArmorRate + (perk == ModPerks.AP_BULLET.get() ? 0.05f * (level - 1) : 0);
projectile.setRGB(ammoPerk.rgb);
if (!ammoPerk.mobEffects.get().isEmpty()) {
int amplifier;
if (perk.descriptionId.equals("blade_bullet")) {
amplifier = level / 3;
} else if (perk.descriptionId.equals("bread_bullet")) {
amplifier = 1;
} else {
amplifier = level - 1;
}
ArrayList<MobEffectInstance> mobEffectInstances = new ArrayList<>();
for (MobEffect effect : ammoPerk.mobEffects.get()) {
mobEffectInstances.add(new MobEffectInstance(Holder.direct(effect), 70 + 30 * level, amplifier));
}
projectile.effect(mobEffectInstances);
}
if (perk.descriptionId.equals("bread_bullet")) {
projectile.knockback(level * 0.3f);
projectile.forceKnockback();
}
}
bypassArmorRate = Math.max(bypassArmorRate, 0);
projectile.bypassArmorRate(bypassArmorRate);
if (perk == ModPerks.SILVER_BULLET.get()) {
int level = PerkHelper.getItemPerkLevel(perk, tag);
projectile.undeadMultiple(1.0f + 0.5f * level);
} else if (perk == ModPerks.BEAST_BULLET.get()) {
projectile.beast();
} else if (perk == ModPerks.JHP_BULLET.get()) {
int level = PerkHelper.getItemPerkLevel(perk, tag);
projectile.jhpBullet(level);
} else if (perk == ModPerks.HE_BULLET.get()) {
int level = PerkHelper.getItemPerkLevel(perk, tag);
projectile.heBullet(level);
} else if (perk == ModPerks.INCENDIARY_BULLET.get()) {
int level = PerkHelper.getItemPerkLevel(perk, tag);
projectile.fireBullet(level, stack.is(ModTags.Items.SHOTGUN));
}
var dmgPerk = PerkHelper.getPerkByType(tag, Perk.Type.DAMAGE);
if (dmgPerk == ModPerks.MONSTER_HUNTER.get()) {
int level = PerkHelper.getItemPerkLevel(dmgPerk, tag);
projectile.monsterMultiple(0.1f + 0.1f * level);
}
projectile.setPos(player.getX() - 0.1 * player.getLookAngle().x, player.getEyeY() - 0.1 - 0.1 * player.getLookAngle().y, player.getZ() + -0.1 * player.getLookAngle().z);
projectile.shoot(player, player.getLookAngle().x, player.getLookAngle().y + 0.001f, player.getLookAngle().z, stack.is(ModTags.Items.SHOTGUN) && perk == ModPerks.INCENDIARY_BULLET.get() ? 4.5f : velocity, (float) spared);
player.level().addFreshEntity(projectile);
}
}
public static double perkDamage(final CompoundTag tag) {
var perk = PerkHelper.getPerkByType(tag, Perk.Type.AMMO);
if (perk instanceof AmmoPerk ammoPerk) {
return ammoPerk.damageRate;
}
return 1;
}
public static double perkSpeed(final CompoundTag tag) {
var perk = PerkHelper.getPerkByType(tag, Perk.Type.AMMO);
if (perk instanceof AmmoPerk ammoPerk) {
return ammoPerk.speedRate;
}
return 1;
}
// TODO 这还有联动的必要吗(
private static boolean handleButterflyBullet(Perk perk, ItemStack heldItem, Player player) {
return true;
// int perkLevel = PerkHelper.getItemPerkLevel(perk, tag);
//
// var entityType = CompatHolder.VRC_RAIN_SHOWER_BUTTERFLY;
// if (entityType != null) {
// Projectile projectile = entityType.create(player.level());
//
// float inaccuracy = Math.max(0.0f, 1.1f - perkLevel * .1f);
// projectile.setOwner(player);
// projectile.setPos(player.getX() - 0.1 * player.getLookAngle().x,
// player.getEyeY() - 0.1 - 0.1 * player.getLookAngle().y, player.getZ() + -0.1 * player.getLookAngle().z);
//
// Vec3 vec3 = (new Vec3(player.getLookAngle().x, player.getLookAngle().y + 0.001f, player.getLookAngle().z)).normalize().scale(1.2).
// add(player.level().random.triangle(0.0D, 0.0172275D * (double) inaccuracy),
// player.level().random.triangle(0.0D, 0.0172275D * (double) inaccuracy),
// player.level().random.triangle(0.0D, 0.0172275D * (double) inaccuracy)).
// add(player.getDeltaMovement().x, player.onGround() ? 0.0 : 0.05 * player.getDeltaMovement().y, player.getDeltaMovement().z).
// scale(5.0f);
// projectile.setDeltaMovement(vec3);
// projectile.setYRot((float) (Mth.atan2(vec3.x, vec3.z) * (double) (180F / (float) Math.PI)));
// projectile.setXRot((float) (Mth.atan2(vec3.y, vec3.horizontalDistance()) * (double) (180F / (float) Math.PI)));
// projectile.yRotO = projectile.getYRot();
// projectile.xRotO = projectile.getXRot();
//
// projectile.setNoGravity(true);
// player.level().addFreshEntity(projectile);
// return true;
// }
//
// return false;
}
/**
* 通用的武器换弹流程
*/
private static void handleGunReload(Player player, final CompoundTag tag) {
ItemStack stack = player.getMainHandItem();
if (!(stack.getItem() instanceof GunItem gunItem)) return;
final CompoundTag data = tag.getCompound("GunData");
// 启动换弹
if (GunsTool.getGunBooleanTag(tag, "StartReload")) {
NeoForge.EVENT_BUS.post(new ReloadEvent.Pre(player, stack));
if (gunItem.isOpenBolt(stack)) {
if (GunsTool.getGunIntTag(tag, "Ammo", 0) == 0) {
data.putInt("ReloadTime", data.getInt("EmptyReloadTime") + 1);
tag.putBoolean("is_empty_reloading", true);
playGunEmptyReloadSounds(player);
} else {
data.putInt("ReloadTime", data.getInt("NormalReloadTime") + 1);
tag.putBoolean("is_normal_reloading", true);
playGunNormalReloadSounds(player);
}
} else {
data.putInt("ReloadTime", data.getInt("EmptyReloadTime") + 2);
tag.putBoolean("is_empty_reloading", true);
playGunEmptyReloadSounds(player);
}
data.putBoolean("StartReload", false);
}
if (data.getInt("ReloadTime") > 0) {
data.putInt("ReloadTime", data.getInt("ReloadTime") - 1);
}
if (stack.getItem() == ModItems.RPG.get()) {
if (data.getInt("ReloadTime") == 84) {
tag.putBoolean("empty", false);
}
if (data.getInt("ReloadTime") == 9) {
data.putBoolean("CloseHammer", false);
}
}
if (stack.getItem() == ModItems.MK_14.get()) {
if (data.getInt("ReloadTime") == 18) {
data.putBoolean("HoldOpen", false);
}
}
if (stack.getItem() == ModItems.SVD.get()) {
if (data.getInt("ReloadTime") == 17) {
data.putBoolean("HoldOpen", false);
}
}
if (stack.getItem() == ModItems.SKS.get()) {
if (data.getInt("ReloadTime") == 14) {
data.putBoolean("HoldOpen", false);
}
}
if (stack.getItem() == ModItems.M_60.get()) {
if (data.getInt("ReloadTime") == 55) {
data.putBoolean("HideBulletChain", false);
}
}
if (stack.getItem() == ModItems.GLOCK_17.get() || stack.getItem() == ModItems.GLOCK_18.get() || stack.getItem() == ModItems.M_1911.get() || stack.getItem() == ModItems.MP_443.get()) {
if (data.getInt("ReloadTime") == 9) {
data.putBoolean("HoldOpen", false);
}
}
if (stack.getItem() == ModItems.QBZ_95.get()) {
if (data.getInt("ReloadTime") == 14) {
data.putBoolean("HoldOpen", false);
}
}
if (data.getInt("ReloadTime") == 1) {
if (gunItem.isOpenBolt(stack)) {
if (GunsTool.getGunIntTag(tag, "Ammo", 0) == 0) {
playGunEmptyReload(player, tag);
} else {
playGunNormalReload(player, tag);
}
} else {
playGunEmptyReload(player, tag);
}
data.putBoolean("StartReload", false);
}
tag.put("GunData", data);
}
public static void playGunNormalReload(Player player, final CompoundTag tag) {
ItemStack stack = player.getMainHandItem();
if (!(stack.getItem() instanceof GunItem gunItem)) return;
if (player.getInventory().hasAnyMatching(item -> item.is(ModItems.CREATIVE_AMMO_BOX.get()))) {
var data = tag.getCompound("GunData");
data.putInt("Ammo", data.getInt("Magazine") + data.getInt("CustomMagazine") + (gunItem.hasBulletInBarrel(stack) ? 1 : 0));
} else {
if (stack.is(ModTags.Items.USE_SHOTGUN_AMMO)) {
GunsTool.reload(player, stack, tag, AmmoType.SHOTGUN, gunItem.hasBulletInBarrel(stack));
} else if (stack.is(ModTags.Items.USE_SNIPER_AMMO)) {
GunsTool.reload(player, stack, tag, AmmoType.SNIPER, true);
} else if (stack.is(ModTags.Items.USE_HANDGUN_AMMO)) {
GunsTool.reload(player, stack, tag, AmmoType.HANDGUN, true);
} else if (stack.is(ModTags.Items.USE_RIFLE_AMMO)) {
GunsTool.reload(player, stack, tag, AmmoType.RIFLE, gunItem.hasBulletInBarrel(stack));
} else if (stack.is(ModTags.Items.USE_HEAVY_AMMO)) {
GunsTool.reload(player, stack, tag, AmmoType.HEAVY, gunItem.hasBulletInBarrel(stack));
}
}
tag.putBoolean("is_normal_reloading", false);
tag.putBoolean("is_empty_reloading", false);
NeoForge.EVENT_BUS.post(new ReloadEvent.Post(player, stack));
}
public static void playGunEmptyReload(Player player, final CompoundTag tag) {
ItemStack stack = player.getMainHandItem();
var data = tag.getCompound("GunData");
if (player.getInventory().hasAnyMatching(item -> item.is(ModItems.CREATIVE_AMMO_BOX.get()))) {
data.putInt("Ammo", data.getInt("Magazine") + data.getInt("CustomMagazine"));
} else {
if (stack.is(ModTags.Items.USE_SHOTGUN_AMMO)) {
GunsTool.reload(player, stack, tag, AmmoType.SHOTGUN);
} else if (stack.is(ModTags.Items.USE_SNIPER_AMMO)) {
GunsTool.reload(player, stack, tag, AmmoType.SNIPER);
} else if (stack.is(ModTags.Items.USE_HANDGUN_AMMO)) {
GunsTool.reload(player, stack, tag, AmmoType.HANDGUN);
} else if (stack.is(ModTags.Items.USE_RIFLE_AMMO)) {
GunsTool.reload(player, stack, tag, AmmoType.RIFLE);
} else if (stack.is(ModTags.Items.USE_HEAVY_AMMO)) {
GunsTool.reload(player, stack, tag, AmmoType.HEAVY);
} else if (stack.getItem() == ModItems.TASER.get()) {
data.putInt("Ammo", 1);
player.getInventory().clearOrCountMatchingItems(p -> p.getItem() == ModItems.TASER_ELECTRODE.get(), 1, player.inventoryMenu.getCraftSlots());
} else if (stack.getItem() == ModItems.M_79.get()) {
data.putInt("Ammo", 1);
player.getInventory().clearOrCountMatchingItems(p -> p.getItem() == ModItems.GRENADE_40MM.get(), 1, player.inventoryMenu.getCraftSlots());
} else if (stack.getItem() == ModItems.RPG.get()) {
data.putInt("Ammo", 1);
player.getInventory().clearOrCountMatchingItems(p -> p.getItem() == ModItems.ROCKET.get(), 1, player.inventoryMenu.getCraftSlots());
} else if (stack.getItem() == ModItems.JAVELIN.get()) {
data.putInt("Ammo", 1);
player.getInventory().clearOrCountMatchingItems(p -> p.getItem() == ModItems.JAVELIN_MISSILE.get(), 1, player.inventoryMenu.getCraftSlots());
}
}
tag.putBoolean("is_normal_reloading", false);
tag.putBoolean("is_empty_reloading", false);
NeoForge.EVENT_BUS.post(new ReloadEvent.Post(player, stack));
}
public static void playGunEmptyReloadSounds(Player player) {
ItemStack stack = player.getMainHandItem();
if (!stack.is(ModTags.Items.GUN)) {
return;
}
if (!player.level().isClientSide) {
String origin = stack.getItem().getDescriptionId();
String name = origin.substring(origin.lastIndexOf(".") + 1);
SoundEvent sound1p = BuiltInRegistries.SOUND_EVENT.get(Mod.loc(name + "_reload_empty"));
if (sound1p != null && player instanceof ServerPlayer serverPlayer) {
SoundTool.playLocalSound(serverPlayer, sound1p, 10f, 1f);
}
}
}
public static void playGunNormalReloadSounds(Player player) {
ItemStack stack = player.getMainHandItem();
if (!stack.is(ModTags.Items.GUN)) {
return;
}
if (!player.level().isClientSide) {
String origin = stack.getItem().getDescriptionId();
String name = origin.substring(origin.lastIndexOf(".") + 1);
SoundEvent sound1p;
sound1p = BuiltInRegistries.SOUND_EVENT.get(Mod.loc(name + "_reload_normal"));
if (sound1p != null && player instanceof ServerPlayer serverPlayer) {
SoundTool.playLocalSound(serverPlayer, sound1p, 10f, 1f);
}
}
}
/**
* 单发装填类的武器换弹流程
*/
private static void handleGunSingleReload(Player player, final CompoundTag tag) {
ItemStack stack = player.getMainHandItem();
if (!(stack.getItem() instanceof GunItem)) return;
// 换弹流程计时器
if (tag.getDouble("prepare") > 0) {
tag.putDouble("prepare", tag.getDouble("prepare") - 1);
}
if (tag.getDouble("prepare_load") > 0) {
tag.putDouble("prepare_load", tag.getDouble("prepare_load") - 1);
}
if (tag.getDouble("iterative") > 0) {
tag.putDouble("iterative", tag.getDouble("iterative") - 1);
}
if (tag.getDouble("finish") > 0) {
tag.putDouble("finish", tag.getDouble("finish") - 1);
}
// player.displayClientMessage(Component.literal("prepare: " + new DecimalFormat("##.#").format(tag.getDouble("prepare"))
// + " prepare_load: " + new DecimalFormat("##.#").format(tag.getDouble("prepare_load"))
// + " iterative: " + new DecimalFormat("##.#").format(tag.getDouble("iterative"))
// + " finish: " + new DecimalFormat("##.#").format(tag.getDouble("finish"))
// + " reload_stage: " + new DecimalFormat("##.#").format(tag.getDouble("reload_stage"))
// ), true);
// 一阶段
if (tag.getBoolean("start_single_reload")) {
NeoForge.EVENT_BUS.post(new ReloadEvent.Pre(player, stack));
if ((GunsTool.getGunIntTag(tag, "PrepareLoadTime", 0) != 0
&& GunsTool.getGunIntTag(tag, "Ammo", 0) == 0)
|| stack.is(ModItems.SECONDARY_CATACLYSM.get())
) {
// 此处判断空仓换弹的时候是否在准备阶段就需要装填一发如M870
playGunPrepareLoadReloadSounds(player);
int prepareLoadTime = GunsTool.getGunIntTag(tag, "PrepareLoadTime", 0);
tag.putInt("prepare_load", prepareLoadTime + 1);
player.getCooldowns().addCooldown(stack.getItem(), prepareLoadTime);
} else if (GunsTool.getGunIntTag(tag, "PrepareEmptyTime", 0) != 0 && GunsTool.getGunIntTag(tag, "Ammo", 0) == 0) {
// 此处判断空仓换弹,如莫辛纳甘
playGunEmptyPrepareSounds(player);
int prepareEmptyTime = GunsTool.getGunIntTag(tag, "PrepareEmptyTime", 0);
tag.putInt("prepare", prepareEmptyTime + 1);
player.getCooldowns().addCooldown(stack.getItem(), prepareEmptyTime);
} else {
playGunPrepareReloadSounds(player);
int prepareTime = GunsTool.getGunIntTag(tag, "PrepareTime", 0);
tag.putInt("prepare", prepareTime + 1);
player.getCooldowns().addCooldown(stack.getItem(), prepareTime);
}
tag.putBoolean("force_stop", false);
tag.putBoolean("stop", false);
tag.putInt("reload_stage", 1);
GunsTool.setGunBooleanTag(tag, "Reloading", true);
tag.putBoolean("start_single_reload", false);
}
if (stack.getItem() == ModItems.M_870.get() && tag.getInt("prepare_load") == 10) {
singleLoad(player, tag);
}
if (stack.getItem() == ModItems.SECONDARY_CATACLYSM.get() && tag.getInt("prepare_load") == 3) {
singleLoad(player, tag);
}
// 一阶段结束,检查备弹,如果有则二阶段启动,无则直接跳到三阶段
if ((tag.getDouble("prepare") == 1 || tag.getDouble("prepare_load") == 1)) {
if (!InventoryTool.hasCreativeAmmoBox(player)) {
var capability = player.getCapability(ModCapabilities.PLAYER_VARIABLE);
if (capability == null) capability = new PlayerVariable();
if (stack.is(ModTags.Items.USE_SHOTGUN_AMMO) && capability.shotgunAmmo == 0) {
tag.putBoolean("force_stage3_start", true);
} else if (stack.is(ModTags.Items.USE_SNIPER_AMMO) && capability.sniperAmmo == 0) {
tag.putBoolean("force_stage3_start", true);
} else if ((stack.is(ModTags.Items.USE_HANDGUN_AMMO) || stack.is(ModTags.Items.SMG)) && capability.handgunAmmo == 0) {
tag.putBoolean("force_stage3_start", true);
} else if (stack.is(ModTags.Items.USE_RIFLE_AMMO) && capability.rifleAmmo == 0) {
tag.putBoolean("force_stage3_start", true);
} else if (stack.is(ModTags.Items.USE_HEAVY_AMMO) && capability.heavyAmmo == 0) {
tag.putBoolean("force_stage3_start", true);
} else if (stack.is(ModTags.Items.LAUNCHER) && GunsTool.getGunIntTag(tag, "MaxAmmo") == 0) {
tag.putBoolean("force_stage3_start", true);
} else if (stack.is(ModItems.SECONDARY_CATACLYSM.get()) && GunsTool.getGunIntTag(tag, "Ammo", 0) >= GunsTool.getGunIntTag(tag, "Magazine", 0)) {
tag.putBoolean("force_stage3_start", true);
} else {
tag.putInt("reload_stage", 2);
}
} else {
if (stack.is(ModItems.SECONDARY_CATACLYSM.get()) && GunsTool.getGunIntTag(tag, "Ammo", 0) >= GunsTool.getGunIntTag(tag, "Magazine", 0)) {
tag.putBoolean("force_stage3_start", true);
} else {
tag.putInt("reload_stage", 2);
}
}
// 检查备弹
}
// 强制停止换弹,进入三阶段
if (tag.getBoolean("force_stop") && tag.getInt("reload_stage") == 2 && tag.getInt("iterative") > 0) {
tag.putBoolean("stop", true);
}
// 二阶段
if ((tag.getDouble("prepare") == 0 || tag.getDouble("prepare_load") == 0)
&& tag.getInt("reload_stage") == 2
&& tag.getInt("iterative") == 0
&& !tag.getBoolean("stop")
&& GunsTool.getGunIntTag(tag, "Ammo", 0) < GunsTool.getGunIntTag(tag, "Magazine", 0)
+ GunsTool.getGunIntTag(tag, "CustomMagazine", 0)) {
playGunLoopReloadSounds(player);
int iterativeTime = GunsTool.getGunIntTag(tag, "IterativeTime", 0);
tag.putDouble("iterative", iterativeTime);
player.getCooldowns().addCooldown(stack.getItem(), iterativeTime);
// 动画播放nbt
if (tag.getDouble("load_index") == 1) {
tag.putDouble("load_index", 0);
} else {
tag.putDouble("load_index", 1);
}
}
// 装填
if ((stack.getItem() == ModItems.M_870.get()
|| stack.getItem() == ModItems.MARLIN.get())
&& tag.getInt("iterative") == 3
) {
singleLoad(player, tag);
}
if (stack.getItem() == ModItems.SECONDARY_CATACLYSM.get() && tag.getInt("iterative") == 16) {
singleLoad(player, tag);
}
if ((stack.getItem() == ModItems.K_98.get()
|| stack.getItem() == ModItems.MOSIN_NAGANT.get())
&& tag.getInt("iterative") == 1
) {
singleLoad(player, tag);
}
// 二阶段结束
if (tag.getInt("iterative") == 1) {
// 装满结束
if (GunsTool.getGunIntTag(tag, "Ammo", 0) >= GunsTool.getGunIntTag(tag, "Magazine", 0)
+ GunsTool.getGunIntTag(tag, "CustomMagazine", 0)) {
tag.putInt("reload_stage", 3);
}
// 备弹耗尽结束
if (!InventoryTool.hasCreativeAmmoBox(player)) {
var capability = player.getCapability(ModCapabilities.PLAYER_VARIABLE);
if (capability == null) capability = new PlayerVariable();
if (stack.is(ModTags.Items.USE_SHOTGUN_AMMO) && capability.shotgunAmmo == 0) {
tag.putInt("reload_stage", 3);
} else if (stack.is(ModTags.Items.USE_SNIPER_AMMO) && capability.sniperAmmo == 0) {
tag.putInt("reload_stage", 3);
} else if ((stack.is(ModTags.Items.USE_HANDGUN_AMMO) || stack.is(ModTags.Items.SMG)) && capability.handgunAmmo == 0) {
tag.putInt("reload_stage", 3);
} else if (stack.is(ModTags.Items.USE_RIFLE_AMMO) && capability.rifleAmmo == 0) {
tag.putInt("reload_stage", 3);
} else if (stack.is(ModTags.Items.USE_HEAVY_AMMO) && capability.heavyAmmo == 0) {
tag.putInt("reload_stage", 3);
}
}
// 强制结束
if (tag.getBoolean("stop")) {
tag.putInt("reload_stage", 3);
tag.putBoolean("force_stop", false);
tag.putBoolean("stop", false);
}
}
// 三阶段
if ((tag.getInt("iterative") == 1 && tag.getInt("reload_stage") == 3) || tag.getBoolean("force_stage3_start")) {
tag.putInt("reload_stage", 3);
tag.putBoolean("force_stage3_start", false);
int finishTime = GunsTool.getGunIntTag(tag, "FinishTime", 0);
tag.putInt("finish", finishTime + 2);
player.getCooldowns().addCooldown(stack.getItem(), finishTime + 2);
playGunEndReloadSounds(player);
}
if (stack.getItem() == ModItems.MARLIN.get() && tag.getInt("finish") == 10) {
tag.putBoolean("empty", false);
}
// 三阶段结束
if (tag.getInt("finish") == 1) {
tag.putInt("reload_stage", 0);
if (GunsTool.getGunIntTag(tag, "BoltActionTime", 0) > 0) {
GunsTool.setGunBooleanTag(tag, "NeedBoltAction", false);
}
GunsTool.setGunBooleanTag(tag, "Reloading", false);
tag.putBoolean("start_single_reload", false);
NeoForge.EVENT_BUS.post(new ReloadEvent.Post(player, stack));
}
}
public static void singleLoad(Player player, final CompoundTag tag) {
final var data = tag.getCompound("GunData");
data.putInt("Ammo", data.getInt("Ammo") + 1);
if (!InventoryTool.hasCreativeAmmoBox(player)) {
var cap = player.getCapability(ModCapabilities.PLAYER_VARIABLE);
if (cap == null) return;
ItemStack stack = player.getMainHandItem();
if (stack.is(ModTags.Items.USE_SHOTGUN_AMMO)) {
AmmoType.SHOTGUN.add(cap, -1);
} else if (stack.is(ModTags.Items.USE_SNIPER_AMMO)) {
AmmoType.SNIPER.add(cap, -1);
} else if (stack.is(ModTags.Items.USE_HANDGUN_AMMO)) {
AmmoType.HANDGUN.add(cap, -1);
} else if (stack.is(ModTags.Items.USE_RIFLE_AMMO)) {
AmmoType.RIFLE.add(cap, -1);
} else if (stack.is(ModTags.Items.USE_HEAVY_AMMO)) {
AmmoType.HEAVY.add(cap, -1);
} else if (stack.getItem() == ModItems.SECONDARY_CATACLYSM.get()) {
player.getInventory().clearOrCountMatchingItems(p -> p.getItem() == ModItems.GRENADE_40MM.get(), 1, player.inventoryMenu.getCraftSlots());
}
cap.syncPlayerVariables(player);
}
}
public static void playGunPrepareReloadSounds(Player player) {
ItemStack stack = player.getMainHandItem();
if (!stack.is(ModTags.Items.GUN)) return;
if (!player.level().isClientSide) {
String origin = stack.getItem().getDescriptionId();
String name = origin.substring(origin.lastIndexOf(".") + 1);
SoundEvent sound1p = BuiltInRegistries.SOUND_EVENT.get(Mod.loc(name + "_prepare"));
if (sound1p != null && player instanceof ServerPlayer serverPlayer) {
SoundTool.playLocalSound(serverPlayer, sound1p, 10f, 1f);
}
}
}
public static void playGunEmptyPrepareSounds(Player player) {
ItemStack stack = player.getMainHandItem();
if (!stack.is(ModTags.Items.GUN)) return;
final var tag = NBTTool.getTag(stack);
if (!player.level().isClientSide) {
String origin = stack.getItem().getDescriptionId();
String name = origin.substring(origin.lastIndexOf(".") + 1);
SoundEvent sound1p = BuiltInRegistries.SOUND_EVENT.get(Mod.loc(name + "_prepare_empty"));
if (sound1p != null && player instanceof ServerPlayer serverPlayer) {
SoundTool.playLocalSound(serverPlayer, sound1p, 10f, 1f);
double shooterHeight = player.getEyePosition().distanceTo((Vec3.atLowerCornerOf(player.level().clip(new ClipContext(player.getEyePosition(), player.getEyePosition().add(new Vec3(0, -1, 0).scale(10)),
ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player)).getBlockPos())));
Mod.queueServerWork((int) (GunsTool.getGunIntTag(tag, "PrepareEmptyTime", 0) / 2 + 3 + 1.5 * shooterHeight), () -> {
if (stack.is(ModTags.Items.SHOTGUN)) {
SoundTool.playLocalSound(serverPlayer, ModSounds.SHELL_CASING_SHOTGUN.get(), (float) Math.max(0.75 - 0.12 * shooterHeight, 0), 1);
} else if (stack.is(ModTags.Items.SNIPER_RIFLE) || stack.is(ModTags.Items.HEAVY_WEAPON)) {
SoundTool.playLocalSound(serverPlayer, ModSounds.SHELL_CASING_50CAL.get(), (float) Math.max(1 - 0.15 * shooterHeight, 0), 1);
} else {
SoundTool.playLocalSound(serverPlayer, ModSounds.SHELL_CASING_NORMAL.get(), (float) Math.max(1.5 - 0.2 * shooterHeight, 0), 1);
}
});
}
}
}
public static void playGunPrepareLoadReloadSounds(Player player) {
ItemStack stack = player.getMainHandItem();
if (!stack.is(ModTags.Items.GUN)) return;
if (!player.level().isClientSide) {
String origin = stack.getItem().getDescriptionId();
String name = origin.substring(origin.lastIndexOf(".") + 1);
SoundEvent sound1p = BuiltInRegistries.SOUND_EVENT.get(Mod.loc(name + "_prepare_load"));
if (sound1p != null && player instanceof ServerPlayer serverPlayer) {
SoundTool.playLocalSound(serverPlayer, sound1p, 10f, 1f);
double shooterHeight = player.getEyePosition().distanceTo((Vec3.atLowerCornerOf(player.level().clip(new ClipContext(player.getEyePosition(), player.getEyePosition().add(new Vec3(0, -1, 0).scale(10)),
ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player)).getBlockPos())));
Mod.queueServerWork((int) (8 + 1.5 * shooterHeight), () -> {
if (stack.is(ModTags.Items.SHOTGUN)) {
SoundTool.playLocalSound(serverPlayer, ModSounds.SHELL_CASING_SHOTGUN.get(), (float) Math.max(0.75 - 0.12 * shooterHeight, 0), 1);
} else if (stack.is(ModTags.Items.SNIPER_RIFLE) || stack.is(ModTags.Items.HEAVY_WEAPON)) {
SoundTool.playLocalSound(serverPlayer, ModSounds.SHELL_CASING_50CAL.get(), (float) Math.max(1 - 0.15 * shooterHeight, 0), 1);
} else {
SoundTool.playLocalSound(serverPlayer, ModSounds.SHELL_CASING_NORMAL.get(), (float) Math.max(1.5 - 0.2 * shooterHeight, 0), 1);
}
});
}
}
}
public static void playGunLoopReloadSounds(Player player) {
ItemStack stack = player.getMainHandItem();
if (!stack.is(ModTags.Items.GUN)) {
return;
}
if (!player.level().isClientSide) {
String origin = stack.getItem().getDescriptionId();
String name = origin.substring(origin.lastIndexOf(".") + 1);
SoundEvent sound1p = BuiltInRegistries.SOUND_EVENT.get(Mod.loc(name + "_loop"));
if (sound1p != null && player instanceof ServerPlayer serverPlayer) {
SoundTool.playLocalSound(serverPlayer, sound1p, 10f, 1f);
}
}
}
public static void playGunEndReloadSounds(Player player) {
ItemStack stack = player.getMainHandItem();
if (!stack.is(ModTags.Items.GUN)) return;
if (!player.level().isClientSide) {
String origin = stack.getItem().getDescriptionId();
String name = origin.substring(origin.lastIndexOf(".") + 1);
SoundEvent sound1p = BuiltInRegistries.SOUND_EVENT.get(Mod.loc(name + "_end"));
if (sound1p != null && player instanceof ServerPlayer serverPlayer) {
SoundTool.playLocalSound(serverPlayer, sound1p, 10f, 1f);
double shooterHeight = player.getEyePosition().distanceTo((Vec3.atLowerCornerOf(player.level().clip(new ClipContext(player.getEyePosition(), player.getEyePosition().add(new Vec3(0, -1, 0).scale(10)),
ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player)).getBlockPos())));
if (stack.is(ModItems.MARLIN.get())) {
Mod.queueServerWork((int) (5 + 1.5 * shooterHeight), () -> SoundTool.playLocalSound(serverPlayer, ModSounds.SHELL_CASING_NORMAL.get(), (float) Math.max(1.5 - 0.2 * shooterHeight, 0), 1));
}
}
}
}
/**
* 哨兵充能
*/
private static void handleSentinelCharge(Player player, final CompoundTag tag) {
if (!(player.getMainHandItem().getItem() instanceof GunItem)) return;
final var data = tag.getCompound("GunData");
// 启动换弹
if (GunsTool.getGunBooleanTag(tag, "StartCharge")) {
data.putInt("ChargeTime", 127);
data.putBoolean("Charging", true);
SoundEvent sound1p = BuiltInRegistries.SOUND_EVENT.get(Mod.loc("sentinel_charge"));
if (sound1p != null && player instanceof ServerPlayer serverPlayer) {
SoundTool.playLocalSound(serverPlayer, sound1p, 2f, 1f);
}
data.putBoolean("StartCharge", true);
}
if (GunsTool.getGunIntTag(tag, "ChargeTime", 0) > 0) {
data.putInt("ChargeTime", data.getInt("ChargeTime") - 1);
}
if (GunsTool.getGunIntTag(tag, "ChargeTime", 0) == 17) {
for (var cell : player.getInventory().items) {
if (cell.is(ModItems.CELL.get())) {
var stackStorage = cell.getCapability(Capabilities.EnergyStorage.ITEM);
if (stackStorage == null) continue;
int stackMaxEnergy = stackStorage.getMaxEnergyStored();
int stackEnergy = stackStorage.getEnergyStored();
var cellStorage = cell.getCapability(Capabilities.EnergyStorage.ITEM);
if (cellStorage == null) continue;
int cellEnergy = cellStorage.getEnergyStored();
int stackEnergyNeed = Math.min(cellEnergy, stackMaxEnergy - stackEnergy);
if (cellEnergy > 0) {
stackStorage.receiveEnergy(stackEnergyNeed, false);
}
cellStorage.extractEnergy(stackEnergyNeed, false);
}
}
}
if (GunsTool.getGunIntTag(tag, "ChargeTime", 0) == 1) {
data.putBoolean("Charging", false);
}
}
// TODO missing mapping event
// @SubscribeEvent
// public static void onMissingMappings(MissingMappingsEvent event) {
// for (MissingMappingsEvent.Mapping<Item> mapping : event.getAllMappings(Registries.ITEM)) {
// if (ModUtils.MODID.equals(mapping.getKey().getNamespace()) && mapping.getKey().getPath().equals("abekiri")) {
// mapping.remap(ModItems.HOMEMADE_SHOTGUN.get());
// }
// }
// }
}