Starsector Nihilism Guidance
首页
GitHub 项目
首页
GitHub 项目
  • 首页
  • 基础及舰船相关
    • MOD 骨架和入口文件
    • 制作一艘基本舰船
    • 制作一艘航母与战机
    • 制作一艘相位舰
    • 制作火炮、光束与导弹
    • 为舰船加入内置武器、船插与战机
    • 补充描述文本
  • 无需入门的代码修改
    • 以船插为例初步熟悉代码
    • 制作完整船插
    • 制作最小战术系统
    • 为武器加入命中与光束特效
  • 势力与生涯星系
    • 注册一个势力
    • 配置势力舰队
    • 制作 MOD 入口类的最基础适配
    • 制作一个生涯星系
    • 补完描述文本
  • 战役与无代码对象
    • 制作测试战役装配
    • 为模拟战与标题画面加入装配
    • 为舰船加入外观风格
    • 制作一艘模块船
    • 制作一种星体类型
    • 制作一个自定义实体
  • 音频资源与播放
    • 准备 OGG 音频资源
    • 注册音频资源
    • 为游戏对象加入音频
  • Java 工程化
    • 确认 Java 与编译依赖
    • 迁移代码文件到 src
    • 配置 Gradle 工程
    • 构建 JAR 并声明产物
  • 全局服务
    • 制作 MOD 入口类
    • 使用 Global 访问游戏服务
    • 读取设置
    • 调用声音播放器
    • 记录和定位 MOD 日志
  • 战斗运行时
    • 读取战斗引擎状态
    • 读取战斗对象
    • 制作每帧战斗插件
    • 修改舰船数值
    • 配置武器脚本
    • 配置战斗监听器
    • 制作分层渲染插件
  • 战斗内容扩展
    • 详解舰船插件
    • 详解战术系统
    • 详解武器动画
  • 生涯世界与基础服务
    • 读取生涯世界状态
    • 构建生涯地点
    • 配置生涯势力
    • 放置生涯实体
  • 生涯舰队与舰队成员
    • 生成生涯舰队
    • 管理舰队中的成员
    • 舰队状态的重算过程
    • 维护舰队成员状态
    • 读取并修改舰船装配
  • 市场与商品
    • 创建生涯市场
    • 读写货舱内容
    • 注册市场商品
    • 实现专用子市场
    • 制作专用产业
    • 注册特殊物品
    • 实现市场条件
  • 人物与技能
    • 配置人物基础
    • 让人物承担角色
    • 制作角色技能
  • 生涯脚本与情报事件
    • 编写生涯逐帧脚本
    • 监听生涯事件
    • 选择生涯插件
    • 管理舰队活动情报
  • 酒吧事件与任务
    • 组织生涯交互对话
    • 实现对话插件
    • 接入酒吧事件
    • 构建阶段任务
    • 接入酒吧任务
  • Rules 系统、命令与内存
    • 组织 Rules 规则表
    • 编排 Rules 对话
    • 接入 Rules 生涯场景
    • 编写 Rules 命令
    • 使用 MemoryAPI 保存状态
  • 文件读取与写入
    • 读取 MOD 内文本
    • 读取 MOD 内 JSON 文件
    • 读取 MOD 内 CSV
    • 读写 common 数据
    • 实现本地化机制
  • 常用依赖库
    • 接入常用依赖库
    • 使用 LazyLib 几何工具
    • 使用 LazyLib 查询战场
    • 使用 LazyLib 保存公共 JSON
    • 注册 GraphicsLib 光照数据
    • 创建 GraphicsLib 动态光源
    • 制作 GraphicsLib 纹理映射
    • 配置 MagicLib 自动尾迹
    • 创建 MagicLib 运行时尾迹
    • 配置 MagicLib 数据赏金
    • 使用 MagicLib 辅助生涯开发
    • 使用 MagicLib 战斗小工具
  • 可选依赖与 Nexerelin
    • 接入可选依赖
    • 登记 Nexerelin 势力与外交配置
    • 配置 Nexerelin 的两种星区开局
    • 配置 Nexerelin 战略 AI 与扩张规模
    • 登记 Nexerelin 地面战单位与产业
    • 为 Nexerelin 特遣队添加命名与事件响应
    • 制作即时生效的 LunaLib 设置面板
  • 着色器与渲染
    • 使用 Java OpenGL
    • 使用 GLSL 进阶
    • 使用 VBO 和 VAO 保存顶点
    • 使用 SSBO 传递参数
    • 使用实例化进行绘制
    • 选择 BoxUtil 渲染方案

