重写perk读写

This commit is contained in:
Light_Quanta 2025-04-07 04:50:31 +08:00
parent 4882c00db8
commit e79812eff6
No known key found for this signature in database
GPG key ID: 11A39A1B8C890959
29 changed files with 469 additions and 575 deletions

View file

@ -12,7 +12,6 @@ import com.atsuishio.superbwarfare.init.*;
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.network.message.send.*; import com.atsuishio.superbwarfare.network.message.send.*;
import com.atsuishio.superbwarfare.perk.PerkHelper;
import com.atsuishio.superbwarfare.tools.NBTTool; import com.atsuishio.superbwarfare.tools.NBTTool;
import com.atsuishio.superbwarfare.tools.SeekTool; import com.atsuishio.superbwarfare.tools.SeekTool;
import com.atsuishio.superbwarfare.tools.TraceTool; import com.atsuishio.superbwarfare.tools.TraceTool;
@ -20,7 +19,6 @@ import com.mojang.blaze3d.platform.InputConstants;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.core.component.DataComponents; import net.minecraft.core.component.DataComponents;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.sounds.SoundSource; import net.minecraft.sounds.SoundSource;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
@ -124,14 +122,15 @@ public class ClickHandler {
handleWeaponFirePress(player, stack); handleWeaponFirePress(player, stack);
} }
var data = GunData.from(stack);
if (button == ModKeyMappings.HOLD_ZOOM.getKey().getValue()) { if (button == ModKeyMappings.HOLD_ZOOM.getKey().getValue()) {
handleWeaponZoomPress(player, tag); handleWeaponZoomPress(player, data);
switchZoom = false; switchZoom = false;
return; return;
} }
if (button == ModKeyMappings.SWITCH_ZOOM.getKey().getValue()) { if (button == ModKeyMappings.SWITCH_ZOOM.getKey().getValue()) {
handleWeaponZoomPress(player, tag); handleWeaponZoomPress(player, data);
switchZoom = !switchZoom; switchZoom = !switchZoom;
} }
} }
@ -267,14 +266,15 @@ public class ClickHandler {
handleWeaponFirePress(player, stack); handleWeaponFirePress(player, stack);
} }
var data = GunData.from(stack);
if (key == ModKeyMappings.HOLD_ZOOM.getKey().getValue()) { if (key == ModKeyMappings.HOLD_ZOOM.getKey().getValue()) {
handleWeaponZoomPress(player, tag); handleWeaponZoomPress(player, data);
switchZoom = false; switchZoom = false;
return; return;
} }
if (key == ModKeyMappings.SWITCH_ZOOM.getKey().getValue()) { if (key == ModKeyMappings.SWITCH_ZOOM.getKey().getValue()) {
handleWeaponZoomPress(player, tag); handleWeaponZoomPress(player, data);
switchZoom = !switchZoom; switchZoom = !switchZoom;
} }
} }
@ -365,7 +365,7 @@ public class ClickHandler {
ClientEventHandler.customRpm = 0; ClientEventHandler.customRpm = 0;
} }
public static void handleWeaponZoomPress(Player player, final CompoundTag tag) { public static void handleWeaponZoomPress(Player player, GunData data) {
PacketDistributor.sendToServer(new ZoomMessage(0)); PacketDistributor.sendToServer(new ZoomMessage(0));
if (player.getVehicle() instanceof VehicleEntity pVehicle && player.getVehicle() instanceof WeaponVehicleEntity iVehicle && iVehicle.hasWeapon(pVehicle.getSeatIndex(player))) { if (player.getVehicle() instanceof VehicleEntity pVehicle && player.getVehicle() instanceof WeaponVehicleEntity iVehicle && iVehicle.hasWeapon(pVehicle.getSeatIndex(player))) {
@ -374,7 +374,7 @@ public class ClickHandler {
} }
ClientEventHandler.zoom = true; ClientEventHandler.zoom = true;
int level = PerkHelper.getItemPerkLevel(ModPerks.INTELLIGENT_CHIP.get(), tag); int level = data.perk.getLevel(ModPerks.INTELLIGENT_CHIP);
if (level > 0) { if (level > 0) {
if (ClientEventHandler.entity == null) { if (ClientEventHandler.entity == null) {
ClientEventHandler.entity = SeekTool.seekLivingEntity(player, player.level(), 32 + 8 * (level - 1), 20); ClientEventHandler.entity = SeekTool.seekLivingEntity(player, player.level(), 32 + 8 * (level - 1), 20);

View file

@ -1,9 +1,8 @@
package com.atsuishio.superbwarfare.client; package com.atsuishio.superbwarfare.client;
import com.atsuishio.superbwarfare.init.ModPerks; import com.atsuishio.superbwarfare.init.ModPerks;
import com.atsuishio.superbwarfare.item.gun.data.GunData;
import com.atsuishio.superbwarfare.perk.Perk; import com.atsuishio.superbwarfare.perk.Perk;
import com.atsuishio.superbwarfare.perk.PerkHelper;
import com.atsuishio.superbwarfare.tools.NBTTool;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
@ -24,14 +23,14 @@ public class TooltipTool {
} }
public static boolean heBullet(ItemStack stack) { public static boolean heBullet(ItemStack stack) {
var perk = PerkHelper.getPerkByType(NBTTool.getTag(stack), Perk.Type.AMMO); var perkInstance = GunData.from(stack).perk.getInstance(Perk.Type.AMMO);
return perk == ModPerks.HE_BULLET.get(); return perkInstance != null && perkInstance.perk() == ModPerks.HE_BULLET.get();
} }
public static int heBulletLevel(ItemStack stack) { public static int heBulletLevel(ItemStack stack) {
var perk = PerkHelper.getPerkByType(NBTTool.getTag(stack), Perk.Type.AMMO); var perkInstance = GunData.from(stack).perk.getInstance(Perk.Type.AMMO);
if (perk == ModPerks.HE_BULLET.get()) { if (perkInstance != null && perkInstance.perk() == ModPerks.HE_BULLET.get()) {
return PerkHelper.getItemPerkLevel(perk, NBTTool.getTag(stack)); return perkInstance.level();
} }
return 0; return 0;
} }

View file

@ -8,9 +8,9 @@ import com.atsuishio.superbwarfare.entity.vehicle.base.ArmedVehicleEntity;
import com.atsuishio.superbwarfare.event.ClientEventHandler; import com.atsuishio.superbwarfare.event.ClientEventHandler;
import com.atsuishio.superbwarfare.init.ModItems; import com.atsuishio.superbwarfare.init.ModItems;
import com.atsuishio.superbwarfare.init.ModTags; import com.atsuishio.superbwarfare.init.ModTags;
import com.atsuishio.superbwarfare.item.gun.data.GunData;
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.PerkHelper;
import com.atsuishio.superbwarfare.tools.NBTTool; import com.atsuishio.superbwarfare.tools.NBTTool;
import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
@ -69,8 +69,8 @@ public class CrossHairOverlay {
float moveX = 0; float moveX = 0;
float moveY = 0; float moveY = 0;
final var tag = NBTTool.getTag(stack); var data = GunData.from(stack);
var perk = PerkHelper.getPerkByType(tag, Perk.Type.AMMO); var perk = data.perk.get(Perk.Type.AMMO);
if (DisplayConfig.FLOAT_CROSS_HAIR.get() && player.getVehicle() == null) { if (DisplayConfig.FLOAT_CROSS_HAIR.get() && player.getVehicle() == null) {
moveX = (float) (-6 * ClientEventHandler.turnRot[1] - (player.isSprinting() ? 10 : 6) * ClientEventHandler.movePosX); moveX = (float) (-6 * ClientEventHandler.turnRot[1] - (player.isSprinting() ? 10 : 6) * ClientEventHandler.movePosX);

View file

@ -7,8 +7,7 @@ import com.atsuishio.superbwarfare.entity.vehicle.base.ArmedVehicleEntity;
import com.atsuishio.superbwarfare.event.ClientEventHandler; import com.atsuishio.superbwarfare.event.ClientEventHandler;
import com.atsuishio.superbwarfare.init.ModPerks; import com.atsuishio.superbwarfare.init.ModPerks;
import com.atsuishio.superbwarfare.item.gun.GunItem; import com.atsuishio.superbwarfare.item.gun.GunItem;
import com.atsuishio.superbwarfare.perk.PerkHelper; import com.atsuishio.superbwarfare.item.gun.data.GunData;
import com.atsuishio.superbwarfare.tools.NBTTool;
import com.atsuishio.superbwarfare.tools.SeekTool; import com.atsuishio.superbwarfare.tools.SeekTool;
import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
@ -50,9 +49,8 @@ public class HandsomeFrameOverlay {
return; return;
if (stack.getItem() instanceof GunItem && Minecraft.getInstance().options.getCameraType().isFirstPerson()) { if (stack.getItem() instanceof GunItem && Minecraft.getInstance().options.getCameraType().isFirstPerson()) {
var data = GunData.from(stack);
final var tag = NBTTool.getTag(stack); int level = data.perk.getLevel(ModPerks.INTELLIGENT_CHIP);
int level = PerkHelper.getItemPerkLevel(ModPerks.INTELLIGENT_CHIP.get(), tag);
if (level == 0) return; if (level == 0) return;
RenderSystem.disableDepthTest(); RenderSystem.disableDepthTest();

View file

@ -4,7 +4,6 @@ import com.atsuishio.superbwarfare.client.TooltipTool;
import com.atsuishio.superbwarfare.client.tooltip.component.GunImageComponent; import com.atsuishio.superbwarfare.client.tooltip.component.GunImageComponent;
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.PerkHelper;
import com.atsuishio.superbwarfare.tools.FormatTool; import com.atsuishio.superbwarfare.tools.FormatTool;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
@ -19,7 +18,7 @@ public class ClientBocekImageTooltip extends ClientGunImageTooltip {
protected Component getDamageComponent() { protected Component getDamageComponent() {
boolean slug = false; boolean slug = false;
var perk = PerkHelper.getPerkByType(data, Perk.Type.AMMO); var perk = data.perk.get(Perk.Type.AMMO);
if (perk instanceof AmmoPerk ammoPerk && ammoPerk.slug) { if (perk instanceof AmmoPerk ammoPerk && ammoPerk.slug) {
slug = true; slug = true;
} }

View file

@ -8,15 +8,12 @@ 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.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.PerkHelper;
import com.atsuishio.superbwarfare.tools.FormatTool; import com.atsuishio.superbwarfare.tools.FormatTool;
import com.atsuishio.superbwarfare.tools.NBTTool;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.Font; import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
@ -76,9 +73,9 @@ public class ClientGunImageTooltip implements ClientTooltipComponent {
} }
protected boolean shouldRenderPerks() { protected boolean shouldRenderPerks() {
return PerkHelper.getPerkByType(data, Perk.Type.AMMO) != null return data.perk.get(Perk.Type.AMMO) != null
|| PerkHelper.getPerkByType(data, Perk.Type.DAMAGE) != null || data.perk.get(Perk.Type.DAMAGE) != null
|| PerkHelper.getPerkByType(data, Perk.Type.FUNCTIONAL) != null; || data.perk.get(Perk.Type.FUNCTIONAL) != null;
} }
/** /**
@ -174,10 +171,11 @@ public class ClientGunImageTooltip implements ClientTooltipComponent {
*/ */
protected Component getBypassComponent() { protected Component getBypassComponent() {
double perkBypassArmorRate = 0; double perkBypassArmorRate = 0;
var perk = PerkHelper.getPerkByType(data, Perk.Type.AMMO); var perk = data.perk.get(Perk.Type.AMMO);
if (perk instanceof AmmoPerk ammoPerk) { if (perk instanceof AmmoPerk ammoPerk) {
int level = PerkHelper.getItemPerkLevel(perk, data); var perkInstance = data.perk.getInstance(perk);
int level = perkInstance == null ? 0 : perkInstance.level();
perkBypassArmorRate = ammoPerk.bypassArmorRate + (perk == ModPerks.AP_BULLET.get() ? 0.05f * (level - 1) : 0); perkBypassArmorRate = ammoPerk.bypassArmorRate + (perk == ModPerks.AP_BULLET.get() ? 0.05f * (level - 1) : 0);
} }
double bypassRate = Math.max(data.bypassArmor() + perkBypassArmorRate, 0); double bypassRate = Math.max(data.bypassArmor() + perkBypassArmorRate, 0);
@ -220,52 +218,17 @@ public class ClientGunImageTooltip implements ClientTooltipComponent {
int xOffset = -20; int xOffset = -20;
Perk ammoPerk = PerkHelper.getPerkByType(data, Perk.Type.AMMO); for (var type : Perk.Type.values()) {
if (ammoPerk != null && PerkHelper.getPerkItem(ammoPerk).isPresent()) { var perkInstance = data.perk.getInstance(type);
if (perkInstance == null) continue;
xOffset += 20; xOffset += 20;
var ammoItem = PerkHelper.getPerkItem(ammoPerk).get().get(); var ammoItem = perkInstance.perk().getItem().get();
ItemStack perkStack = ammoItem.getDefaultInstance(); ItemStack perkStack = ammoItem.getDefaultInstance();
CompoundTag ammoTag = PerkHelper.getPerkTag(data, Perk.Type.AMMO); int level = perkInstance.level();
if (!ammoTag.isEmpty()) { perkStack.setCount(level);
int level = PerkHelper.getItemPerkLevel(ammoPerk, data);
perkStack.setCount(level);
}
guiGraphics.renderItem(perkStack, x + xOffset, y + 2);
guiGraphics.renderItemDecorations(font, perkStack, x + xOffset, y + 2);
}
Perk funcPerk = PerkHelper.getPerkByType(data, Perk.Type.FUNCTIONAL);
if (funcPerk != null && PerkHelper.getPerkItem(funcPerk).isPresent()) {
xOffset += 20;
var funcItem = PerkHelper.getPerkItem(funcPerk).get().get();
ItemStack perkStack = funcItem.getDefaultInstance();
CompoundTag funcTag = PerkHelper.getPerkTag(data, Perk.Type.FUNCTIONAL);
if (!funcTag.isEmpty()) {
int level = PerkHelper.getItemPerkLevel(funcPerk, data);
perkStack.setCount(level);
}
guiGraphics.renderItem(perkStack, x + xOffset, y + 2);
guiGraphics.renderItemDecorations(font, perkStack, x + xOffset, y + 2);
}
Perk damagePerk = PerkHelper.getPerkByType(data, Perk.Type.DAMAGE);
if (damagePerk != null && PerkHelper.getPerkItem(damagePerk).isPresent()) {
xOffset += 20;
var damageItem = PerkHelper.getPerkItem(damagePerk).get().get();
ItemStack perkStack = damageItem.getDefaultInstance();
CompoundTag damageTag = PerkHelper.getPerkTag(data, Perk.Type.DAMAGE);
if (!damageTag.isEmpty()) {
int level = PerkHelper.getItemPerkLevel(damagePerk, data);
perkStack.setCount(level);
}
guiGraphics.renderItem(perkStack, x + xOffset, y + 2); guiGraphics.renderItem(perkStack, x + xOffset, y + 2);
guiGraphics.renderItemDecorations(font, perkStack, x + xOffset, y + 2); guiGraphics.renderItemDecorations(font, perkStack, x + xOffset, y + 2);
} }
@ -283,70 +246,27 @@ public class ClientGunImageTooltip implements ClientTooltipComponent {
int yOffset = -5; int yOffset = -5;
Perk ammoPerk = PerkHelper.getPerkByType(data, Perk.Type.AMMO); for (var type : Perk.Type.values()) {
if (ammoPerk != null && PerkHelper.getPerkItem(ammoPerk).isPresent()) { var perkInstance = data.perk.getInstance(type);
if (perkInstance == null) continue;
yOffset += 25; yOffset += 25;
var ammoItem = PerkHelper.getPerkItem(ammoPerk).get().get();
var ammoItem = perkInstance.perk().getItem().get();
guiGraphics.renderItem(ammoItem.getDefaultInstance(), x, y + 4 + yOffset); guiGraphics.renderItem(ammoItem.getDefaultInstance(), x, y + 4 + yOffset);
CompoundTag ammoTag = PerkHelper.getPerkTag(data, Perk.Type.AMMO); var ids = perkInstance.perk().descriptionId.split(":");
if (!ammoTag.isEmpty()) { if (ids.length <= 1) continue;
var ids = ammoTag.getString("id").split(":");
if (ids.length > 1) {
String id = ids[1];
var ammoComponent = Component.translatable("item.superbwarfare." + id).withStyle(ChatFormatting.YELLOW)
.append(Component.literal(" ").withStyle(ChatFormatting.RESET))
.append(Component.literal(" Lvl. " + ammoTag.getInt("level")).withStyle(ChatFormatting.WHITE));
var ammoDesComponent = Component.translatable("des.superbwarfare." + id).withStyle(ChatFormatting.GRAY);
guiGraphics.drawString(font, ammoComponent, x + 20, y + yOffset + 2, 0xFFFFFF); String id = ids[1];
guiGraphics.drawString(font, ammoDesComponent, x + 20, y + yOffset + 12, 0xFFFFFF); var component = Component.translatable("item.superbwarfare." + id).withStyle(type.getColor())
} .append(Component.literal(" ").withStyle(ChatFormatting.RESET))
} .append(Component.literal(" Lvl. " + perkInstance.level()).withStyle(ChatFormatting.WHITE));
} var descComponent = Component.translatable("des.superbwarfare." + id).withStyle(ChatFormatting.GRAY);
Perk funcPerk = PerkHelper.getPerkByType(data, Perk.Type.FUNCTIONAL); guiGraphics.drawString(font, component, x + 20, y + yOffset + 2, 0xFFFFFF);
if (funcPerk != null && PerkHelper.getPerkItem(funcPerk).isPresent()) { guiGraphics.drawString(font, descComponent, x + 20, y + yOffset + 12, 0xFFFFFF);
yOffset += 25;
var funcItem = PerkHelper.getPerkItem(funcPerk).get().get();
guiGraphics.renderItem(funcItem.getDefaultInstance(), x, y + 4 + yOffset);
CompoundTag funcTag = PerkHelper.getPerkTag(data, Perk.Type.FUNCTIONAL);
if (!funcTag.isEmpty()) {
var ids = funcTag.getString("id").split(":");
if (ids.length > 1) {
String id = ids[1];
var funcComponent = Component.translatable("item.superbwarfare." + id).withStyle(ChatFormatting.GREEN)
.append(Component.literal(" ").withStyle(ChatFormatting.RESET))
.append(Component.literal(" Lvl. " + funcTag.getInt("level")).withStyle(ChatFormatting.WHITE));
var funcDesComponent = Component.translatable("des.superbwarfare." + id).withStyle(ChatFormatting.GRAY);
guiGraphics.drawString(font, funcComponent, x + 20, y + yOffset + 2, 0xFFFFFF);
guiGraphics.drawString(font, funcDesComponent, x + 20, y + yOffset + 12, 0xFFFFFF);
}
}
}
Perk damagePerk = PerkHelper.getPerkByType(data, Perk.Type.DAMAGE);
if (damagePerk != null && PerkHelper.getPerkItem(damagePerk).isPresent()) {
yOffset += 25;
var damageItem = PerkHelper.getPerkItem(damagePerk).get().get();
guiGraphics.renderItem(damageItem.getDefaultInstance(), x, y + 4 + yOffset);
CompoundTag damageTag = PerkHelper.getPerkTag(data, Perk.Type.DAMAGE);
if (!damageTag.isEmpty()) {
var ids = damageTag.getString("id").split(":");
if (ids.length > 1) {
String id = ids[1];
var damageComponent = Component.translatable("item.superbwarfare." + id).withStyle(ChatFormatting.RED)
.append(Component.literal(" ").withStyle(ChatFormatting.RESET))
.append(Component.literal(" Lvl. " + damageTag.getInt("level")).withStyle(ChatFormatting.WHITE));
var damageDesComponent = Component.translatable("des.superbwarfare." + id).withStyle(ChatFormatting.GRAY);
guiGraphics.drawString(font, damageComponent, x + 20, y + yOffset + 2, 0xFFFFFF);
guiGraphics.drawString(font, damageDesComponent, x + 20, y + yOffset + 12, 0xFFFFFF);
}
}
} }
guiGraphics.pose().popPose(); guiGraphics.pose().popPose();
@ -370,34 +290,16 @@ public class ClientGunImageTooltip implements ClientTooltipComponent {
int width = 0; int width = 0;
CompoundTag ammoTag = PerkHelper.getPerkTag(data, Perk.Type.AMMO); for (var type : Perk.Type.values()) {
if (!ammoTag.isEmpty()) { var perkInstance = data.perk.getInstance(type);
var ids = ammoTag.getString("id").split(":"); if (perkInstance == null) continue;
if (ids.length > 1) {
String id = ids[1];
var ammoDesComponent = Component.translatable("des.superbwarfare." + id).withStyle(ChatFormatting.GRAY);
width = Math.max(width, font.width(ammoDesComponent));
}
}
CompoundTag funcTag = PerkHelper.getPerkTag(data, Perk.Type.FUNCTIONAL); var ids = perkInstance.perk().descriptionId.split(":");
if (!funcTag.isEmpty()) { if (ids.length <= 1) continue;
var ids = funcTag.getString("id").split(":");
if (ids.length > 1) {
String id = ids[1];
var funcDesComponent = Component.translatable("des.superbwarfare." + id).withStyle(ChatFormatting.GRAY);
width = Math.max(width, font.width(funcDesComponent));
}
}
CompoundTag damageTag = PerkHelper.getPerkTag(data, Perk.Type.DAMAGE); String id = ids[1];
if (!damageTag.isEmpty()) { var ammoDesComponent = Component.translatable("des.superbwarfare." + id).withStyle(ChatFormatting.GRAY);
var ids = damageTag.getString("id").split(":"); width = Math.max(width, font.width(ammoDesComponent));
if (ids.length > 1) {
String id = ids[1];
var damageDesComponent = Component.translatable("des.superbwarfare." + id).withStyle(ChatFormatting.GRAY);
width = Math.max(width, font.width(damageDesComponent));
}
} }
return width + 25; return width + 25;
@ -410,19 +312,13 @@ public class ClientGunImageTooltip implements ClientTooltipComponent {
if (shouldRenderBypassAndHeadshotTooltip()) height += 10; if (shouldRenderBypassAndHeadshotTooltip()) height += 10;
if (shouldRenderEditTooltip()) height += 20; if (shouldRenderEditTooltip()) height += 20;
if (shouldRenderPerks()) { if (shouldRenderPerks()) {
if (!Screen.hasShiftDown()) { height += 16;
height += 16;
} else { if (Screen.hasShiftDown()) {
height += 16; for (var type : Perk.Type.values()) {
final var tag = NBTTool.getTag(stack); if (data.perk.has(type)) {
if (PerkHelper.getPerkByType(tag, Perk.Type.AMMO) != null) { height += 25;
height += 25; }
}
if (PerkHelper.getPerkByType(tag, Perk.Type.FUNCTIONAL) != null) {
height += 25;
}
if (PerkHelper.getPerkByType(tag, Perk.Type.DAMAGE) != null) {
height += 25;
} }
} }
} }

View file

@ -1,9 +1,7 @@
package com.atsuishio.superbwarfare.client.tooltip; package com.atsuishio.superbwarfare.client.tooltip;
import com.atsuishio.superbwarfare.client.TooltipTool;
import com.atsuishio.superbwarfare.client.tooltip.component.GunImageComponent; import com.atsuishio.superbwarfare.client.tooltip.component.GunImageComponent;
import com.atsuishio.superbwarfare.init.ModPerks; import com.atsuishio.superbwarfare.init.ModPerks;
import com.atsuishio.superbwarfare.perk.PerkHelper;
import com.atsuishio.superbwarfare.tools.FormatTool; import com.atsuishio.superbwarfare.tools.FormatTool;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
@ -17,7 +15,8 @@ public class ClientLauncherImageTooltip extends ClientGunImageTooltip {
@Override @Override
protected Component getDamageComponent() { protected Component getDamageComponent() {
double damage = data.damage(); double damage = data.damage();
int perkLevel = PerkHelper.getItemPerkLevel(ModPerks.MICRO_MISSILE.get(), data); var perkInstance = data.perk.getInstance(ModPerks.MICRO_MISSILE.get());
int perkLevel = perkInstance == null ? 0 : perkInstance.level();
if (perkLevel > 0) damage *= 1.1f + perkLevel * 0.1f; if (perkLevel > 0) damage *= 1.1f + perkLevel * 0.1f;
double explosionDamage = data.explosionDamage(); double explosionDamage = data.explosionDamage();

View file

@ -2,7 +2,6 @@ package com.atsuishio.superbwarfare.client.tooltip;
import com.atsuishio.superbwarfare.client.tooltip.component.GunImageComponent; import com.atsuishio.superbwarfare.client.tooltip.component.GunImageComponent;
import com.atsuishio.superbwarfare.init.ModPerks; import com.atsuishio.superbwarfare.init.ModPerks;
import com.atsuishio.superbwarfare.perk.PerkHelper;
import com.atsuishio.superbwarfare.tools.FormatTool; import com.atsuishio.superbwarfare.tools.FormatTool;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
@ -16,7 +15,8 @@ public class ClientSecondaryCataclysmImageTooltip extends ClientEnergyImageToolt
@Override @Override
protected Component getDamageComponent() { protected Component getDamageComponent() {
double damage = data.damage(); double damage = data.damage();
int perkLevel = PerkHelper.getItemPerkLevel(ModPerks.MICRO_MISSILE.get(), data); var perkInstance = data.perk.getInstance(ModPerks.MICRO_MISSILE.get());
int perkLevel = perkInstance == null ? 0 : perkInstance.level();
if (perkLevel > 0) damage *= 1.1f + perkLevel * 0.1f; if (perkLevel > 0) damage *= 1.1f + perkLevel * 0.1f;
double explosionDamage = data.explosionDamage(); double explosionDamage = data.explosionDamage();

View file

@ -4,7 +4,6 @@ import com.atsuishio.superbwarfare.client.TooltipTool;
import com.atsuishio.superbwarfare.client.tooltip.component.GunImageComponent; import com.atsuishio.superbwarfare.client.tooltip.component.GunImageComponent;
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.PerkHelper;
import com.atsuishio.superbwarfare.tools.FormatTool; import com.atsuishio.superbwarfare.tools.FormatTool;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
@ -19,7 +18,7 @@ public class ClientShotgunImageTooltip extends ClientGunImageTooltip {
protected Component getDamageComponent() { protected Component getDamageComponent() {
boolean slug = false; boolean slug = false;
var perk = PerkHelper.getPerkByType(data, Perk.Type.AMMO); var perk = data.perk.get(Perk.Type.AMMO);
if (perk instanceof AmmoPerk ammoPerk && ammoPerk.slug) { if (perk instanceof AmmoPerk ammoPerk && ammoPerk.slug) {
slug = true; slug = true;
} }

View file

@ -16,7 +16,6 @@ import com.atsuishio.superbwarfare.item.gun.data.GunData;
import com.atsuishio.superbwarfare.network.message.send.*; import com.atsuishio.superbwarfare.network.message.send.*;
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.PerkHelper;
import com.atsuishio.superbwarfare.tools.*; import com.atsuishio.superbwarfare.tools.*;
import com.atsuishio.superbwarfare.tools.animation.AnimationCurves; import com.atsuishio.superbwarfare.tools.animation.AnimationCurves;
import net.minecraft.client.CameraType; import net.minecraft.client.CameraType;
@ -396,7 +395,7 @@ public class ClientEventHandler {
var data = GunData.from(stack); var data = GunData.from(stack);
final var tag = data.tag(); final var tag = data.tag();
var perk = PerkHelper.getPerkByType(tag, Perk.Type.AMMO); var perk = data.perk.get(Perk.Type.AMMO);
int mode = data.fireMode(); int mode = data.fireMode();
// 精准度 // 精准度
@ -446,7 +445,7 @@ public class ClientEventHandler {
} }
if (GunsTool.getPerkIntTag(tag, "DesperadoTimePost") > 0) { if (GunsTool.getPerkIntTag(tag, "DesperadoTimePost") > 0) {
int perkLevel = PerkHelper.getItemPerkLevel(ModPerks.DESPERADO.get(), tag); int perkLevel = data.perk.getLevel(ModPerks.DESPERADO);
rpm *= (int) (1.285 + 0.015 * perkLevel); rpm *= (int) (1.285 + 0.015 * perkLevel);
} }
@ -574,7 +573,7 @@ public class ClientEventHandler {
} }
if (stack.is(ModItems.DEVOTION.get())) { if (stack.is(ModItems.DEVOTION.get())) {
int perkLevel = PerkHelper.getItemPerkLevel(ModPerks.TURBO_CHARGER.get(), tag); int perkLevel = data.perk.getLevel(ModPerks.TURBO_CHARGER);
customRpm = Math.min(customRpm + 15 + ((perkLevel > 0 ? 5 : 0) + 3 * perkLevel), 500); customRpm = Math.min(customRpm + 15 + ((perkLevel > 0 ? 5 : 0) + 3 * perkLevel), 500);
} }
@ -600,7 +599,7 @@ public class ClientEventHandler {
} else if (stack.is(ModItems.MINIGUN.get())) { } else if (stack.is(ModItems.MINIGUN.get())) {
var cap = player.getCapability(ModCapabilities.PLAYER_VARIABLE); var cap = player.getCapability(ModCapabilities.PLAYER_VARIABLE);
if (cap != null && cap.rifleAmmo > 0 || InventoryTool.hasCreativeAmmoBox(player)) { if (cap != null && cap.rifleAmmo > 0 || InventoryTool.hasCreativeAmmoBox(player)) {
var perk = PerkHelper.getPerkByType(tag, Perk.Type.AMMO); var perk = data.perk.get(Perk.Type.AMMO);
float pitch = tag.getDouble("heat") <= 40 ? 1 : (float) (1 - 0.025 * Math.abs(40 - tag.getDouble("heat"))); float pitch = tag.getDouble("heat") <= 40 ? 1 : (float) (1 - 0.025 * Math.abs(40 - tag.getDouble("heat")));
player.playSound(ModSounds.MINIGUN_FIRE_1P.get(), 1f, pitch); player.playSound(ModSounds.MINIGUN_FIRE_1P.get(), 1f, pitch);
@ -680,14 +679,13 @@ public class ClientEventHandler {
return; return;
} }
} }
var data = GunData.from(stack);
var perk = PerkHelper.getPerkByType(tag, Perk.Type.AMMO); var perk = data.perk.get(Perk.Type.AMMO);
if (perk == ModPerks.BEAST_BULLET.get()) { if (perk == ModPerks.BEAST_BULLET.get()) {
player.playSound(ModSounds.HENG.get(), 1f, 1f); player.playSound(ModSounds.HENG.get(), 1f, 1f);
} }
var data = GunData.from(stack);
int barrelType = data.attachment.get(AttachmentType.BARREL); int barrelType = data.attachment.get(AttachmentType.BARREL);
SoundEvent sound1p = BuiltInRegistries.SOUND_EVENT.get(Mod.loc(name + (barrelType == 2 ? "_fire_1p_s" : "_fire_1p"))); SoundEvent sound1p = BuiltInRegistries.SOUND_EVENT.get(Mod.loc(name + (barrelType == 2 ? "_fire_1p_s" : "_fire_1p")));
@ -1420,7 +1418,7 @@ public class ClientEventHandler {
&& cap != null && cap != null
&& !cap.edit) { && !cap.edit) {
if (!player.isShiftKeyDown()) { if (!player.isShiftKeyDown()) {
int intelligentChipLevel = PerkHelper.getItemPerkLevel(ModPerks.INTELLIGENT_CHIP.get(), tag); int intelligentChipLevel = data.perk.getLevel(ModPerks.INTELLIGENT_CHIP);
if (intelligentChipLevel > 0) { if (intelligentChipLevel > 0) {
if (ClientEventHandler.entity == null || !entity.isAlive()) { if (ClientEventHandler.entity == null || !entity.isAlive()) {

View file

@ -15,7 +15,6 @@ import com.atsuishio.superbwarfare.item.gun.data.GunData;
import com.atsuishio.superbwarfare.item.gun.data.ReloadState; import com.atsuishio.superbwarfare.item.gun.data.ReloadState;
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.PerkHelper;
import com.atsuishio.superbwarfare.tools.AmmoType; import com.atsuishio.superbwarfare.tools.AmmoType;
import com.atsuishio.superbwarfare.tools.GunsTool; import com.atsuishio.superbwarfare.tools.GunsTool;
import com.atsuishio.superbwarfare.tools.InventoryTool; import com.atsuishio.superbwarfare.tools.InventoryTool;
@ -123,7 +122,7 @@ public class GunEventHandler {
} }
} }
var perk = PerkHelper.getPerkByType(tag, Perk.Type.AMMO); var perk = data.perk.get(Perk.Type.AMMO);
if (perk == ModPerks.BEAST_BULLET.get()) { if (perk == ModPerks.BEAST_BULLET.get()) {
player.playSound(ModSounds.HENG.get(), 4f, 1f); player.playSound(ModSounds.HENG.get(), 4f, 1f);
} }
@ -186,12 +185,13 @@ public class GunEventHandler {
if (!player.level().isClientSide()) { if (!player.level().isClientSide()) {
float headshot = (float) data.headshot(); float headshot = (float) data.headshot();
float damage = (float) data.damage(); float damage = (float) data.damage();
float velocity = (float) ((data.velocity() + GunsTool.getGunDoubleTag(tag, "CustomVelocity")) * perkSpeed(tag)); float velocity = (float) ((data.velocity() + GunsTool.getGunDoubleTag(tag, "CustomVelocity")) * perkSpeed(data));
int projectileAmount = data.projectileAmount(); int projectileAmount = data.projectileAmount();
float bypassArmorRate = (float) data.bypassArmor(); float bypassArmorRate = (float) data.bypassArmor();
var cap = player.getCapability(ModCapabilities.PLAYER_VARIABLE); var cap = player.getCapability(ModCapabilities.PLAYER_VARIABLE);
boolean zoom = cap != null && cap.zoom; boolean zoom = cap != null && cap.zoom;
var perk = PerkHelper.getPerkByType(tag, Perk.Type.AMMO); var perkInstance = data.perk.getInstance(Perk.Type.AMMO);
var perk = perkInstance != null ? perkInstance.perk() : null;
if (perk != null && perk.descriptionId.equals("butterfly_bullet")) { if (perk != null && perk.descriptionId.equals("butterfly_bullet")) {
if (handleButterflyBullet(perk, stack, player)) return; if (handleButterflyBullet(perk, stack, player)) return;
@ -205,7 +205,7 @@ public class GunEventHandler {
.zoom(zoom); .zoom(zoom);
if (perk instanceof AmmoPerk ammoPerk) { if (perk instanceof AmmoPerk ammoPerk) {
int level = PerkHelper.getItemPerkLevel(perk, tag); int level = data.perk.getLevel(perk);
bypassArmorRate += ammoPerk.bypassArmorRate + (perk == ModPerks.AP_BULLET.get() ? 0.05f * (level - 1) : 0); bypassArmorRate += ammoPerk.bypassArmorRate + (perk == ModPerks.AP_BULLET.get() ? 0.05f * (level - 1) : 0);
projectile.setRGB(ammoPerk.rgb); projectile.setRGB(ammoPerk.rgb);
@ -237,24 +237,24 @@ public class GunEventHandler {
projectile.bypassArmorRate(bypassArmorRate); projectile.bypassArmorRate(bypassArmorRate);
if (perk == ModPerks.SILVER_BULLET.get()) { if (perk == ModPerks.SILVER_BULLET.get()) {
int level = PerkHelper.getItemPerkLevel(perk, tag); int level = data.perk.getLevel(perk);
projectile.undeadMultiple(1.0f + 0.5f * level); projectile.undeadMultiple(1.0f + 0.5f * level);
} else if (perk == ModPerks.BEAST_BULLET.get()) { } else if (perk == ModPerks.BEAST_BULLET.get()) {
projectile.beast(); projectile.beast();
} else if (perk == ModPerks.JHP_BULLET.get()) { } else if (perk == ModPerks.JHP_BULLET.get()) {
int level = PerkHelper.getItemPerkLevel(perk, tag); int level = data.perk.getLevel(perk);
projectile.jhpBullet(level); projectile.jhpBullet(level);
} else if (perk == ModPerks.HE_BULLET.get()) { } else if (perk == ModPerks.HE_BULLET.get()) {
int level = PerkHelper.getItemPerkLevel(perk, tag); int level = data.perk.getLevel(perk);
projectile.heBullet(level); projectile.heBullet(level);
} else if (perk == ModPerks.INCENDIARY_BULLET.get()) { } else if (perk == ModPerks.INCENDIARY_BULLET.get()) {
int level = PerkHelper.getItemPerkLevel(perk, tag); int level = data.perk.getLevel(perk);
projectile.fireBullet(level, stack.is(ModTags.Items.SHOTGUN)); projectile.fireBullet(level, stack.is(ModTags.Items.SHOTGUN));
} }
var dmgPerk = PerkHelper.getPerkByType(tag, Perk.Type.DAMAGE); var dmgPerk = data.perk.get(Perk.Type.DAMAGE);
if (dmgPerk == ModPerks.MONSTER_HUNTER.get()) { if (dmgPerk == ModPerks.MONSTER_HUNTER.get()) {
int level = PerkHelper.getItemPerkLevel(dmgPerk, tag); int level = data.perk.getLevel(dmgPerk);
projectile.monsterMultiple(0.1f + 0.1f * level); projectile.monsterMultiple(0.1f + 0.1f * level);
} }
@ -264,8 +264,8 @@ public class GunEventHandler {
} }
} }
public static double perkSpeed(final CompoundTag tag) { public static double perkSpeed(GunData data) {
var perk = PerkHelper.getPerkByType(tag, Perk.Type.AMMO); var perk = data.perk.get(Perk.Type.AMMO);
if (perk instanceof AmmoPerk ammoPerk) { if (perk instanceof AmmoPerk ammoPerk) {
return ammoPerk.speedRate; return ammoPerk.speedRate;
} }
@ -275,7 +275,7 @@ public class GunEventHandler {
// TODO 这还有联动的必要吗 // TODO 这还有联动的必要吗
private static boolean handleButterflyBullet(Perk perk, ItemStack heldItem, Player player) { private static boolean handleButterflyBullet(Perk perk, ItemStack heldItem, Player player) {
return true; return true;
// int perkLevel = PerkHelper.getItemPerkLevel(perk, tag); // int perkLevel = data.perk.getLevel(perk);
// //
// var entityType = CompatHolder.VRC_RAIN_SHOWER_BUTTERFLY; // var entityType = CompatHolder.VRC_RAIN_SHOWER_BUTTERFLY;
// if (entityType != null) { // if (entityType != null) {

View file

@ -24,7 +24,6 @@ import com.atsuishio.superbwarfare.network.message.receive.DrawClientMessage;
import com.atsuishio.superbwarfare.network.message.receive.PlayerGunKillMessage; import com.atsuishio.superbwarfare.network.message.receive.PlayerGunKillMessage;
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.PerkHelper;
import com.atsuishio.superbwarfare.tools.*; import com.atsuishio.superbwarfare.tools.*;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.ClientboundStopSoundPacket; import net.minecraft.network.protocol.game.ClientboundStopSoundPacket;
@ -139,13 +138,15 @@ public class LivingEventHandler {
ItemStack stack = sourceEntity instanceof LivingEntity living ? living.getMainHandItem() : ItemStack.EMPTY; ItemStack stack = sourceEntity instanceof LivingEntity living ? living.getMainHandItem() : ItemStack.EMPTY;
final var tag = NBTTool.getTag(stack); final var tag = NBTTool.getTag(stack);
var perk = PerkHelper.getPerkByType(tag, Perk.Type.AMMO);
// 距离衰减 // 距离衰减
if (DamageTypeTool.isGunDamage(source)) { if (DamageTypeTool.isGunDamage(source) && stack.getItem() instanceof GunItem) {
double distance = entity.position().distanceTo(sourceEntity.position()); double distance = entity.position().distanceTo(sourceEntity.position());
var data = GunData.from(stack);
if (stack.is(ModTags.Items.USE_SHOTGUN_AMMO)) { if (stack.is(ModTags.Items.USE_SHOTGUN_AMMO)) {
var perk = data.perk.get(Perk.Type.AMMO);
if (perk instanceof AmmoPerk ammoPerk && ammoPerk.slug) { if (perk instanceof AmmoPerk ammoPerk && ammoPerk.slug) {
damage = reduceDamageByDistance(amount, distance, 0.015, 30); damage = reduceDamageByDistance(amount, distance, 0.015, 30);
} else { } else {
@ -219,7 +220,7 @@ public class LivingEventHandler {
// 先处理发射器类武器或高爆弹的爆炸伤害 // 先处理发射器类武器或高爆弹的爆炸伤害
if (source.is(ModDamageTypes.PROJECTILE_BOOM)) { if (source.is(ModDamageTypes.PROJECTILE_BOOM)) {
if (stack.is(ModTags.Items.LAUNCHER) || PerkHelper.getItemPerkLevel(ModPerks.HE_BULLET.get(), tag) > 0) { if (stack.is(ModTags.Items.LAUNCHER) || data.perk.getLevel(ModPerks.HE_BULLET) > 0) {
data.setExp(data.exp() + amount); data.setExp(data.exp() + amount);
} }
} }
@ -241,11 +242,10 @@ public class LivingEventHandler {
var data = GunData.from(stack); var data = GunData.from(stack);
double amount = 20 + 2 * event.getEntity().getMaxHealth(); double amount = 20 + 2 * event.getEntity().getMaxHealth();
final var tag = NBTTool.getTag(stack);
// 先处理发射器类武器或高爆弹的爆炸伤害 // 先处理发射器类武器或高爆弹的爆炸伤害
if (source.is(ModDamageTypes.PROJECTILE_BOOM)) { if (source.is(ModDamageTypes.PROJECTILE_BOOM)) {
if (stack.is(ModTags.Items.LAUNCHER) || PerkHelper.getItemPerkLevel(ModPerks.HE_BULLET.get(), tag) > 0) { if (stack.is(ModTags.Items.LAUNCHER) || data.perk.getLevel(ModPerks.HE_BULLET) > 0) {
data.setExp(data.exp() + amount); data.setExp(data.exp() + amount);
} }
} }
@ -424,7 +424,7 @@ public class LivingEventHandler {
newData.charge.reset(); newData.charge.reset();
} }
int level = PerkHelper.getItemPerkLevel(ModPerks.KILLING_TALLY.get(), newTag); int level = newData.perk.getLevel(ModPerks.KILLING_TALLY);
if (level != 0) { if (level != 0) {
GunsTool.setPerkIntTag(newTag, "KillingTally", 0); GunsTool.setPerkIntTag(newTag, "KillingTally", 0);
} }
@ -498,9 +498,8 @@ public class LivingEventHandler {
} }
ItemStack stack = attacker.getMainHandItem(); ItemStack stack = attacker.getMainHandItem();
if (!stack.is(ModTags.Items.GUN)) { if (!stack.is(ModTags.Items.GUN)) return;
return; var data = GunData.from(stack);
}
if (DamageTypeTool.isGunDamage(source) || source.is(ModDamageTypes.PROJECTILE_BOOM)) { if (DamageTypeTool.isGunDamage(source) || source.is(ModDamageTypes.PROJECTILE_BOOM)) {
handleKillClipDamage(stack, event); handleKillClipDamage(stack, event);
@ -520,8 +519,7 @@ public class LivingEventHandler {
} }
if (source.getDirectEntity() instanceof ProjectileEntity projectile) { if (source.getDirectEntity() instanceof ProjectileEntity projectile) {
final var tag = NBTTool.getTag(stack); if (data.perk.getLevel(ModPerks.FOURTH_TIMES_CHARM) > 0) {
if (PerkHelper.getItemPerkLevel(ModPerks.FOURTH_TIMES_CHARM.get(), tag) > 0) {
float bypassArmorRate = projectile.getBypassArmorRate(); float bypassArmorRate = projectile.getBypassArmorRate();
if (bypassArmorRate >= 1.0f && source.is(ModDamageTypes.GUN_FIRE_HEADSHOT_ABSOLUTE)) { if (bypassArmorRate >= 1.0f && source.is(ModDamageTypes.GUN_FIRE_HEADSHOT_ABSOLUTE)) {
handleFourthTimesCharm(stack); handleFourthTimesCharm(stack);
@ -576,27 +574,25 @@ public class LivingEventHandler {
private static void handleClipPerks(ItemStack stack) { private static void handleClipPerks(ItemStack stack) {
var data = GunData.from(stack); var data = GunData.from(stack);
final var tag = data.tag(); int healClipLevel = data.perk.getLevel(ModPerks.HEAL_CLIP);
int healClipLevel = PerkHelper.getItemPerkLevel(ModPerks.HEAL_CLIP.get(), tag); var tag = data.perk.getTag(ModPerks.HEAL_CLIP);
if (healClipLevel != 0) { if (healClipLevel != 0) {
GunsTool.setPerkIntTag(tag, "HealClipTime", 80 + healClipLevel * 20); tag.putInt("HealClipTime", 80 + healClipLevel * 20);
} }
int killClipLevel = PerkHelper.getItemPerkLevel(ModPerks.KILL_CLIP.get(), tag); int killClipLevel = data.perk.getLevel(ModPerks.KILL_CLIP);
if (killClipLevel != 0) { if (killClipLevel != 0) {
GunsTool.setPerkIntTag(tag, "KillClipReloadTime", 80); tag.putInt("KillClipReloadTime", 80);
} }
data.save(); data.save();
} }
private static void handleKillClipDamage(ItemStack stack, LivingIncomingDamageEvent event) { private static void handleKillClipDamage(ItemStack stack, LivingIncomingDamageEvent event) {
var data = GunData.from(stack); var data = GunData.from(stack);
final var tag = data.tag(); final var tag = data.perk.getTag(ModPerks.KILL_CLIP);
if (GunsTool.getPerkIntTag(tag, "KillClipTime") > 0) { if (tag.getInt("KillClipTime") > 0) {
int level = PerkHelper.getItemPerkLevel(ModPerks.KILL_CLIP.get(), tag); int level = data.perk.getLevel(ModPerks.KILL_CLIP);
if (level == 0) { if (level == 0) return;
return;
}
event.setAmount(event.getAmount() * (1.2f + 0.05f * level)); event.setAmount(event.getAmount() * (1.2f + 0.05f * level));
} }
@ -604,8 +600,7 @@ public class LivingEventHandler {
private static void handleGutshotStraightDamage(ItemStack stack, LivingIncomingDamageEvent event) { private static void handleGutshotStraightDamage(ItemStack stack, LivingIncomingDamageEvent event) {
var data = GunData.from(stack); var data = GunData.from(stack);
final var tag = data.tag(); int level = data.perk.getLevel(ModPerks.GUTSHOT_STRAIGHT);
int level = PerkHelper.getItemPerkLevel(ModPerks.GUTSHOT_STRAIGHT.get(), tag);
if (level == 0) return; if (level == 0) return;
event.setAmount(event.getAmount() * (1.15f + 0.05f * level)); event.setAmount(event.getAmount() * (1.15f + 0.05f * level));
@ -614,10 +609,10 @@ public class LivingEventHandler {
private static void handleKillingTallyDamage(ItemStack stack, LivingIncomingDamageEvent event) { private static void handleKillingTallyDamage(ItemStack stack, LivingIncomingDamageEvent event) {
var data = GunData.from(stack); var data = GunData.from(stack);
final var tag = data.tag(); final var tag = data.tag();
int level = PerkHelper.getItemPerkLevel(ModPerks.KILLING_TALLY.get(), tag); int level = data.perk.getLevel(ModPerks.KILLING_TALLY);
if (level == 0) return; if (level == 0) return;
int killTally = GunsTool.getPerkIntTag(tag, "KillingTally"); int killTally = data.perk.getTag(ModPerks.KILLING_TALLY).getInt("KillingTally");
if (killTally == 0) { if (killTally == 0) {
return; return;
} }
@ -627,37 +622,37 @@ public class LivingEventHandler {
private static void handleKillingTallyAddCount(ItemStack stack) { private static void handleKillingTallyAddCount(ItemStack stack) {
var data = GunData.from(stack); var data = GunData.from(stack);
final var tag = data.tag(); int level = data.perk.getLevel(ModPerks.KILLING_TALLY);
int level = PerkHelper.getItemPerkLevel(ModPerks.KILLING_TALLY.get(), tag);
if (level != 0) { if (level != 0) {
GunsTool.setPerkIntTag(tag, "KillingTally", Math.min(3, GunsTool.getPerkIntTag(tag, "KillingTally") + 1)); var tag = data.perk.getTag(ModPerks.KILLING_TALLY);
tag.putInt("KillingTally", Math.min(3, tag.getInt("KillingTally") + 1));
data.save(); data.save();
} }
} }
private static void handleFourthTimesCharm(ItemStack stack) { private static void handleFourthTimesCharm(ItemStack stack) {
var data = GunData.from(stack); var data = GunData.from(stack);
final var tag = data.tag(); int level = data.perk.getLevel(ModPerks.FOURTH_TIMES_CHARM);
int level = PerkHelper.getItemPerkLevel(ModPerks.FOURTH_TIMES_CHARM.get(), tag);
if (level == 0) return; if (level == 0) return;
final var tag = data.perk.getTag(ModPerks.FOURTH_TIMES_CHARM);
int fourthTimesCharmTick = GunsTool.getPerkIntTag(tag, "FourthTimesCharmTick"); int fourthTimesCharmTick = tag.getInt("FourthTimesCharmTick");
if (fourthTimesCharmTick <= 0) { if (fourthTimesCharmTick <= 0) {
GunsTool.setPerkIntTag(tag, "FourthTimesCharmTick", 40 + 10 * level); tag.putInt("FourthTimesCharmTick", 40 + 10 * level);
GunsTool.setPerkIntTag(tag, "FourthTimesCharmCount", 1); tag.putInt("FourthTimesCharmCount", 1);
} else { } else {
int count = GunsTool.getPerkIntTag(tag, "FourthTimesCharmCount"); int count = tag.getInt("FourthTimesCharmCount");
if (count < 4) { if (count < 4) {
GunsTool.setPerkIntTag(tag, "FourthTimesCharmCount", Math.min(4, count + 1)); tag.putInt("FourthTimesCharmCount", Math.min(4, count + 1));
} }
} }
data.save(); data.save();
} }
private static void handleSubsistence(ItemStack stack, Player player) { private static void handleSubsistence(ItemStack stack, Player player) {
var data = GunData.from(stack); var data = GunData.from(stack);
final var tag = data.tag(); int level = data.perk.getLevel(ModPerks.SUBSISTENCE);
int level = PerkHelper.getItemPerkLevel(ModPerks.SUBSISTENCE.get(), tag);
if (level == 0) return; if (level == 0) return;
float rate = level * 0.1f + (stack.is(ModTags.Items.SMG) || stack.is(ModTags.Items.RIFLE) ? 0.07f : 0f); float rate = level * 0.1f + (stack.is(ModTags.Items.SMG) || stack.is(ModTags.Items.RIFLE) ? 0.07f : 0f);
@ -696,8 +691,7 @@ public class LivingEventHandler {
private static void handleFieldDoctor(ItemStack stack, LivingIncomingDamageEvent event, Player player) { private static void handleFieldDoctor(ItemStack stack, LivingIncomingDamageEvent event, Player player) {
var data = GunData.from(stack); var data = GunData.from(stack);
final var tag = data.tag(); int level = data.perk.getLevel(ModPerks.FIELD_DOCTOR);
int level = PerkHelper.getItemPerkLevel(ModPerks.FIELD_DOCTOR.get(), tag);
if (level == 0) return; if (level == 0) return;
if (event.getEntity().isAlliedTo(player)) { if (event.getEntity().isAlliedTo(player)) {
@ -708,32 +702,31 @@ public class LivingEventHandler {
private static void handleHeadSeekerTime(ItemStack stack) { private static void handleHeadSeekerTime(ItemStack stack) {
var data = GunData.from(stack); var data = GunData.from(stack);
final var tag = data.tag(); int level = data.perk.getLevel(ModPerks.HEAD_SEEKER);
int level = PerkHelper.getItemPerkLevel(ModPerks.HEAD_SEEKER.get(), tag);
if (level == 0) return; if (level == 0) return;
GunsTool.setPerkIntTag(tag, "HeadSeeker", 11 + level * 2); data.perk.getTag(ModPerks.HEAD_SEEKER).putInt("HeadSeeker", 11 + level * 2);
data.save(); data.save();
} }
private static void handleHeadSeekerDamage(ItemStack stack, LivingIncomingDamageEvent event) { private static void handleHeadSeekerDamage(ItemStack stack, LivingIncomingDamageEvent event) {
var data = GunData.from(stack); var data = GunData.from(stack);
final var tag = data.tag(); int level = data.perk.getLevel(ModPerks.HEAD_SEEKER);
int level = PerkHelper.getItemPerkLevel(ModPerks.HEAD_SEEKER.get(), tag);
if (level == 0) return; if (level == 0) return;
if (GunsTool.getPerkIntTag(tag, "HeadSeeker") > 0) { var tag = data.perk.getTag(ModPerks.HEAD_SEEKER);
if (tag.getInt("HeadSeeker") > 0) {
event.setAmount(event.getAmount() * (1.095f + 0.0225f * level)); event.setAmount(event.getAmount() * (1.095f + 0.0225f * level));
} }
} }
private static void handleDesperado(ItemStack stack) { private static void handleDesperado(ItemStack stack) {
var data = GunData.from(stack); var data = GunData.from(stack);
final var tag = data.tag(); int level = data.perk.getLevel(ModPerks.DESPERADO);
int level = PerkHelper.getItemPerkLevel(ModPerks.DESPERADO.get(), tag);
if (level == 0) return; if (level == 0) return;
GunsTool.setPerkIntTag(tag, "DesperadoTime", 90 + level * 10); var tag = data.perk.getTag(ModPerks.DESPERADO);
tag.putInt("DesperadoTime", 90 + level * 10);
data.save(); data.save();
} }
@ -801,8 +794,10 @@ public class LivingEventHandler {
} }
// 磁吸Perk // 磁吸Perk
final var mainHandTag = NBTTool.getTag(mainHandItem); if (mainHandItem.is(ModTags.Items.GUN)
if (mainHandItem.is(ModTags.Items.GUN) && PerkHelper.getItemPerkLevel(ModPerks.POWERFUL_ATTRACTION.get(), mainHandTag) > 0 && (DamageTypeTool.isGunDamage(source) || DamageTypeTool.isExplosionDamage(source))) { && GunData.from(mainHandItem).perk.has(ModPerks.POWERFUL_ATTRACTION.get())
&& (DamageTypeTool.isGunDamage(source) || DamageTypeTool.isExplosionDamage(source))
) {
var drops = event.getDrops(); var drops = event.getDrops();
drops.forEach(itemEntity -> { drops.forEach(itemEntity -> {
ItemStack item = itemEntity.getItem(); ItemStack item = itemEntity.getItem();
@ -827,9 +822,9 @@ public class LivingEventHandler {
ItemStack stack = player.getMainHandItem(); ItemStack stack = player.getMainHandItem();
if (!stack.is(ModTags.Items.GUN)) return; if (!stack.is(ModTags.Items.GUN)) return;
var data = GunData.from(stack);
final var tag = NBTTool.getTag(stack); int level = data.perk.getLevel(ModPerks.POWERFUL_ATTRACTION);
int level = PerkHelper.getItemPerkLevel(ModPerks.POWERFUL_ATTRACTION.get(), tag);
if (level > 0) { if (level > 0) {
player.giveExperiencePoints((int) (event.getDroppedExperience() * (0.8f + 0.2f * level))); player.giveExperiencePoints((int) (event.getDroppedExperience() * (0.8f + 0.2f * level)));
@ -846,9 +841,9 @@ public class LivingEventHandler {
private static void handleVorpalWeaponDamage(ItemStack stack, LivingIncomingDamageEvent event) { private static void handleVorpalWeaponDamage(ItemStack stack, LivingIncomingDamageEvent event) {
var entity = event.getEntity(); var entity = event.getEntity();
var data = GunData.from(stack);
final var tag = NBTTool.getTag(stack); int level = data.perk.getLevel(ModPerks.VORPAL_WEAPON);
int level = PerkHelper.getItemPerkLevel(ModPerks.VORPAL_WEAPON.get(), tag);
if (level <= 0) return; if (level <= 0) return;
if (entity.getHealth() < 100.0f) return; if (entity.getHealth() < 100.0f) return;

View file

@ -4,7 +4,6 @@ import com.atsuishio.superbwarfare.event.events.ReloadEvent;
import com.atsuishio.superbwarfare.init.ModPerks; import com.atsuishio.superbwarfare.init.ModPerks;
import com.atsuishio.superbwarfare.init.ModTags; import com.atsuishio.superbwarfare.init.ModTags;
import com.atsuishio.superbwarfare.item.gun.data.GunData; import com.atsuishio.superbwarfare.item.gun.data.GunData;
import com.atsuishio.superbwarfare.perk.PerkHelper;
import com.atsuishio.superbwarfare.tools.GunsTool; import com.atsuishio.superbwarfare.tools.GunsTool;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
@ -66,7 +65,7 @@ public class ReloadEventHandler {
final var tag = data.tag(); final var tag = data.tag();
if (!GunsTool.getPerkBooleanTag(tag, "HealClip")) return; if (!GunsTool.getPerkBooleanTag(tag, "HealClip")) return;
int healClipLevel = PerkHelper.getItemPerkLevel(ModPerks.HEAL_CLIP.get(), tag); int healClipLevel = data.perk.getLevel(ModPerks.HEAL_CLIP);
if (healClipLevel == 0) { if (healClipLevel == 0) {
healClipLevel = 1; healClipLevel = 1;
} }
@ -96,7 +95,7 @@ public class ReloadEventHandler {
final var tag = data.tag(); final var tag = data.tag();
if (!GunsTool.getPerkBooleanTag(tag, "KillClip")) return; if (!GunsTool.getPerkBooleanTag(tag, "KillClip")) return;
int level = PerkHelper.getItemPerkLevel(ModPerks.KILL_CLIP.get(), tag); int level = data.perk.getLevel(ModPerks.KILL_CLIP);
GunsTool.setPerkIntTag(tag, "KillClipTime", 90 + 10 * level); GunsTool.setPerkIntTag(tag, "KillClipTime", 90 + 10 * level);
data.save(); data.save();
} }
@ -104,7 +103,7 @@ public class ReloadEventHandler {
private static void handleKillingTallyPre(ItemStack stack) { private static void handleKillingTallyPre(ItemStack stack) {
var data = GunData.from(stack); var data = GunData.from(stack);
final var tag = data.tag(); final var tag = data.tag();
int level = PerkHelper.getItemPerkLevel(ModPerks.KILLING_TALLY.get(), tag); int level = data.perk.getLevel(ModPerks.KILLING_TALLY);
if (level == 0) return; if (level == 0) return;
GunsTool.setPerkIntTag(tag, "KillingTally", 0); GunsTool.setPerkIntTag(tag, "KillingTally", 0);
@ -129,7 +128,7 @@ public class ReloadEventHandler {
final var tag = data.tag(); final var tag = data.tag();
if (!GunsTool.getPerkBooleanTag(tag, "Desperado")) return; if (!GunsTool.getPerkBooleanTag(tag, "Desperado")) return;
int level = PerkHelper.getItemPerkLevel(ModPerks.DESPERADO.get(), tag); int level = data.perk.getLevel(ModPerks.DESPERADO);
GunsTool.setPerkIntTag(tag, "DesperadoTimePost", 110 + level * 10); GunsTool.setPerkIntTag(tag, "DesperadoTimePost", 110 + level * 10);
data.save(); data.save();
} }

View file

@ -75,7 +75,7 @@ public class ModPerks {
public static final DeferredHolder<Perk, Perk> DESPERADO = DAMAGE_PERKS.register("desperado", () -> new Perk("desperado", Perk.Type.DAMAGE)); public static final DeferredHolder<Perk, Perk> DESPERADO = DAMAGE_PERKS.register("desperado", () -> new Perk("desperado", Perk.Type.DAMAGE));
public static final DeferredHolder<Perk, Perk> VORPAL_WEAPON = DAMAGE_PERKS.register("vorpal_weapon", () -> new Perk("vorpal_weapon", Perk.Type.DAMAGE)); public static final DeferredHolder<Perk, Perk> VORPAL_WEAPON = DAMAGE_PERKS.register("vorpal_weapon", () -> new Perk("vorpal_weapon", Perk.Type.DAMAGE));
public static void registerCompatPerks() { // public static void registerCompatPerks() {
// if (ModList.get().isLoaded(CompatHolder.DMV)) { // if (ModList.get().isLoaded(CompatHolder.DMV)) {
// AMMO_PERKS.register("blade_bullet", () -> new AmmoPerk(new AmmoPerk.Builder("blade_bullet", Perk.Type.AMMO) // AMMO_PERKS.register("blade_bullet", () -> new AmmoPerk(new AmmoPerk.Builder("blade_bullet", Perk.Type.AMMO)
// .bypassArmorRate(-0.2f).damageRate(0.7f).speedRate(0.8f).rgb(0xB4, 0x4B, 0x88).mobEffect(() -> CompatHolder.DMV_BLEEDING))); // .bypassArmorRate(-0.2f).damageRate(0.7f).speedRate(0.8f).rgb(0xB4, 0x4B, 0x88).mobEffect(() -> CompatHolder.DMV_BLEEDING)));
@ -88,10 +88,10 @@ public class ModPerks {
// AMMO_PERKS.register("butterfly_bullet", () -> new AmmoPerk(new AmmoPerk.Builder("butterfly_bullet", Perk.Type.AMMO) // AMMO_PERKS.register("butterfly_bullet", () -> new AmmoPerk(new AmmoPerk.Builder("butterfly_bullet", Perk.Type.AMMO)
// .bypassArmorRate(0.0f))); // .bypassArmorRate(0.0f)));
// } // }
} // }
public static void register(IEventBus bus) { public static void register(IEventBus bus) {
registerCompatPerks(); // registerCompatPerks();
AMMO_PERKS.register(bus); AMMO_PERKS.register(bus);
FUNC_PERKS.register(bus); FUNC_PERKS.register(bus);
DAMAGE_PERKS.register(bus); DAMAGE_PERKS.register(bus);

View file

@ -11,14 +11,11 @@ import com.atsuishio.superbwarfare.item.CustomRendererItem;
import com.atsuishio.superbwarfare.item.gun.data.AttachmentType; import com.atsuishio.superbwarfare.item.gun.data.AttachmentType;
import com.atsuishio.superbwarfare.item.gun.data.GunData; import com.atsuishio.superbwarfare.item.gun.data.GunData;
import com.atsuishio.superbwarfare.perk.Perk; import com.atsuishio.superbwarfare.perk.Perk;
import com.atsuishio.superbwarfare.perk.PerkHelper;
import com.atsuishio.superbwarfare.tools.AmmoType; import com.atsuishio.superbwarfare.tools.AmmoType;
import com.atsuishio.superbwarfare.tools.GunsTool;
import net.minecraft.client.model.HumanoidModel; import net.minecraft.client.model.HumanoidModel;
import net.minecraft.client.renderer.BlockEntityWithoutLevelRenderer; import net.minecraft.client.renderer.BlockEntityWithoutLevelRenderer;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
@ -166,41 +163,40 @@ public abstract class GunItem extends Item implements CustomRendererItem {
private void handleGunPerks(GunData data) { private void handleGunPerks(GunData data) {
var tag = data.tag(); var perk = data.perk;
reducePerkTagCoolDown(tag, "HealClipTime", "KillClipReloadTime", "KillClipTime", "FourthTimesCharmTick", "HeadSeeker", perk.reduceCooldown(ModPerks.HEAL_CLIP, "HealClipTime");
"DesperadoTime", "DesperadoTimePost");
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");
perk.reduceCooldown(ModPerks.DESPERADO, "DesperadoTime");
perk.reduceCooldown(ModPerks.DESPERADO, "DesperadoTimePost");
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 (PerkHelper.getItemPerkLevel(ModPerks.FOURTH_TIMES_CHARM.get(), tag) > 0) {
int count = GunsTool.getPerkIntTag(tag, "FourthTimesCharmCount");
if (count >= 4) { if (count >= 4) {
GunsTool.setPerkIntTag(tag, "FourthTimesCharmTick", 0); tag.remove("FourthTimesCharmTick");
GunsTool.setPerkIntTag(tag, "FourthTimesCharmCount", 0); tag.remove("FourthTimesCharmCount");
int mag = data.magazine(); int mag = data.magazine();
data.setAmmo(Math.min(mag, data.ammo() + 2)); data.setAmmo(Math.min(mag, data.ammo() + 2));
} }
} }
data.save();
} }
public boolean canApplyPerk(Perk perk) { public boolean canApplyPerk(Perk perk) {
return true; return true;
} }
private void reducePerkTagCoolDown(final CompoundTag tag, String... tags) {
var compound = tag.getCompound("PerkData");
for (String t : tags) {
if (!compound.contains(t)) {
continue;
}
if (compound.getInt(t) > 0) {
compound.putInt(t, Math.max(0, compound.getInt(t) - 1));
}
}
tag.put("PerkData", compound);
}
/** /**
* 是否使用弹匣换弹 * 是否使用弹匣换弹

View file

@ -3,7 +3,6 @@ package com.atsuishio.superbwarfare.item.gun.data;
import com.atsuishio.superbwarfare.item.gun.GunItem; import com.atsuishio.superbwarfare.item.gun.GunItem;
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.PerkHelper;
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;
@ -20,7 +19,7 @@ public class GunData {
private final GunItem item; private final GunItem item;
private final CompoundTag tag; private final CompoundTag tag;
private final CompoundTag data; private final CompoundTag data;
private final CompoundTag perk; private final CompoundTag perkTag;
private final CompoundTag attachmentTag; private final CompoundTag attachmentTag;
private final String id; private final String id;
@ -39,13 +38,14 @@ public class GunData {
this.tag = customData != null ? customData.copyTag() : new CompoundTag(); this.tag = customData != null ? customData.copyTag() : new CompoundTag();
data = getOrPut("GunData"); data = getOrPut("GunData");
perk = getOrPut("PerkData"); perkTag = getOrPut("Perks");
attachmentTag = getOrPut("Attachments"); attachmentTag = getOrPut("Attachments");
reload = new Reload(this); reload = new Reload(this);
charge = new Charge(this); charge = new Charge(this);
bolt = new Bolt(this); bolt = new Bolt(this);
attachment = new Attachment(this); attachment = new Attachment(this);
perk = new Perks(this);
} }
private CompoundTag getOrPut(String name) { private CompoundTag getOrPut(String name) {
@ -96,7 +96,7 @@ public class GunData {
} }
public CompoundTag perk() { public CompoundTag perk() {
return perk; return perkTag;
} }
public CompoundTag attachment() { public CompoundTag attachment() {
@ -116,7 +116,7 @@ public class GunData {
} }
public double perkDamageRate() { public double perkDamageRate() {
var perk = PerkHelper.getPerkByType(tag, Perk.Type.AMMO); var perk = this.perk.get(Perk.Type.AMMO);
if (perk instanceof AmmoPerk ammoPerk) { if (perk instanceof AmmoPerk ammoPerk) {
return ammoPerk.damageRate; return ammoPerk.damageRate;
} }
@ -302,6 +302,7 @@ public class GunData {
public final Bolt bolt; public final Bolt bolt;
public final Attachment attachment; public final Attachment attachment;
public final Perks perk;
public void save() { public void save() {
stack.set(DataComponents.CUSTOM_DATA, CustomData.of(tag)); stack.set(DataComponents.CUSTOM_DATA, CustomData.of(tag));

View file

@ -0,0 +1,136 @@
package com.atsuishio.superbwarfare.item.gun.data;
import com.atsuishio.superbwarfare.init.ModPerks;
import com.atsuishio.superbwarfare.item.PerkItem;
import com.atsuishio.superbwarfare.perk.Perk;
import com.atsuishio.superbwarfare.perk.PerkInstance;
import net.minecraft.nbt.CompoundTag;
import net.neoforged.neoforge.registries.DeferredHolder;
import javax.annotation.Nullable;
import java.util.ArrayList;
public final class Perks {
private final CompoundTag perks;
Perks(GunData gun) {
this.perks = gun.perk();
}
public boolean has(Perk perk) {
if (!has(perk.type)) return false;
return getTag(perk).getString("Name").equals(perk.name);
}
public boolean has(Perk.Type type) {
return perks.contains(type.getName());
}
public void set(PerkInstance instance) {
set(instance.perk(), instance.level());
}
public CompoundTag getTag(DeferredHolder<Perk, Perk> registry) {
return getTag(registry.get().type);
}
public CompoundTag getTag(Perk perk) {
return getTag(perk.type);
}
public CompoundTag getTag(Perk.Type type) {
CompoundTag typeTag;
if (!perks.contains(type.getName())) {
typeTag = new CompoundTag();
perks.put(type.getName(), typeTag);
}
return perks.getCompound(type.getName());
}
public void set(Perk perk, short level) {
getTag(perk).putString("Name", perk.name);
getTag(perk).putShort("Level", level);
}
public short getLevel(PerkItem<?> item) {
return getLevel(item.getPerk());
}
public short getLevel(DeferredHolder<Perk, Perk> perk) {
return getLevel(perk.get());
}
public short getLevel(Perk perk) {
var name = perk.name;
var tag = getTag(perk);
if (!tag.getString("Name").equals(name)) return 0;
return getLevel(perk.type);
}
public short getLevel(Perk.Type type) {
return getTag(type).getShort("Level");
}
public @Nullable Perk get(DeferredHolder<Perk, Perk> registry) {
return get(registry.get());
}
public @Nullable Perk get(Perk perk) {
return get(perk.type);
}
public @Nullable Perk get(Perk.Type type) {
var perksRegistry = new ArrayList<DeferredHolder<Perk, ? extends Perk>>();
perksRegistry.addAll(ModPerks.AMMO_PERKS.getEntries());
perksRegistry.addAll(ModPerks.FUNC_PERKS.getEntries());
perksRegistry.addAll(ModPerks.DAMAGE_PERKS.getEntries());
for (var registry : perksRegistry) {
var name = getTag(type).getString("Name");
if (registry.get().name.equals(name)) {
return registry.get();
}
}
return null;
}
public @Nullable PerkInstance getInstance(Perk perk) {
return getInstance(perk.type);
}
public @Nullable PerkInstance getInstance(Perk.Type type) {
var perk = get(type);
if (perk == null) return null;
return new PerkInstance(perk, getLevel(type));
}
public void reduceCooldown(DeferredHolder<Perk, Perk> registry, String name) {
reduceCooldown(registry.get(), name);
}
public void reduceCooldown(Perk perk, String name) {
reduceCooldown(perk.type, name);
}
public void reduceCooldown(Perk.Type type, String name) {
var tag = getTag(type);
var value = tag.getInt(name);
value--;
if (value <= 0) {
tag.remove(name);
} else {
tag.putInt(name, value);
}
}
public void remove(Perk perk) {
remove(perk.type);
}
public void remove(Perk.Type type) {
perks.remove(type.getName());
}
}

View file

@ -262,9 +262,9 @@ public class JavelinItem extends GunItem implements GeoItem, SpecialFireWeapon {
new Vec3(tag.getDouble("TargetPosX"), tag.getDouble("TargetPosY"), tag.getDouble("TargetPosZ")) new Vec3(tag.getDouble("TargetPosX"), tag.getDouble("TargetPosY"), tag.getDouble("TargetPosZ"))
); );
var dmgPerk = PerkHelper.getPerkByType(tag, Perk.Type.DAMAGE); var dmgPerk = data.perk.get(Perk.Type.DAMAGE);
if (dmgPerk == ModPerks.MONSTER_HUNTER.get()) { if (dmgPerk == ModPerks.MONSTER_HUNTER.get()) {
int perkLevel = PerkHelper.getItemPerkLevel(dmgPerk, tag); int perkLevel = data.perk.getLevel(dmgPerk);
missileEntity.setMonsterMultiplier(0.1f + 0.1f * perkLevel); missileEntity.setMonsterMultiplier(0.1f + 0.1f * perkLevel);
} }

View file

@ -187,16 +187,16 @@ public class M79Item extends GunItem implements GeoItem, SpecialFireWeapon {
(float) data.explosionRadius() (float) data.explosionRadius()
); );
var dmgPerk = PerkHelper.getPerkByType(tag, Perk.Type.DAMAGE); var dmgPerk = data.perk.get(Perk.Type.DAMAGE);
if (dmgPerk == ModPerks.MONSTER_HUNTER.get()) { if (dmgPerk == ModPerks.MONSTER_HUNTER.get()) {
int perkLevel = PerkHelper.getItemPerkLevel(dmgPerk, tag); int perkLevel = data.perk.getLevel(dmgPerk);
gunGrenadeEntity.setMonsterMultiplier(0.1f + 0.1f * perkLevel); gunGrenadeEntity.setMonsterMultiplier(0.1f + 0.1f * perkLevel);
} }
gunGrenadeEntity.setNoGravity(PerkHelper.getPerkByType(tag, Perk.Type.AMMO) == ModPerks.MICRO_MISSILE.get()); gunGrenadeEntity.setNoGravity(data.perk.get(Perk.Type.AMMO) == ModPerks.MICRO_MISSILE.get());
float velocity = (float) data.velocity(); float velocity = (float) data.velocity();
int perkLevel = PerkHelper.getItemPerkLevel(ModPerks.MICRO_MISSILE.get(), data.tag()); int perkLevel = data.perk.getLevel(ModPerks.MICRO_MISSILE);
if (perkLevel > 0) { if (perkLevel > 0) {
gunGrenadeEntity.setExplosionRadius((float) data.explosionRadius() * 0.5f); gunGrenadeEntity.setExplosionRadius((float) data.explosionRadius() * 0.5f);
gunGrenadeEntity.setDamage((float) data.explosionDamage() * (1.1f + perkLevel * 0.1f)); gunGrenadeEntity.setDamage((float) data.explosionDamage() * (1.1f + perkLevel * 0.1f));

View file

@ -201,18 +201,18 @@ public class RpgItem extends GunItem implements GeoItem, SpecialFireWeapon {
(float) data.explosionRadius() (float) data.explosionRadius()
); );
var dmgPerk = PerkHelper.getPerkByType(tag, Perk.Type.DAMAGE); var dmgPerk = data.perk.get(Perk.Type.DAMAGE);
if (dmgPerk == ModPerks.MONSTER_HUNTER.get()) { if (dmgPerk == ModPerks.MONSTER_HUNTER.get()) {
int perkLevel = PerkHelper.getItemPerkLevel(dmgPerk, tag); int perkLevel = data.perk.getLevel(dmgPerk);
rocket.setMonsterMultiplier(0.1f + 0.1f * perkLevel); rocket.setMonsterMultiplier(0.1f + 0.1f * perkLevel);
} }
float velocity = (float) data.velocity(); float velocity = (float) data.velocity();
if (PerkHelper.getPerkByType(tag, Perk.Type.AMMO) == ModPerks.MICRO_MISSILE.get()) { if (data.perk.get(Perk.Type.AMMO) == ModPerks.MICRO_MISSILE.get()) {
rocket.setNoGravity(true); rocket.setNoGravity(true);
int perkLevel = PerkHelper.getItemPerkLevel(ModPerks.MICRO_MISSILE.get(), tag); int perkLevel = data.perk.getLevel(ModPerks.MICRO_MISSILE);
if (perkLevel > 0) { if (perkLevel > 0) {
rocket.setExplosionRadius(0.5f); rocket.setExplosionRadius(0.5f);
rocket.setDamage((float) data.damage() * (1.1f + perkLevel * 0.1f)); rocket.setDamage((float) data.damage() * (1.1f + perkLevel * 0.1f));

View file

@ -291,17 +291,17 @@ public class SecondaryCataclysm extends GunItem implements GeoItem, SpecialFireW
(float) data.explosionRadius() (float) data.explosionRadius()
); );
var dmgPerk = PerkHelper.getPerkByType(tag, Perk.Type.DAMAGE); var dmgPerk = data.perk.get(Perk.Type.DAMAGE);
if (dmgPerk == ModPerks.MONSTER_HUNTER.get()) { if (dmgPerk == ModPerks.MONSTER_HUNTER.get()) {
int perkLevel = PerkHelper.getItemPerkLevel(dmgPerk, tag); int perkLevel = data.perk.getLevel(dmgPerk);
gunGrenadeEntity.setMonsterMultiplier(0.1f + 0.1f * perkLevel); gunGrenadeEntity.setMonsterMultiplier(0.1f + 0.1f * perkLevel);
} }
gunGrenadeEntity.setNoGravity(PerkHelper.getPerkByType(tag, Perk.Type.AMMO) == ModPerks.MICRO_MISSILE.get()); gunGrenadeEntity.setNoGravity(data.perk.get(Perk.Type.AMMO) == ModPerks.MICRO_MISSILE.get());
gunGrenadeEntity.charged(isChargedFire); gunGrenadeEntity.charged(isChargedFire);
float velocity = (float) data.velocity(); float velocity = (float) data.velocity();
int perkLevel = PerkHelper.getItemPerkLevel(ModPerks.MICRO_MISSILE.get(), data.tag()); int perkLevel = data.perk.getLevel(ModPerks.MICRO_MISSILE);
if (perkLevel > 0) { if (perkLevel > 0) {
gunGrenadeEntity.setExplosionRadius((float) data.explosionRadius() * 0.5f); gunGrenadeEntity.setExplosionRadius((float) data.explosionRadius() * 0.5f);
gunGrenadeEntity.setDamage((float) data.damage() * (1.1f + perkLevel * 0.1f)); gunGrenadeEntity.setDamage((float) data.damage() * (1.1f + perkLevel * 0.1f));

View file

@ -15,7 +15,6 @@ 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.AmmoPerk; import com.atsuishio.superbwarfare.perk.AmmoPerk;
import com.atsuishio.superbwarfare.perk.Perk; import com.atsuishio.superbwarfare.perk.Perk;
import com.atsuishio.superbwarfare.perk.PerkHelper;
import com.atsuishio.superbwarfare.tools.GunsTool; import com.atsuishio.superbwarfare.tools.GunsTool;
import com.atsuishio.superbwarfare.tools.InventoryTool; import com.atsuishio.superbwarfare.tools.InventoryTool;
import com.atsuishio.superbwarfare.tools.SoundTool; import com.atsuishio.superbwarfare.tools.SoundTool;
@ -174,7 +173,7 @@ public class BocekItem extends GunItem implements GeoItem, SpecialFireWeapon {
var tag = data.tag(); var tag = data.tag();
var stack = data.stack(); var stack = data.stack();
var perk = PerkHelper.getPerkByType(tag, Perk.Type.AMMO); var perk = data.perk.get(Perk.Type.AMMO);
if (player instanceof ServerPlayer serverPlayer) { if (player instanceof ServerPlayer serverPlayer) {
SoundTool.stopSound(serverPlayer, ModSounds.BOCEK_PULL_1P.getId(), SoundSource.PLAYERS); SoundTool.stopSound(serverPlayer, ModSounds.BOCEK_PULL_1P.getId(), SoundSource.PLAYERS);

View file

@ -16,7 +16,6 @@ import com.atsuishio.superbwarfare.item.gun.SpecialFireWeapon;
import com.atsuishio.superbwarfare.item.gun.data.GunData; 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.tools.GunsTool; import com.atsuishio.superbwarfare.tools.GunsTool;
import com.atsuishio.superbwarfare.tools.SoundTool; import com.atsuishio.superbwarfare.tools.SoundTool;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@ -154,7 +153,7 @@ public class TaserItem extends GunItem implements GeoItem, SpecialFireWeapon, En
data.save(); data.save();
} }
int perkLevel = PerkHelper.getItemPerkLevel(ModPerks.REGENERATION.get(), tag); int perkLevel = data.perk.getLevel(ModPerks.REGENERATION);
var stackStorage = stack.getCapability(Capabilities.EnergyStorage.ITEM); var stackStorage = stack.getCapability(Capabilities.EnergyStorage.ITEM);
if (stackStorage != null) { if (stackStorage != null) {
@ -228,7 +227,7 @@ public class TaserItem extends GunItem implements GeoItem, SpecialFireWeapon, En
ItemStack stack = data.stack(); ItemStack stack = data.stack();
var tag = data.tag(); var tag = data.tag();
int perkLevel = PerkHelper.getItemPerkLevel(ModPerks.VOLT_OVERLOAD.get(), tag); int perkLevel = data.perk.getLevel(ModPerks.VOLT_OVERLOAD);
var energyStorage = stack.getCapability(Capabilities.EnergyStorage.ITEM); var energyStorage = stack.getCapability(Capabilities.EnergyStorage.ITEM);
var hasEnoughEnergy = energyStorage != null && energyStorage.getEnergyStored() >= 400 + 100 * perkLevel; var hasEnoughEnergy = energyStorage != null && energyStorage.getEnergyStored() >= 400 + 100 * perkLevel;
@ -244,8 +243,8 @@ public class TaserItem extends GunItem implements GeoItem, SpecialFireWeapon, En
boolean zoom = cap != null && cap.zoom; boolean zoom = cap != null && cap.zoom;
double spread = data.spread(); double spread = data.spread();
int volt = PerkHelper.getItemPerkLevel(ModPerks.VOLT_OVERLOAD.get(), tag); int volt = data.perk.getLevel(ModPerks.VOLT_OVERLOAD);
int wireLength = PerkHelper.getItemPerkLevel(ModPerks.LONGER_WIRE.get(), tag); int wireLength = data.perk.getLevel(ModPerks.LONGER_WIRE);
SoundTool.playLocalSound(serverPlayer, ModSounds.TASER_FIRE_1P.get(), 1, 1); SoundTool.playLocalSound(serverPlayer, ModSounds.TASER_FIRE_1P.get(), 1, 1);
serverPlayer.level().playSound(null, serverPlayer.getOnPos(), ModSounds.TASER_FIRE_3P.get(), SoundSource.PLAYERS, 1, 1); serverPlayer.level().playSound(null, serverPlayer.getOnPos(), ModSounds.TASER_FIRE_3P.get(), SoundSource.PLAYERS, 1, 1);

View file

@ -7,8 +7,7 @@ import com.atsuishio.superbwarfare.item.PerkItem;
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.perk.Perk; import com.atsuishio.superbwarfare.perk.Perk;
import com.atsuishio.superbwarfare.perk.PerkHelper; import com.atsuishio.superbwarfare.perk.PerkInstance;
import com.atsuishio.superbwarfare.tools.NBTTool;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
import net.minecraft.world.Container; import net.minecraft.world.Container;
import net.minecraft.world.SimpleContainer; import net.minecraft.world.SimpleContainer;
@ -22,6 +21,7 @@ import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.List;
public class ReforgingTableMenu extends AbstractContainerMenu { public class ReforgingTableMenu extends AbstractContainerMenu {
@ -164,12 +164,12 @@ public class ReforgingTableMenu extends AbstractContainerMenu {
for (int i = 0; i < this.container.getContainerSize(); ++i) { for (int i = 0; i < this.container.getContainerSize(); ++i) {
ItemStack itemstack = this.container.getItem(i); ItemStack itemstack = this.container.getItem(i);
if (itemstack.getItem() instanceof PerkItem<?> perkItem) { if (copy.getItem() instanceof GunItem
final var tag = NBTTool.getTag(copy); && itemstack.getItem() instanceof PerkItem<?> perkItem
if (!copy.isEmpty() && PerkHelper.getItemPerkLevel(perkItem.getPerk(), tag) > 0) { && !copy.isEmpty()
continue; && GunData.from(copy).perk.getLevel(perkItem) > 0
} ) continue;
}
if (!itemstack.isEmpty()) { if (!itemstack.isEmpty()) {
pPlayer.getInventory().placeItemBackInInventory(itemstack); pPlayer.getInventory().placeItemBackInInventory(itemstack);
@ -238,28 +238,24 @@ public class ReforgingTableMenu extends AbstractContainerMenu {
ItemStack result = gun.copy(); ItemStack result = gun.copy();
var data = GunData.from(result); var data = GunData.from(result);
final var tag = data.tag();
if (!ammo.isEmpty() && ammo.getItem() instanceof PerkItem<?> perkItem) { List.of(ammo, func, damage).forEach(item -> {
if (gunItem.canApplyPerk(perkItem.getPerk())) { if (!item.isEmpty()
PerkHelper.setPerk(tag, perkItem.getPerk(), this.ammoPerkLevel.get()); && item.getItem() instanceof PerkItem<?> perkItem
this.container.setItem(AMMO_PERK_SLOT, ItemStack.EMPTY); && gunItem.canApplyPerk(perkItem.getPerk())
) {
data.perk.set(new PerkInstance(perkItem.getPerk(), (short) switch (perkItem.getPerk().type) {
case AMMO -> this.ammoPerkLevel.get();
case FUNCTIONAL -> this.funcPerkLevel.get();
case DAMAGE -> this.damagePerkLevel.get();
}));
this.container.setItem(switch (perkItem.getPerk().type) {
case AMMO -> AMMO_PERK_SLOT;
case FUNCTIONAL -> FUNC_PERK_SLOT;
case DAMAGE -> DAMAGE_PERK_SLOT;
}, ItemStack.EMPTY);
} }
} });
if (!func.isEmpty() && func.getItem() instanceof PerkItem<?> perkItem) {
if (gunItem.canApplyPerk(perkItem.getPerk())) {
PerkHelper.setPerk(tag, perkItem.getPerk(), this.funcPerkLevel.get());
this.container.setItem(FUNC_PERK_SLOT, ItemStack.EMPTY);
}
}
if (!damage.isEmpty() && damage.getItem() instanceof PerkItem<?> perkItem) {
if (gunItem.canApplyPerk(perkItem.getPerk())) {
PerkHelper.setPerk(tag, perkItem.getPerk(), this.damagePerkLevel.get());
this.container.setItem(DAMAGE_PERK_SLOT, ItemStack.EMPTY);
}
}
data.save(); data.save();
handleUpgradePoint(result); handleUpgradePoint(result);
@ -292,22 +288,23 @@ public class ReforgingTableMenu extends AbstractContainerMenu {
case DAMAGE -> this.damagePerkLevel.set(0); case DAMAGE -> this.damagePerkLevel.set(0);
} }
final var tag = NBTTool.getTag(gun); var inputData = GunData.from(gun);
int level = PerkHelper.getItemPerkLevel(perkItem.getPerk(), tag); int level = inputData.perk.getLevel(perkItem);
var data = GunData.from(gun);
if (level <= 0) { if (level <= 0) {
this.upgradePoint.set((int) data.upgradePoint()); this.upgradePoint.set((int) inputData.upgradePoint());
return; return;
} }
ItemStack output = gun.copy(); ItemStack output = gun.copy();
final var outputTag = NBTTool.getTag(output); var outputData = GunData.from(output);
PerkHelper.removePerkByType(outputTag, perkItem.getPerk().type); outputData.perk.remove(perkItem.getPerk());
data.setUpgradePoint(Math.min(MAX_UPGRADE_POINT, level - 1 + data.upgradePoint()));
this.upgradePoint.set((int) data.upgradePoint());
data.save(); inputData.setUpgradePoint(Math.min(MAX_UPGRADE_POINT, level - 1 + inputData.upgradePoint()));
this.upgradePoint.set((int) inputData.upgradePoint());
outputData.save();
inputData.save();
this.container.setItem(INPUT_SLOT, output); this.container.setItem(INPUT_SLOT, output);
this.container.setChanged(); this.container.setChanged();
} }
@ -338,30 +335,27 @@ public class ReforgingTableMenu extends AbstractContainerMenu {
private void onPlaceGun(ItemStack stack) { private void onPlaceGun(ItemStack stack) {
if (!(stack.getItem() instanceof GunItem)) return; if (!(stack.getItem() instanceof GunItem)) return;
var data = GunData.from(stack); var data = GunData.from(stack);
var tag = data.tag();
int point = (int) data.upgradePoint(); int point = (int) data.upgradePoint();
this.upgradePoint.set(Mth.clamp(point, 0, MAX_UPGRADE_POINT)); this.upgradePoint.set(Mth.clamp(point, 0, MAX_UPGRADE_POINT));
var ammoPerk = PerkHelper.getPerkByType(tag, Perk.Type.AMMO); for (var type : Perk.Type.values()) {
if (ammoPerk != null) { var perkInstance = data.perk.getInstance(type);
this.ammoPerkLevel.set(PerkHelper.getItemPerkLevel(ammoPerk, tag)); if (perkInstance != null) {
var ammoPerkItem = PerkHelper.getPerkItem(ammoPerk); switch (type) {
ammoPerkItem.ifPresent(registryObject -> this.container.setItem(AMMO_PERK_SLOT, registryObject.get().getDefaultInstance())); case AMMO -> this.ammoPerkLevel.set(perkInstance.level());
} case FUNCTIONAL -> this.funcPerkLevel.set(perkInstance.level());
case DAMAGE -> this.damagePerkLevel.set(perkInstance.level());
}
var funcPerk = PerkHelper.getPerkByType(tag, Perk.Type.FUNCTIONAL); var ammoPerkItem = perkInstance.perk().getItem().get();
if (funcPerk != null) {
this.funcPerkLevel.set(PerkHelper.getItemPerkLevel(funcPerk, tag));
var funcPerkItem = PerkHelper.getPerkItem(funcPerk);
funcPerkItem.ifPresent(registryObject -> this.container.setItem(FUNC_PERK_SLOT, registryObject.get().getDefaultInstance()));
}
var damagePerk = PerkHelper.getPerkByType(tag, Perk.Type.DAMAGE); this.container.setItem(switch (type) {
if (damagePerk != null) { case AMMO -> AMMO_PERK_SLOT;
this.damagePerkLevel.set(PerkHelper.getItemPerkLevel(damagePerk, tag)); case FUNCTIONAL -> FUNC_PERK_SLOT;
var damagePerkItem = PerkHelper.getPerkItem(damagePerk); case DAMAGE -> DAMAGE_PERK_SLOT;
damagePerkItem.ifPresent(registryObject -> this.container.setItem(DAMAGE_PERK_SLOT, registryObject.get().getDefaultInstance())); }, ammoPerkItem.getDefaultInstance());
}
} }
this.container.setChanged(); this.container.setChanged();
@ -374,28 +368,23 @@ public class ReforgingTableMenu extends AbstractContainerMenu {
* @param stack 输入的枪械 * @param stack 输入的枪械
*/ */
private void onTakeGun(ItemStack stack) { private void onTakeGun(ItemStack stack) {
if (!(stack.getItem() instanceof GunItem)) { if (!(stack.getItem() instanceof GunItem)) return;
return;
}
final var tag = NBTTool.getTag(stack);
var ammoPerk = PerkHelper.getPerkByType(tag, Perk.Type.AMMO);
if (ammoPerk != null) {
if (this.container.getItem(AMMO_PERK_SLOT).getItem() instanceof PerkItem<?> perkItem && perkItem.getPerk() == ammoPerk) {
this.container.setItem(AMMO_PERK_SLOT, ItemStack.EMPTY);
}
}
var funcPerk = PerkHelper.getPerkByType(tag, Perk.Type.FUNCTIONAL); var data = GunData.from(stack);
if (funcPerk != null) {
if (this.container.getItem(FUNC_PERK_SLOT).getItem() instanceof PerkItem<?> perkItem && perkItem.getPerk() == funcPerk) {
this.container.setItem(FUNC_PERK_SLOT, ItemStack.EMPTY);
}
}
var damagePerk = PerkHelper.getPerkByType(tag, Perk.Type.DAMAGE); for (var type : Perk.Type.values()) {
if (damagePerk != null) { var perk = data.perk.get(type);
if (this.container.getItem(DAMAGE_PERK_SLOT).getItem() instanceof PerkItem<?> perkItem && perkItem.getPerk() == damagePerk) { var slot = switch (type) {
this.container.setItem(DAMAGE_PERK_SLOT, ItemStack.EMPTY); case AMMO -> AMMO_PERK_SLOT;
case FUNCTIONAL -> FUNC_PERK_SLOT;
case DAMAGE -> DAMAGE_PERK_SLOT;
};
if (perk != null &&
this.container.getItem(slot).getItem() instanceof PerkItem<?> perkItem
&& perkItem.getPerk() == perk
) {
this.container.setItem(slot, ItemStack.EMPTY);
} }
} }

View file

@ -10,7 +10,6 @@ import com.atsuishio.superbwarfare.item.gun.SpecialFireWeapon;
import com.atsuishio.superbwarfare.item.gun.data.GunData; import com.atsuishio.superbwarfare.item.gun.data.GunData;
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.PerkHelper;
import com.atsuishio.superbwarfare.tools.GunsTool; import com.atsuishio.superbwarfare.tools.GunsTool;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
@ -105,8 +104,7 @@ public record FireMessage(int msgType) implements CustomPacketPayload {
} }
} }
public static double perkSpeed(final CompoundTag tag) { public static double perkSpeed(Perk perk) {
var perk = PerkHelper.getPerkByType(tag, Perk.Type.AMMO);
if (perk instanceof AmmoPerk ammoPerk) { if (perk instanceof AmmoPerk ammoPerk) {
return ammoPerk.speedRate; return ammoPerk.speedRate;
} }
@ -118,9 +116,9 @@ public record FireMessage(int msgType) implements CustomPacketPayload {
if (player.level().isClientSide()) return; if (player.level().isClientSide()) return;
var data = GunData.from(stack); var data = GunData.from(stack);
var perk = PerkHelper.getPerkByType(tag, Perk.Type.AMMO); var perk = data.perk.get(Perk.Type.AMMO);
float headshot = (float) data.headshot(); float headshot = (float) data.headshot();
float velocity = 2 * (float) GunsTool.getGunDoubleTag(tag, "Power", 6) * (float) perkSpeed(tag); float velocity = 2 * (float) GunsTool.getGunDoubleTag(tag, "Power", 6) * (float) perkSpeed(perk);
float bypassArmorRate = (float) data.bypassArmor(); float bypassArmorRate = (float) data.bypassArmor();
double damage; double damage;
@ -145,7 +143,7 @@ public record FireMessage(int msgType) implements CustomPacketPayload {
.zoom(zoom); .zoom(zoom);
if (perk instanceof AmmoPerk ammoPerk) { if (perk instanceof AmmoPerk ammoPerk) {
int level = PerkHelper.getItemPerkLevel(perk, tag); int level = data.perk.getLevel(perk);
bypassArmorRate += ammoPerk.bypassArmorRate + (perk == ModPerks.AP_BULLET.get() ? 0.05f * (level - 1) : 0); bypassArmorRate += ammoPerk.bypassArmorRate + (perk == ModPerks.AP_BULLET.get() ? 0.05f * (level - 1) : 0);
projectile.setRGB(ammoPerk.rgb); projectile.setRGB(ammoPerk.rgb);
@ -177,24 +175,24 @@ public record FireMessage(int msgType) implements CustomPacketPayload {
projectile.bypassArmorRate(bypassArmorRate); projectile.bypassArmorRate(bypassArmorRate);
if (perk == ModPerks.SILVER_BULLET.get()) { if (perk == ModPerks.SILVER_BULLET.get()) {
int level = PerkHelper.getItemPerkLevel(perk, tag); int level = data.perk.getLevel(perk);
projectile.undeadMultiple(1.0f + 0.5f * level); projectile.undeadMultiple(1.0f + 0.5f * level);
} else if (perk == ModPerks.BEAST_BULLET.get()) { } else if (perk == ModPerks.BEAST_BULLET.get()) {
projectile.beast(); projectile.beast();
} else if (perk == ModPerks.JHP_BULLET.get()) { } else if (perk == ModPerks.JHP_BULLET.get()) {
int level = PerkHelper.getItemPerkLevel(perk, tag); int level = data.perk.getLevel(perk);
projectile.jhpBullet(level); projectile.jhpBullet(level);
} else if (perk == ModPerks.HE_BULLET.get()) { } else if (perk == ModPerks.HE_BULLET.get()) {
int level = PerkHelper.getItemPerkLevel(perk, tag); int level = data.perk.getLevel(perk);
projectile.heBullet(level); projectile.heBullet(level);
} else if (perk == ModPerks.INCENDIARY_BULLET.get()) { } else if (perk == ModPerks.INCENDIARY_BULLET.get()) {
int level = PerkHelper.getItemPerkLevel(perk, tag); int level = data.perk.getLevel(perk);
projectile.fireBullet(level, !zoom); projectile.fireBullet(level, !zoom);
} }
var dmgPerk = PerkHelper.getPerkByType(tag, Perk.Type.DAMAGE); var dmgPerk = data.perk.get(Perk.Type.DAMAGE);
if (dmgPerk == ModPerks.MONSTER_HUNTER.get()) { if (dmgPerk == ModPerks.MONSTER_HUNTER.get()) {
int perkLevel = PerkHelper.getItemPerkLevel(dmgPerk, tag); int perkLevel = data.perk.getLevel(dmgPerk);
projectile.monsterMultiple(0.1f + 0.1f * perkLevel); projectile.monsterMultiple(0.1f + 0.1f * perkLevel);
} }

View file

@ -10,7 +10,6 @@ import com.atsuishio.superbwarfare.init.ModTags;
import com.atsuishio.superbwarfare.item.gun.data.GunData; import com.atsuishio.superbwarfare.item.gun.data.GunData;
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.PerkHelper;
import com.atsuishio.superbwarfare.tools.GunsTool; import com.atsuishio.superbwarfare.tools.GunsTool;
import com.atsuishio.superbwarfare.tools.InventoryTool; import com.atsuishio.superbwarfare.tools.InventoryTool;
import com.atsuishio.superbwarfare.tools.ParticleTool; import com.atsuishio.superbwarfare.tools.ParticleTool;
@ -88,7 +87,7 @@ public record ShootMessage(double spread) implements CustomPacketPayload {
} }
} }
var perk = PerkHelper.getPerkByType(tag, Perk.Type.AMMO); var perk = data.perk.get(Perk.Type.AMMO);
for (int index0 = 0; index0 < (perk instanceof AmmoPerk ammoPerk && ammoPerk.slug ? 1 : projectileAmount); index0++) { for (int index0 = 0; index0 < (perk instanceof AmmoPerk ammoPerk && ammoPerk.slug ? 1 : projectileAmount); index0++) {
GunEventHandler.gunShoot(player, tag, spared); GunEventHandler.gunShoot(player, tag, spared);
@ -110,7 +109,7 @@ public record ShootMessage(double spread) implements CustomPacketPayload {
} }
} }
var perk = PerkHelper.getPerkByType(tag, Perk.Type.AMMO); var perk = data.perk.get(Perk.Type.AMMO);
float pitch = tag.getDouble("heat") <= 40 ? 1 : (float) (1 - 0.025 * Math.abs(40 - tag.getDouble("heat"))); float pitch = tag.getDouble("heat") <= 40 ? 1 : (float) (1 - 0.025 * Math.abs(40 - tag.getDouble("heat")));
if (!player.level().isClientSide() && player instanceof ServerPlayer) { if (!player.level().isClientSide() && player instanceof ServerPlayer) {

View file

@ -1,26 +1,77 @@
package com.atsuishio.superbwarfare.perk; package com.atsuishio.superbwarfare.perk;
import com.atsuishio.superbwarfare.init.ModItems;
import com.atsuishio.superbwarfare.item.PerkItem;
import com.atsuishio.superbwarfare.item.gun.data.GunData;
import net.minecraft.ChatFormatting;
import net.minecraft.world.item.Item;
import net.neoforged.neoforge.registries.DeferredHolder;
import java.util.function.BiFunction;
public class Perk { public class Perk {
public String descriptionId; public final String descriptionId;
public Type type; 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) { public Perk(String descriptionId, Type type) {
this.descriptionId = descriptionId; this.descriptionId = descriptionId;
this.type = type; this.type = type;
StringBuilder builder = new StringBuilder();
boolean useUpperCase = false;
boolean isFirst = true;
for (char c : descriptionId.toCharArray()) {
if (isFirst || useUpperCase) {
builder.append(Character.toUpperCase(c));
isFirst = false;
useUpperCase = false;
} else if (c == '_') {
useUpperCase = true;
} else {
builder.append(c);
}
}
this.name = builder.toString();
}
public DeferredHolder<Item, ? extends Item> getItem() {
var result = ModItems.PERKS.getEntries().stream().filter(p -> {
if (p.get() instanceof PerkItem<?> perkItem) {
return perkItem.getPerk() == this;
}
return false;
}).findFirst();
if (result.isEmpty()) throw new IllegalStateException("Perk " + this.name + " not found");
return result.get();
} }
public enum Type { public enum Type {
AMMO("Ammo"), AMMO("Ammo", ChatFormatting.YELLOW),
FUNCTIONAL("Functional"), FUNCTIONAL("Functional", ChatFormatting.GREEN),
DAMAGE("Damage"); DAMAGE("Damage", ChatFormatting.RED);
private final String type; private final String name;
private final ChatFormatting color;
Type(String type) { Type(String type, ChatFormatting color) {
this.type = type; this.name = type;
this.color = color;
} }
public String getName() { public String getName() {
return type; return name;
}
public ChatFormatting getColor() {
return color;
} }
} }
} }

View file

@ -1,171 +1,11 @@
package com.atsuishio.superbwarfare.perk; package com.atsuishio.superbwarfare.perk;
import com.atsuishio.superbwarfare.init.ModItems;
import com.atsuishio.superbwarfare.init.ModPerks; import com.atsuishio.superbwarfare.init.ModPerks;
import com.atsuishio.superbwarfare.item.PerkItem;
import com.atsuishio.superbwarfare.item.gun.data.GunData;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth;
import net.minecraft.world.item.Item;
import net.neoforged.neoforge.registries.DeferredHolder;
import javax.annotation.Nullable;
import java.util.Optional;
import java.util.function.Predicate; import java.util.function.Predicate;
public class PerkHelper { public class PerkHelper {
private static final String TAG_PERK_ID = "id";
private static final String TAG_PERK_LEVEL = "level";
private static final String TAG_PERK = "Perks";
/**
* 把一个Perk封装成nbt进行存储
*/
public static CompoundTag makePerk(@Nullable ResourceLocation pId, int pLevel) {
CompoundTag compoundtag = new CompoundTag();
compoundtag.putString(TAG_PERK_ID, String.valueOf(pId));
compoundtag.putShort(TAG_PERK_LEVEL, (short) pLevel);
return compoundtag;
}
public static CompoundTag setPerkLevel(CompoundTag pCompound, int pLevel) {
pCompound.putShort(TAG_PERK_LEVEL, (short) pLevel);
return pCompound;
}
public static int getPerkLevel(CompoundTag pCompound) {
return Mth.clamp(pCompound.getInt(TAG_PERK_LEVEL), 0, 255);
}
@Nullable
public static ResourceLocation getPerkId(CompoundTag pCompoundTag) {
return ResourceLocation.tryParse(pCompoundTag.getString(TAG_PERK_ID));
}
@Nullable
public static ResourceLocation getPerkId(Perk perk) {
return switch (perk.type) {
case AMMO -> ModPerks.AMMO_PERKS.getEntries().stream()
.filter(p -> p.get().descriptionId.equals(perk.descriptionId))
.findFirst()
.map(p -> ResourceLocation.tryParse(p.value().descriptionId))
.orElse(null);
case FUNCTIONAL -> ModPerks.FUNC_PERKS.getEntries().stream()
.filter(p -> p.get().descriptionId.equals(perk.descriptionId))
.findFirst()
.map(p -> ResourceLocation.tryParse(p.value().descriptionId))
.orElse(null);
case DAMAGE -> ModPerks.DAMAGE_PERKS.getEntries().stream()
.filter(p -> p.get().descriptionId.equals(perk.descriptionId))
.findFirst()
.map(p -> ResourceLocation.tryParse(p.value().descriptionId))
.orElse(null);
};
}
public static int getItemPerkLevel(Perk perk, GunData data) {
return getItemPerkLevel(perk, data.tag());
}
public static int getItemPerkLevel(Perk perk, final CompoundTag tag) {
var tagPerk = tag.getCompound(TAG_PERK);
if (!tagPerk.contains(perk.type.getName())) {
return 0;
}
var pt = tagPerk.getCompound(perk.type.getName());
ResourceLocation id = getPerkId(perk);
if (id == null) {
return 0;
}
if (!pt.getString(TAG_PERK_ID).equals(makeId(id))) {
return 0;
}
return getPerkLevel(getPerkTag(tag, perk.type));
}
public static CompoundTag getPerkTag(GunData data, Perk.Type type) {
return getPerkTag(data.tag(), type);
}
public static CompoundTag getPerkTag(final CompoundTag tag, Perk.Type type) {
var tagPerk = tag.getCompound(TAG_PERK);
if (!tagPerk.contains(type.getName())) return new CompoundTag();
return tagPerk.getCompound(type.getName());
}
public static void setPerk(final CompoundTag tag, Perk perk, int level) {
var perkTag = tag.getCompound(TAG_PERK);
if (perkTag.isEmpty()) {
perkTag = new CompoundTag();
}
perkTag.put(perk.type.getName(), makePerk(getPerkId(perk), level));
tag.put(TAG_PERK, perkTag);
}
public static void setPerk(final CompoundTag tag, Perk perk) {
setPerk(tag, perk, 1);
}
public static Perk getPerkByType(GunData data, Perk.Type type) {
return getPerkByType(data.tag(), type);
}
@Nullable
public static Perk getPerkByType(final CompoundTag tag, Perk.Type type) {
var tagPerk = tag.getCompound(TAG_PERK);
if (!tagPerk.contains(type.getName())) {
return null;
}
return switch (type) {
case AMMO -> ModPerks.AMMO_PERKS.getEntries().stream()
.filter(p -> makeId(p.getId()).equals(tagPerk.getCompound(type.getName()).getString(TAG_PERK_ID)))
.findFirst()
.map(DeferredHolder::value)
.orElse(null);
case FUNCTIONAL -> ModPerks.FUNC_PERKS.getEntries().stream()
.filter(p -> makeId(p.getId()).equals(tagPerk.getCompound(type.getName()).getString(TAG_PERK_ID)))
.findFirst()
.map(DeferredHolder::value)
.orElse(null);
case DAMAGE -> ModPerks.DAMAGE_PERKS.getEntries().stream()
.filter(p -> makeId(p.getId()).equals(tagPerk.getCompound(type.getName()).getString(TAG_PERK_ID)))
.findFirst()
.map(DeferredHolder::value)
.orElse(null);
};
}
public static void removePerkByType(final CompoundTag tag, Perk.Type type) {
var tagPerk = tag.getCompound(TAG_PERK);
if (!tagPerk.contains(type.getName())) {
return;
}
tagPerk.remove(type.getName());
tag.put(TAG_PERK, tagPerk);
}
public static Optional<DeferredHolder<Item, ? extends Item>> getPerkItem(Perk perk) {
return ModItems.PERKS.getEntries().stream().filter(p -> {
if (p.get() instanceof PerkItem<?> perkItem) {
return perkItem.getPerk() == perk;
}
return false;
}).findFirst();
}
public static String makeId(ResourceLocation resourceLocation) {
return resourceLocation.getNamespace() + ":" + resourceLocation.getPath();
}
public static final Predicate<Perk> SHOTGUN_PERKS = perk -> switch (perk.type) { public static final Predicate<Perk> SHOTGUN_PERKS = perk -> switch (perk.type) {
case AMMO -> !perk.descriptionId.equals("butterfly_bullet") && perk != ModPerks.MICRO_MISSILE.get() case AMMO -> !perk.descriptionId.equals("butterfly_bullet") && perk != ModPerks.MICRO_MISSILE.get()
&& perk != ModPerks.LONGER_WIRE.get(); && perk != ModPerks.LONGER_WIRE.get();

View file

@ -0,0 +1,4 @@
package com.atsuishio.superbwarfare.perk;
public record PerkInstance(Perk perk, short level) {
}