# 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` - 太阳镜