制作最小战术系统

本节为工匠制作 "突击填弹器":以原版加速填弹器为基础,增加速度与机动加成,再为它设置持续时间和冷却。随后制作右键使用的抵抗力场。两种系统都由定义文件、CSV 参数和效果类组成,舰船数据决定安装哪个系统。

本节预期阅读时间:~20 分钟。

本节预期操作时间:~25 分钟。

学习目标

完成后,您将能够:

  • 用 .system 声明战术系统类型和效果类;
  • 在 ship_systems.csv 登记名称、时间和幅能参数,通过舰船数据挂载;
  • 区分前摇、全功率、后摇与冷却;
  • 根据效果强度修改加成,并在结束时撤销;
  • 调整加成、持续时间与冷却,在模拟战中比较结果。

前置知识

  • [C1-S2] 的工匠船体与 ship_data.csv;
  • [C1-S7] 的 CSV 表头、空列与转义;
  • [C2-S1] 的 Java 文件、参数修改、注册与回调;
  • [C2-S2] 的效果类与数据登记对应关系。

从原版加速填弹器开始

把原版 data/shipsystems/ammofeed.system 复制到 MOD 的同目录,改名为 GearIn_assaultfeed.system。系统名称定为 "突击填弹器",ID 为 GearIn_assaultfeed,效果类为 GearInAssaultFeedSystem。

编者准备让工匠在提高实弹射速的同时获得短暂的机动优势,便于压近距离或调整射击位置。原版加速填弹器的武器收益继续保留,机动收益则写进同一个效果类。 持续时间稍短一些,让使用时机也成为操作的一部分。

先修改定义文件,让它登记自己的 ID 并引用新的效果类,内容如下:

{
    "id": "GearIn_assaultfeed",
    "type": "STAT_MOD",
    "aiType": "WEAPON_BOOST",
    "statsScript": "data.scripts.gearin.shipsystems.GearInAssaultFeedSystem",
    "weaponGlowColor": [255, 200, 0, 155],
    "weaponTypes": ["BALLISTIC"],
    "engineGlowLengthMult": 2.5,
    "engineGlowWidthMult": 3,
    "engineGlowGlowMult": 2,
    "useSound": "system_ammo_feeder",
    "outOfUsesSound": "gun_out_of_ammo"
}

id 与后面的 CSV 共用;statsScript 指向效果类,写法与船插的完整类名相同。type: "STAT_MOD" 表示属性修改型系统,aiType: "WEAPON_BOOST" 沿用加速填弹器的使用判断。当前先保留这一对类型与 AI,系统 AI 的详细写法由 [C9-S2] 讲解。

weaponGlowColor 与 weaponTypes 控制实弹武器的激活光效,三个 engineGlow* 字段调整引擎焰表现。它们决定系统的视觉表现;具体数值增益稍后写入效果类。useSound 继续使用原版激活声音,这里填的是声音 ID,文件关系按原版样本保留即可。

登记时间与使用参数

打开 MOD 的 data/shipsystems/ship_systems.csv,复制原版 ammofeed 行,修改名称、ID 与时间参数。本例登记行如下,已有表头时只追加系统数据:

name,id,flux/second,f/s (base rate),f/s (base cap),flux/use,f/u (base rate),f/u (base cap),cr/u,max uses,regen,charge up,active,down,cooldown,toggle,noDissipation,noHardDissipation,hardFlux,noFiring,noTurning,noStrafing,noAccel,noShield,noVent,isPhaseCloak,tags,icon
突击填弹器,GearIn_assaultfeed,,,,,,,,,,0.5,3,0.5,10,,,,,,,,,,,,offensive,graphics/icons/hullsys/ammo_feeder.png

本例前摇 0.5 秒、全功率 3 秒、后摇 0.5 秒、冷却 10 秒。系统的强度既取决于效果,也取决于能维持多久、多久能再用。 这组时间对应前面的短时强化设计,完成测试后再根据工匠的实际表现调整。

常用系统参数速查表

