提取AmmoType

This commit is contained in:
Light_Quanta 2025-04-14 15:38:12 +08:00
parent bf2e574a06
commit aa8e951e51
No known key found for this signature in database
GPG key ID: 11A39A1B8C890959
49 changed files with 290 additions and 266 deletions

View file

@ -9,6 +9,7 @@ import com.atsuishio.superbwarfare.init.ModKeyMappings;
import com.atsuishio.superbwarfare.init.ModTags; import com.atsuishio.superbwarfare.init.ModTags;
import com.atsuishio.superbwarfare.item.gun.GunItem; import com.atsuishio.superbwarfare.item.gun.GunItem;
import com.atsuishio.superbwarfare.item.gun.data.GunData; import com.atsuishio.superbwarfare.item.gun.data.GunData;
import com.atsuishio.superbwarfare.tools.AmmoType;
import com.atsuishio.superbwarfare.tools.InventoryTool; import com.atsuishio.superbwarfare.tools.InventoryTool;
import com.atsuishio.superbwarfare.tools.NBTTool; import com.atsuishio.superbwarfare.tools.NBTTool;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
@ -71,22 +72,19 @@ public class AmmoBarOverlay implements LayeredDraw.Layer {
if (stack.is(ModTags.Items.LAUNCHER) || stack.getItem() == ModItems.TASER.get()) { if (stack.is(ModTags.Items.LAUNCHER) || stack.getItem() == ModItems.TASER.get()) {
return "" + data.maxAmmo.get(); return "" + data.maxAmmo.get();
} }
if (stack.is(ModTags.Items.USE_RIFLE_AMMO)) { var ammoTypeInfo = data.ammoTypeInfo();
return "" + cap.rifleAmmo; return switch (ammoTypeInfo.type()) {
case PLAYER_AMMO -> {
var type = AmmoType.getType(ammoTypeInfo.value());
assert type != null;
yield type.get(cap) + "";
} }
if (stack.is(ModTags.Items.USE_HANDGUN_AMMO)) {
return "" + cap.handgunAmmo; // TODO 正确计算弹药数量
} case ITEM, TAG -> "" + data.maxAmmo.get();
if (stack.is(ModTags.Items.USE_SHOTGUN_AMMO)) { default -> "";
return "" + cap.shotgunAmmo; };
}
if (stack.is(ModTags.Items.USE_SNIPER_AMMO)) {
return "" + cap.sniperAmmo;
}
if (stack.is(ModTags.Items.USE_HEAVY_AMMO)) {
return "" + cap.heavyAmmo;
}
return "";
} }
return ""; return "";
@ -247,7 +245,7 @@ public class AmmoBarOverlay implements LayeredDraw.Layer {
); );
// 渲染弹药类型 // 渲染弹药类型
String ammoName = gunItem.getAmmoDisplayName(stack); String ammoName = gunItem.getAmmoDisplayName(data);
guiGraphics.drawString( guiGraphics.drawString(
Minecraft.getInstance().font, Minecraft.getInstance().font,
ammoName, ammoName,

View file

@ -16,8 +16,10 @@ import com.atsuishio.superbwarfare.tools.InventoryTool;
import com.atsuishio.superbwarfare.tools.SoundTool; import com.atsuishio.superbwarfare.tools.SoundTool;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvent;
import net.minecraft.tags.ItemTags;
import net.minecraft.world.effect.MobEffect; import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
@ -286,6 +288,7 @@ public class GunEventHandler {
reload.reduce(); reload.reduce();
// 换弹时额外行为
var behavior = gunItem.reloadTimeBehaviors.get(reload.time()); var behavior = gunItem.reloadTimeBehaviors.get(reload.time());
if (behavior != null) { if (behavior != null) {
behavior.accept(gun); behavior.accept(gun);
@ -305,26 +308,20 @@ public class GunEventHandler {
} }
} }
public static void playGunNormalReload(Player player, GunData gunData) { public static void playGunNormalReload(Player player, GunData data) {
var stack = gunData.stack(); var stack = data.stack();
var gunItem = gunData.item(); var gunItem = data.item();
if (player.getInventory().hasAnyMatching(item -> item.is(ModItems.CREATIVE_AMMO_BOX.get()))) { if (player.getInventory().hasAnyMatching(item -> item.is(ModItems.CREATIVE_AMMO_BOX.get()))) {
gunData.ammo.set(gunData.magazine() + (gunItem.hasBulletInBarrel(stack) ? 1 : 0)); data.ammo.set(data.magazine() + (gunItem.hasBulletInBarrel(stack) ? 1 : 0));
} else { } else {
if (stack.is(ModTags.Items.USE_SHOTGUN_AMMO)) { var ammoTypeInfo = data.ammoTypeInfo();
GunsTool.reload(player, stack, gunData, AmmoType.SHOTGUN, gunItem.hasBulletInBarrel(stack));
} else if (stack.is(ModTags.Items.USE_SNIPER_AMMO)) { if (ammoTypeInfo.type() == GunData.AmmoConsumeType.PLAYER_AMMO) {
GunsTool.reload(player, stack, gunData, AmmoType.SNIPER, true); GunsTool.reload(player, stack, data, AmmoType.getType(ammoTypeInfo.value()), gunItem.hasBulletInBarrel(stack));
} else if (stack.is(ModTags.Items.USE_HANDGUN_AMMO)) {
GunsTool.reload(player, stack, gunData, AmmoType.HANDGUN, true);
} else if (stack.is(ModTags.Items.USE_RIFLE_AMMO)) {
GunsTool.reload(player, stack, gunData, AmmoType.RIFLE, gunItem.hasBulletInBarrel(stack));
} else if (stack.is(ModTags.Items.USE_HEAVY_AMMO)) {
GunsTool.reload(player, stack, gunData, AmmoType.HEAVY, gunItem.hasBulletInBarrel(stack));
} }
} }
gunData.reload.setState(ReloadState.NOT_RELOADING); data.reload.setState(ReloadState.NOT_RELOADING);
NeoForge.EVENT_BUS.post(new ReloadEvent.Post(player, stack)); NeoForge.EVENT_BUS.post(new ReloadEvent.Post(player, stack));
} }
@ -334,20 +331,25 @@ public class GunEventHandler {
if (player.getInventory().hasAnyMatching(item -> item.is(ModItems.CREATIVE_AMMO_BOX.get()))) { if (player.getInventory().hasAnyMatching(item -> item.is(ModItems.CREATIVE_AMMO_BOX.get()))) {
data.ammo.set(data.magazine()); data.ammo.set(data.magazine());
} else { } else {
if (stack.is(ModTags.Items.USE_SHOTGUN_AMMO)) { var ammoTypeInfo = data.ammoTypeInfo();
GunsTool.reload(player, stack, data, AmmoType.SHOTGUN); switch (ammoTypeInfo.type()) {
} else if (stack.is(ModTags.Items.USE_SNIPER_AMMO)) { case PLAYER_AMMO -> GunsTool.reload(player, stack, data, AmmoType.getType(ammoTypeInfo.value()));
GunsTool.reload(player, stack, data, AmmoType.SNIPER); case TAG -> {
} else if (stack.is(ModTags.Items.USE_HANDGUN_AMMO)) {
GunsTool.reload(player, stack, data, AmmoType.HANDGUN);
} else if (stack.is(ModTags.Items.USE_RIFLE_AMMO)) {
GunsTool.reload(player, stack, data, AmmoType.RIFLE);
} else if (stack.is(ModTags.Items.USE_HEAVY_AMMO)) {
GunsTool.reload(player, stack, data, AmmoType.HEAVY);
} else if (data.item().getCustomAmmoItem() != null) {
var ammoItem = data.item().getCustomAmmoItem();
data.ammo.set(1); data.ammo.set(1);
player.getInventory().clearOrCountMatchingItems(p -> p.getItem() == ammoItem, 1, player.inventoryMenu.getCraftSlots()); player.getInventory().clearOrCountMatchingItems(
p -> p.is(ItemTags.create(ResourceLocation.parse(ammoTypeInfo.value()))),
1,
player.inventoryMenu.getCraftSlots()
);
}
case ITEM -> {
data.ammo.set(1);
player.getInventory().clearOrCountMatchingItems(
p -> p.getItem().getDescriptionId().equals(ammoTypeInfo.value()),
1,
player.inventoryMenu.getCraftSlots()
);
}
} }
} }
data.reload.setState(ReloadState.NOT_RELOADING); data.reload.setState(ReloadState.NOT_RELOADING);
@ -449,15 +451,26 @@ public class GunEventHandler {
if ((reload.prepareTimer.get() == 1 || reload.prepareLoadTimer.get() == 1)) { if ((reload.prepareTimer.get() == 1 || reload.prepareLoadTimer.get() == 1)) {
if (!InventoryTool.hasCreativeAmmoBox(player)) { if (!InventoryTool.hasCreativeAmmoBox(player)) {
var capability = player.getData(ModAttachments.PLAYER_VARIABLE); var capability = player.getData(ModAttachments.PLAYER_VARIABLE);
var startStage3 = false;
if (stack.is(ModTags.Items.USE_SHOTGUN_AMMO) && capability.shotgunAmmo == 0 var ammoTypeInfo = data.ammoTypeInfo();
|| stack.is(ModTags.Items.USE_SNIPER_AMMO) && capability.sniperAmmo == 0 if (ammoTypeInfo.type() == GunData.AmmoConsumeType.PLAYER_AMMO) {
|| stack.is(ModTags.Items.USE_HANDGUN_AMMO) && capability.handgunAmmo == 0 var type = AmmoType.getType(ammoTypeInfo.value());
|| stack.is(ModTags.Items.USE_RIFLE_AMMO) && capability.rifleAmmo == 0 assert type != null;
|| stack.is(ModTags.Items.USE_HEAVY_AMMO) && capability.heavyAmmo == 0
|| stack.is(ModTags.Items.LAUNCHER) && data.maxAmmo.get() == 0 if (type.get(capability) == 0) {
startStage3 = true;
}
}
// TODO 优化这坨判断
if (stack.is(ModTags.Items.LAUNCHER) && data.maxAmmo.get() == 0
|| stack.is(ModItems.SECONDARY_CATACLYSM.get()) && data.ammo.get() >= data.magazine() || stack.is(ModItems.SECONDARY_CATACLYSM.get()) && data.ammo.get() >= data.magazine()
) { ) {
startStage3 = true;
}
if (startStage3) {
reload.stage3Starter.markStart(); reload.stage3Starter.markStart();
} else { } else {
reload.setStage(2); reload.setStage(2);
@ -521,18 +534,16 @@ public class GunEventHandler {
if (!InventoryTool.hasCreativeAmmoBox(player)) { if (!InventoryTool.hasCreativeAmmoBox(player)) {
var capability = player.getData(ModAttachments.PLAYER_VARIABLE); var capability = player.getData(ModAttachments.PLAYER_VARIABLE);
if (stack.is(ModTags.Items.USE_SHOTGUN_AMMO) && capability.shotgunAmmo == 0) { var ammoTypeInfo = data.ammoTypeInfo();
reload.setStage(3); if (ammoTypeInfo.type() == GunData.AmmoConsumeType.PLAYER_AMMO) {
} else if (stack.is(ModTags.Items.USE_SNIPER_AMMO) && capability.sniperAmmo == 0) { var type = AmmoType.getType(ammoTypeInfo.value());
reload.setStage(3); assert type != null;
} else if (stack.is(ModTags.Items.USE_HANDGUN_AMMO) && capability.handgunAmmo == 0) {
reload.setStage(3); if (type.get(capability) == 0) {
} else if (stack.is(ModTags.Items.USE_RIFLE_AMMO) && capability.rifleAmmo == 0) {
reload.setStage(3);
} else if (stack.is(ModTags.Items.USE_HEAVY_AMMO) && capability.heavyAmmo == 0) {
reload.setStage(3); reload.setStage(3);
} }
} }
}
// 强制结束 // 强制结束
if (data.stopped.get()) { if (data.stopped.get()) {
@ -577,19 +588,24 @@ public class GunEventHandler {
if (!InventoryTool.hasCreativeAmmoBox(player)) { if (!InventoryTool.hasCreativeAmmoBox(player)) {
var cap = player.getData(ModAttachments.PLAYER_VARIABLE); var cap = player.getData(ModAttachments.PLAYER_VARIABLE);
ItemStack stack = player.getMainHandItem(); var ammoTypeInfo = data.ammoTypeInfo();
if (stack.is(ModTags.Items.USE_SHOTGUN_AMMO)) { switch (ammoTypeInfo.type()) {
AmmoType.SHOTGUN.add(cap, -1); case PLAYER_AMMO -> {
} else if (stack.is(ModTags.Items.USE_SNIPER_AMMO)) { var type = AmmoType.getType(ammoTypeInfo.value());
AmmoType.SNIPER.add(cap, -1); assert type != null;
} else if (stack.is(ModTags.Items.USE_HANDGUN_AMMO)) {
AmmoType.HANDGUN.add(cap, -1); type.add(cap, -1);
} else if (stack.is(ModTags.Items.USE_RIFLE_AMMO)) { }
AmmoType.RIFLE.add(cap, -1); case ITEM -> player.getInventory().clearOrCountMatchingItems(
} else if (stack.is(ModTags.Items.USE_HEAVY_AMMO)) { p -> p.getItem().getDescriptionId().equals(ammoTypeInfo.value()),
AmmoType.HEAVY.add(cap, -1); 1,
} else if (stack.getItem() == ModItems.SECONDARY_CATACLYSM.get()) { player.inventoryMenu.getCraftSlots()
player.getInventory().clearOrCountMatchingItems(p -> p.getItem() == data.item().getCustomAmmoItem(), 1, player.inventoryMenu.getCraftSlots()); );
case TAG -> player.getInventory().clearOrCountMatchingItems(
p -> p.is(ItemTags.create(ResourceLocation.parse(ammoTypeInfo.value()))),
1,
player.inventoryMenu.getCraftSlots()
);
} }
player.setData(ModAttachments.PLAYER_VARIABLE, cap); player.setData(ModAttachments.PLAYER_VARIABLE, cap);

View file

@ -143,6 +143,7 @@ public class LivingEventHandler {
if (DamageTypeTool.isGunDamage(source) && stack.getItem() instanceof GunItem) { if (DamageTypeTool.isGunDamage(source) && stack.getItem() instanceof GunItem) {
double distance = entity.position().distanceTo(sourceEntity.position()); double distance = entity.position().distanceTo(sourceEntity.position());
// TODO 正确计算距离衰减
if (stack.is(ModTags.Items.USE_SHOTGUN_AMMO)) { if (stack.is(ModTags.Items.USE_SHOTGUN_AMMO)) {
var perk = data.perk.get(Perk.Type.AMMO); var perk = data.perk.get(Perk.Type.AMMO);
@ -650,45 +651,18 @@ public class LivingEventHandler {
boolean flag = InventoryTool.hasCreativeAmmoBox(player); boolean flag = InventoryTool.hasCreativeAmmoBox(player);
if (stack.is(ModTags.Items.USE_RIFLE_AMMO)) { var ammoTypeInfo = data.ammoTypeInfo();
int ammoFinal = Math.min(cap.rifleAmmo, ammoNeed); if (ammoTypeInfo.type() == GunData.AmmoConsumeType.PLAYER_AMMO) {
var type = AmmoType.getType(ammoTypeInfo.value());
assert type != null;
int ammoFinal = Math.min(type.get(cap), ammoNeed);
if (flag) { if (flag) {
ammoFinal = ammoNeed; ammoFinal = ammoNeed;
} else { } else {
cap.rifleAmmo -= ammoFinal; type.add(cap, -ammoFinal);
}
data.ammo.set(Math.min(mag, ammo + ammoFinal));
} else if (stack.is(ModTags.Items.USE_HANDGUN_AMMO)) {
int ammoFinal = Math.min(cap.handgunAmmo, ammoNeed);
if (flag) {
ammoFinal = ammoNeed;
} else {
cap.handgunAmmo -= ammoFinal;
}
data.ammo.set(Math.min(mag, ammo + ammoFinal));
} else if (stack.is(ModTags.Items.USE_SHOTGUN_AMMO)) {
int ammoFinal = Math.min(cap.handgunAmmo, ammoNeed);
if (flag) {
ammoFinal = ammoNeed;
} else {
cap.shotgunAmmo -= ammoFinal;
}
data.ammo.set(Math.min(mag, ammo + ammoFinal));
} else if (stack.is(ModTags.Items.USE_SNIPER_AMMO)) {
int ammoFinal = Math.min(cap.handgunAmmo, ammoNeed);
if (flag) {
ammoFinal = ammoNeed;
} else {
cap.sniperAmmo -= ammoFinal;
}
data.ammo.set(Math.min(mag, ammo + ammoFinal));
} else if (stack.is(ModTags.Items.USE_HEAVY_AMMO)) {
int ammoFinal = Math.min(cap.heavyAmmo, ammoNeed);
if (flag) {
ammoFinal = ammoNeed;
} else {
cap.heavyAmmo -= ammoFinal;
} }
data.ammo.set(Math.min(mag, ammo + ammoFinal)); data.ammo.set(Math.min(mag, ammo + ammoFinal));
} }

View file

@ -17,6 +17,7 @@ import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource; import net.minecraft.sounds.SoundSource;
import net.minecraft.tags.ItemTags;
import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.ai.attributes.AttributeModifier; import net.minecraft.world.entity.ai.attributes.AttributeModifier;
import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.ai.attributes.Attributes;
@ -110,38 +111,38 @@ public class PlayerEventHandler {
if (!InventoryTool.hasCreativeAmmoBox(player)) { if (!InventoryTool.hasCreativeAmmoBox(player)) {
var cap = player.getData(ModAttachments.PLAYER_VARIABLE); var cap = player.getData(ModAttachments.PLAYER_VARIABLE);
var ammoTypeInfo = data.ammoTypeInfo();
switch (ammoTypeInfo.type()) {
case PLAYER_AMMO -> {
var type = AmmoType.getType(ammoTypeInfo.value());
assert type != null;
if (stack.is(ModTags.Items.USE_SHOTGUN_AMMO) && cap.shotgunAmmo > 0) { if (type.get(cap) == 0) {
GunsTool.reload(player, stack, data, AmmoType.SHOTGUN); GunsTool.reload(player, stack, data, type);
} }
if (stack.is(ModTags.Items.USE_SNIPER_AMMO) && cap.sniperAmmo > 0) {
GunsTool.reload(player, stack, data, AmmoType.SNIPER);
} }
if (stack.is(ModTags.Items.USE_HANDGUN_AMMO) && cap.handgunAmmo > 0) { case ITEM -> {
GunsTool.reload(player, stack, data, AmmoType.HANDGUN); // TODO 弃用maxAmmo
} if (data.ammo.get() == 0 && data.maxAmmo.get() == 0) {
if (stack.is(ModTags.Items.USE_RIFLE_AMMO) && cap.rifleAmmo > 0) {
GunsTool.reload(player, stack, data, AmmoType.RIFLE);
}
if (stack.is(ModTags.Items.USE_HEAVY_AMMO) && cap.heavyAmmo > 0) {
GunsTool.reload(player, stack, data, AmmoType.HEAVY);
}
if (stack.getItem() == ModItems.TASER.get() && data.maxAmmo.get() > 0 && data.ammo.get() == 0) {
data.ammo.set(1); data.ammo.set(1);
player.getInventory().clearOrCountMatchingItems(p -> p.getItem() == ModItems.TASER_ELECTRODE.get(), 1, player.inventoryMenu.getCraftSlots()); player.getInventory().clearOrCountMatchingItems(
p -> p.getItem().getDescriptionId().equals(ammoTypeInfo.value()),
1,
player.inventoryMenu.getCraftSlots()
);
} }
if (stack.getItem() == ModItems.M_79.get() && data.maxAmmo.get() > 0 && data.ammo.get() == 0) {
data.ammo.set(1);
player.getInventory().clearOrCountMatchingItems(p -> p.getItem() == ModItems.GRENADE_40MM.get(), 1, player.inventoryMenu.getCraftSlots());
} }
if (stack.getItem() == ModItems.RPG.get() && data.maxAmmo.get() > 0 && data.ammo.get() == 0) { case TAG -> {
// TODO 弃用maxAmmo
if (data.ammo.get() == 0 && data.maxAmmo.get() == 0) {
data.ammo.set(1); data.ammo.set(1);
player.getInventory().clearOrCountMatchingItems(p -> p.getItem() == ModItems.ROCKET.get(), 1, player.inventoryMenu.getCraftSlots()); player.getInventory().clearOrCountMatchingItems(
p -> p.is(ItemTags.create(ResourceLocation.parse(ammoTypeInfo.value()))),
1,
player.inventoryMenu.getCraftSlots()
);
}
} }
if (stack.getItem() == ModItems.JAVELIN.get() && data.maxAmmo.get() > 0 && data.ammo.get() == 0) {
data.ammo.set(1);
player.getInventory().clearOrCountMatchingItems(p -> p.getItem() == ModItems.JAVELIN_MISSILE.get(), 1, player.inventoryMenu.getCraftSlots());
} }
} else { } else {
data.ammo.set(data.magazine()); data.ammo.set(data.magazine());

View file

@ -6,7 +6,6 @@ import com.atsuishio.superbwarfare.client.tooltip.component.GunImageComponent;
import com.atsuishio.superbwarfare.init.ModAttachments; import com.atsuishio.superbwarfare.init.ModAttachments;
import com.atsuishio.superbwarfare.init.ModItems; import com.atsuishio.superbwarfare.init.ModItems;
import com.atsuishio.superbwarfare.init.ModPerks; import com.atsuishio.superbwarfare.init.ModPerks;
import com.atsuishio.superbwarfare.init.ModTags;
import com.atsuishio.superbwarfare.item.CustomRendererItem; import com.atsuishio.superbwarfare.item.CustomRendererItem;
import com.atsuishio.superbwarfare.item.gun.data.GunData; import com.atsuishio.superbwarfare.item.gun.data.GunData;
import com.atsuishio.superbwarfare.item.gun.data.value.AttachmentType; import com.atsuishio.superbwarfare.item.gun.data.value.AttachmentType;
@ -59,10 +58,7 @@ public abstract class GunItem extends Item implements CustomRendererItem {
@Override @Override
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
public void inventoryTick(ItemStack stack, Level level, Entity entity, int slot, boolean selected) { public void inventoryTick(ItemStack stack, Level level, Entity entity, int slot, boolean selected) {
if (!(entity instanceof LivingEntity) if (!(entity instanceof LivingEntity) || !(stack.getItem() instanceof GunItem gunItem)) return;
|| !(stack.getItem() instanceof GunItem)
|| !(stack.getItem() instanceof GunItem gunItem)
) return;
var data = GunData.from(stack); var data = GunData.from(stack);
@ -81,19 +77,16 @@ public abstract class GunItem extends Item implements CustomRendererItem {
if ((hasBulletInBarrel && ammoCount > magazine + 1) || (!hasBulletInBarrel && ammoCount > magazine)) { if ((hasBulletInBarrel && ammoCount > magazine + 1) || (!hasBulletInBarrel && ammoCount > magazine)) {
int count = ammoCount - magazine - (hasBulletInBarrel ? 1 : 0); int count = ammoCount - magazine - (hasBulletInBarrel ? 1 : 0);
var capability = entity.getData(ModAttachments.PLAYER_VARIABLE).watch(); var capability = entity.getData(ModAttachments.PLAYER_VARIABLE).watch();
if (stack.is(ModTags.Items.USE_SHOTGUN_AMMO)) {
AmmoType.SHOTGUN.add(capability, count); var ammoTypeInfo = data.ammoTypeInfo();
} else if (stack.is(ModTags.Items.USE_SNIPER_AMMO)) { if (ammoTypeInfo.type() == GunData.AmmoConsumeType.PLAYER_AMMO) {
AmmoType.SNIPER.add(capability, count); var type = AmmoType.getType(ammoTypeInfo.value());
} else if (stack.is(ModTags.Items.USE_HANDGUN_AMMO)) { assert type != null;
AmmoType.HANDGUN.add(capability, count);
} else if (stack.is(ModTags.Items.USE_RIFLE_AMMO)) { type.add(capability, count);
AmmoType.RIFLE.add(capability, count);
} else if (stack.is(ModTags.Items.USE_HEAVY_AMMO)) {
AmmoType.HEAVY.add(capability, count);
} }
entity.setData(ModAttachments.PLAYER_VARIABLE, capability); entity.setData(ModAttachments.PLAYER_VARIABLE, capability);
capability.sync(entity); capability.sync(entity);
data.ammo.set(magazine + (hasBulletInBarrel ? 1 : 0)); data.ammo.set(magazine + (hasBulletInBarrel ? 1 : 0));
@ -465,21 +458,19 @@ public abstract class GunItem extends Item implements CustomRendererItem {
/** /**
* 右下角弹药显示名称 * 右下角弹药显示名称
*/ */
public String getAmmoDisplayName(ItemStack stack) { public String getAmmoDisplayName(GunData data) {
if (stack.is(ModTags.Items.USE_RIFLE_AMMO)) { var ammoTypeInfo = data.ammoTypeInfo();
return "Rifle Ammo"; if (ammoTypeInfo.type() == GunData.AmmoConsumeType.PLAYER_AMMO) {
} var type = AmmoType.getType(ammoTypeInfo.value());
if (stack.is(ModTags.Items.USE_HANDGUN_AMMO)) { assert type != null;
return "Handgun Ammo";
} return switch (type) {
if (stack.is(ModTags.Items.USE_SHOTGUN_AMMO)) { case RIFLE -> "Rifle Ammo";
return "Shotgun Ammo"; case HANDGUN -> "Handgun Ammo";
} case SHOTGUN -> "Shotgun Ammo";
if (stack.is(ModTags.Items.USE_SNIPER_AMMO)) { case SNIPER -> "Sniper Ammo";
return "Sniper Ammo"; case HEAVY -> "Heavy Ammo";
} };
if (stack.is(ModTags.Items.USE_HEAVY_AMMO)) {
return "Heavy Ammo";
} }
return ""; return "";
} }
@ -504,10 +495,6 @@ public abstract class GunItem extends Item implements CustomRendererItem {
public void addReloadTimeBehavior(Map<Integer, Consumer<GunData>> behaviors) { public void addReloadTimeBehavior(Map<Integer, Consumer<GunData>> behaviors) {
} }
public Item getCustomAmmoItem() {
return null;
}
@SubscribeEvent @SubscribeEvent
private static void registerGunExtensions(RegisterClientExtensionsEvent event) { private static void registerGunExtensions(RegisterClientExtensionsEvent event) {
for (var item : ModItems.GUNS.getEntries()) { for (var item : ModItems.GUNS.getEntries()) {

View file

@ -37,6 +37,9 @@ public class DefaultGunData {
@SerializedName("BypassesArmor") @SerializedName("BypassesArmor")
public double bypassArmor; public double bypassArmor;
@SerializedName("AmmoType")
public String ammoType = "";
@SerializedName("NormalReloadTime") @SerializedName("NormalReloadTime")
public int normalReloadTime; public int normalReloadTime;
@SerializedName("EmptyReloadTime") @SerializedName("EmptyReloadTime")

View file

@ -5,9 +5,11 @@ import com.atsuishio.superbwarfare.item.gun.data.subdata.*;
import com.atsuishio.superbwarfare.item.gun.data.value.*; import com.atsuishio.superbwarfare.item.gun.data.value.*;
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.tools.AmmoType;
import com.atsuishio.superbwarfare.tools.GunsTool; import com.atsuishio.superbwarfare.tools.GunsTool;
import net.minecraft.core.component.DataComponents; import net.minecraft.core.component.DataComponents;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.component.CustomData; import net.minecraft.world.item.component.CustomData;
@ -259,10 +261,44 @@ public class GunData {
return defaultGunData().burstAmount; return defaultGunData().burstAmount;
} }
public enum AmmoConsumeType {
PLAYER_AMMO, ITEM, TAG, INVALID,
}
public record AmmoTypeInfo(AmmoConsumeType type, String value) {
}
public AmmoTypeInfo ammoTypeInfo() {
var ammoType = defaultGunData().ammoType;
if (ammoType.isEmpty()) {
return new AmmoTypeInfo(AmmoConsumeType.INVALID, "");
}
// 玩家弹药
if (ammoType.startsWith("@")) {
if (AmmoType.getType(ammoType.substring(1)) == null) {
return new AmmoTypeInfo(AmmoConsumeType.INVALID, ammoType.substring(1));
}
return new AmmoTypeInfo(AmmoConsumeType.PLAYER_AMMO, ammoType.substring(1));
}
// 物品Tag
if (ammoType.startsWith("#")) {
if (ResourceLocation.tryParse(ammoType.substring(1)) == null) {
return new AmmoTypeInfo(AmmoConsumeType.INVALID, ammoType.substring(1));
}
return new AmmoTypeInfo(AmmoConsumeType.TAG, ammoType.substring(1));
}
// 普通物品
if (ResourceLocation.tryParse(ammoType) == null) {
return new AmmoTypeInfo(AmmoConsumeType.INVALID, ammoType);
}
return new AmmoTypeInfo(AmmoConsumeType.ITEM, ammoType);
}
// 可持久化属性开始 // 可持久化属性开始
public final IntValue ammo; public final IntValue ammo;
public final IntValue fireMode; public final IntValue fireMode;
public final IntValue level; public final IntValue level;

View file

@ -237,7 +237,7 @@ public class JavelinItem extends GunItem implements GeoItem, SpecialFireWeapon {
} }
@Override @Override
public String getAmmoDisplayName(ItemStack stack) { public String getAmmoDisplayName(GunData data) {
return "Javelin Missile"; return "Javelin Missile";
} }
@ -335,8 +335,4 @@ public class JavelinItem extends GunItem implements GeoItem, SpecialFireWeapon {
tag.putInt("SeekTime", 0); tag.putInt("SeekTime", 0);
} }
@Override
public Item getCustomAmmoItem() {
return ModItems.JAVELIN_MISSILE.get();
}
} }

View file

@ -162,7 +162,7 @@ public class M79Item extends GunItem implements GeoItem, SpecialFireWeapon {
} }
@Override @Override
public String getAmmoDisplayName(ItemStack stack) { public String getAmmoDisplayName(GunData data) {
return "40mm Grenade"; return "40mm Grenade";
} }
@ -221,8 +221,4 @@ public class M79Item extends GunItem implements GeoItem, SpecialFireWeapon {
data.ammo.set(data.ammo.get() - 1); data.ammo.set(data.ammo.get() - 1);
} }
@Override
public Item getCustomAmmoItem() {
return ModItems.GRENADE_40MM.get();
}
} }

View file

@ -50,7 +50,7 @@ import java.util.function.Supplier;
public class RpgItem extends GunItem implements GeoItem, SpecialFireWeapon { public class RpgItem extends GunItem implements GeoItem, SpecialFireWeapon {
@Override @Override
public String getAmmoDisplayName(ItemStack stack) { public String getAmmoDisplayName(GunData data) {
return "Yassin105 TBG"; return "Yassin105 TBG";
} }
@ -253,8 +253,4 @@ public class RpgItem extends GunItem implements GeoItem, SpecialFireWeapon {
behaviors.put(9, data -> data.closeHammer.set(false)); behaviors.put(9, data -> data.closeHammer.set(false));
} }
@Override
public Item getCustomAmmoItem() {
return ModItems.ROCKET.get();
}
} }

View file

@ -16,6 +16,7 @@ import com.atsuishio.superbwarfare.item.gun.data.GunData;
import com.atsuishio.superbwarfare.network.message.receive.ShootClientMessage; import com.atsuishio.superbwarfare.network.message.receive.ShootClientMessage;
import com.atsuishio.superbwarfare.perk.Perk; import com.atsuishio.superbwarfare.perk.Perk;
import com.atsuishio.superbwarfare.perk.PerkHelper; import com.atsuishio.superbwarfare.perk.PerkHelper;
import com.atsuishio.superbwarfare.tools.InventoryTool;
import com.atsuishio.superbwarfare.tools.ParticleTool; import com.atsuishio.superbwarfare.tools.ParticleTool;
import com.atsuishio.superbwarfare.tools.SoundTool; import com.atsuishio.superbwarfare.tools.SoundTool;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@ -155,14 +156,10 @@ public class SecondaryCataclysm extends GunItem implements GeoItem, SpecialFireW
} }
public static int getAmmoCount(Player player) { public static int getAmmoCount(Player player) {
int count = 0; if (InventoryTool.hasCreativeAmmoBox(player)) {
for (var inv : player.getInventory().items) { return (int) Double.POSITIVE_INFINITY;
if (inv.is(ModItems.CREATIVE_AMMO_BOX.get())) {
count++;
}
} }
if (count == 0) {
int sum = 0; int sum = 0;
for (int i = 0; i < player.getInventory().getContainerSize(); ++i) { for (int i = 0; i < player.getInventory().getContainerSize(); ++i) {
ItemStack itemstack = player.getInventory().getItem(i); ItemStack itemstack = player.getInventory().getItem(i);
@ -172,8 +169,6 @@ public class SecondaryCataclysm extends GunItem implements GeoItem, SpecialFireW
} }
return sum; return sum;
} }
return (int) Double.POSITIVE_INFINITY;
}
@Override @Override
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
@ -264,7 +259,7 @@ public class SecondaryCataclysm extends GunItem implements GeoItem, SpecialFireW
} }
@Override @Override
public String getAmmoDisplayName(ItemStack stack) { public String getAmmoDisplayName(GunData data) {
return "40mm Grenade"; return "40mm Grenade";
} }
@ -347,8 +342,4 @@ public class SecondaryCataclysm extends GunItem implements GeoItem, SpecialFireW
return 24000; return 24000;
} }
@Override
public Item getCustomAmmoItem() {
return ModItems.GRENADE_40MM.get();
}
} }

View file

@ -124,6 +124,7 @@ public class BocekItem extends GunItem implements GeoItem, SpecialFireWeapon {
} }
} }
// TODO 替换硬编码判断
protected static boolean check(ItemStack stack) { protected static boolean check(ItemStack stack) {
return stack.getItem() == Items.ARROW; return stack.getItem() == Items.ARROW;
} }
@ -158,7 +159,7 @@ public class BocekItem extends GunItem implements GeoItem, SpecialFireWeapon {
} }
@Override @Override
public String getAmmoDisplayName(ItemStack stack) { public String getAmmoDisplayName(GunData data) {
return "Arrow"; return "Arrow";
} }

View file

@ -213,7 +213,7 @@ public class TaserItem extends GunItem implements GeoItem, SpecialFireWeapon, En
} }
@Override @Override
public String getAmmoDisplayName(ItemStack stack) { public String getAmmoDisplayName(GunData data) {
return "Electrode Rod"; return "Electrode Rod";
} }
@ -264,8 +264,4 @@ public class TaserItem extends GunItem implements GeoItem, SpecialFireWeapon, En
return MAX_ENERGY; return MAX_ENERGY;
} }
@Override
public Item getCustomAmmoItem() {
return ModItems.TASER_ELECTRODE.get();
}
} }

View file

@ -3,9 +3,9 @@ package com.atsuishio.superbwarfare.network.message.send;
import com.atsuishio.superbwarfare.Mod; import com.atsuishio.superbwarfare.Mod;
import com.atsuishio.superbwarfare.init.ModAttachments; import com.atsuishio.superbwarfare.init.ModAttachments;
import com.atsuishio.superbwarfare.init.ModItems; import com.atsuishio.superbwarfare.init.ModItems;
import com.atsuishio.superbwarfare.init.ModTags;
import com.atsuishio.superbwarfare.item.gun.GunItem; import com.atsuishio.superbwarfare.item.gun.GunItem;
import com.atsuishio.superbwarfare.item.gun.data.GunData; import com.atsuishio.superbwarfare.item.gun.data.GunData;
import com.atsuishio.superbwarfare.tools.AmmoType;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec; import net.minecraft.network.codec.StreamCodec;
@ -54,19 +54,17 @@ public record ReloadMessage(int msgType) implements CustomPacketPayload {
boolean hasCreativeAmmoBox = player.getInventory().hasAnyMatching(item -> item.is(ModItems.CREATIVE_AMMO_BOX.get())); boolean hasCreativeAmmoBox = player.getInventory().hasAnyMatching(item -> item.is(ModItems.CREATIVE_AMMO_BOX.get()));
if (!hasCreativeAmmoBox) { if (!hasCreativeAmmoBox) {
if (stack.is(ModTags.Items.USE_SHOTGUN_AMMO) && cap.shotgunAmmo == 0) { var ammoTypeInfo = data.ammoTypeInfo();
return;
} else if (stack.is(ModTags.Items.USE_SNIPER_AMMO) && cap.sniperAmmo == 0) { if (ammoTypeInfo.type() == GunData.AmmoConsumeType.PLAYER_AMMO) {
return; var ammoType = AmmoType.getType(ammoTypeInfo.value());
} else if (stack.is(ModTags.Items.USE_HANDGUN_AMMO) && cap.handgunAmmo == 0) { assert ammoType != null;
return;
} else if (stack.is(ModTags.Items.USE_RIFLE_AMMO) && cap.rifleAmmo == 0) { if (ammoType.get(cap) == 0) return;
return; } else if ((ammoTypeInfo.type() == GunData.AmmoConsumeType.ITEM || ammoTypeInfo.type() == GunData.AmmoConsumeType.TAG)
} else if (stack.is(ModTags.Items.USE_HEAVY_AMMO) && cap.heavyAmmo == 0) { // TODO 弃用maxAmmo
return; && data.maxAmmo.get() == 0
} else if (stack.getItem() == ModItems.TASER.get() && data.maxAmmo.get() == 0) { ) {
return;
} else if (stack.is(ModTags.Items.LAUNCHER) && data.maxAmmo.get() == 0) {
return; return;
} }
} }

View file

@ -13,5 +13,6 @@
"EmptyReloadTime": 85, "EmptyReloadTime": 85,
"BypassesArmor": 0.05, "BypassesArmor": 0.05,
"SoundRadius": 18, "SoundRadius": 18,
"RPM": 360 "RPM": 360,
"AmmoType": "@ShotgunAmmo"
} }

View file

@ -14,5 +14,6 @@
"EmptyReloadTime": 58, "EmptyReloadTime": 58,
"BypassesArmor": 0.23, "BypassesArmor": 0.23,
"SoundRadius": 12, "SoundRadius": 12,
"RPM": 700 "RPM": 700,
"AmmoType": "@RifleAmmo"
} }

View file

@ -14,5 +14,6 @@
"EmptyReloadTime": 65, "EmptyReloadTime": 65,
"BypassesArmor": 0.2, "BypassesArmor": 0.2,
"SoundRadius": 14, "SoundRadius": 14,
"RPM": 600 "RPM": 600,
"AmmoType": "@RifleAmmo"
} }

View file

@ -4,5 +4,6 @@
"Headshot": 2.5, "Headshot": 2.5,
"Damage": 48, "Damage": 48,
"Weight": 3, "Weight": 3,
"BypassesArmor": 0.25 "BypassesArmor": 0.25,
"AmmoType": "minecraft:arrow"
} }

View file

@ -13,5 +13,6 @@
"EmptyReloadTime": 95, "EmptyReloadTime": 95,
"BypassesArmor": 0.25, "BypassesArmor": 0.25,
"SoundRadius": 13, "SoundRadius": 13,
"RPM": 400 "RPM": 400,
"AmmoType": "@RifleAmmo"
} }

View file

@ -11,5 +11,6 @@
"EmptyReloadTime": 47, "EmptyReloadTime": 47,
"BypassesArmor": 0.15, "BypassesArmor": 0.15,
"SoundRadius": 8, "SoundRadius": 8,
"RPM": 400 "RPM": 400,
"AmmoType": "@HandgunAmmo"
} }

