diff --git a/DungeonShooting_ExcelTool/DungeonShooting_ExcelTool.csproj b/DungeonShooting_ExcelTool/DungeonShooting_ExcelTool.csproj index b27240e..9a963c3 100644 --- a/DungeonShooting_ExcelTool/DungeonShooting_ExcelTool.csproj +++ b/DungeonShooting_ExcelTool/DungeonShooting_ExcelTool.csproj @@ -15,6 +15,9 @@ PreserveNewest + + PreserveNewest + diff --git a/DungeonShooting_ExcelTool/ExcelGenerator.cs b/DungeonShooting_ExcelTool/ExcelGenerator.cs index 89a4165..2c96016 100644 --- a/DungeonShooting_ExcelTool/ExcelGenerator.cs +++ b/DungeonShooting_ExcelTool/ExcelGenerator.cs @@ -12,16 +12,44 @@ #else private const string ExcelFilePath = "excel/excelFile"; #endif + + private static HashSet _excelNames = new HashSet(); + + + private enum CollectionsType + { + None, + Array, + Map + } private class MappingData { + public string TypeStr; public string TypeName; + public CollectionsType CollectionsType; + + public bool IsRefExcel; + public string RefTypeStr; + public string RefTypeName; - public MappingData(string typeStr, string typeName) + public MappingData(string typeStr, string typeName, CollectionsType collectionsType) { TypeStr = typeStr; TypeName = typeName; + CollectionsType = collectionsType; + IsRefExcel = false; + } + + public MappingData(string typeStr, string typeName, CollectionsType collectionsType, string refTypeStr, string refTypeName) + { + TypeStr = typeStr; + TypeName = typeName; + CollectionsType = collectionsType; + IsRefExcel = true; + RefTypeStr = refTypeStr; + RefTypeName = refTypeName; } } @@ -46,6 +74,13 @@ if (directoryInfo.Exists) { var fileInfos = directoryInfo.GetFiles(); + //记录文件 + foreach (var fileInfo in fileInfos) + { + var fileName = Path.GetFileNameWithoutExtension(fileInfo.Name).FirstToUpper(); + _excelNames.Add(fileName); + } + //读取配置文件 foreach (var fileInfo in fileInfos) { if (fileInfo.Extension == ".xlsx") @@ -113,13 +148,49 @@ var fieldCode = ""; var callFuncCode = ""; + var callInitRefFuncCode = ""; var funcCode = ""; + var initRefFuncCode = ""; foreach (var excelData in excelList) { var idName = excelData.ColumnNames[0]; var idTypeStr = excelData.ColumnMappingData[idName].TypeStr; + //---------------------------- 引用其他表处理 ---------------------------- + var hasRefColumn = false; + var refColumnNoneCode = ""; + foreach (var columnName in excelData.ColumnNames) + { + var mappingData = excelData.ColumnMappingData[columnName]; + if (mappingData.IsRefExcel) + { + hasRefColumn = true; + if (mappingData.CollectionsType == CollectionsType.None) + { + refColumnNoneCode += $" item.{columnName} = {mappingData.RefTypeName}_Map[item.__{columnName}];\n"; + } + else if (mappingData.CollectionsType == CollectionsType.Array) + { + refColumnNoneCode += $" item.{columnName} = new {mappingData.RefTypeName}[item.__{columnName}.Length];\n"; + refColumnNoneCode += $" for (var i = 0; i < item.__{columnName}.Length; i++)\n"; + refColumnNoneCode += $" {{\n"; + refColumnNoneCode += $" item.{columnName}[i] = {mappingData.RefTypeName}_Map[item.__{columnName}[i]];\n"; + refColumnNoneCode += $" }}\n"; + } + else + { + refColumnNoneCode += $" item.{columnName} = new {mappingData.RefTypeStr}();\n"; + refColumnNoneCode += $" foreach (var pair in item.__{columnName})\n"; + refColumnNoneCode += $" {{\n"; + refColumnNoneCode += $" item.{columnName}.Add(pair.Key, {mappingData.RefTypeName}_Map[pair.Value]);\n"; + refColumnNoneCode += $" }}\n"; + } + refColumnNoneCode += $"\n"; + } + } + + //----------------------------- 数据集合 ------------------------------------ fieldCode += $" /// \n"; fieldCode += $" /// {excelData.TableName}.xlsx表数据集合, 以 List 形式存储, 数据顺序与 Excel 表相同\n"; fieldCode += $" /// \n"; @@ -130,6 +201,7 @@ fieldCode += $" public static Dictionary<{idTypeStr}, {excelData.TableName}> {excelData.TableName}_Map {{ get; private set; }}\n"; fieldCode += $"\n"; + //------------------------------- 初始化函数 ------------------------------------- callFuncCode += $" _Init{excelData.TableName}Config();\n"; funcCode += $" private static void _Init{excelData.TableName}Config()\n"; @@ -137,7 +209,14 @@ funcCode += $" try\n"; funcCode += $" {{\n"; funcCode += $" var text = _ReadConfigAsText(\"res://resource/config/{excelData.TableName}.json\");\n"; - funcCode += $" {excelData.TableName}_List = JsonSerializer.Deserialize>(text);\n"; + if (hasRefColumn) //存在引用列 + { + funcCode += $" {excelData.TableName}_List = new List<{excelData.TableName}>(JsonSerializer.Deserialize>(text));\n"; + } + else + { + funcCode += $" {excelData.TableName}_List = JsonSerializer.Deserialize>(text);\n"; + } funcCode += $" {excelData.TableName}_Map = new Dictionary<{idTypeStr}, {excelData.TableName}>();\n"; funcCode += $" foreach (var item in {excelData.TableName}_List)\n"; funcCode += $" {{\n"; @@ -150,6 +229,29 @@ funcCode += $" throw new Exception(\"初始化表'{excelData.TableName}'失败!\");\n"; funcCode += $" }}\n"; funcCode += $" }}\n"; + + + //------------------------------- 初始化引用 --------------------------------- + if (hasRefColumn) + { + callInitRefFuncCode += $" _Init{excelData.TableName}Ref();\n"; + + initRefFuncCode += $" private static void _Init{excelData.TableName}Ref()\n"; + initRefFuncCode += $" {{\n"; + initRefFuncCode += $" foreach (Ref_{excelData.TableName} item in {excelData.TableName}_List)\n"; + initRefFuncCode += $" {{\n"; + initRefFuncCode += $" try\n"; + initRefFuncCode += $" {{\n"; + initRefFuncCode += refColumnNoneCode; + initRefFuncCode += $" }}\n"; + initRefFuncCode += $" catch (Exception e)\n"; + initRefFuncCode += $" {{\n"; + initRefFuncCode += $" GD.PrintErr(e.ToString());\n"; + initRefFuncCode += $" throw new Exception(\"初始化'{excelData.TableName}'引用其他表数据失败, 当前行id: \" + item.Id);\n"; + initRefFuncCode += $" }}\n"; + initRefFuncCode += $" }}\n"; + initRefFuncCode += $" }}\n"; + } } code += fieldCode; @@ -164,8 +266,12 @@ code += $" _init = true;\n"; code += $"\n"; code += callFuncCode; + code += $"\n"; + code += callInitRefFuncCode; code += $" }}\n"; code += funcCode; + code += $"\n"; + code += initRefFuncCode; code += $" private static string _ReadConfigAsText(string path)\n"; code += $" {{\n"; code += $" var file = FileAccess.Open(path, FileAccess.ModeFlags.Read);\n"; @@ -190,7 +296,9 @@ outStr += $"public static partial class ExcelConfig\n{{\n"; outStr += $" public class {fileName}\n"; outStr += $" {{\n"; - + //继承的带有引用其他表的类代码 + var outRefStr = ""; + var cloneFuncStr = $" /// \n"; cloneFuncStr += $" /// 返回浅拷贝出的新对象\n"; cloneFuncStr += $" /// \n"; @@ -274,8 +382,26 @@ outStr += $" /// \n"; outStr += $" /// {description}\n"; outStr += $" /// \n"; - outStr += $" [JsonInclude]\n"; - outStr += $" public {mappingData.TypeStr} {field};\n\n"; + if (!mappingData.IsRefExcel) //没有引用其他表 + { + outStr += $" [JsonInclude]\n"; + outStr += $" public {mappingData.TypeStr} {field};\n\n"; + } + else + { + outStr += $" public {mappingData.RefTypeStr} {field};\n\n"; + } + + if (mappingData.IsRefExcel) //引用其他表 + { + if (string.IsNullOrEmpty(outRefStr)) + { + outRefStr += $" private class Ref_{fileName} : {fileName}\n"; + outRefStr += $" {{\n"; + } + outRefStr += $" [JsonInclude]\n"; + outRefStr += $" public {mappingData.TypeStr} __{field};\n\n"; + } cloneFuncStr += $" inst.{field} = {field};\n"; } @@ -284,6 +410,13 @@ cloneFuncStr += " }\n"; outStr += cloneFuncStr; outStr += " }\n"; + + if (!string.IsNullOrEmpty(outRefStr)) + { + outRefStr += " }\n"; + outStr += outRefStr; + } + outStr += "}"; //解析字段类型 @@ -324,57 +457,58 @@ var fieldName = excelData.ColumnNames[j]; var mappingData = excelData.ColumnMappingData[fieldName]; + var field = mappingData.IsRefExcel ? "__" + fieldName : fieldName; try { switch (mappingData.TypeStr) { case "bool": case "boolean": - data.Add(fieldName, GetCellBooleanValue(cell)); + data.Add(field, GetCellBooleanValue(cell)); break; case "byte": - data.Add(fieldName, Convert.ToByte(GetCellNumberValue(cell))); + data.Add(field, Convert.ToByte(GetCellNumberValue(cell))); break; case "sbyte": - data.Add(fieldName, Convert.ToSByte(GetCellNumberValue(cell))); + data.Add(field, Convert.ToSByte(GetCellNumberValue(cell))); break; case "short": - data.Add(fieldName, Convert.ToInt16(GetCellNumberValue(cell))); + data.Add(field, Convert.ToInt16(GetCellNumberValue(cell))); break; case "ushort": - data.Add(fieldName, Convert.ToUInt16(GetCellNumberValue(cell))); + data.Add(field, Convert.ToUInt16(GetCellNumberValue(cell))); break; case "int": - data.Add(fieldName, Convert.ToInt32(GetCellNumberValue(cell))); + data.Add(field, Convert.ToInt32(GetCellNumberValue(cell))); break; case "uint": - data.Add(fieldName, Convert.ToUInt32(GetCellNumberValue(cell))); + data.Add(field, Convert.ToUInt32(GetCellNumberValue(cell))); break; case "long": - data.Add(fieldName, Convert.ToInt64(GetCellNumberValue(cell))); + data.Add(field, Convert.ToInt64(GetCellNumberValue(cell))); break; case "ulong": - data.Add(fieldName, Convert.ToUInt64(GetCellNumberValue(cell))); + data.Add(field, Convert.ToUInt64(GetCellNumberValue(cell))); break; case "float": - data.Add(fieldName, Convert.ToSingle(GetCellNumberValue(cell))); + data.Add(field, Convert.ToSingle(GetCellNumberValue(cell))); break; case "double": - data.Add(fieldName, GetCellNumberValue(cell)); + data.Add(field, GetCellNumberValue(cell)); break; case "string": - data.Add(fieldName, GetCellStringValue(cell)); + data.Add(field, GetCellStringValue(cell)); break; default: { var cellStringValue = GetCellStringValue(cell); if (cellStringValue.Length == 0) { - data.Add(fieldName, null); + data.Add(field, null); } else { - data.Add(fieldName, JsonSerializer.Deserialize(cellStringValue, excelData.ColumnType[fieldName])); + data.Add(field, JsonSerializer.Deserialize(cellStringValue, excelData.ColumnType[fieldName])); } } break; @@ -434,15 +568,30 @@ return cell.BooleanCellValue; } - private static MappingData ConvertToType(string str) + private static MappingData ConvertToType(string str, int depth = 0) { if (Regex.IsMatch(str, "^\\w+$")) { var typeStr = TypeStrMapping(str); var typeName = TypeNameMapping(str); - return new MappingData(typeStr, typeName); + return new MappingData(typeStr, typeName, CollectionsType.None); } - else if (str.StartsWith('{')) + else if (Regex.IsMatch(str, "^\\$\\w+$")) //引用其他表 + { + var realName = str.Substring(1); + if (!_excelNames.Contains(realName)) + { + throw new Exception($"引用表数据失败, 未找到表: {realName}!"); + } + + if (depth > 1) + { + throw new Exception("引用表数据失败, 引用表数据仅支持放入第一层的数组和字典!"); + } + + return new MappingData(TypeStrMapping("string"), TypeNameMapping("string"), CollectionsType.None, realName, realName); + } + else if (str.StartsWith('{')) //字典 { var tempStr = str.Substring(1, str.Length - 2); var index = tempStr.IndexOf(':'); @@ -456,19 +605,35 @@ { throw new Exception($"字典key类型必须是基础类型!"); } - var type1 = ConvertToType(keyStr); - var type2 = ConvertToType(tempStr.Substring(index + 1)); + + var type1 = ConvertToType(keyStr, depth + 1); + var type2 = ConvertToType(tempStr.Substring(index + 1), depth + 1); + var typeStr = $"Dictionary<{type1.TypeStr}, {type2.TypeStr}>"; var typeName = $"System.Collections.Generic.Dictionary`2[[{type1.TypeName}],[{type2.TypeName}]]"; - return new MappingData(typeStr, typeName); + + if (type2.IsRefExcel) //引用过其他表 + { + var refTypeStr = $"Dictionary<{type1.TypeStr}, {type2.RefTypeStr}>"; + return new MappingData(typeStr, typeName, CollectionsType.Map, refTypeStr, type2.RefTypeName); + } + + return new MappingData(typeStr, typeName, CollectionsType.Map); } - else if (str.StartsWith('[')) + else if (str.StartsWith('[')) //数组 { var tempStr = str.Substring(1, str.Length - 2); - var typeData = ConvertToType(tempStr); + var typeData = ConvertToType(tempStr, depth + 1); var typeStr = typeData.TypeStr + "[]"; var typeName = typeData.TypeName + "[]"; - return new MappingData(typeStr, typeName); + + if (typeData.IsRefExcel) //引用过其他表 + { + var refTypeStr = typeData.RefTypeStr + "[]"; + return new MappingData(typeStr, typeName, CollectionsType.Array, refTypeStr, typeData.RefTypeName); + } + + return new MappingData(typeStr, typeName, CollectionsType.Array); } throw new Exception("类型描述语法错误!"); } diff --git a/DungeonShooting_ExcelTool/excelFile/ActivityObject.xlsx b/DungeonShooting_ExcelTool/excelFile/ActivityObject.xlsx new file mode 100644 index 0000000..b5ef62e --- /dev/null +++ b/DungeonShooting_ExcelTool/excelFile/ActivityObject.xlsx Binary files differ diff --git a/DungeonShooting_ExcelTool/excelFile/Role.xlsx b/DungeonShooting_ExcelTool/excelFile/Role.xlsx deleted file mode 100644 index b062c08..0000000 --- a/DungeonShooting_ExcelTool/excelFile/Role.xlsx +++ /dev/null Binary files differ diff --git a/DungeonShooting_ExcelTool/excelFile/Test.xlsx b/DungeonShooting_ExcelTool/excelFile/Test.xlsx new file mode 100644 index 0000000..3699e31 --- /dev/null +++ b/DungeonShooting_ExcelTool/excelFile/Test.xlsx Binary files differ diff --git a/DungeonShooting_ExcelTool/excelFile/Weapon.xlsx b/DungeonShooting_ExcelTool/excelFile/Weapon.xlsx index 11248a8..bd6cc04 100644 --- a/DungeonShooting_ExcelTool/excelFile/Weapon.xlsx +++ b/DungeonShooting_ExcelTool/excelFile/Weapon.xlsx Binary files differ diff --git a/DungeonShooting_ExcelTool/serialize/test/ExcelConfig.cs b/DungeonShooting_ExcelTool/serialize/test/ExcelConfig.cs new file mode 100644 index 0000000..bdd2459 --- /dev/null +++ b/DungeonShooting_ExcelTool/serialize/test/ExcelConfig.cs @@ -0,0 +1,140 @@ +using System; +using System.Collections.Generic; +using System.Text.Json; +//using Godot; + +namespace Config; + +public static partial class ExcelConfig +{ + /// + /// ActivityObject.xlsx表数据集合, 以 List 形式存储, 数据顺序与 Excel 表相同 + /// + public static List ActivityObject_List { get; private set; } + /// + /// ActivityObject.xlsx表数据集合, 里 Map 形式存储, key 为 Id + /// + public static Dictionary ActivityObject_Map { get; private set; } + + /// + /// Test.xlsx表数据集合, 以 List 形式存储, 数据顺序与 Excel 表相同 + /// + public static List Test_List { get; private set; } + /// + /// Test.xlsx表数据集合, 里 Map 形式存储, key 为 Id + /// + public static Dictionary Test_Map { get; private set; } + + /// + /// Weapon.xlsx表数据集合, 以 List 形式存储, 数据顺序与 Excel 表相同 + /// + public static List Weapon_List { get; private set; } + /// + /// Weapon.xlsx表数据集合, 里 Map 形式存储, key 为 Id + /// + public static Dictionary Weapon_Map { get; private set; } + + + private static bool _init = false; + /// + /// 初始化所有配置表数据 + /// + public static void Init() + { + if (_init) return; + _init = true; + + _InitActivityObjectConfig(); + _InitTestConfig(); + _InitWeaponConfig(); + + _InitTestRef(); + } + private static void _InitActivityObjectConfig() + { + try + { + var text = _ReadConfigAsText("res://resource/config/ActivityObject.json"); + ActivityObject_List = JsonSerializer.Deserialize>(text); + ActivityObject_Map = new Dictionary(); + foreach (var item in ActivityObject_List) + { + ActivityObject_Map.Add(item.Id, item); + } + } + catch (Exception e) + { + //GD.PrintErr(e.ToString()); + throw new Exception("初始化表'ActivityObject'失败!"); + } + } + private static void _InitTestConfig() + { + try + { + var text = _ReadConfigAsText("res://resource/config/Test.json"); + Test_List = JsonSerializer.Deserialize>(text); + Test_Map = new Dictionary(); + foreach (var item in Test_List) + { + Test_Map.Add(item.Id, item); + } + } + catch (Exception e) + { + //GD.PrintErr(e.ToString()); + throw new Exception("初始化表'Test'失败!"); + } + } + private static void _InitWeaponConfig() + { + try + { + var text = _ReadConfigAsText("res://resource/config/Weapon.json"); + Weapon_List = JsonSerializer.Deserialize>(text); + Weapon_Map = new Dictionary(); + foreach (var item in Weapon_List) + { + Weapon_Map.Add(item.Id, item); + } + } + catch (Exception e) + { + //GD.PrintErr(e.ToString()); + throw new Exception("初始化表'Weapon'失败!"); + } + } + + private static void _InitTestRef() + { + foreach (var item in Test_List) + { + try + { + item.Weapon = Weapon_Map[item._Weapon]; + item.ActivityObject = ActivityObject_Map[item._ActivityObject]; + + item.Weapons = new Weapon[item._Weapons.Length]; + for (var i = 0; i < item._Weapons.Length; i++) + { + item.Weapons[i] = Weapon_Map[item._Weapons[i]]; + } + + item.WeaponMap = new Dictionary(); + foreach (var pair in item._WeaponMap) + { + item.WeaponMap.Add(pair.Key, Weapon_Map[pair.Value]); + } + } + catch (Exception e) + { + //GD.PrintErr(e.ToString()); + throw new Exception("初始化'Test'引用其他表数据失败, 当前行id: " + item.Id); + } + } + } + private static string _ReadConfigAsText(string path) + { + return ""; + } +} \ No newline at end of file diff --git a/DungeonShooting_ExcelTool/serialize/test/ExcelConfig_ActivityObject.cs b/DungeonShooting_ExcelTool/serialize/test/ExcelConfig_ActivityObject.cs new file mode 100644 index 0000000..12e9730 --- /dev/null +++ b/DungeonShooting_ExcelTool/serialize/test/ExcelConfig_ActivityObject.cs @@ -0,0 +1,55 @@ +using System.Text.Json.Serialization; +using System.Collections.Generic; + +namespace Config; + +public static partial class ExcelConfig +{ + public class ActivityObject + { + /// + /// 物体唯一id
+ /// 需要添加类型前缀 + ///
+ [JsonInclude] + public string Id; + + /// + /// Test(测试对象): 2
+ /// Role(角色): 3
+ /// Enemy(敌人): 4
+ /// Weapon(武器): 5
+ /// Bullet(子弹): 6
+ /// Shell(弹壳): 7
+ /// Effect(特效): 8
+ /// Other(其它类型): 9 + ///
+ [JsonInclude] + public int Type; + + /// + /// 物体预制场景路径, 场景根节点必须是ActivityObject子类 + /// + [JsonInclude] + public string Prefab; + + /// + /// 物体备注 + /// + [JsonInclude] + public string Remark; + + /// + /// 返回浅拷贝出的新对象 + /// + public ActivityObject Clone() + { + var inst = new ActivityObject(); + inst.Id = Id; + inst.Type = Type; + inst.Prefab = Prefab; + inst.Remark = Remark; + return inst; + } + } +} \ No newline at end of file diff --git a/DungeonShooting_ExcelTool/serialize/test/ExcelConfig_Test.cs b/DungeonShooting_ExcelTool/serialize/test/ExcelConfig_Test.cs new file mode 100644 index 0000000..52ccb6f --- /dev/null +++ b/DungeonShooting_ExcelTool/serialize/test/ExcelConfig_Test.cs @@ -0,0 +1,58 @@ +using System.Text.Json.Serialization; +using System.Collections.Generic; + +namespace Config; + +public static partial class ExcelConfig +{ + public class Test + { + /// + /// 唯一id + /// + [JsonInclude] + public string Id; + + /// + /// 引用的武器数据 + /// + public Weapon Weapon; + [JsonInclude] + public string _Weapon; + + /// + /// 引用的武器数据(数组) + /// + public Weapon[] Weapons; + [JsonInclude] + public string[] _Weapons; + + /// + /// 引用的武器数据(字典) + /// + public Dictionary WeaponMap; + [JsonInclude] + public Dictionary _WeaponMap; + + /// + /// 引用ActivityObject + /// + public ActivityObject ActivityObject; + [JsonInclude] + public string _ActivityObject; + + /// + /// 返回浅拷贝出的新对象 + /// + public Test Clone() + { + var inst = new Test(); + inst.Id = Id; + inst.Weapon = Weapon; + inst.Weapons = Weapons; + inst.WeaponMap = WeaponMap; + inst.ActivityObject = ActivityObject; + return inst; + } + } +} \ No newline at end of file diff --git a/DungeonShooting_ExcelTool/serialize/test/ExcelConfig_Weapon.cs b/DungeonShooting_ExcelTool/serialize/test/ExcelConfig_Weapon.cs new file mode 100644 index 0000000..a2953d8 --- /dev/null +++ b/DungeonShooting_ExcelTool/serialize/test/ExcelConfig_Weapon.cs @@ -0,0 +1,377 @@ +using System.Text.Json.Serialization; +using System.Collections.Generic; + +namespace Config; + +public static partial class ExcelConfig +{ + public class Weapon + { + /// + /// 武器属性id + /// + [JsonInclude] + public string Id; + + /// + /// 属性绑定武器的Id,如果是Ai使用的数据, 则填空字符串串 + /// + [JsonInclude] + public string WeaponId; + + /// + /// 武器显示的名称 + /// + [JsonInclude] + public string Name; + + /// + /// 武器的图标 + /// + [JsonInclude] + public string Icon; + + /// + /// 重量 + /// + [JsonInclude] + public float Weight; + + /// + /// 武器类型:
+ /// 1.副武器
+ /// 2.主武器
+ /// 3.重型武器 + ///
+ [JsonInclude] + public byte WeightType; + + /// + /// 是否连续发射, 如果为false, 则每次发射都需要扣动扳机 + /// + [JsonInclude] + public bool ContinuousShoot; + + /// + /// 弹夹容量 + /// + [JsonInclude] + public int AmmoCapacity; + + /// + /// 弹药容量上限 + /// + [JsonInclude] + public int MaxAmmoCapacity; + + /// + /// 默认起始备用弹药数量 + /// + [JsonInclude] + public int StandbyAmmoCapacity; + + /// + /// 装弹时间 (单位: 秒) + /// + [JsonInclude] + public float ReloadTime; + + /// + /// 每粒子弹是否是单独装填, 如果是, 那么每上一发子弹的时间就是 ReloadTime, 可以做霰弹武器装填效果 + /// + [JsonInclude] + public bool AloneReload; + + /// + /// 单独装填时每次装填子弹数量, 必须要将 'AloneReload' 属性设置为 true + /// + [JsonInclude] + public int AloneReloadCount; + + /// + /// 单独装填的子弹时可以立即射击, 必须要将 'AloneReload' 属性设置为 true + /// + [JsonInclude] + public bool AloneReloadCanShoot; + + /// + /// 是否为松发开火, 也就是松开扳机才开火, 若要启用该属性, 必须将 'ContinuousShoot' 设置为 false + /// + [JsonInclude] + public bool LooseShoot; + + /// + /// 最少需要蓄力多久才能开火, 必须将 'LooseShoot' 设置为 true + /// + [JsonInclude] + public float MinChargeTime; + + /// + /// 连续发射最小次数, 仅当 ContinuousShoot 为 false 时生效 + /// + [JsonInclude] + public int MinContinuousCount; + + /// + /// 连续发射最大次数, 仅当 ContinuousShoot 为 false 时生效 + /// + [JsonInclude] + public int MaxContinuousCount; + + /// + /// 按下一次扳机后需要多长时间才能再次感应按下 + /// + [JsonInclude] + public float TriggerInterval; + + /// + /// 初始射速, 初始每分钟能开火次数 + /// + [JsonInclude] + public float StartFiringSpeed; + + /// + /// 最终射速, 最终每分钟能开火次数, 仅当 ContinuousShoot 为 true 时生效 + /// + [JsonInclude] + public float FinalFiringSpeed; + + /// + /// 按下扳机并开火后射速增加速率 + /// + [JsonInclude] + public float FiringSpeedAddSpeed; + + /// + /// 松开扳机后射速消散速率 + /// + [JsonInclude] + public float FiringSpeedBackSpeed; + + /// + /// 单次开火发射子弹最小数量 + /// + [JsonInclude] + public int MinFireBulletCount; + + /// + /// 单次开火发射子弹最大数量 + /// + [JsonInclude] + public int MaxFireBulletCount; + + /// + /// 开火前延时 + /// + [JsonInclude] + public float DelayedTime; + + /// + /// 初始散射半径 + /// + [JsonInclude] + public float StartScatteringRange; + + /// + /// 最终散射半径 + /// + [JsonInclude] + public float FinalScatteringRange; + + /// + /// 每次发射后散射增加值 + /// + [JsonInclude] + public float ScatteringRangeAddValue; + + /// + /// 松开扳机后散射销退速率 + /// + [JsonInclude] + public float ScatteringRangeBackSpeed; + + /// + /// 松开扳机多久后开始销退散射值 (单位: 秒) + /// + [JsonInclude] + public float ScatteringRangeBackTime; + + /// + /// 子弹飞行最小距离 + /// + [JsonInclude] + public float MinDistance; + + /// + /// 子弹飞行最大距离 + /// + [JsonInclude] + public float MaxDistance; + + /// + /// 最小后坐力 (仅用于开火后武器身抖动) + /// + [JsonInclude] + public float MinBacklash; + + /// + /// 最大后坐力 (仅用于开火后武器身抖动) + /// + [JsonInclude] + public float MaxBacklash; + + /// + /// 后坐力偏移回归回归速度 + /// + [JsonInclude] + public float BacklashRegressionSpeed; + + /// + /// 开火后武器口上抬角度 + /// + [JsonInclude] + public float UpliftAngle; + + /// + /// 武器默认上抬角度 + /// + [JsonInclude] + public float DefaultAngle; + + /// + /// 开火后武器口角度恢复速度倍数 + /// + [JsonInclude] + public float UpliftAngleRestore; + + /// + /// 默认射出的子弹id + /// + [JsonInclude] + public string BulletId; + + /// + /// 投抛状态下物体碰撞器大小 + /// + [JsonInclude] + public SerializeVector2 ThrowCollisionSize; + + /// + /// 射击音效 + /// + [JsonInclude] + public string ShootSound; + + /// + /// 换弹音效 + /// + [JsonInclude] + public string ReloadSound; + + /// + /// 换弹音效延时时间 + /// + [JsonInclude] + public float ReloadSoundDelayTime; + + /// + /// 上膛音效 + /// + [JsonInclude] + public string EquipSound; + + /// + /// 上膛音效延时时间 + /// + [JsonInclude] + public float EquipSoundDelayTime; + + /// + /// Ai属性
+ /// Ai 使用该武器时的武器数据, 设置该字段, 可让同一把武器在敌人和玩家手上有不同属性
+ /// 如果不填则Ai和玩家使用同一种属性 + ///
+ [JsonInclude] + public string AiUseAttributeId; + + /// + /// Ai属性
+ /// 目标锁定时间, 也就是瞄准目标多久才会开火, (单位: 秒) + ///
+ [JsonInclude] + public float AiTargetLockingTime; + + /// + /// Ai属性
+ /// Ai使用该武器发射的子弹速度缩放比 + ///
+ [JsonInclude] + public float AiBulletSpeedScale; + + /// + /// Ai属性
+ /// Ai使用该武器消耗弹药的概率, (0 - 1) + ///
+ [JsonInclude] + public float AiAmmoConsumptionProbability; + + /// + /// 返回浅拷贝出的新对象 + /// + public Weapon Clone() + { + var inst = new Weapon(); + inst.Id = Id; + inst.WeaponId = WeaponId; + inst.Name = Name; + inst.Icon = Icon; + inst.Weight = Weight; + inst.WeightType = WeightType; + inst.ContinuousShoot = ContinuousShoot; + inst.AmmoCapacity = AmmoCapacity; + inst.MaxAmmoCapacity = MaxAmmoCapacity; + inst.StandbyAmmoCapacity = StandbyAmmoCapacity; + inst.ReloadTime = ReloadTime; + inst.AloneReload = AloneReload; + inst.AloneReloadCount = AloneReloadCount; + inst.AloneReloadCanShoot = AloneReloadCanShoot; + inst.LooseShoot = LooseShoot; + inst.MinChargeTime = MinChargeTime; + inst.MinContinuousCount = MinContinuousCount; + inst.MaxContinuousCount = MaxContinuousCount; + inst.TriggerInterval = TriggerInterval; + inst.StartFiringSpeed = StartFiringSpeed; + inst.FinalFiringSpeed = FinalFiringSpeed; + inst.FiringSpeedAddSpeed = FiringSpeedAddSpeed; + inst.FiringSpeedBackSpeed = FiringSpeedBackSpeed; + inst.MinFireBulletCount = MinFireBulletCount; + inst.MaxFireBulletCount = MaxFireBulletCount; + inst.DelayedTime = DelayedTime; + inst.StartScatteringRange = StartScatteringRange; + inst.FinalScatteringRange = FinalScatteringRange; + inst.ScatteringRangeAddValue = ScatteringRangeAddValue; + inst.ScatteringRangeBackSpeed = ScatteringRangeBackSpeed; + inst.ScatteringRangeBackTime = ScatteringRangeBackTime; + inst.MinDistance = MinDistance; + inst.MaxDistance = MaxDistance; + inst.MinBacklash = MinBacklash; + inst.MaxBacklash = MaxBacklash; + inst.BacklashRegressionSpeed = BacklashRegressionSpeed; + inst.UpliftAngle = UpliftAngle; + inst.DefaultAngle = DefaultAngle; + inst.UpliftAngleRestore = UpliftAngleRestore; + inst.BulletId = BulletId; + inst.ThrowCollisionSize = ThrowCollisionSize; + inst.ShootSound = ShootSound; + inst.ReloadSound = ReloadSound; + inst.ReloadSoundDelayTime = ReloadSoundDelayTime; + inst.EquipSound = EquipSound; + inst.EquipSoundDelayTime = EquipSoundDelayTime; + inst.AiUseAttributeId = AiUseAttributeId; + inst.AiTargetLockingTime = AiTargetLockingTime; + inst.AiBulletSpeedScale = AiBulletSpeedScale; + inst.AiAmmoConsumptionProbability = AiAmmoConsumptionProbability; + return inst; + } + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.dll b/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.dll index 76d2690..9f59015 100644 --- a/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.dll +++ b/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.dll Binary files differ diff --git a/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.exe b/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.exe index bb1931a..c623fc8 100644 --- a/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.exe +++ b/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.exe Binary files differ diff --git a/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.pdb b/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.pdb index 109bb56..b10e380 100644 --- a/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.pdb +++ b/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.pdb Binary files differ diff --git a/DungeonShooting_Godot/excel/excelFile/ActivityObject.xlsx b/DungeonShooting_Godot/excel/excelFile/ActivityObject.xlsx index b5ef62e..e7f3499 100644 --- a/DungeonShooting_Godot/excel/excelFile/ActivityObject.xlsx +++ b/DungeonShooting_Godot/excel/excelFile/ActivityObject.xlsx Binary files differ diff --git a/DungeonShooting_Godot/excel/excelFile/Weapon.xlsx b/DungeonShooting_Godot/excel/excelFile/Weapon.xlsx index bd6cc04..70d7bb4 100644 --- a/DungeonShooting_Godot/excel/excelFile/Weapon.xlsx +++ b/DungeonShooting_Godot/excel/excelFile/Weapon.xlsx Binary files differ diff --git a/DungeonShooting_Godot/src/config/ExcelConfig.cs b/DungeonShooting_Godot/src/config/ExcelConfig.cs index 11458d0..c3e4ed0 100644 --- a/DungeonShooting_Godot/src/config/ExcelConfig.cs +++ b/DungeonShooting_Godot/src/config/ExcelConfig.cs @@ -37,6 +37,7 @@ _InitActivityObjectConfig(); _InitWeaponConfig(); + } private static void _InitActivityObjectConfig() { @@ -74,6 +75,7 @@ throw new Exception("初始化表'Weapon'失败!"); } } + private static string _ReadConfigAsText(string path) { var file = FileAccess.Open(path, FileAccess.ModeFlags.Read);