列作用
charge up前摇秒数,效果强度从 0 升至 1
active全功率秒数,效果强度保持 1
down后摇秒数,效果强度从 1 回到 0
cooldown冷却秒数,结束后到下一次可用
flux/second激活期间每秒产生的幅能
toggleTRUE 为开关式,再按一次关闭;留空按持续时间结束
max uses可用次数,留空表示无限
noAccel、noFiring、noTurning 等激活期间禁止的对应操作,TRUE 表示禁止

突击填弹器的 toggle 留空,按一次后运行前摇、全功率、后摇与冷却周期。开关式系统采用同一组阶段,但关闭动作由再次按键触发。当前这行同时保留加速填弹器的使用参数;f/s、f/u 和 cr/u 等进阶列以后再结合具体系统处理。

把射速与机动效果写进同一个类

效果类参考原版 data/shipsystems/scripts/AmmoFeedStats.java 与 ManeuveringJetsStats.java。创建 data/scripts/gearin/shipsystems/GearInAssaultFeedSystem.java,包名和 import 按完整文件填写。

这两份原版效果分别提供实弹强化与辅助推进。组合时,我们选择当前设计需要的操作,在同一个 apply 中写入,随后在 unapply 中逐项解除。需要组合的是效果语句,下面仍然只保存一个系统类。

参数与效果强度

先在类的字段区填写本例的可调整参数:

public static final float SPEED_BONUS = 50f;
public static final float MANEUVER_BONUS = 200f;
public static final float ROF_BONUS = 1f;
public static final float FLUX_REDUCTION = 50f;

最大速度增加 50,前进加速、减速与转向加速采用 200% 加成;ROF_BONUS = 1f 表示额外增加一倍射速,FLUX_REDUCTION = 50f 表示实弹武器开火幅能降低 50%。

刚才的参数表示满效果加成,当前能获得多少则由系统阶段决定。游戏在效果期间反复调用 apply(...),并传入 effectLevel。前摇时该值从 0 升至 1,全功率为 1,后摇时再回到 0。 以速度为例,局部片段如下:

stats.getMaxSpeed().modifyFlat(id, SPEED_BONUS * effectLevel);

effectLevel 为 0.5 时,加成是 25;为 1 时,加成是 50。CSV 决定这些阶段持续多久,乘上 effectLevel 的效果代码则决定加成怎样随阶段变化。本例让各项增益都随这个值变化,进入和退出系统时便有相应的过渡。

射速和幅能的倍率

速度使用固定增量,实弹射速与开火幅能则通过倍率修改,局部片段如下:

stats.getBallisticRoFMult().modifyMult(id, 1f + ROF_BONUS * effectLevel);
stats.getBallisticWeaponFluxCostMod().modifyMult(id,
        1f - FLUX_REDUCTION * 0.01f * effectLevel);

modifyMult 写入倍率。这里的 1f 是原始倍率,再随 effectLevel 加上射速收益或扣去幅能比例。满效果时,射速倍率为 2,幅能倍率为 0.5;200% 射速和 50% 单发幅能同时生效,持续开火的每秒幅能也会随射速变化。评价幅能收益时,射速与单发幅能需要共同计算。

结束时撤销,状态栏显示参数

unapply(...) 在系统未生效或结束时解除修饰,舰船生成时也会调用它。下面是速度与射速清理的局部片段:

stats.getMaxSpeed().unmodify(id);
stats.getBallisticRoFMult().unmodify(id);

完整文件把所有写入项都清理。写入与解除使用相同的 id,才能找到当前系统留下的修饰;系统结束后,数值恢复到其余效果共同决定的结果。

getStatusData(...) 返回左下角状态栏文字,index 选择显示哪一行,false 表示增益,true 表示红色减益。本例显示速度、机动、幅能与射速四项状态,数值从当前参数和效果强度计算。

给工匠安装突击填弹器

打开 data/hulls/ship_data.csv,把工匠行的 system id 改为 GearIn_assaultfeed:

