info_outline
# Desperate City Armory — 武器系統模組使用教學
> ## ⚠️ !!注意!! 在使用前需要先初始化武器
> 在遊戲開始時(通常是「初始化」事件),**必須**先執行 `InitGameData` 動作,否則所有武器功能都不會正常運作。
>
> ```
> 事件:初始化
> 動作:InitGameData
> ├── 武器資料別名:datas_weaponType(預設)
> ├── 殭屍資料別名:datas_zombieType(預設)
> └── 除錯日誌:false(正式版請關閉)
> ```
---
## 目錄
1. [模組架構](#模組架構)
2. [初始化設定](#初始化設定)
3. [新增武器到地圖](#新增武器到地圖)
4. [讓角色裝備武器](#讓角色裝備武器)
5. [自訂武器處理器(Actions)](#自訂武器處理器)
6. [weapon_utils 工具函式](#weapon_utils-工具函式)
7. [datas_gameConfig 武器資料設定](#datas_gameconfig-武器資料設定)
8. [新增武器的完整流程](#新增武器的完整流程)
9. [注意事項與常見問題](#注意事項與常見問題)
---
## 模組架構
```
datas/
├── datas_gameConfig.ts ← 武器資料定義(FarWeaponData)與 WeaponTypeData 管理器
└── weapon/
├── weapon_utils.ts ← 共用工具函式(registerWeapon、actorCustomGAF 等)
├── InitGameData.action.ts ← 【必須】初始化動作,負責事件監聽與切換偵測
├── WeaponActions.action.ts ← WeaponSpawn(生成武器到地上)
├── WeaponEquip.action.ts ← WeaponEquip(讓角色裝備武器)
└── weapons/
├── Demo_actions.ts ← 新增武器用的模板
├── Barret_actions.ts
├── AA12_actions.ts
├── M249_actions.ts
├── P90_actions.ts
├── MP5_actions.ts
├── SCAR_actions.ts
├── M200_actions.ts
├── Revolver_actions.ts
├── Gating_actions.ts
├── GrenadeGun_actions.ts
├── Crossbow_actions.ts
├── SR16_actions.ts
├── ElectricGun_actions.ts
├── AUG_actions.ts
└── CombatShotgun_actions.ts
```
---
## 初始化設定
> ### ⚠️ 使用前必須先執行 InitGameData,否則所有武器功能不會正常運作!
`InitGameData` 會執行以下工作:
- 載入所有武器資料(`WeaponTypeData`)
- 建立自訂彈匣(`initMagazines`)
- 註冊所有武器處理器(Handler)
- 掛上 `ACTOR_PICKUP_STUFF`、`ACTOR_DROP_STUFF`、`ACTOR_FIRE` 事件監聽
- 啟動輪詢(每 100ms)偵測武器切換與裝填
**動作參數說明:**
| 參數 | 說明 | 預設值 |
|------|------|--------|
| 武器資料別名 | JSON 資源的別名 | `datas_weaponType` |
| 殭屍資料別名 | JSON 資源的別名 | `datas_zombieType` |
| 除錯日誌 | 開啟後顯示詳細 log,上架前請關閉 | `false` |
---
## 新增武器到地圖
使用 `WeaponSpawn` 動作將武器放到地圖上。
**動作參數說明:**
| 參數 | 說明 |
|------|------|
| 武器種類 | 從下拉選單選擇 |
| 位置 | 在地圖上點選位置 |
| 道具代碼 | 武器物件的事件代碼(`item*` 自動生成唯一代碼) |
| 區域變數名稱 | 儲存道具代碼的區域變數 |
| 除錯日誌 | 顯示生成 log |
**支援的武器種類:**
| 武器代碼 | 武器名稱 | 特效 | 自訂音效 |
|---------|---------|------|---------|
| `barret` | 巴雷特 | GAF ✅ | ✅ |
| `m249` | M249 | GAF ✅ | ✅ |
| `p90` | P90 | GAF ✅ | ✅ |
| `mp5` | MP5 | GAF ✅ | ✅ |
| `scar` | SCAR | GAF ✅ | ✅ |
| `m200` | M200 | GAF ✅ | ✅ |
| `revolver` | 左輪槍 | GAF ✅ | ✅ |
| `gating` | 加特林 | GAF ✅ | ✅ |
| `aa12` | AA-12 | GAF ✅ | ✅ |
| `combat_shotgun` | 戰鬥霰彈槍 | — | ❌ |
| `aug` | AUG | — | ✅ |
| `sr16` | SR-16 | — | ✅ |
| `electric_gun` | 電擊槍 | — | ✅ |
| `grenadegun` | 榴彈槍 | ❌ | ❌ |
| `crossbow` | 弩 | GAF ✅ | ✅ |
| `uzi` | 烏茲 | — | — |
| `mk18` | MK18 | — | — |
| `svd` | SVD | — | — |
| `glock17` | 格洛克17 | — | — |
| `victor` | 維克托 | — | — |
| `m2_machinegun` | M2機槍 | ❌ | ❌ |
---
## 讓角色裝備武器
使用 `WeaponEquip` 動作讓角色直接持有武器(不需要從地上撿起)。
**動作參數說明:**
| 參數 | 說明 | 預設值 |
|------|------|--------|
| 角色代碼 | 目標角色 | 必填 |
| 武器種類 | 從下拉選單選擇 | `barret` |
| 裝備在哪一手 | -1 當前手 / 0 第一手 / 1 第二手 | `-1` |
| 裝備後切換至此武器 | 裝備後立即切換 | `false` |
| 在角色位置放下之前的武器 | 換武器時丟棄舊武器 | `false` |
| 設為角色預設武器 | 手空時自動拿出 | `false` |
| 除錯日誌 | 顯示裝備 log | `false` |
---
## 自訂武器處理器
每把有 GAF 動畫或自訂音效的武器,需要一個對應的 `_actions.ts` 檔案。**複製 `Demo_actions.ts` 作為起點。**
```typescript
const myHandler: WeaponHandler = {
stuffCode: 'cusfar_myWeapon', // 對應 WEAPON_DATAS 的 stuff 欄位
onPickup(actor, game, manager) {
// 撿起武器:隱藏引擎動畫、設旗標、播 GAF
setActorDisplayVisible(actor, 'rightHand', false);
setActorDisplayVisible(actor, 'leftHand', false);
setWeaponAlpha(actor, 0);
setGlobal(manager, `${actor.code}_hold_myWeapon`, 1);
actorCustomGAF({ ..., linkage: 'Idle', stop: true });
},
onFire(actor, game, manager) {
// 開槍:播射擊動畫 + 音效
actorCustomGAF({ ..., linkage: 'Shoot' });
mapSoundEffect(game, actor, 'Desperate_City.myWeapon_music', 1.0);
},
onReload(actor, game, manager) {
// 裝填:播裝填動畫
actorCustomGAF({ ..., linkage: 'Reload' });
},
onUnequip(actor, game, manager) {
// 卸除:移除 GAF、清旗標、恢復引擎動畫
actorCustomGAF({ actorCode: actor.code, actorCustomGAFCode: gafCode(actor), add: 'remove' });
setGlobal(manager, `${actor.code}_hold_myWeapon`, 0);
setActorDisplayVisible(actor, 'rightHand', true);
setActorDisplayVisible(actor, 'leftHand', true);
setWeaponAlpha(actor, 100);
},
};
export function registerMyWeapon(): void {
registerWeapon(myHandler);
}
```
---
## 新增武器的完整流程
1. **複製 `Demo_actions.ts`**,改名為 `MyWeapon_actions.ts`
2. **修改三個常數**:`STUFF_CODE`、`GAF_ALIAS`、`HOLD_SUFFIX`
3. **調整各 handler** 的 linkage、fps、音效等細節
4. **`InitGameData.action.ts`** 加上 import 和 `registerMyWeapon()` 呼叫
5. **`datas_gameConfig.ts`** 的 `WEAPON_DATAS` 加上武器設定
---
## 注意事項與常見問題
### Q:武器沒有子彈特效?
確認 `SpawnedFarWeapon` 沒有 override `createBulletsData` 方法,必須使用引擎原始邏輯。
### Q:onPickup 沒有觸發?
確認 `stuffCode` 能被 `_resolveStuffCode` 正確對應,系統嘗試順序:
1. 直接查 handler(如 `cusfar_barret`)
2. 去掉 `cusfar_` 前綴(如 `SCAR`、`p90`)
3. 去掉 `homemade_` 前綴(如 `m249`)
### Q:切換武器時 GAF 沒更新?
系統每 100ms 輪詢 `_currentWeapon`,偵測切換時觸發 `onUnequip`(舊)+ `onPickup`(新)。初次撿起由 `ACTOR_PICKUP_STUFF` 事件負責。
### Q:引擎手持動畫沒有隱藏?
確認 `datas_gameConfig` 裡該武器設定 `hasCustomAnim: true`。
### Q:clip 設什麼?
- 使用 `TwilightWarsLib.actors` → 填 `lib_rifle`、`lib_handgun`、`lib_shotgun` 等
- 使用自訂資源 → 填該資源內的 linkage 名稱(如 `mp5_clip`、`barret_clip`)
### Q:weaponCode 需要手動填?
大多數情況不需要,系統自動從 `stuff` 推算。以下需手動填:
- `gating`:`weaponCode: 'gating_gun'`
- `m249`:`weaponCode: 'homemade_m249'`
## Authors
**[Autumn](/profile/113266227571469019286@google)**