View file

@ -12,5 +12,6 @@
"EmptyReloadTime": 47, "EmptyReloadTime": 47,
"BypassesArmor": 0.15, "BypassesArmor": 0.15,
"SoundRadius": 8, "SoundRadius": 8,
"RPM": 1300 "RPM": 1300,
"AmmoType": "@HandgunAmmo"
} }

View file

@ -14,5 +14,6 @@
"EmptyReloadTime": 64, "EmptyReloadTime": 64,
"BypassesArmor": 0.25, "BypassesArmor": 0.25,
"SoundRadius": 14, "SoundRadius": 14,
"RPM": 900 "RPM": 900,
"AmmoType": "@RifleAmmo"
} }

View file

@ -12,5 +12,6 @@
"EmptyReloadTime": 83, "EmptyReloadTime": 83,
"BypassesArmor": 0.01, "BypassesArmor": 0.01,
"SoundRadius": 16, "SoundRadius": 16,
"RPM": 600 "RPM": 600,
"AmmoType": "@ShotgunAmmo"
} }

View file

@ -9,5 +9,6 @@
"Weight": 5, "Weight": 5,
"EmptyReloadTime": 64, "EmptyReloadTime": 64,
"BypassesArmor": 0.7, "BypassesArmor": 0.7,
"SoundRadius": 20 "SoundRadius": 20,
"AmmoType": "@SniperAmmo"
} }