name,id,designation,tech/manufacturer,system id,fleet pts,hitpoints,armor rating,max flux,8/6/5/4%,flux dissipation,ordnance points,fighter bays,max speed,acceleration,deceleration,max turn rate,turn acceleration,mass,shield type,defense id,shield arc,shield upkeep,shield efficiency,phase cost,phase upkeep,min crew,max crew,cargo,fuel,fuel/ly,range,max burn,base value,cr %/day,CR to deploy,peak CR sec,CR loss/sec,supplies/rec,supplies/mo,c/s,c/f,f/s,f/f,crew/s,crew/f,hints,tags,logistics n/a reason,codex variant id,rarity,breakProb,minPieces,maxPieces,travel drive,number
工匠,GearIn_artizan,驱逐舰,未知,GearIn_assaultfeed,10,5000,500,3800,4167,200,95,,80,60,40,30,60,400,FRONT,,300,0.4,0.8,,,50,100,100,60,2,30,9,40000,5,12,360,0.25,10,10,,,,,,,,GearIn_bp,,,,0.5,2,3,,300

定义文件、系统 CSV 和舰船引用使用同一个系统 ID;效果类使用的是 statsScript 中的完整类名。保存这些文件后,主系统就接到了工匠上。

再制作右键抵抗力场

右键系统采用相同的注册过程,变化的是基础样本和舰船的挂载字段。把原版 data/shipsystems/damper.system 复制为 GearIn_resistfield.system,改名为 "抵抗力场",并填写自己的 ID 与效果类:

{
    "id": "GearIn_resistfield",
    "type": "STAT_MOD",
    "aiType": "DAMPER_FIELD",

    "statsScript": "data.scripts.gearin.shipsystems.GearInResistFieldSystem",

    "jitterUnderColor": [255, 165, 90, 155],
    "jitterUnderCopies": 25,
    "jitterUnderMinRange": 0,
    "jitterUnderRange": 7,
    "jitterUnderRangeRadiusFraction": 0,

    "jitterColor": [255, 165, 90, 55],
    "jitterCopies": 2,
    "jitterMinRange": 0,
    "jitterRange": 5,
    "jitterRangeRadiusFraction": 0,

    "soundFilterType": "LOWPASS",
    "soundFilterGain": 0.75,
    "soundFilterGainHF": 0.25,

    "fadeActivationSoundOnChargedown": true,
    "useSound": "system_damper",
    "loopSound": "system_damper_loop",
    "deactivateSound": "system_damper_off",
    "outOfUsesSound": "gun_out_of_ammo"
}

STAT_MOD 和 DAMPER_FIELD 沿用阻尼力场的类型和 AI。橙色扰动与声音字段也由原版文件提供。

在 ship_systems.csv 追加:

name,id,flux/second,f/s (base rate),f/s (base cap),flux/use,f/u (base rate),f/u (base cap),cr/u,max uses,regen,charge up,active,down,cooldown,toggle,noDissipation,noHardDissipation,hardFlux,noFiring,noTurning,noStrafing,noAccel,noShield,noVent,isPhaseCloak,tags,icon
抵抗力场,GearIn_resistfield,1,,,,,,,2,0.05,0.25,3,0.25,0,,,,,TRUE,,,,TRUE,TRUE,,"uses_damper_ai, defensive",graphics/icons/hullsys/damper_field.png

该行的 uses_damper_ai 与 defensive 标签继续保留。效果类保存到 data/scripts/gearin/shipsystems/GearInResistFieldSystem.java。

设置分伤害类型的减伤

本例让高爆与 EMP 最高降低 75%,动能与能量最高降低 50%。局部写法如下:

stats.getHighExplosiveDamageTakenMult().modifyMult(id,
        1f - HE_REDUCTION * 0.01f * effectLevel);

满效果时,高爆伤害倍率为 0.25,意味着承担原来 25% 的伤害。这里仍然使用前面的倍率写法,只是修改对象换成了高爆伤害承受值。其他类型使用对应 getter,结束时各自清理。

最后把工匠行的 shield type 改为 PHASE,defense id 填为 GearIn_resistfield。PHASE 在这里选择右键系统入口,实际行为由抵抗力场定义与脚本决定,所以本例仍然是减伤系统。

观察舰船详情中主系统与右键系统的位置:

工匠详情中的突击填弹器与抵抗力场

主系统和右键系统分别显示在 System 与 Special 位置,两个名称来自各自的系统数据行。

完整最小例

两个效果类分别保存到上文指定的包目录。系统定义、CSV 和工匠挂载沿用上面的成品;CSV 表头只保留一次。

完整成品:GearInAssaultFeedSystem
package data.scripts.gearin.shipsystems;

