# SC-Accessory-Mod
**Repository Path**: tp16b/sc-accessory-mod
## Basic Information
- **Project Name**: SC-Accessory-Mod
- **Description**: 生存战争衣服配件基础模组。提供衣服扩展基础能力
- **Primary Language**: C#
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 4
- **Forks**: 1
- **Created**: 2026-04-06
- **Last Updated**: 2026-04-13
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# SC-Accessory-Mod
## 简介
生存战争衣服配件基础模组。提供衣服扩展基础能力,支持多模组共享使用。
## 功能特性
- 支持在服装上挂载额外的 3D 模型配件
- 支持 4 个配件槽位:头部(Head)、躯干(Torso)、左腿(LeftLeg)、右腿(RightLeg)
- 提供实时调试界面,方便调整配件参数
- 配置文件持久化保存(使用命名空间.类名作为唯一标识,跨存档稳定)
## 模组开发者使用指南
### 1. 项目配置
#### 1.1 添加项目引用
在你的模组项目文件 `.csproj` 中添加:
```xml
```
> **重要**:`Private="False"` 确保不会将 Accessory.dll 复制到输出目录,避免重复打包。
#### 1.2 声明模组依赖
在你的 `modinfo.json` 中添加依赖声明:
```json
{
"Name": "YourMod",
"Dependencies": {
"Tp.Accessory": "1.0.0"
}
}
```
### 2. 创建配件方块
```csharp
using Engine;
using Engine.Graphics;
using Game;
using Accessory;
public class MyAccessoryBlock : Block, IAccessory {
public Texture2D texture;
public Model m_standaloneModel;
public ClothingData m_clothingData;
public override void Initialize() {
m_standaloneModel = ContentManager.Get("Models/MyAccessory");
texture = ContentManager.Get("Textures/Clothing/MyAccessory");
m_clothingData = new ClothingData {
DisplayName = "我的配件",
Slot = ClothingSlot.Head,
ArmorProtection = 0f,
Sturdiness = 100f,
Insulation = 1.0f,
MovementSpeedFactor = 1.0f,
IsOuter = true,
CanBeDyed = false,
Layer = 1,
Texture = texture,
};
// 设置配件参数(关键步骤!)
m_clothingData.DictionaryForOtherMods.SetValue("AccessorySlot", (int)AccessorySlot.Head);
m_clothingData.DictionaryForOtherMods.SetValue("AccessoryOffset", new Vector3(0f, 0.1f, 0f));
m_clothingData.DictionaryForOtherMods.SetValue("AccessoryScale", new Vector3(1f, 1f, 1f));
m_clothingData.DictionaryForOtherMods.SetValue("AccessoryRotation", new Vector3(0f, 0f, 0f));
m_clothingData.DictionaryForOtherMods.SetValue("AccessoryUiOffset", new Vector3(0f, 1.5f, 0f));
m_clothingData.DictionaryForOtherMods.SetValue("AccessoryUiScale", new Vector3(1f, 1f, 1f));
m_clothingData.DictionaryForOtherMods.SetValue("AccessoryUiRotation", new Vector3(0f, 0f, 0f));
// 注册配件(必须在 base.Initialize() 之前)
AccessoryAPI.RegisterAccessory(m_clothingData);
base.Initialize();
}
public override ClothingData GetClothingData(int value) => m_clothingData;
public override bool CanWear(int value) => true;
public Model GetStandaloneModel() => m_standaloneModel;
public Texture2D GetClothingTexture() => texture;
}
```
### 3. 配件参数说明
| 参数 | 类型 | 说明 |
|------|------|------|
| AccessorySlot | int | 配件槽位:Head=0, Torso=1, LeftLeg=2, RightLeg=3 |
| AccessoryOffset | Vector3 | 世界空间中的位置偏移 |
| AccessoryScale | Vector3 | 世界空间中的缩放 |
| AccessoryRotation | Vector3 | 世界空间中的旋转(弧度) |
| AccessoryUiOffset | Vector3 | UI界面(背包/服装界面)中的位置偏移 |
| AccessoryUiScale | Vector3 | UI界面中的缩放 |
| AccessoryUiRotation | Vector3 | UI界面中的旋转(弧度) |
### 4. API 参考
```csharp
namespace Accessory {
///
/// 配件方块接口
///
public interface IAccessory {
Model GetStandaloneModel();
Texture2D GetClothingTexture();
}
// 配件槽位枚举
public enum AccessorySlot {
Head, Torso, LeftLeg, RightLeg,
}
// 配件参数
public class AccessoryParam {
public Vector3 Offset, Scale, Rotation;
public Vector3 UiOffset, UiScale, UiRotation;
}
// 配件数据
public struct AccessoryData {
public AccessorySlot Slot;
public int Layer;
public Vector3 Offset, Scale, Rotation;
public Vector3 UiOffset, UiScale, UiRotation;
public int BlockValue; // 用于存档、渲染
public int BlockIndex { get; } // 动态获取方块类型索引
public string AccessoryId { get; } // 唯一标识(命名空间.类名)
}
// API 方法
public static class AccessoryAPI {
// 注册配件
public static void RegisterAccessory(ClothingData clothingData);
// 检查是否穿戴指定配件(多种方式)
public static bool HasAccessory(ComponentPlayer player, int blockIndex);
public static bool HasAccessory(ComponentPlayer player, string accessoryId);
public static bool HasAccessory(ComponentPlayer player) where T : Block;
public static bool HasAccessory(ComponentPlayer player, Block block);
// 获取配件列表
public static List GetAccessories(ComponentPlayer player);
public static IReadOnlyList GetAccessories(ComponentPlayer player, AccessorySlot slot);
// 获取配件组件
public static ComponentClothingAccessory GetComponent(ComponentPlayer player);
// 更新配件参数(调试用)
public static void UpdateAccessoryParam(ComponentPlayer player, string accessoryId, AccessoryParam param);
public static void UpdateAccessoryParam(ComponentPlayer player, Block block, AccessoryParam param);
// 获取原始默认参数
public static AccessoryParam GetOriginalDefaultParam(string accessoryId);
public static AccessoryParam GetOriginalDefaultParam(Block block);
}
}
```
### 5. 检查玩家是否穿戴特定配件
```csharp
using Accessory;
using Game;
// 方法1:通过泛型(推荐)
bool hasAccessory = AccessoryAPI.HasAccessory(player);
// 方法2:通过 Block 实例
Block block = BlocksManager.Blocks[someIndex];
bool hasAccessory = AccessoryAPI.HasAccessory(player, block);
// 方法3:通过 AccessoryId(命名空间.类名)
bool hasAccessory = AccessoryAPI.HasAccessory(player, "WonderfulEra.BambooHatBlock");
// 方法4:通过 BlockIndex
int blockIndex = BlocksManager.GetBlockIndex();
bool hasAccessory = AccessoryAPI.HasAccessory(player, blockIndex);
// 方法5:获取配件组件直接检查
var accessoryComponent = AccessoryAPI.GetComponent(player);
if (accessoryComponent != null) {
bool hasAccessory = accessoryComponent.HasAccessory();
}
// 方法6:获取指定槽位的所有配件
var headAccessories = AccessoryAPI.GetAccessories(player, AccessorySlot.Head);
foreach (var accessory in headAccessories) {
// accessory.AccessoryId - 唯一标识(如 "WonderfulEra.BambooHatBlock")
// accessory.BlockValue - 方块完整值
// accessory.BlockIndex - 方块类型索引(动态)
}
```
### 6. 调试功能
配件模组提供调试按钮(默认显示在右上角展开菜单中),点击可打开调试界面:
- 实时调整配件的位置、缩放、旋转参数
- 保存配置到文件(保存到游戏存档目录)
- 重置为默认参数
调试按钮可通过 F7 快捷键打开/关闭。
### 7. 配置文件
配件配置保存在:`游戏存档目录/AccessoryConfig.xml`
配置文件使用**命名空间.类名**作为唯一标识,跨存档稳定:
```xml
0, 0.1, 0
1, 1, 1
0, 0, 0
0, 1.5, 0
1, 1, 1
0, 0, 0
0, 0.05, 0
...
```
## 唯一标识说明
配件系统使用 **命名空间.类名**(如 `WonderfulEra.BambooHatBlock`)作为配件的唯一标识:
| 标识方式 | 稳定性 | 说明 |
|----------|--------|------|
| BlockIndex | 不稳定 | 动态分配,不同存档/模组加载顺序可能不同 |
| AccessoryId | 稳定 | 基于类名,跨存档、跨模组加载顺序保持一致 |
**推荐使用方式**:
- 配置文件:使用 `AccessoryId`
- 运行时查询:使用泛型方法 `HasAccessory()`
## 注意事项
1. **注册时机**:必须在 `base.Initialize()` 之前调用 `AccessoryAPI.RegisterAccessory()`
2. **模型要求**:配件需要提供独立的 3D 模型,实现 `GetStandaloneModel()` 方法
3. **纹理要求**:需要提供服装纹理,实现 `GetClothingTexture()` 方法
4. **存档兼容**:配件数据保存在玩家实体的 `Accessories` 字典中,格式为 `BlockValue` 列表
## 示例项目
参考 WonderfulEra 模组中的配件方块实现:
- `BambooHatBlock.cs` - 斗笠
- `PirateHatBlock.cs` - 海盗帽
- `HmlHatBlock.cs` - 矿灯帽
- `SunGlassesBlock.cs` - 太阳镜