View file

@ -12,5 +12,6 @@
"EmptyReloadTime": 56, "EmptyReloadTime": 56,
"BypassesArmor": 0.4, "BypassesArmor": 0.4,
"SoundRadius": 12, "SoundRadius": 12,
"RPM": 900 "RPM": 900,
"AmmoType": "@RifleAmmo"
} }

View file

@ -6,5 +6,6 @@
"EmptyReloadTime": 78, "EmptyReloadTime": 78,
"Damage": 700, "Damage": 700,
"ExplosionDamage": 60, "ExplosionDamage": 60,
"ExplosionRadius": 5 "ExplosionRadius": 5,
"AmmoType": "superbwarfare:javelin_missile"
} }

View file

@ -14,5 +14,6 @@
"IterativeTime": 11, "IterativeTime": 11,
"FinishTime": 18, "FinishTime": 18,
"BypassesArmor": 0.5, "BypassesArmor": 0.5,
"SoundRadius": 18 "SoundRadius": 18,
"AmmoType": "@SniperAmmo"
} }

View file

@ -11,5 +11,6 @@
"EmptyReloadTime": 47, "EmptyReloadTime": 47,
"BypassesArmor": 0.2, "BypassesArmor": 0.2,
"SoundRadius": 10, "SoundRadius": 10,
"RPM": 400 "RPM": 400,
"AmmoType": "@HandgunAmmo"
} }