import com.fs.starfarer.api.combat.MutableShipStatsAPI;
import com.fs.starfarer.api.impl.combat.BaseShipSystemScript;

public class GearInAssaultFeedSystem extends BaseShipSystemScript {

    public static final float SPEED_BONUS = 50f;
    public static final float MANEUVER_BONUS = 200f;
    public static final float ROF_BONUS = 1f;
    public static final float FLUX_REDUCTION = 50f;

    @Override
    public void apply(MutableShipStatsAPI stats, String id, State state, float effectLevel) {
        stats.getBallisticRoFMult().modifyMult(id, 1f + ROF_BONUS * effectLevel);
        stats.getBallisticWeaponFluxCostMod().modifyMult(id,
                1f - FLUX_REDUCTION * 0.01f * effectLevel);
        stats.getMaxSpeed().modifyFlat(id, SPEED_BONUS * effectLevel);
        stats.getAcceleration().modifyPercent(id, MANEUVER_BONUS * effectLevel);
        stats.getDeceleration().modifyPercent(id, MANEUVER_BONUS * effectLevel);
        stats.getTurnAcceleration().modifyFlat(id, 30f * effectLevel);
        stats.getTurnAcceleration().modifyPercent(id, MANEUVER_BONUS * effectLevel);
        stats.getMaxTurnRate().modifyFlat(id, 15f * effectLevel);
        stats.getMaxTurnRate().modifyPercent(id, 100f * effectLevel);
    }

    @Override
    public void unapply(MutableShipStatsAPI stats, String id) {
        stats.getBallisticRoFMult().unmodify(id);
        stats.getBallisticWeaponFluxCostMod().unmodify(id);
        stats.getMaxSpeed().unmodify(id);
        stats.getAcceleration().unmodify(id);
        stats.getDeceleration().unmodify(id);
        stats.getTurnAcceleration().unmodify(id);
        stats.getMaxTurnRate().unmodify(id);
    }

    @Override
    public StatusData getStatusData(int index, State state, float effectLevel) {
        if (index == 0) {
            return new StatusData("+" + (int) (SPEED_BONUS * effectLevel) + " top speed", false);
        }
        if (index == 1) {
            return new StatusData("improved maneuverability", false);
        }
        if (index == 2) {
            return new StatusData("ballistic flux use -" + (int) (FLUX_REDUCTION * effectLevel) + "%", false);
        }
        if (index == 3) {
            return new StatusData("ballistic rate of fire +" + (int) (ROF_BONUS * effectLevel * 100f) + "%", false);
        }
        return null;
    }
}
完整成品:GearInResistFieldSystem
package data.scripts.gearin.shipsystems;

import com.fs.starfarer.api.combat.MutableShipStatsAPI;
import com.fs.starfarer.api.impl.combat.BaseShipSystemScript;
import com.fs.starfarer.api.plugins.ShipSystemStatsScript;

public class GearInResistFieldSystem extends BaseShipSystemScript {

    public static final float HE_REDUCTION = 75f;
    public static final float EMP_REDUCTION = 75f;
    public static final float OTHER_REDUCTION = 50f;

    @Override
    public void apply(MutableShipStatsAPI stats, String id, State state, float effectLevel) {
        stats.getHighExplosiveDamageTakenMult().modifyMult(id, 1f - HE_REDUCTION * 0.01f * effectLevel);
        stats.getKineticDamageTakenMult().modifyMult(id, 1f - OTHER_REDUCTION * 0.01f * effectLevel);
        stats.getEnergyDamageTakenMult().modifyMult(id, 1f - OTHER_REDUCTION * 0.01f * effectLevel);
        stats.getEmpDamageTakenMult().modifyMult(id, 1f - EMP_REDUCTION * 0.01f * effectLevel);
    }

    @Override
    public void unapply(MutableShipStatsAPI stats, String id) {
        stats.getHighExplosiveDamageTakenMult().unmodify(id);
        stats.getKineticDamageTakenMult().unmodify(id);
        stats.getEnergyDamageTakenMult().unmodify(id);
        stats.getEmpDamageTakenMult().unmodify(id);
    }

    @Override
    public StatusData getStatusData(int index, State state, float effectLevel) {
        if (index == 0) {
            return new StatusData("reduce damage taken", false);
        }
        return null;
    }
}

