> For the complete documentation index, see [llms.txt](https://hamsterbaron.gitbook.io/hamsterbaron/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hamsterbaron.gitbook.io/hamsterbaron/augment-guide/secweapon/wei-tuo-zhan-bao-tian-jia-gong-neng.md).

# 为拓展包添加功能

## 了解原理

在开始前，您需要了解 Arcana 在原理上如何实现这一切，以方便您后续的制作：该组件本质上通过在两个不同的**枪械素材索引文件** (gun\_display.json) 与**枪械数据配置文件** (gun\_data.json) 中切换以模拟游戏中无感的启用另一发射器的效果。

当前次级发射器的启用配置段可存在于被指定<mark style="color:$warning;">可安装于握把槽位</mark>的配件数据中 (即启用次级发射器则需有一个可被安装至对应武器上的握把槽位配件) 该配件数据中应有如下字段：

```json
{
  "weight": 0.2,
  //其他的配件数据项，即extras属性为一个顶级属性与其他属性并列
  "extras":
  {
    "under_barrel":
    {
      "gun": "tacz:m320", 
      //该项指定次级发射器激活后切换的目标数据文件
      "gun_display_namespace": null, 
      //该项指定素材索引的特定命名空间，一般用于跨枪包下挂配件，不理解用途请设为null
      "gun_display_prefix": "m320_" 
      //该项指定配件安装后调用的资源前缀
    }
  }
}
```

在未安装特定配件时，武器会像 Tacz 模组原版一般的物品一样正常运作。**一旦检测到特定的配件被安装，程序会立即启用另一份枪械素材索引文件**，并更换当前渲染使用的模型文件与动画文件至新的特定文件。

> E.g. 假设此时已有配置好的 M16A4 突击步枪相关素材，包括原枪械素材索引 m16a4\_display.json 与添加的变体枪械素材文件 m320\_m16a4\_display.json ，则当枪械安装了 gun\_display\_prefix 项中值为"m320\_"的握把配件时，程序会立即使用 m320\_m16a4\_display.json 作为素材索引文件，此时模型与动画等都将由新素材索引文件中所指定的值确定。这也意味着<mark style="color:$warning;">您完全可以在新的素材索引文件中仍指定使用同样的模型与动画文件</mark>，以方便一体化复合武器的制作过程。

此时，玩家在游戏内可以通过“切换至下挂发射器”按键来在两份**不同的枪械数据配置文件**中切换。手持武器是否正在使用次级发射器数据的状态是可持久化的，不会因为退出游戏或物品掉落，所有者切换等原因而重置。因此，下挂配置的相关设置需正确。

***

## 准备相关素材

当开始为您的枪械制作独特的次级发射器时，首先需要准备好以下素材:

#### 安装次级发射器时使用的模型文件

* 一份新的模型文件。通常为添加了下挂武器/次级发射器部分模型的目标武器。您也可以根据需求使用与原本毫无关联的全新模型文件。

<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-cover data-type="image">Cover image</th></tr></thead><tbody><tr><td>默认的 M4A1 模型文件</td><td data-object-fit="contain"><a href="/files/EyB2bk6IgMN4RY2xDCwv">/files/EyB2bk6IgMN4RY2xDCwv</a></td></tr><tr><td>所需要准备的添加了 M320 下挂榴弹发射器的模型文件</td><td data-object-fit="contain"><a href="/files/eHfIdA1ozDxlV0HF0GWt">/files/eHfIdA1ozDxlV0HF0GWt</a></td></tr><tr><td>启用后即与原模型无任何关系，因此可使用全新模型</td><td data-object-fit="contain"><a href="/files/jBqDZ9vbJSND74i2R8Ku">/files/jBqDZ9vbJSND74i2R8Ku</a></td></tr></tbody></table>

#### 安装次级发射器时使用的动画文件

* 一份新的动画文件。一般在制作过程中是基于新的模型文件而制作的。该动画文件<mark style="color:$primary;">**应包括两部分内容**</mark>：正常情况下（未启用次级发射器时）所使用的一系列动画与使用次级发射器时播放的动画。如果想要更流畅的发射器切换动画，则还需包含两个在不同发射器之间切换的动画。

{% columns %}
{% column %}
基础动画与正常制作拓展包时的操作一致：

* [x] 待机动画 static\_idle
* [x] 持枪动画 draw
* [x] 装填动画 reload\_empty

...

* [x] 切入发射器 transform \[可选]

次级发射器启用时，所有的动画将会优先播放带有sub\_前缀的对应动画名：

* [x] 待机动画 sub\_static\_idle
* [x] 持枪动画 sub\_draw

...

* [x] 切出发射器 sub\_transform \[可选]

{% hint style="danger" %}
由于特殊原因，建议您将音效文件直接放入动画中，不建议使用素材索引文件来指定音效，这会导致次级发射器缺失动画音效。
{% endhint %}
{% endcolumn %}

{% column %}

<figure><img src="/files/LFu3O6qkT9koy9wZ3Ct3" alt=""><figcaption></figcaption></figure>
{% endcolumn %}
{% endcolumns %}

#### 安装次级发射器时使用的素材索引文件

* 一份新的素材索引文件，位于..\assets\\{your\_namespace}\display\guns目录下，用于指定在配件被安装后将使用哪一模型，对应的模型贴图，以及所使用的动画文件。

#### 启用次级发射器时读取的数据文件

* 一份新的数据文件。该数据文件通过指定一个命名空间内的特定枪械ID来选定使用的数据，此项将不受配置中的 gun\_display\_namespace 项的影响。新的武器数据与主要发射器无需拥有任何关联，使用的弹种，发射方式，装填逻辑等均可不同。<mark style="color:$warning;">目前暂不支持与主武器共享剩余弹药量，相关实现可通过机制组件部分作为暂代方案。</mark>
* 该数据文件**需被注册为一把可用的枪械**，但无需为其添加物品栏贴图，描述文本，模型和动画等其他部分。该道具枪械仅需作为次级发射器的数据载体。

#### 用以激活次级发射器的配件数据文件

* 一份该特殊配件的index索引文件，用以将该特殊配件注册到游戏内。
* 一份该特殊配件的data数据文件，用以告知程序该配件能够激活特殊的次级发射器。配件可拥有 TacZ 自带的各类属性效果，但必须拥有如下对象字段：

```json
"extras":
{
  "under_barrel":
  {
    "gun": "specific_GunId", 
    "gun_display_namespace": "your_gunpack_namespace, 
    "gun_display_prefix": "your_specific_prefix" 
  }
}//键值对具体含义请查阅上述"实现原理"段落
```

> E.g. 当键值对"gun"的值为"tacz:m320"时，该配件对应的次级发射器武器数据将使用命名空间为 tacz 中枪械id为 tacz:m320 所对应的 m320\_data.json 该键值对所填入的值需为一个已有枪械。
>
> 键值对"gun\_display\_prefix"默认搜寻安装了该配件的武器所在的命名空间(拓展资源包)中具有特定前缀的 display 文件。因此，当您想要为另一个资源包的武器制作可安装下挂武器时，需指定该项。

* 可准备一份该特殊配件的icon图标文件，位于texture/attachment/slot文件夹下，作为需手动加装的配件的游戏内物品栏图标。

***

## 配置与测试

为方便理解，下文中我们将需要装配次级发射器的枪械称为<mark style="color:$warning;">原枪械</mark>，将诸如下挂榴弹等次级发射器简称为<mark style="color:$warning;">发射器</mark>，将需要安装的包含了新发射器素材的目标枪械称为<mark style="color:$warning;">变体枪械</mark>。

例如，为一把M4A1突击步枪安装M320下挂榴弹发射器时，位于默认资源包内的M4A1枪械相关的所有文件都被称为原枪械素材，M320榴弹则被称为发射器，我们最终需要的安装了M320下挂榴弹的M4A1枪械相关的文件则称为变体枪械素材。以下是一个开发示例，方便制作者理解这一过程。

{% file src="/files/bkDcgbT1BY296pOd0OID" %}

{% stepper %}
{% step %}

### 制作发射器配件数据

依照上文段落中的说明制作握把类型的发射器配件数据，在示例包中即为weapon\_m320配件。通常情况下，用于启用次级发射器的握把配件不应拥有配件模型及其uv贴图，它们只需要素材索引文件与一个物品栏贴图文件。即便设置正确，该配件模型也是不会渲染到握把位置上的。
{% endstep %}

{% step %}

### 配置变体枪械素材索引文件

为变体枪械设置新的 display 文件。此索引文件的文件名必须在与原武器一致的基础上加上配件数据中所设定的需求前缀。例如，配件中所设定安装此配件时将请求调用"m320\_"前缀的对应索引文件，则 M4A1 卡宾枪安装该下挂榴弹配件时候，程序会试图寻找名为m320\_m4a1\_display.json的素材索引文件；M16A4 突击步枪安装该配件时，程序则会寻找m320\_m16a4\_display。因此，每一设想可使用该次级发射器配件的枪械武器，<mark style="color:$primary;">都需要拥有对应的有效素材索引文件</mark>。
{% endstep %}

{% step %}

### \[可选] 配置动画状态机

如希望枪械在不同发射器之间切换时有流畅的切换动画，请在变体枪械素材索引文件（display文件）中添加键值对`"state_machine": "example:underbarrel_default_state_machine"`，并复制一份示例包中位于路径assets/example/scripts下的同名lua脚本文件，将其放到拓展包中相同路径下，并在变体枪械的动画文件中添加transform与sub\_transform为名称的动画作为切换动画。如果您的拓展包中已使用了特殊的动画状态机，请参照本段末尾说明自行添加。

{% hint style="info" %}
**开发须知**：此处`example`字段为示例包命名空间，在制作拓展包时，请务必将此处字段替换为存放文件的实际命名空间名称，否则将导致脚本不加载。
{% endhint %}
{% endstep %}

{% step %}

### 导入变体枪械素材文件

将上文所提及的变体枪械模型文件，动画文件，贴图文件导入至拓展包对应位置中，并确保名称为变体枪械素材索引文件中所指定的正确名称。
{% endstep %}

{% step %}

### 为原枪械设定可用配件标签

相关的标签文件，位于tacz\_tags下，用以指定目标枪械可使用该配件从而启用次级发射器。有关操作请参阅 TacZ 官方制作的拓展包开发wiki。
{% endstep %}
{% endstepper %}

#### 测试与调整

一切就绪后，在游戏内拿出已绑定了次级发射器功能字段的握把槽位配件，安装到已为其做了特定适配的枪械上。此时，在改装界面您应该会看到武器播放了一次 draw 动画(这是重新启动新状态机的过程，后续版本将去除安装配件时播放的 draw 动画)，意味着此时枪械的模型渲染与动画系统等均已切换至您上面所准备的新素材资产。关闭改装界面后，单击"Switch to Underbarrel"按键 (默认为 I 键) 正常情况下，您就可以发现武器的数据和武器的 tooltip 中显示所使用的弹药均已切换到您配置的新武器。

对于次级发射器所使用的动画与模型素材等，与 TacZ 原版一样可使用热重载功能在游戏内直接进行调试，无需在每次调整后重启游戏。

#### 使用特殊切换动画

在切换发射器时直接拿出另一把枪未免显得过于生硬。程序提供了两个新的动画接口，用于调用特定的转入转出动画。为方便制作者使用，这边演示基础的调用方式。

在官方资源包assets/tacz/scripts目录下的<mark style="color:$primary;">default\_state\_machine.lua</mark>脚本文件，其中对应位置插入以下代码段： (起始位置和结尾位置**为原有字段**，用于定位插入位置，<mark style="color:$warning;">高亮的代码段即为需增加部分</mark>)

<pre class="language-lua"><code class="lang-lua">-- 转出闲置态
function main_track_states.idle.transition(this, context, input)
    -- 发射器切换动画将在该轨道的idle切换状态下启用
<strong>    if (input == "sub_transform") then
</strong><strong>        this.main_track_states.final.isfinal = -1
</strong><strong>        context:runAnimation("transform", context:getTrack(STATIC_TRACK_LINE, MAIN_TRACK), false, PLAY_ONCE_STOP, 0)
</strong><strong>        context:runAnimation("static_idle", context:getTrack(STATIC_TRACK_LINE, BASE_TRACK), false, LOOP, 0)
</strong><strong>        return this.main_track_states.idle
</strong><strong>    end
</strong><strong>    -- 监听切换发射器的输入信号名称
</strong><strong>    if (input == "transform") then
</strong><strong>        this.main_track_states.final.isfinal = -1
</strong><strong>        context:runAnimation("transform", context:getTrack(STATIC_TRACK_LINE, MAIN_TRACK), false, PLAY_ONCE_STOP, 0)
</strong><strong>        context:runAnimation("static_idle", context:getTrack(STATIC_TRACK_LINE, BASE_TRACK), false, LOOP, 0)
</strong><strong>        return this.main_track_states.idle
</strong><strong>    end
</strong>
    if (input == INPUT_PUT_AWAY) then
        runPutAwayAnimation(context)
        this.main_track_states.final.isfinal = 1
        -- 丢枪后转到最终态
-- Other Code...
</code></pre>