View file

@ -14,5 +14,6 @@
"EmptyReloadTime": 64, "EmptyReloadTime": 64,
"BypassesArmor": 0.25, "BypassesArmor": 0.25,
"SoundRadius": 14, "SoundRadius": 14,
"RPM": 850 "RPM": 850,
"AmmoType": "@RifleAmmo"
} }

View file

@ -12,5 +12,6 @@
"EmptyReloadTime": 133, "EmptyReloadTime": 133,
"BypassesArmor": 0.25, "BypassesArmor": 0.25,
"SoundRadius": 15, "SoundRadius": 15,
"RPM": 600 "RPM": 600,
"AmmoType": "@RifleAmmo"
} }

View file

@ -8,5 +8,6 @@
"Velocity": 3.75, "Velocity": 3.75,
"Magazine": 1, "Magazine": 1,
"Weight": 4, "Weight": 4,
"EmptyReloadTime": 64 "EmptyReloadTime": 64,
"AmmoType": "superbwarfare:grenade_40mm"
} }

View file

@ -14,5 +14,6 @@
"FinishTime": 12, "FinishTime": 12,
"BypassesArmor": 0.05, "BypassesArmor": 0.05,
"SoundRadius": 16, "SoundRadius": 16,
"BoltActionTime": 11 "BoltActionTime": 11,
"AmmoType": "@ShotgunAmmo"
} }