验证方案

  1. 保存两个效果类、系统定义、系统 CSV 与工匠数据,重启游戏,检查系统加载日志。
  2. 获取工匠并进入模拟战,安装实弹武器,按 F 激活突击填弹器,观察射速、开火幅能、速度与转向。
  3. 比较 0.5 秒前摇、3 秒全功率和 0.5 秒后摇中的变化,结束后等待 10 秒冷却。
  4. 修改 SPEED_BONUS、active 或 cooldown 中的一项,保存并重启,在同一测试配置下比较结果。
  5. 使用右键抵抗力场,观察橙色扰动、状态文字、持续时间及减伤效果。

预期结果:

  • 日志包含 GearIn_assaultfeed.system、GearIn_resistfield.system 的加载与 CSV 应用记录。
  • 突击填弹器满效果时,速度增加 50,机动提高,实弹射速增加 100%,开火幅能降低 50%。
  • 增益随前摇上升、后摇回落,系统结束后各项修饰解除,冷却完成后可再次激活。
  • 参数实验分别改变速度加成、持续时间或下一次可用时机。
  • 抵抗力场满效果时,高爆与 EMP 减伤为 75%,动能与能量为 50%,结束后恢复。
  • 左下角状态栏分别显示主系统增益与右键减伤说明。

观察突击填弹器激活后的引擎与四项状态:

突击填弹器的引擎表现与增益状态

图中额外的 "Zero Flux Engine Boost" 来自舰船的零幅能加速。核对本系统时,使用以 "突击填弹器" 为标题的四项状态与脚本参数比较。

再观察抵抗力场的橙色扰动:

抵抗力场激活时的舰船扰动效果

主系统与右键系统可以分别验证。视效来自定义文件,减伤则由效果脚本写入。

故障分析

  • 加载时报 Fatal: ship_systems.csv is missing systems:系统定义已有 ID,但 CSV 缺少对应行或该行被注释。

    • 解决方案:登记同一个系统 ID,检查行首与表头,保存后重启。
  • 系统按键后立即结束:前摇、全功率、后摇和冷却参数均为空或为 0,状态在一帧内完成。

    • 解决方案:填写对应时间;定义与 CSV 的 ID 不一致时先修正加载错误。
  • 舰船部署时报 System with id [...] not found:舰船引用的系统 ID 拼错或没有注册。

    • 解决方案:核对工匠的 system id、defense id 与两份系统定义和 CSV。
  • 系统结束后加成保留:unapply 缺少某个写入项的清理。

    • 解决方案:按 apply 中的对象逐项补齐相同 ID 的 unmodify,重启后完整测试一个周期。
  • 加载时报 Error loading [...]:statsScript 与源码包名、类名或当前保存目录不一致。

    • 解决方案:把源码保存到 MOD 根目录对应的 data/scripts/gearin/shipsystems/,核对完整类名后重启。

总结

主系统与右键系统采用相同的定义、登记和效果类结构,舰船数据使用不同字段挂载。系统的时间参数决定各阶段长度,effectLevel 把阶段进度交给效果类,unapply 负责解除当前系统的修饰。

本例组合了实弹强化与机动加成,右键则处理不同伤害类型。继续调整时,把数值、持续时间和冷却一起测试;系统 AI 与更深入的调用规则在 [C9-S2] 展开。

建议参考项

  • data/shipsystems/ammofeed.system:突击填弹器的定义基础。
  • data/shipsystems/damper.system:右键抵抗力场的定义基础。
  • data/shipsystems/ship_systems.csv:名称、时间、幅能、使用限制与标签。
  • data/hulls/ship_data.csv:system id 和 defense id 的挂载位置。
  • data/shipsystems/scripts/AmmoFeedStats.java:实弹射速与幅能修改。
  • data/shipsystems/scripts/ManeuveringJetsStats.java:速度与机动修改。
  • com.fs.starfarer.api.impl.combat.BaseShipSystemScript:效果类的基类。
  • com.fs.starfarer.api.plugins.ShipSystemStatsScript:状态、效果强度和效果回调。
  • com.fs.starfarer.api.combat.MutableShipStatsAPI:各类舰船数值的修改入口。
在 GitHub 上编辑此页
上次更新: 2026/10/14 12:25
贡献者: 1847905557
上一页
制作完整船插
下一页
为武器加入命中与光束特效