添加M18烟雾弹
This commit is contained in:
parent
2b466a0036
commit
2643a97445
10 changed files with 343 additions and 12 deletions
|
@ -0,0 +1,26 @@
|
|||
package com.atsuishio.superbwarfare.client.model.entity;
|
||||
|
||||
import com.atsuishio.superbwarfare.Mod;
|
||||
import com.atsuishio.superbwarfare.entity.projectile.M18SmokeGrenadeEntity;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import software.bernie.geckolib.model.GeoModel;
|
||||
|
||||
public class M18SmokeGrenadeEntityModel extends GeoModel<M18SmokeGrenadeEntity> {
|
||||
|
||||
@Override
|
||||
public ResourceLocation getAnimationResource(M18SmokeGrenadeEntity entity) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO 添加烟雾手雷资源文件
|
||||
|
||||
@Override
|
||||
public ResourceLocation getModelResource(M18SmokeGrenadeEntity entity) {
|
||||
return Mod.loc("geo/rgo_grenade.geo.json");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getTextureResource(M18SmokeGrenadeEntity entity) {
|
||||
return Mod.loc("textures/item/rgo_grenade.png");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package com.atsuishio.superbwarfare.client.renderer.entity;
|
||||
|
||||
import com.atsuishio.superbwarfare.client.model.entity.M18SmokeGrenadeEntityModel;
|
||||
import com.atsuishio.superbwarfare.entity.projectile.M18SmokeGrenadeEntity;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.mojang.math.Axis;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.entity.EntityRendererProvider;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.Mth;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import software.bernie.geckolib.cache.object.BakedGeoModel;
|
||||
import software.bernie.geckolib.renderer.GeoEntityRenderer;
|
||||
|
||||
public class M18SmokeGrenadeRenderer extends GeoEntityRenderer<M18SmokeGrenadeEntity> {
|
||||
public M18SmokeGrenadeRenderer(EntityRendererProvider.Context renderManager) {
|
||||
super(renderManager, new M18SmokeGrenadeEntityModel());
|
||||
}
|
||||
|
||||
@Override
|
||||
public RenderType getRenderType(M18SmokeGrenadeEntity animatable, ResourceLocation texture, MultiBufferSource bufferSource, float partialTick) {
|
||||
return RenderType.entityTranslucent(getTextureLocation(animatable));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRender(PoseStack poseStack, M18SmokeGrenadeEntity entity, BakedGeoModel model, MultiBufferSource bufferSource, VertexConsumer buffer, boolean isReRender, float partialTick, int packedLight, int packedOverlay, int color) {
|
||||
float scale = 1f;
|
||||
this.scaleHeight = scale;
|
||||
this.scaleWidth = scale;
|
||||
super.preRender(poseStack, entity, model, bufferSource, buffer, isReRender, partialTick, packedLight, packedOverlay, color);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(M18SmokeGrenadeEntity entityIn, float entityYaw, float partialTicks, PoseStack poseStack, @NotNull MultiBufferSource bufferIn, int packedLightIn) {
|
||||
poseStack.pushPose();
|
||||
poseStack.mulPose(Axis.YP.rotationDegrees(Mth.lerp(partialTicks, entityIn.yRotO, entityIn.getYRot()) - 90));
|
||||
poseStack.mulPose(Axis.ZP.rotationDegrees(90 + Mth.lerp(partialTicks, entityIn.xRotO, entityIn.getXRot())));
|
||||
super.render(entityIn, entityYaw, partialTicks, poseStack, bufferIn, packedLightIn);
|
||||
poseStack.popPose();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getDeathMaxRotation(M18SmokeGrenadeEntity entityLivingBaseIn) {
|
||||
return 0.0F;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,147 @@
|
|||
package com.atsuishio.superbwarfare.entity.projectile;
|
||||
|
||||
import com.atsuishio.superbwarfare.init.ModEntities;
|
||||
import com.atsuishio.superbwarfare.init.ModItems;
|
||||
import com.atsuishio.superbwarfare.init.ModSounds;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.BellBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.EntityHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import software.bernie.geckolib.animatable.GeoEntity;
|
||||
import software.bernie.geckolib.animatable.instance.AnimatableInstanceCache;
|
||||
import software.bernie.geckolib.animation.AnimatableManager;
|
||||
import software.bernie.geckolib.util.GeckoLibUtil;
|
||||
|
||||
public class M18SmokeGrenadeEntity extends FastThrowableProjectile implements GeoEntity {
|
||||
|
||||
private int fuse = 80;
|
||||
private int count = 8;
|
||||
private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this);
|
||||
|
||||
public M18SmokeGrenadeEntity(EntityType<? extends M18SmokeGrenadeEntity> type, Level world) {
|
||||
super(type, world);
|
||||
this.noCulling = true;
|
||||
}
|
||||
|
||||
public M18SmokeGrenadeEntity(EntityType<? extends M18SmokeGrenadeEntity> type, double x, double y, double z, Level world) {
|
||||
super(type, x, y, z, world);
|
||||
this.noCulling = true;
|
||||
}
|
||||
|
||||
public M18SmokeGrenadeEntity(LivingEntity entity, Level level, int fuse) {
|
||||
super(ModEntities.M18_SMOKE_GRENADE.get(), entity, level);
|
||||
this.noCulling = true;
|
||||
|
||||
this.fuse = fuse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAdditionalSaveData(@NotNull CompoundTag pCompound) {
|
||||
super.addAdditionalSaveData(pCompound);
|
||||
pCompound.putFloat("Fuse", this.fuse);
|
||||
pCompound.putInt("Count", this.count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readAdditionalSaveData(@NotNull CompoundTag pCompound) {
|
||||
super.readAdditionalSaveData(pCompound);
|
||||
if (pCompound.contains("Fuse")) {
|
||||
this.fuse = pCompound.getInt("Fuse");
|
||||
}
|
||||
if (pCompound.contains("Count")) {
|
||||
this.count = Mth.clamp(pCompound.getInt("Count"), 1, 64);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull Item getDefaultItem() {
|
||||
return ModItems.RGO_GRENADE.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldRenderAtSqrDistance(double pDistance) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onHit(@NotNull HitResult result) {
|
||||
if (level().isClientSide) return;
|
||||
|
||||
switch (result.getType()) {
|
||||
case BLOCK:
|
||||
BlockHitResult blockResult = (BlockHitResult) result;
|
||||
BlockPos resultPos = blockResult.getBlockPos();
|
||||
BlockState state = this.level().getBlockState(resultPos);
|
||||
if (state.getBlock() instanceof BellBlock bell) {
|
||||
bell.attemptToRing(this.level(), resultPos, blockResult.getDirection());
|
||||
}
|
||||
|
||||
releaseSmoke();
|
||||
break;
|
||||
case ENTITY:
|
||||
EntityHitResult entityResult = (EntityHitResult) result;
|
||||
Entity entity = entityResult.getEntity();
|
||||
if (this.getOwner() != null
|
||||
&& this.getOwner().getVehicle() != null
|
||||
&& entity == this.getOwner().getVehicle()
|
||||
|| entity == this.getOwner()
|
||||
) return;
|
||||
|
||||
releaseSmoke();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
--this.fuse;
|
||||
|
||||
if (this.fuse <= 0) {
|
||||
this.discard();
|
||||
releaseSmoke();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO 优化烟雾效果
|
||||
public void releaseSmoke() {
|
||||
var vec3 = new Vec3(1, 1, 0);
|
||||
|
||||
for (int i = 0; i < this.count; i++) {
|
||||
var decoy = new SmokeDecoyEntity(this.level());
|
||||
decoy.setPos(this.getX(), this.getY() + getBbHeight(), this.getZ());
|
||||
decoy.decoyShoot(this, vec3.yRot(i * (360f / this.count) * Mth.DEG_TO_RAD), 3, 2);
|
||||
this.level().addFreshEntity(decoy);
|
||||
}
|
||||
|
||||
this.level().playSound(null, this, ModSounds.DECOY_FIRE.get(), this.getSoundSource(), 1, 1);
|
||||
this.discard();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double getDefaultGravity() {
|
||||
return 0.07F;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerControllers(AnimatableManager.ControllerRegistrar data) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnimatableInstanceCache getAnimatableInstanceCache() {
|
||||
return this.cache;
|
||||
}
|
||||
|
||||
}
|
|
@ -14,7 +14,6 @@ import net.minecraft.nbt.CompoundTag;
|
|||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
|
@ -25,7 +24,6 @@ import net.minecraft.world.level.block.state.BlockState;
|
|||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.EntityHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.neoforged.neoforge.network.PacketDistributor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import software.bernie.geckolib.animatable.GeoEntity;
|
||||
|
@ -155,16 +153,6 @@ public class RgoGrenadeEntity extends FastThrowableProjectile implements GeoEnti
|
|||
return this.cache;
|
||||
}
|
||||
|
||||
public void droneShoot(Entity drone) {
|
||||
Vec3 vec3 = (new Vec3(0.2 * drone.getDeltaMovement().x, 0.2 * drone.getDeltaMovement().y, 0.2 * drone.getDeltaMovement().z));
|
||||
this.setDeltaMovement(vec3);
|
||||
double d0 = vec3.horizontalDistance();
|
||||
this.setYRot((float) (Mth.atan2(vec3.x, vec3.z) * (double) (180F / (float) Math.PI)));
|
||||
this.setXRot((float) (Mth.atan2(vec3.y, d0) * (double) (180F / (float) Math.PI)));
|
||||
this.yRotO = this.getYRot();
|
||||
this.xRotO = this.getXRot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDamage(float damage) {
|
||||
}
|
||||
|
|
|
@ -76,6 +76,8 @@ public class ModEntities {
|
|||
EntityType.Builder.<HandGrenadeEntity>of(HandGrenadeEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(false).noSave().setTrackingRange(64).setUpdateInterval(1).sized(0.3f, 0.3f));
|
||||
public static final DeferredHolder<EntityType<?>, EntityType<RgoGrenadeEntity>> RGO_GRENADE = register("rgo_grenade",
|
||||
EntityType.Builder.<RgoGrenadeEntity>of(RgoGrenadeEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(false).noSave().setTrackingRange(64).setUpdateInterval(1).sized(0.3f, 0.3f));
|
||||
public static final DeferredHolder<EntityType<?>, EntityType<M18SmokeGrenadeEntity>> M18_SMOKE_GRENADE = register("m18_smoke_grenade",
|
||||
EntityType.Builder.<M18SmokeGrenadeEntity>of(M18SmokeGrenadeEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(false).noSave().setTrackingRange(64).setUpdateInterval(1).sized(0.3f, 0.3f));
|
||||
public static final DeferredHolder<EntityType<?>, EntityType<JavelinMissileEntity>> JAVELIN_MISSILE = register("javelin_missile",
|
||||
EntityType.Builder.<JavelinMissileEntity>of(JavelinMissileEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(false).noSave().setTrackingRange(64).setUpdateInterval(1).sized(0.5f, 0.5f));
|
||||
public static final DeferredHolder<EntityType<?>, EntityType<Agm65Entity>> AGM_65 = register("agm_65",
|
||||
|
|
|
@ -29,6 +29,7 @@ public class ModEntityRenderers {
|
|||
event.registerEntityRenderer(ModEntities.DRONE.get(), DroneRenderer::new);
|
||||
event.registerEntityRenderer(ModEntities.HAND_GRENADE.get(), HandGrenadeRenderer::new);
|
||||
event.registerEntityRenderer(ModEntities.RGO_GRENADE.get(), RgoGrenadeRenderer::new);
|
||||
event.registerEntityRenderer(ModEntities.M18_SMOKE_GRENADE.get(), M18SmokeGrenadeRenderer::new);
|
||||
event.registerEntityRenderer(ModEntities.MLE_1934.get(), Mle1934Renderer::new);
|
||||
event.registerEntityRenderer(ModEntities.JAVELIN_MISSILE.get(), JavelinMissileRenderer::new);
|
||||
event.registerEntityRenderer(ModEntities.LASER.get(), LaserEntityRenderer::new);
|
||||
|
|
|
@ -113,6 +113,7 @@ public class ModItems {
|
|||
public static final DeferredHolder<Item, Item> AP_5_INCHES = AMMO.register("ap_5_inches", () -> new CannonShellItem(new Item.Properties().rarity(Rarity.RARE)));
|
||||
public static final DeferredHolder<Item, HandGrenade> HAND_GRENADE = AMMO.register("hand_grenade", HandGrenade::new);
|
||||
public static final DeferredHolder<Item, RgoGrenade> RGO_GRENADE = AMMO.register("rgo_grenade", RgoGrenade::new);
|
||||
public static final DeferredHolder<Item, M18SmokeGrenade> M18_SMOKE_GRENADE = AMMO.register("m18_smoke_grenade", M18SmokeGrenade::new);
|
||||
public static final DeferredHolder<Item, ClaymoreMine> CLAYMORE_MINE = AMMO.register("claymore_mine", ClaymoreMine::new);
|
||||
public static final DeferredHolder<Item, Tm62Item> TM_62 = AMMO.register("tm_62", Tm62Item::new);
|
||||
public static final DeferredHolder<Item, C4BombItem> C4_BOMB = AMMO.register("c4_bomb", C4BombItem::new);
|
||||
|
@ -349,6 +350,7 @@ public class ModItems {
|
|||
DispenserBlock.registerBehavior(ROCKET_70.get(), new Rocket70Item.Rocket70DispenseBehavior());
|
||||
DispenserBlock.registerBehavior(MEDIUM_AERIAL_BOMB.get(), new MediumAerialBombItem.MediumAerialBombDispenseBehavior());
|
||||
DispenserBlock.registerBehavior(RGO_GRENADE.get(), new RgoGrenade.RgoGrenadeDispenserBehavior());
|
||||
DispenserBlock.registerBehavior(M18_SMOKE_GRENADE.get(), new M18SmokeGrenade.SmokeGrenadeDispenserBehavior());
|
||||
DispenserBlock.registerBehavior(TM_62.get(), new Tm62Item.Tm62DispenseBehavior());
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
package com.atsuishio.superbwarfare.item;
|
||||
|
||||
import com.atsuishio.superbwarfare.entity.projectile.M18SmokeGrenadeEntity;
|
||||
import com.atsuishio.superbwarfare.init.ModEntities;
|
||||
import com.atsuishio.superbwarfare.init.ModItems;
|
||||
import com.atsuishio.superbwarfare.init.ModSounds;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Position;
|
||||
import net.minecraft.core.dispenser.BlockSource;
|
||||
import net.minecraft.core.dispenser.ProjectileDispenseBehavior;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResultHolder;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.entity.projectile.Projectile;
|
||||
import net.minecraft.world.item.*;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
// TODO 物品图标,合成配方等资源
|
||||
|
||||
public class M18SmokeGrenade extends Item implements ProjectileItem {
|
||||
|
||||
public M18SmokeGrenade() {
|
||||
super(new Properties().rarity(Rarity.UNCOMMON));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ParametersAreNonnullByDefault
|
||||
public @NotNull InteractionResultHolder<ItemStack> use(Level worldIn, Player playerIn, InteractionHand handIn) {
|
||||
ItemStack stack = playerIn.getItemInHand(handIn);
|
||||
playerIn.startUsingItem(handIn);
|
||||
if (playerIn instanceof ServerPlayer serverPlayer) {
|
||||
serverPlayer.level().playSound(null, serverPlayer.getOnPos(), ModSounds.GRENADE_PULL.get(), SoundSource.PLAYERS, 1, 1);
|
||||
}
|
||||
return InteractionResultHolder.consume(stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull UseAnim getUseAnimation(@NotNull ItemStack stack) {
|
||||
return UseAnim.SPEAR;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ParametersAreNonnullByDefault
|
||||
public void releaseUsing(ItemStack stack, Level worldIn, LivingEntity entityLiving, int timeLeft) {
|
||||
if (!worldIn.isClientSide && entityLiving instanceof Player player) {
|
||||
int usingTime = this.getUseDuration(stack, player) - timeLeft;
|
||||
if (usingTime > 3) {
|
||||
player.getCooldowns().addCooldown(stack.getItem(), 20);
|
||||
float power = Math.min(usingTime / 8f, 1.8f);
|
||||
|
||||
M18SmokeGrenadeEntity grenade = new M18SmokeGrenadeEntity(player, worldIn, 80 - usingTime);
|
||||
grenade.shootFromRotation(player, player.getXRot(), player.getYRot(), 0, power, 0);
|
||||
worldIn.addFreshEntity(grenade);
|
||||
|
||||
if (player instanceof ServerPlayer serverPlayer) {
|
||||
serverPlayer.level().playSound(null, serverPlayer.getOnPos(), ModSounds.GRENADE_THROW.get(), SoundSource.PLAYERS, 1, 1);
|
||||
}
|
||||
|
||||
if (!player.isCreative()) {
|
||||
stack.shrink(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ParametersAreNonnullByDefault
|
||||
public @NotNull ItemStack finishUsingItem(ItemStack pStack, Level pLevel, LivingEntity pLivingEntity) {
|
||||
if (!pLevel.isClientSide) {
|
||||
var grenade = new M18SmokeGrenadeEntity(pLivingEntity, pLevel, 100);
|
||||
grenade.setPos(pLivingEntity.position());
|
||||
grenade.releaseSmoke();
|
||||
|
||||
if (pLivingEntity instanceof Player player) {
|
||||
player.getCooldowns().addCooldown(pStack.getItem(), 20);
|
||||
}
|
||||
|
||||
if (pLivingEntity instanceof Player player && !player.isCreative()) {
|
||||
pStack.shrink(1);
|
||||
}
|
||||
}
|
||||
|
||||
return super.finishUsingItem(pStack, pLevel, pLivingEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ParametersAreNonnullByDefault
|
||||
public int getUseDuration(ItemStack stack, LivingEntity entity) {
|
||||
return 80;
|
||||
}
|
||||
|
||||
public static class SmokeGrenadeDispenserBehavior extends ProjectileDispenseBehavior {
|
||||
public SmokeGrenadeDispenserBehavior() {
|
||||
super(ModItems.M18_SMOKE_GRENADE.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void playSound(BlockSource blockSource) {
|
||||
blockSource.level().playSound(null, blockSource.pos(), ModSounds.GRENADE_THROW.get(), SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ParametersAreNonnullByDefault
|
||||
public @NotNull Projectile asProjectile(Level level, Position pos, ItemStack stack, Direction direction) {
|
||||
return new M18SmokeGrenadeEntity(ModEntities.M18_SMOKE_GRENADE.get(), pos.x(), pos.y(), pos.z(), level);
|
||||
}
|
||||
}
|
||||
|
|
@ -240,6 +240,7 @@
|
|||
"item.superbwarfare.track": "Track",
|
||||
"item.superbwarfare.hand_grenade": "Hand Grenade",
|
||||
"item.superbwarfare.rgo_grenade": "RGO Grenade",
|
||||
"item.superbwarfare.m18_smoke_grenade": "M18 Smoke Grenade",
|
||||
"item.superbwarfare.transcript": "Transcript",
|
||||
"des.superbwarfare.transcript": "Recent 10 shooting records:",
|
||||
"des.superbwarfare.transcript.score": "Score: ",
|
||||
|
|
|
@ -240,6 +240,7 @@
|
|||
"item.superbwarfare.track": "履带",
|
||||
"item.superbwarfare.hand_grenade": "M67手榴弹",
|
||||
"item.superbwarfare.rgo_grenade": "RGO手榴弹",
|
||||
"item.superbwarfare.m18_smoke_grenade": "M18烟雾弹",
|
||||
"item.superbwarfare.transcript": "成绩单",
|
||||
"des.superbwarfare.transcript": "最近10次的射击成绩:",
|
||||
"des.superbwarfare.transcript.score": "环数:",
|
||||
|
|
Loading…
Add table
Reference in a new issue