View file

@ -14,5 +14,6 @@
"NormalReloadTime": 60, "NormalReloadTime": 60,
"EmptyReloadTime": 78, "EmptyReloadTime": 78,
"BypassesArmor": 0.6, "BypassesArmor": 0.6,
"SoundRadius": 18 "SoundRadius": 18,
"AmmoType": "@SniperAmmo"
} }

View file

@ -12,5 +12,6 @@
"FinishTime": 19, "FinishTime": 19,
"BypassesArmor": 0.3, "BypassesArmor": 0.3,
"SoundRadius": 15, "SoundRadius": 15,
"BoltActionTime": 12 "BoltActionTime": 12,
"AmmoType": "@RifleAmmo"
} }

View file

@ -8,5 +8,6 @@
"Weight": 10, "Weight": 10,
"BypassesArmor": 0.3, "BypassesArmor": 0.3,
"SoundRadius": 14, "SoundRadius": 14,
"RPM": 1200 "RPM": 1200,
"AmmoType": "@RifleAmmo"
} }

View file

@ -14,5 +14,6 @@
"EmptyReloadTime": 71, "EmptyReloadTime": 71,
"BypassesArmor": 0.4, "BypassesArmor": 0.4,
"SoundRadius": 16, "SoundRadius": 16,
"RPM": 700 "RPM": 700,
"AmmoType": "@RifleAmmo"
} }

View file

@ -14,5 +14,6 @@
"IterativeTime": 11, "IterativeTime": 11,
"FinishTime": 18, "FinishTime": 18,
"BypassesArmor": 0.54, "BypassesArmor": 0.54,
"SoundRadius": 18 "SoundRadius": 18,
"AmmoType": "@SniperAmmo"
} }

View file

@ -11,5 +11,6 @@
"EmptyReloadTime": 47, "EmptyReloadTime": 47,
"BypassesArmor": 0.15, "BypassesArmor": 0.15,
"SoundRadius": 8, "SoundRadius": 8,
"RPM": 400 "RPM": 400,
"AmmoType": "@HandgunAmmo"
} }

View file

@ -13,5 +13,6 @@
"NormalReloadTime": 84, "NormalReloadTime": 84,
"EmptyReloadTime": 112, "EmptyReloadTime": 112,
"BypassesArmor": 1, "BypassesArmor": 1,
"SoundRadius": 22 "SoundRadius": 22,
"AmmoType": "@HeavyAmmo"
} }

View file

@ -14,5 +14,6 @@
"EmptyReloadTime": 74, "EmptyReloadTime": 74,
"BypassesArmor": 0.28, "BypassesArmor": 0.28,
"SoundRadius": 13, "SoundRadius": 13,
"RPM": 650 "RPM": 650,
"AmmoType": "@RifleAmmo"
} }

View file

@ -8,5 +8,6 @@
"Velocity": 4, "Velocity": 4,
"Magazine": 1, "Magazine": 1,
"Weight": 7, "Weight": 7,
"EmptyReloadTime": 103 "EmptyReloadTime": 103,
"AmmoType": "superbwarfare:rocket"
} }

View file

@ -14,5 +14,6 @@
"EmptyReloadTime": 65, "EmptyReloadTime": 65,
"BypassesArmor": 0.23, "BypassesArmor": 0.23,
"SoundRadius": 14, "SoundRadius": 14,
"RPM": 600 "RPM": 600,
"AmmoType": "@RifleAmmo"
} }

View file

@ -11,5 +11,6 @@
"PrepareLoadTime": 31, "PrepareLoadTime": 31,
"IterativeTime": 20, "IterativeTime": 20,
"FinishTime": 19, "FinishTime": 19,
"SoundRadius": 8 "SoundRadius": 8,
"AmmoType": "superbwarfare:grenade_40mm"
} }

View file

@ -12,5 +12,6 @@
"NormalReloadTime": 59, "NormalReloadTime": 59,
"EmptyReloadTime": 89, "EmptyReloadTime": 89,
"BypassesArmor": 0.8, "BypassesArmor": 0.8,
"SoundRadius": 20 "SoundRadius": 20,
"AmmoType": "@SniperAmmo"
} }

View file

@ -11,5 +11,6 @@
"EmptyReloadTime": 75, "EmptyReloadTime": 75,
"BypassesArmor": 0.23, "BypassesArmor": 0.23,
"SoundRadius": 16, "SoundRadius": 16,
"RPM": 400 "RPM": 400,
"AmmoType": "@RifleAmmo"
} }

View file

@ -13,5 +13,6 @@
"EmptyReloadTime": 78, "EmptyReloadTime": 78,
"BypassesArmor": 0.45, "BypassesArmor": 0.45,
"SoundRadius": 17, "SoundRadius": 17,
"RPM": 300 "RPM": 300,
"AmmoType": "@SniperAmmo"
} }

View file

@ -6,5 +6,6 @@
"Velocity": 3, "Velocity": 3,
"Magazine": 1, "Magazine": 1,
"Weight": 1, "Weight": 1,
"EmptyReloadTime": 58 "EmptyReloadTime": 58,
"AmmoType": "superbwarfare:taser_electrode"
} }

View file

@ -10,5 +10,6 @@
"EmptyReloadTime": 65, "EmptyReloadTime": 65,
"BypassesArmor": 0.3, "BypassesArmor": 0.3,
"SoundRadius": 10, "SoundRadius": 10,
"RPM": 240 "RPM": 240,
"AmmoType": "@RifleAmmo"
} }

View file

@ -13,5 +13,6 @@
"EmptyReloadTime": 64, "EmptyReloadTime": 64,
"BypassesArmor": 0.15, "BypassesArmor": 0.15,
"SoundRadius": 11, "SoundRadius": 11,
"RPM": 1200 "RPM": 1200,
"AmmoType": "@HandgunAmmo"
} }