From 8ea04f00bed4a13bcd7267bdd949992b93d1bc99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9C=A7=E9=9B=A8=E7=83=A8?= Date: Fri, 14 Jun 2024 22:38:29 +0800 Subject: [PATCH 01/15] Move RegisterFromFile to ItemTypeRegister.cs --- scripts/item/ItemTypeManager.cs | 50 ----------------- scripts/item/ItemTypeRegister.cs | 67 +++++++++++++++++++++++ scripts/loader/uiLoader/MainMenuLoader.cs | 2 +- 3 files changed, 68 insertions(+), 51 deletions(-) create mode 100644 scripts/item/ItemTypeRegister.cs diff --git a/scripts/item/ItemTypeManager.cs b/scripts/item/ItemTypeManager.cs index 5b553a6..9416d07 100644 --- a/scripts/item/ItemTypeManager.cs +++ b/scripts/item/ItemTypeManager.cs @@ -16,56 +16,6 @@ namespace ColdMint.scripts.item; /// public static class ItemTypeManager { - //Use for yaml deserialization - private record struct ItemTypeInfo(string Id, string ScenePath, string IconPath, int MaxStackValue) { } - - /// - /// Register items from yaml file - /// 从文件注册物品 - /// - public static void RegisterFromFile() - { - LogCat.Log("start_item_register_from_file"); - - // initialize yaml deserializer - var deserializer = new DeserializerBuilder() - .WithNamingConvention(UnderscoredNamingConvention.Instance) // convent snake_case - .Build(); - - // initialize file dir - string itemRegsDirPath = "res://data/itemRegs/"; - var itemRegsDir = DirAccess.Open(itemRegsDirPath); - if (DirAccess.GetOpenError() is not Error.Ok) - { - LogCat.LogError("error_when_open_item_regs_dir"); - } - - // traverse the dir, find files to register - foreach (var file in itemRegsDir.GetFiles()) - { - if (file is null) continue; - LogCat.LogWithFormat("item_register_from_file", file); - - // read file, parse to an IEnumerable of type infos - var yamlFile = FileAccess.Open($"{itemRegsDirPath}/{file}", FileAccess.ModeFlags.Read); - var yamlString = yamlFile.GetAsText(); - var typeInfos = deserializer.Deserialize>(yamlString); - yamlFile.Close(); - - // traverse type infos and register them. - foreach (var typeInfo in typeInfos) - { - LogCat.LogWithFormat("item_register_find_item_in_file", typeInfo.Id); - var scene = ResourceLoader.Load(typeInfo.ScenePath); - var icon = ResourceLoader.Load(typeInfo.IconPath); - var itemType = new ItemType(typeInfo.Id, - () => NodeUtils.InstantiatePackedScene(scene), - icon, typeInfo.MaxStackValue); - Register(itemType); - } - } - } - /// /// Register items here /// 在这里注册物品 diff --git a/scripts/item/ItemTypeRegister.cs b/scripts/item/ItemTypeRegister.cs new file mode 100644 index 0000000..933492a --- /dev/null +++ b/scripts/item/ItemTypeRegister.cs @@ -0,0 +1,67 @@ +using System.Collections.Generic; + +using ColdMint.scripts.debug; +using ColdMint.scripts.utils; + +using Godot; + +using YamlDotNet.Serialization; +using YamlDotNet.Serialization.NamingConventions; + +namespace ColdMint.scripts.item; + +/// +/// 负责从文件注册物品 +/// +public static class ItemTypeRegister +{ + /// + /// Register items from yaml file + /// 从文件注册物品 + /// + public static void RegisterFromFile() + { + LogCat.Log("start_item_register_from_file"); + + // initialize yaml deserializer + var deserializer = new DeserializerBuilder() + .WithNamingConvention(UnderscoredNamingConvention.Instance) // convent snake_case + .Build(); + + // initialize file dir + string itemRegsDirPath = "res://data/itemRegs/"; + var itemRegsDir = DirAccess.Open(itemRegsDirPath); + if (DirAccess.GetOpenError() is not Error.Ok) + { + LogCat.LogError("error_when_open_item_regs_dir"); + } + + // traverse the dir, find files to register + foreach (var file in itemRegsDir.GetFiles()) + { + if (file is null) continue; + LogCat.LogWithFormat("item_register_from_file", file); + + // read file, parse to an IEnumerable of type infos + var yamlFile = FileAccess.Open($"{itemRegsDirPath}/{file}", FileAccess.ModeFlags.Read); + var yamlString = yamlFile.GetAsText(); + var typeInfos = deserializer.Deserialize>(yamlString); + yamlFile.Close(); + + // traverse type infos and register them. + foreach (var typeInfo in typeInfos) + { + LogCat.LogWithFormat("item_register_find_item_in_file", typeInfo.Id); + var scene = ResourceLoader.Load(typeInfo.ScenePath); + var icon = ResourceLoader.Load(typeInfo.IconPath); + var itemType = new ItemType(typeInfo.Id, + () => NodeUtils.InstantiatePackedScene(scene), + icon, typeInfo.MaxStackValue); + ItemTypeManager.Register(itemType); + } + } + } + + //Use for yaml deserialization + private record struct ItemTypeInfo(string Id, string ScenePath, string IconPath, int MaxStackValue) { } +} \ No newline at end of file diff --git a/scripts/loader/uiLoader/MainMenuLoader.cs b/scripts/loader/uiLoader/MainMenuLoader.cs index 5bad091..3659e79 100644 --- a/scripts/loader/uiLoader/MainMenuLoader.cs +++ b/scripts/loader/uiLoader/MainMenuLoader.cs @@ -97,7 +97,7 @@ public partial class MainMenuLoader : UiLoaderTemplate //Register ItemTypes from file //从文件注册物品类型 - ItemTypeManager.RegisterFromFile(); + ItemTypeRegister.RegisterFromFile(); //Hardcoded ItemTypes Register //硬编码注册物品类型 ItemTypeManager.StaticRegister(); From 2661fd2735c2e2b4203783bf27d32c16eb92017e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9C=A7=E9=9B=A8=E7=83=A8?= Date: Sat, 15 Jun 2024 09:04:16 +0800 Subject: [PATCH 02/15] Fixed the bug that GetItem returns null when the PacksackStack is not empty --- scripts/item/itemStacks/PacksackStack.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/item/itemStacks/PacksackStack.cs b/scripts/item/itemStacks/PacksackStack.cs index a70a22e..0e78007 100644 --- a/scripts/item/itemStacks/PacksackStack.cs +++ b/scripts/item/itemStacks/PacksackStack.cs @@ -45,7 +45,7 @@ public class PacksackStack(Packsack packsack) : IItemStack public IItem? GetItem() { - return Empty ? packsack : null; + return Empty ? null : packsack; } public IItem? PickItem() From 437d136421053d8d01ff9c704275bcf10b2e833b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9C=A7=E9=9B=A8=E7=83=A8?= Date: Sat, 15 Jun 2024 11:27:04 +0800 Subject: [PATCH 03/15] Fixed a bug that caused some text of UI elements to be displayed incorrectly in the level editor. --- scenes/LevelGraphEditor.tscn | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/scenes/LevelGraphEditor.tscn b/scenes/LevelGraphEditor.tscn index a09ba4e..98dbcd7 100644 --- a/scenes/LevelGraphEditor.tscn +++ b/scenes/LevelGraphEditor.tscn @@ -53,7 +53,7 @@ offset_left = 10.0 offset_top = 13.0 offset_right = 97.0 offset_bottom = 38.0 -text = "create_room" +text = "ui_create_room" [node name="Label3" type="Label" parent="CreateOrEditorPanel"] layout_mode = 1 @@ -61,7 +61,7 @@ offset_left = 12.0 offset_top = 106.0 offset_right = 72.0 offset_bottom = 131.0 -text = "describe" +text = "ui_describe" [node name="Label4" type="Label" parent="CreateOrEditorPanel"] layout_mode = 1 @@ -69,7 +69,7 @@ offset_left = 15.0 offset_top = 152.0 offset_right = 75.0 offset_bottom = 177.0 -text = "room_template_collection_prompt" +text = "ui_room_template_collection_prompt" [node name="RoomTemplateTipsLabel" type="Label" parent="CreateOrEditorPanel"] layout_mode = 1 @@ -109,7 +109,7 @@ offset_top = 6.0 offset_right = -11.0 offset_bottom = 39.0 grow_horizontal = 0 -text = "close" +text = "ui_close" [node name="Label2" type="Label" parent="CreateOrEditorPanel"] layout_mode = 1 @@ -117,7 +117,7 @@ offset_left = 13.0 offset_top = 60.0 offset_right = 48.0 offset_bottom = 85.0 -text = "name" +text = "ui_name" [node name="CreateRoomButton" type="Button" parent="CreateOrEditorPanel"] layout_mode = 1 @@ -132,7 +132,7 @@ offset_right = -13.0 offset_bottom = -13.0 grow_horizontal = 0 grow_vertical = 0 -text = "creation" +text = "ui_creation" [node name="RoomTemplateCollectionTextEdit" type="TextEdit" parent="CreateOrEditorPanel"] layout_mode = 1 @@ -150,7 +150,7 @@ offset_left = 16.0 offset_top = 289.0 offset_right = 56.0 offset_bottom = 314.0 -text = "tags" +text = "ui_tags" [node name="TagLineEdit" type="LineEdit" parent="CreateOrEditorPanel"] layout_mode = 1 @@ -168,7 +168,7 @@ offset_left = 14.0 offset_top = 368.0 offset_right = 283.0 offset_bottom = 393.0 -text = "room_injection_processor" +text = "ui_room_injection_processor" [node name="RoomInjectionProcessorDataTextEdit" type="TextEdit" parent="CreateOrEditorPanel"] layout_mode = 1 From efc289b3ad58446f2e62612c41c0f8ddd63daca7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9C=A7=E9=9B=A8=E7=83=A8?= Date: Sat, 15 Jun 2024 11:34:07 +0800 Subject: [PATCH 04/15] Add dotsettings file --- .gitignore | 1 - ColdMint.Traveler.sln.DotSettings | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 ColdMint.Traveler.sln.DotSettings diff --git a/.gitignore b/.gitignore index 267c058..1ebcbdd 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,3 @@ export_presets.cfg .vs/ *.translation *.user -*.DotSettings diff --git a/ColdMint.Traveler.sln.DotSettings b/ColdMint.Traveler.sln.DotSettings new file mode 100644 index 0000000..1f777d6 --- /dev/null +++ b/ColdMint.Traveler.sln.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file From 4f2a6e8110afcec36af528f9fa14ddeebb613663 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9C=A7=E9=9B=A8=E7=83=A8?= Date: Sat, 15 Jun 2024 14:30:22 +0800 Subject: [PATCH 05/15] Split loops and extract functions --- locals/Log.csv | 4 +-- scripts/item/ItemTypeRegister.cs | 61 +++++++++++++++++++------------- 2 files changed, 39 insertions(+), 26 deletions(-) diff --git a/locals/Log.csv b/locals/Log.csv index 78c2114..96c110d 100644 --- a/locals/Log.csv +++ b/locals/Log.csv @@ -28,6 +28,6 @@ log_not_within_the_loot_spawn_range,给定的数值{0}没有在战利品{1}的 log_loot_data_quantity,有{0}个战利品数据被返回。,{0} loot data was returned.,{0}個の戦利品データが返されます。 log_start_item_register_from_file,开始从文件注册物品信息,Start registering item information from files,アイテム情報をファイルから登録開始 -log_item_register_from_file,从文件{0}中注册物品信息,Registering item information from file {0},ファイル{0}からアイテム情報を登録する -log_item_register_find_item_in_file,注册发现的物品{0},Register discovered item {0},見つかったアイテム{0}を登録 +log_found_files,找到{0}个文件,Found {0} files,{0}ファイルが見つかりました +log_found_item_types,从文件中找到{0}个物品类型,Found {0} item types in files,ファイルから{0}個のアイテム・タイプが見つかった log_error_when_open_item_regs_dir,尝试打开物品信息目录时发生错误,Error when opening itemRegs dir,アイテム情報カタログを開こうとしてエラーが発生しました。 \ No newline at end of file diff --git a/scripts/item/ItemTypeRegister.cs b/scripts/item/ItemTypeRegister.cs index 933492a..3e93c51 100644 --- a/scripts/item/ItemTypeRegister.cs +++ b/scripts/item/ItemTypeRegister.cs @@ -1,4 +1,6 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Linq; using ColdMint.scripts.debug; using ColdMint.scripts.utils; @@ -36,32 +38,43 @@ public static class ItemTypeRegister LogCat.LogError("error_when_open_item_regs_dir"); } - // traverse the dir, find files to register - foreach (var file in itemRegsDir.GetFiles()) + // find files + var files = itemRegsDir.GetFiles(); + LogCat.LogWithFormat("found_files", files.Length); + + // parse files to item type infos + IEnumerable typeInfos = + files.SelectMany(file => ParseFile(deserializer, $"{itemRegsDirPath}/{file}")).ToList(); + LogCat.LogWithFormat("found_item_types", typeInfos.Count()); + + // traverse type infos and register them. + foreach (var typeInfo in typeInfos) { - if (file is null) continue; - LogCat.LogWithFormat("item_register_from_file", file); - - // read file, parse to an IEnumerable of type infos - var yamlFile = FileAccess.Open($"{itemRegsDirPath}/{file}", FileAccess.ModeFlags.Read); - var yamlString = yamlFile.GetAsText(); - var typeInfos = deserializer.Deserialize>(yamlString); - yamlFile.Close(); - - // traverse type infos and register them. - foreach (var typeInfo in typeInfos) - { - LogCat.LogWithFormat("item_register_find_item_in_file", typeInfo.Id); - var scene = ResourceLoader.Load(typeInfo.ScenePath); - var icon = ResourceLoader.Load(typeInfo.IconPath); - var itemType = new ItemType(typeInfo.Id, - () => NodeUtils.InstantiatePackedScene(scene), - icon, typeInfo.MaxStackValue); - ItemTypeManager.Register(itemType); - } + RegisterTypeInfo(typeInfo); } } - + + private static IList ParseFile(IDeserializer deserializer, string filePath) + { + string itemRegsDirPath; + string file; + var yamlFile = FileAccess.Open(filePath, FileAccess.ModeFlags.Read); + var yamlString = yamlFile.GetAsText(); + var typeInfos = deserializer.Deserialize>(yamlString); + yamlFile.Close(); + return typeInfos; + } + + private static void RegisterTypeInfo(ItemTypeInfo typeInfo) + { + var scene = ResourceLoader.Load(typeInfo.ScenePath); + var icon = ResourceLoader.Load(typeInfo.IconPath); + var itemType = new ItemType(typeInfo.Id, + () => NodeUtils.InstantiatePackedScene(scene), + icon, typeInfo.MaxStackValue); + ItemTypeManager.Register(itemType); + } + //Use for yaml deserialization private record struct ItemTypeInfo(string Id, string ScenePath, string IconPath, int MaxStackValue) { } } \ No newline at end of file From 9a83fd1dd2674ff6b332c22b1228f5a440108b44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9C=A7=E9=9B=A8=E7=83=A8?= Date: Sat, 15 Jun 2024 17:07:02 +0800 Subject: [PATCH 06/15] =?UTF-8?q?Creates=20a=20non-generic=20overload=20fo?= =?UTF-8?q?r=20NodeUtils.InstantiatePackedScene=20and=20removes=20the?= =?UTF-8?q?=20Try-Catch=20block=20from=20the=20generic=20version=20?= =?UTF-8?q?=E4=B8=BANodeUtils.InstantiatePackedScene=E5=88=9B=E5=BB=BA?= =?UTF-8?q?=E9=9D=9E=E6=B3=9B=E5=9E=8B=E9=87=8D=E8=BD=BD=EF=BC=8C=E5=B9=B6?= =?UTF-8?q?=E7=A7=BB=E9=99=A4=E6=B3=9B=E5=9E=8B=E7=89=88=E6=9C=AC=E4=B8=AD?= =?UTF-8?q?=E7=9A=84Try-Catch=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- locals/Log.csv | 2 + scripts/utils/NodeUtils.cs | 92 ++++++++++++++++++++++++++------------ 2 files changed, 65 insertions(+), 29 deletions(-) diff --git a/locals/Log.csv b/locals/Log.csv index 96c110d..76bc83f 100644 --- a/locals/Log.csv +++ b/locals/Log.csv @@ -27,6 +27,8 @@ log_loot_list_has_no_entries,ID为{0}的战利品表,没有指定条目。,"Lo log_not_within_the_loot_spawn_range,给定的数值{0}没有在战利品{1}的生成范围{2}内。,The given value {0} is not within the spawn range {2} of loot {1}.,与えられた数値{0}は戦利品{1}の生成範囲{2}内にありません。 log_loot_data_quantity,有{0}个战利品数据被返回。,{0} loot data was returned.,{0}個の戦利品データが返されます。 +log_warning_node_cannot_cast_to,创建的物品{0}无法被转型为类型{1},Created items {0} cannot be cast into type {1},作成されたアイテム {0} をタイプ {1} にキャストすることはできません。 + log_start_item_register_from_file,开始从文件注册物品信息,Start registering item information from files,アイテム情報をファイルから登録開始 log_found_files,找到{0}个文件,Found {0} files,{0}ファイルが見つかりました log_found_item_types,从文件中找到{0}个物品类型,Found {0} item types in files,ファイルから{0}個のアイテム・タイプが見つかった diff --git a/scripts/utils/NodeUtils.cs b/scripts/utils/NodeUtils.cs index 5ec5d65..270937d 100644 --- a/scripts/utils/NodeUtils.cs +++ b/scripts/utils/NodeUtils.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; + using ColdMint.scripts.debug; using ColdMint.scripts.item; using ColdMint.scripts.item.weapon; + using Godot; @@ -69,7 +71,7 @@ public static class NodeUtils /// /// public static Node2D? GetTheNearestNode(Node2D origin, Node[] array, HashSet? exclude = null, - bool excludeInvisibleNodes = true) + bool excludeInvisibleNodes = true) { var closestDistance = float.MaxValue; Node2D? closestNode = null; @@ -125,10 +127,11 @@ public static class NodeUtils return GameSceneNodeHolder.WeaponContainer; } - if (GameSceneNodeHolder.PacksackContainer!= null && childNode is Packsack) + if (GameSceneNodeHolder.PacksackContainer != null && childNode is Packsack) { return GameSceneNodeHolder.PacksackContainer; } + return defaultParentNode; } @@ -153,37 +156,68 @@ public static class NodeUtils /// 默认父节点,如果传入null,则不会将实例化后的节点放入父节点内。您需要手动放置,这对于延迟设置父节点相当有用。 /// /// - public static T? InstantiatePackedScene(PackedScene packedScene, Node? defaultParentNode = null, - bool assignedByRootNodeType = true) where T : Node + /// + public static Node InstantiatePackedScene(PackedScene packedScene, Node? defaultParentNode = null, + bool assignedByRootNodeType = true) { - try + var instantiateNode = packedScene.Instantiate(); + //An attempt is made to place an instantiated node under a parent node only after the default parent node is set. + //只有设定了默认父节点后才会尝试将实例化的节点放置到父节点下。 + if (defaultParentNode != null) { - var instantiateNode = packedScene.Instantiate(); - //An attempt is made to place an instantiated node under a husband node only after the default parent node is set. - //只有设定了默认父节点后才会尝试将实例化的节点放置到夫节点下。 - if (defaultParentNode != null) + if (assignedByRootNodeType) { - if (assignedByRootNodeType) - { - var containerNode = FindContainerNode(instantiateNode, defaultParentNode); - containerNode.AddChild(instantiateNode); - } - else - { - //If you do not need to assign by type, place it under the default parent node. - //如果不需要按照类型分配,那么将其放到默认父节点下。 - defaultParentNode.AddChild(instantiateNode); - } + var containerNode = FindContainerNode(instantiateNode, defaultParentNode); + containerNode.AddChild(instantiateNode); } + else + { + //If you do not need to assign by type, place it under the default parent node. + //如果不需要按照类型分配,那么将其放到默认父节点下。 + defaultParentNode.AddChild(instantiateNode); + } + } - return instantiateNode; - } - catch (InvalidCastException e) - { - //null is returned if the type conversion fails. - //在类型转换失败时,返回null。 - LogCat.WhenCaughtException(e); - return null; - } + return instantiateNode; + } + + /// + /// + /// Generic version of that transforms the created node to type, + /// if the created node can't be transformed to the specified type, return null and release it. + /// + /// 的泛型版本,转换创建的节点至类型,如果创建的节点无法转型至指定的类型,返回null并释放它 + /// + /// + ///This method is recommended in place of all packedScene.Instantiate<T>() calls within a project, using it to instantiate a scene, optionally assigned to a container that matches the type of the root node. + ///推荐使用此方法代替项目内所有的packedScene.Instantiate<T>()调用,使用此方法实例化场景,可选择将其分配到与根节点类型相匹配的容器内。 + /// + /// + ///packedScene + ///打包的场景 + /// + /// + ///Enabled by default, whether to place a node into a container node that matches the type of the root node after it is instantiated. If the assignment fails by type, it is placed under the default parent node. + ///默认启用,实例化节点后,是否将其放置到与根节点类型相匹配的容器节点内。如果按照类型分配失败,则放置在默认父节点下。 + /// + /// + /// Default parent. If null is passed, the instantiated node is not put into the parent. You need to place it manually, which is quite useful for delaying setting the parent node. + /// 默认父节点,如果传入null,则不会将实例化后的节点放入父节点内。您需要手动放置,这对于延迟设置父节点相当有用。 + /// + /// + /// If new node cannot cast to given type, return null + /// 如果创建的节点无法转型至指定的类型,返回null + /// + public static T? InstantiatePackedScene(PackedScene packedScene, Node? defaultParentNode = null, + bool assignedByRootNodeType = true) + where T : class + { + var node = InstantiatePackedScene(packedScene, defaultParentNode, assignedByRootNodeType); + // 检查类型转化,成功返回结果 + if (node is T result) return result; + //如果转型失败,释放所创建的节点 + LogCat.LogWarningWithFormat("warning_node_cannot_cast_to",node,nameof(T)); + node.QueueFree(); + return null; } } \ No newline at end of file From 197930f4466592e4985c7d30bda154bc5907725e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9C=A7=E9=9B=A8=E7=83=A8?= Date: Sat, 15 Jun 2024 17:07:50 +0800 Subject: [PATCH 07/15] =?UTF-8?q?Support=20for=20optional=20custom=20param?= =?UTF-8?q?eters=20for=20registering=20item=20information=20from=20yaml=20?= =?UTF-8?q?=E4=B8=BA=E4=BB=8Eyaml=E6=B3=A8=E5=86=8C=E7=89=A9=E5=93=81?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E6=8F=90=E4=BE=9B=E4=BA=86=E5=8F=AF=E9=80=89?= =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E5=8F=82=E6=95=B0=E7=9A=84=E6=94=AF?= =?UTF-8?q?=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- locals/Log.csv | 3 +- scripts/item/ICommonItem.cs | 4 +- scripts/item/ItemTypeRegister.cs | 71 ++++++++++++++++++++-- scripts/item/itemStacks/CommonItemStack.cs | 4 +- 4 files changed, 73 insertions(+), 9 deletions(-) diff --git a/locals/Log.csv b/locals/Log.csv index 76bc83f..63ca9e8 100644 --- a/locals/Log.csv +++ b/locals/Log.csv @@ -32,4 +32,5 @@ log_warning_node_cannot_cast_to,创建的物品{0}无法被转型为类型{1},Cr log_start_item_register_from_file,开始从文件注册物品信息,Start registering item information from files,アイテム情報をファイルから登録開始 log_found_files,找到{0}个文件,Found {0} files,{0}ファイルが見つかりました log_found_item_types,从文件中找到{0}个物品类型,Found {0} item types in files,ファイルから{0}個のアイテム・タイプが見つかった -log_error_when_open_item_regs_dir,尝试打开物品信息目录时发生错误,Error when opening itemRegs dir,アイテム情報カタログを開こうとしてエラーが発生しました。 \ No newline at end of file +log_error_when_open_item_regs_dir,尝试打开物品信息目录时发生错误,Error when opening itemRegs dir,アイテム情報カタログを開こうとしてエラーが発生しました。 +log_wrong_custom_arg,不匹配的参数:类型为{0}而值为{1},Mismatched parameter: type {0} and value {1},パラメータの不一致:型{0}と値{1}。 \ No newline at end of file diff --git a/scripts/item/ICommonItem.cs b/scripts/item/ICommonItem.cs index b223a92..a41a60e 100644 --- a/scripts/item/ICommonItem.cs +++ b/scripts/item/ICommonItem.cs @@ -16,9 +16,9 @@ namespace ColdMint.scripts.item; public interface ICommonItem : IItem { /// - /// Method to copy an instance same with self. Will be used to pick out item instance from a + /// Method to clone an instance same with self. Will be used to pick out item instance from a /// 复制与自身相同的实例的方法。将用于从 中拿取新的物品实例。 /// /// - ICommonItem CopyInstance(); + ICommonItem CloneInstance(); } \ No newline at end of file diff --git a/scripts/item/ItemTypeRegister.cs b/scripts/item/ItemTypeRegister.cs index 3e93c51..9b22422 100644 --- a/scripts/item/ItemTypeRegister.cs +++ b/scripts/item/ItemTypeRegister.cs @@ -56,25 +56,88 @@ public static class ItemTypeRegister private static IList ParseFile(IDeserializer deserializer, string filePath) { - string itemRegsDirPath; - string file; var yamlFile = FileAccess.Open(filePath, FileAccess.ModeFlags.Read); + //Read & deserialize var yamlString = yamlFile.GetAsText(); var typeInfos = deserializer.Deserialize>(yamlString); + yamlFile.Close(); return typeInfos; } private static void RegisterTypeInfo(ItemTypeInfo typeInfo) { + //Load scene and icon var scene = ResourceLoader.Load(typeInfo.ScenePath); var icon = ResourceLoader.Load(typeInfo.IconPath); + + //Create init delegate + Func newItemFunc; + if (typeInfo.CustomArgs is null or []) + { + newItemFunc = () => NodeUtils.InstantiatePackedScene(scene); + } + else + { + Action? setArgs = null; + foreach (var arg in typeInfo.CustomArgs) + { + setArgs += + node => node?.SetDeferred(arg.Name, arg.ParseValue()); + } + + newItemFunc = () => + { + var newItem = NodeUtils.InstantiatePackedScene(scene); + setArgs?.Invoke(newItem as Node); + return newItem; + }; + } + + //construct item type, register var itemType = new ItemType(typeInfo.Id, - () => NodeUtils.InstantiatePackedScene(scene), + newItemFunc, icon, typeInfo.MaxStackValue); ItemTypeManager.Register(itemType); } //Use for yaml deserialization - private record struct ItemTypeInfo(string Id, string ScenePath, string IconPath, int MaxStackValue) { } + private record struct ItemTypeInfo( + string Id, string ScenePath, string IconPath, int MaxStackValue, + IList? CustomArgs) { } + + private readonly record struct CustomArg(string Name, CustomArgType Type, string Value) + { + public Variant ParseValue() => + Type switch + { + CustomArgType.String => Value, + CustomArgType.Int => int.Parse(Value), + CustomArgType.Float => double.Parse(Value), + CustomArgType.Vector2 => ParseVector2FromString(Value), + CustomArgType.Texture => ResourceLoader.Load("res://sprites/" + Value), + _ => throw new ArgumentOutOfRangeException($"Unknown Arg Type {Type}") + }; + + private Vector2 ParseVector2FromString(string s) + { + var ss = s.Split(','); + if (ss.Length != 2) + { + LogCat.LogErrorWithFormat("wrong_custom_arg", "Vector2", s); + return Vector2.Zero; + } + + return new Vector2(float.Parse(ss[0]), float.Parse(ss[1])); + } + } + + private enum CustomArgType + { + String, + Int, + Float, + Vector2, + Texture, + } } \ No newline at end of file diff --git a/scripts/item/itemStacks/CommonItemStack.cs b/scripts/item/itemStacks/CommonItemStack.cs index 1887718..0018e04 100644 --- a/scripts/item/itemStacks/CommonItemStack.cs +++ b/scripts/item/itemStacks/CommonItemStack.cs @@ -67,7 +67,7 @@ public class CommonItemStack(ICommonItem innerItem) : IItemStack { if(Empty) return null; Quantity--; - var result = innerItem.CopyInstance(); + var result = innerItem.CloneInstance(); if(Empty) innerItem.Destroy(); return result; } @@ -75,7 +75,7 @@ public class CommonItemStack(ICommonItem innerItem) : IItemStack public IItemStack? PickItems(int value) { if (Empty) return null; - var result = new CommonItemStack(innerItem.CopyInstance()); + var result = new CommonItemStack(innerItem.CloneInstance()); var n = Math.Min(Quantity, value); if (n < 0) { From edaa490b5beb828084a2656a28f87d40269757b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9C=A7=E9=9B=A8=E7=83=A8?= Date: Sat, 15 Jun 2024 17:16:41 +0800 Subject: [PATCH 08/15] =?UTF-8?q?Updated=20WeaponTemplate's=20FiringInterv?= =?UTF-8?q?al=20calculation=20so=20that=20it=20can=20be=20changed=20by=20F?= =?UTF-8?q?iringIntervalAsMillisecond=20even=20after=20instantiation.=20?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E4=BA=86WeaponTemplate=E7=9A=84FiringInterva?= =?UTF-8?q?l=E8=AE=A1=E7=AE=97=E6=96=B9=E5=BC=8F=E4=BB=A5=E4=BD=BF?= =?UTF-8?q?=E8=AF=A5=E5=80=BC=E5=8D=B3=E4=BE=BF=E5=9C=A8=E5=AE=9E=E4=BE=8B?= =?UTF-8?q?=E5=8C=96=E4=B9=8B=E5=90=8E=E4=B9=9F=E5=8F=AF=E9=80=9A=E8=BF=87?= =?UTF-8?q?FiringIntervalAsMillisecond=E6=9B=B4=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prefab/weapons/staffOfTheUndead.tscn | 1 + scripts/item/weapon/WeaponTemplate.cs | 14 +++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/prefab/weapons/staffOfTheUndead.tscn b/prefab/weapons/staffOfTheUndead.tscn index d4732bf..ca0c9c0 100644 --- a/prefab/weapons/staffOfTheUndead.tscn +++ b/prefab/weapons/staffOfTheUndead.tscn @@ -16,6 +16,7 @@ collision_mask = 34 script = ExtResource("1_w8hhv") ProjectileScenes = [ExtResource("2_34250")] Id = "staff_of_the_undead" +FiringIntervalAsMillisecond = 300 metadata/Projectiles = PackedStringArray("res://prefab/projectile/curseOfTheUndead.tscn") [node name="DamageArea2D" type="Area2D" parent="."] diff --git a/scripts/item/weapon/WeaponTemplate.cs b/scripts/item/weapon/WeaponTemplate.cs index e05fc82..c7e600a 100644 --- a/scripts/item/weapon/WeaponTemplate.cs +++ b/scripts/item/weapon/WeaponTemplate.cs @@ -3,6 +3,7 @@ using System; using ColdMint.scripts.camp; using ColdMint.scripts.character; using ColdMint.scripts.damage; + using Godot; namespace ColdMint.scripts.item.weapon; @@ -70,7 +71,16 @@ public abstract partial class WeaponTemplate : RigidBody2D, IItem /// 开火间隔 /// private TimeSpan _firingInterval; - [Export] private long _firingIntervalAsMillisecond = 100; + private long _firingIntervalAsMillisecond = 100; + [Export] protected long FiringIntervalAsMillisecond + { + get => _firingIntervalAsMillisecond; + set + { + _firingIntervalAsMillisecond = value; + _firingInterval = TimeSpan.FromMilliseconds(_firingIntervalAsMillisecond); + } + } /// @@ -101,8 +111,6 @@ public abstract partial class WeaponTemplate : RigidBody2D, IItem _damageArea2D = GetNode("DamageArea2D"); _damageArea2D.BodyEntered += OnBodyEnter; _damageArea2D.BodyExited += OnBodyExited; - - _firingInterval = TimeSpan.FromMilliseconds(_firingIntervalAsMillisecond); } private void OnBodyExited(Node node) From abf03c00a12223cb8dacc1e34850dc37643a3ecb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9C=A7=E9=9B=A8=E7=83=A8?= Date: Sun, 16 Jun 2024 16:56:45 +0800 Subject: [PATCH 09/15] =?UTF-8?q?Preliminary=20rewrite=20of=20the=20loot?= =?UTF-8?q?=20system=20=E5=88=9D=E6=AD=A5=E9=87=8D=E5=86=99=E6=8E=89?= =?UTF-8?q?=E8=90=BD=E7=B3=BB=E7=BB=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- data/itemRegs/weapons.yaml | 6 +- locals/Log.csv | 2 + prefab/entitys/DelivererOfDarkMagic.tscn | 2 +- scripts/Config.cs | 2 +- scripts/character/CharacterTemplate.cs | 50 +++------ scripts/inventory/LootData.cs | 9 -- scripts/inventory/LootEntry.cs | 32 ------ scripts/inventory/LootList.cs | 93 ----------------- scripts/inventory/LootListManager.cs | 117 ---------------------- scripts/item/ItemTypeManager.cs | 67 +++++++++++-- scripts/item/ItemTypeRegister.cs | 6 ++ scripts/loader/uiLoader/MainMenuLoader.cs | 34 ++----- scripts/loot/LootDatum.cs | 8 ++ scripts/loot/LootEntry.cs | 68 +++++++++++++ scripts/loot/LootList.cs | 53 ++++++++++ scripts/loot/LootListManager.cs | 51 ++++++++++ scripts/loot/LootRegister.cs | 30 ++++++ scripts/utils/RandomUtils.cs | 8 ++ 18 files changed, 312 insertions(+), 326 deletions(-) delete mode 100644 scripts/inventory/LootData.cs delete mode 100644 scripts/inventory/LootEntry.cs delete mode 100644 scripts/inventory/LootList.cs delete mode 100644 scripts/inventory/LootListManager.cs create mode 100644 scripts/loot/LootDatum.cs create mode 100644 scripts/loot/LootEntry.cs create mode 100644 scripts/loot/LootList.cs create mode 100644 scripts/loot/LootListManager.cs create mode 100644 scripts/loot/LootRegister.cs create mode 100644 scripts/utils/RandomUtils.cs diff --git a/data/itemRegs/weapons.yaml b/data/itemRegs/weapons.yaml index 171c341..0d8abb7 100644 --- a/data/itemRegs/weapons.yaml +++ b/data/itemRegs/weapons.yaml @@ -1,4 +1,8 @@ - id: staff_of_the_undead scene_path: res://prefab/weapons/staffOfTheUndead.tscn icon_path: res://sprites/weapon/staffOfTheUndead.png - max_stack_value: 1 \ No newline at end of file + max_stack_value: 1 + custom_args: + - name: FiringIntervalAsMillisecond + type: int + value: 1000 diff --git a/locals/Log.csv b/locals/Log.csv index 63ca9e8..4a39692 100644 --- a/locals/Log.csv +++ b/locals/Log.csv @@ -23,9 +23,11 @@ log_player_packed_scene_not_exist,玩家预制场景不存在。,Player packed s log_exit_the_room_debug,节点{0}退出房间{1}。,"Node {0} exits room {1}.",ノード{0}が部屋{1}を退出します。 log_enter_the_room_debug,节点{0}进入房间{1}。,"Node {0} enters room {1}.",ノード{0}が部屋{1}に入ります。 log_death_info,生物{0}被{1}击败。,"Creature {0} was defeated by {1}.",生物{0}が{1}によって打ち負かされました。 + log_loot_list_has_no_entries,ID为{0}的战利品表,没有指定条目。,"Loot list with ID {0}, no entry specified.",ID{0}の戦利品テーブルは、エントリ指定されていません。 log_not_within_the_loot_spawn_range,给定的数值{0}没有在战利品{1}的生成范围{2}内。,The given value {0} is not within the spawn range {2} of loot {1}.,与えられた数値{0}は戦利品{1}の生成範囲{2}内にありません。 log_loot_data_quantity,有{0}个战利品数据被返回。,{0} loot data was returned.,{0}個の戦利品データが返されます。 +log_loot_data_add,生成战利品{0},Add loot {0},戦利品{0}を生成する log_warning_node_cannot_cast_to,创建的物品{0}无法被转型为类型{1},Created items {0} cannot be cast into type {1},作成されたアイテム {0} をタイプ {1} にキャストすることはできません。 diff --git a/prefab/entitys/DelivererOfDarkMagic.tscn b/prefab/entitys/DelivererOfDarkMagic.tscn index f665553..a7535a0 100644 --- a/prefab/entitys/DelivererOfDarkMagic.tscn +++ b/prefab/entitys/DelivererOfDarkMagic.tscn @@ -31,10 +31,10 @@ radius = 129.027 collision_layer = 64 collision_mask = 38 script = ExtResource("1_ubaid") +LootListId = "test" metadata/CampId = "Mazoku" metadata/MaxHp = 50 metadata/Name = "死灵法师" -metadata/LootListId = "Test" [node name="CollisionShape2D" type="CollisionShape2D" parent="."] position = Vector2(0, 4) diff --git a/scripts/Config.cs b/scripts/Config.cs index 5263cc5..119f521 100644 --- a/scripts/Config.cs +++ b/scripts/Config.cs @@ -31,7 +31,7 @@ public static class Config /// A trophy table for testing /// 测试用的战利品表 /// - public const string Test = "Test"; + public const string Test = "test"; } /// diff --git a/scripts/character/CharacterTemplate.cs b/scripts/character/CharacterTemplate.cs index dac5540..a5eec70 100644 --- a/scripts/character/CharacterTemplate.cs +++ b/scripts/character/CharacterTemplate.cs @@ -10,6 +10,7 @@ using ColdMint.scripts.inventory; using ColdMint.scripts.item; using ColdMint.scripts.utils; using ColdMint.scripts.item.weapon; +using ColdMint.scripts.loot; using Godot; @@ -107,11 +108,7 @@ public partial class CharacterTemplate : CharacterBody2D private DamageNumberNodeSpawn? _damageNumber; - /// - /// Character referenced loot table - /// 角色引用的战利品表 - /// - private LootList? _lootList; + [Export] public string LootListId { get; private set; } = ""; private HealthBar? _healthBar; private DateTime _lastDamageTime; @@ -208,12 +205,6 @@ public partial class CharacterTemplate : CharacterBody2D CampId = GetMeta("CampId", Config.CampId.Default).AsString(); MaxHp = GetMeta("MaxHp", Config.DefaultMaxHp).AsInt32(); var lootListId = GetMeta("LootListId", string.Empty).AsString(); - if (!string.IsNullOrEmpty(lootListId)) - { - //If a loot table is specified, get the loot table. - //如果指定了战利品表,那么获取战利品表。 - _lootList = LootListManager.GetLootList(lootListId); - } if (MaxHp <= 0) { @@ -461,20 +452,11 @@ public partial class CharacterTemplate : CharacterBody2D /// protected void CreateLootObject() { - if (_lootList == null) - { - return; - } - - var lootDataArray = _lootList.GenerateLootData(); - if (lootDataArray.Length == 0) - { - return; - } - - + var lootData = LootListManager.GenerateLootData(LootListId); var finalGlobalPosition = GlobalPosition; - CallDeferred("GenerateLootObjects", this, lootDataArray, finalGlobalPosition); + //Todo : change name str to nameof(), like this + // CallDeferred(nameof(GenerateLootObjects), this, lootData, finalGlobalPosition); + GenerateLootObjects(GetParent(), lootData, finalGlobalPosition); } /// @@ -482,13 +464,17 @@ public partial class CharacterTemplate : CharacterBody2D /// 生成战利品对象 /// /// - /// + /// /// public void GenerateLootObjects(Node parentNode, - LootData[] lootDataArray, + IEnumerable lootData, Vector2 position) { - LootListManager.GenerateLootObjects(parentNode, lootDataArray, position); + foreach (var lootDatum in lootData) + { + var (id, amount) = lootDatum.Value; + ItemTypeManager.CreateItems(id, amount, parentNode, position); + } } /// @@ -601,14 +587,8 @@ public partial class CharacterTemplate : CharacterBody2D //Generates a random number that controls the horizontal velocity of thrown items (range: 0.01 to 1) //生成一个随机数,用于控制抛出物品的水平方向速度(范围为:0.01到1) var percent = GD.Randf() + 0.01f; - if (GD.Randf() > 0.5) - { - ThrowItem(i, -1, new Vector2(horizontalDirection * percent, height)); - } - else - { - ThrowItem(i, -1, new Vector2(-horizontalDirection * percent, height)); - } + var horizontalVelocity = horizontalDirection * percent * GD.Randf() > 0.5 ? 1f : -1f; + ThrowItem(i, -1, new Vector2(horizontalVelocity, height)); } } diff --git a/scripts/inventory/LootData.cs b/scripts/inventory/LootData.cs deleted file mode 100644 index 0a6d863..0000000 --- a/scripts/inventory/LootData.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Godot; - -namespace ColdMint.scripts.inventory; - -public partial class LootData : GodotObject -{ - public string? ResPath { get; set; } - public int Quantity { get; set; } -} \ No newline at end of file diff --git a/scripts/inventory/LootEntry.cs b/scripts/inventory/LootEntry.cs deleted file mode 100644 index 0c4b2fa..0000000 --- a/scripts/inventory/LootEntry.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace ColdMint.scripts.inventory; - -/// -/// Loot entry -/// 战利品条目 -/// -public class LootEntry -{ - /// - /// generation probability - /// 生成概率 - /// - public double? Chance { get; set; } - - /// - /// Minimum number of generated - /// 最小生成多少个 - /// - public int MinQuantity { get; set; } - - /// - /// The maximum number of files to be generated - /// 最多生成多少个 - /// - public int MaxQuantity { get; set; } - - /// - /// resources path - /// 资源路径 - /// - public string? ResPath { get; set; } -} \ No newline at end of file diff --git a/scripts/inventory/LootList.cs b/scripts/inventory/LootList.cs deleted file mode 100644 index fe4a924..0000000 --- a/scripts/inventory/LootList.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System.Collections.Generic; -using ColdMint.scripts.debug; -using Godot; - -namespace ColdMint.scripts.inventory; - -/// -/// Loot list -/// 战利品表 -/// -public class LootList -{ - /// - /// Id - /// 战利品表的Id - /// - public string? Id { get; set; } - - private List? _lootEntrieList; - - /// - /// Add loot entry - /// 添加战利品条目 - /// - /// - public void AddLootEntry(LootEntry lootEntry) - { - if (_lootEntrieList == null) - { - _lootEntrieList = new List(); - } - - _lootEntrieList.Add(lootEntry); - } - - - /// - /// GenerateLootData - /// 生成战利品数据 - /// - /// - public LootData[] GenerateLootData() - { - var lootDataList = new List(); - if (_lootEntrieList == null) - { - LogCat.LogWithFormat("loot_list_has_no_entries", Id); - return lootDataList.ToArray(); - } - - foreach (var lootEntry in _lootEntrieList) - { - var chance = GD.Randf(); - if (chance > lootEntry.Chance) - { - //If the random number is greater than the generation probability, skip the current loop. - //如果随机数大于生成概率,则跳过当前循环。 - LogCat.LogWithFormat("not_within_the_loot_spawn_range", chance, lootEntry.ResPath, lootEntry.Chance); - continue; - } - - //We generate a loot data for each loot entry. - //我们为每个战利品条目生成一个战利品数据。 - var quantity = GD.RandRange(lootEntry.MinQuantity, lootEntry.MaxQuantity); - var lootData = new LootData - { - ResPath = lootEntry.ResPath, - Quantity = quantity - }; - lootDataList.Add(lootData); - } - - LogCat.LogWithFormat("loot_data_quantity", lootDataList.Count); - return lootDataList.ToArray(); - } - - - /// - /// Remove loot entry - /// 移除战利品条目 - /// - /// - /// - public bool RemoveLootEntry(LootEntry lootEntry) - { - if (_lootEntrieList == null) - { - return false; - } - - return _lootEntrieList.Remove(lootEntry); - } -} \ No newline at end of file diff --git a/scripts/inventory/LootListManager.cs b/scripts/inventory/LootListManager.cs deleted file mode 100644 index 0b60dcf..0000000 --- a/scripts/inventory/LootListManager.cs +++ /dev/null @@ -1,117 +0,0 @@ -using System.Collections.Generic; -using ColdMint.scripts.utils; -using Godot; - -namespace ColdMint.scripts.inventory; - -/// -/// LootListManager -/// 战利品表管理器 -/// -public static class LootListManager -{ - private static Dictionary? _lootListDictionary; - - - /// - /// Register loot table - /// 注册战利品表 - /// - /// - public static bool RegisterLootList(LootList lootList) - { - var id = lootList.Id; - if (id == null) - { - return false; - } - - if (_lootListDictionary != null) return _lootListDictionary.TryAdd(id, lootList); - _lootListDictionary = new Dictionary { { id, lootList } }; - return true; - } - - /// - /// Get Loot List - /// 获取战利品表 - /// - /// - /// - public static LootList? GetLootList(string id) - { - return _lootListDictionary?.GetValueOrDefault(id); - } - - /// - /// Generate loot objects - /// 生成战利品对象 - /// - public static void GenerateLootObjects(Node parentNode, LootData[] lootDataArray, Vector2 position) - { - if (lootDataArray.Length == 0) - { - return; - } - - //Cache the loaded PackedScene object. - //缓存已加载的PackedScene对象。 - Dictionary packedSceneDictionary = new(); - foreach (var lootData in lootDataArray) - { - if (string.IsNullOrEmpty(lootData.ResPath) || lootData.Quantity == 0) - { - continue; - } - - if (!packedSceneDictionary.TryGetValue(lootData.ResPath, out var packedScene)) - { - packedScene = GD.Load(lootData.ResPath); - packedSceneDictionary.TryAdd(lootData.ResPath, packedScene); - } - - for (var i = 0; i < lootData.Quantity; i++) - { - //Generate as many loot instance objects as there are loot. - //有多少个战利品就生成多少个战利品实例对象。 - CreateLootInstanceObject(parentNode, packedScene, position); - } - } - } - - - /// - /// Create a loot instance object - /// 创建战利品实例对象 - /// - private static void CreateLootInstanceObject(Node parent, PackedScene? packedScene, Vector2 position) - { - if (packedScene == null) - { - return; - } - - var lootObject = NodeUtils.InstantiatePackedScene(packedScene, parent); - if (lootObject == null) - { - return; - } - - lootObject.Position = position; - } - - /// - /// Remove loot list - /// 移除战利品表 - /// - /// - /// - public static bool UnregisterLootList(string id) - { - if (_lootListDictionary == null) - { - return false; - } - - return _lootListDictionary.Remove(id); - } -} \ No newline at end of file diff --git a/scripts/item/ItemTypeManager.cs b/scripts/item/ItemTypeManager.cs index 9416d07..cf7261d 100644 --- a/scripts/item/ItemTypeManager.cs +++ b/scripts/item/ItemTypeManager.cs @@ -1,13 +1,9 @@ using System.Collections.Generic; -using ColdMint.scripts.debug; using ColdMint.scripts.utils; using Godot; -using YamlDotNet.Serialization; -using YamlDotNet.Serialization.NamingConventions; - namespace ColdMint.scripts.item; /// @@ -16,12 +12,6 @@ namespace ColdMint.scripts.item; /// public static class ItemTypeManager { - /// - /// Register items here - /// 在这里注册物品 - /// - public static void StaticRegister() { } - private static Dictionary Registry { get; } = []; private static Texture2D DefaultTexture { get; } = new PlaceholderTexture2D(); @@ -45,9 +35,66 @@ public static class ItemTypeManager /// Returns null when the id is not registered. /// 当物品id没有注册时返回null /// + /// public static IItem? NewItem(string id) => Registry.TryGetValue(id, out var itemType) ? itemType.NewItemFunc() : null; + /// + /// Creates new instances in given amount of the item registered to the given id. + /// 创建给定数量的注册到给定 id 的物品的新实例。 + /// + /// + /// + public static IList NewItems(string id, int amount) + { + IList result = []; + for (int i = 0; i < amount; i++) + { + if (NewItem(id) is { } item) result.Add(item); + } + + return result; + } + + /// + /// Creates new instance of the item registered to the given id, and put it into given position in both node tree and 2D space + /// 创建以给定 id 注册的物品的新实例,并将其放到节点树和二维空间中的给定位置 + /// + /// + /// + /// + /// Position in global coordinate + /// 全局坐标中的位置 + /// + /// + public static void CreateItem(string id, Node? parent = null, Vector2? position = null) + { + var item = NewItem(id); + parent?.AddChild(item as Node); + if (item is not Node2D node) return; + if (position is { } pos) node.GlobalPosition = pos; + } + + /// + /// Creates new instances in given amount of the item registered to the given id, and put them into given position in both node tree and 2D space + /// 创建以给定 id 注册的物品的给定数量的新实例,并将其放到节点树和二维空间中的给定位置 + /// + /// + /// + /// + /// + /// Position in global coordinate + /// 全局坐标中的位置 + /// + /// + public static void CreateItems(string id, int amount, Node? parent = null, Vector2? position = null) + { + for (int i = 0; i < amount; i++) + { + CreateItem(id, parent, position); + } + } + /// /// Get the translated default name of the item type for the given id /// 获取指定物品id翻译后的物品名 diff --git a/scripts/item/ItemTypeRegister.cs b/scripts/item/ItemTypeRegister.cs index 9b22422..00b20f2 100644 --- a/scripts/item/ItemTypeRegister.cs +++ b/scripts/item/ItemTypeRegister.cs @@ -17,6 +17,12 @@ namespace ColdMint.scripts.item; /// public static class ItemTypeRegister { + /// + /// Register items here + /// 在这里注册物品 + /// + public static void StaticRegister() { } + /// /// Register items from yaml file /// 从文件注册物品 diff --git a/scripts/loader/uiLoader/MainMenuLoader.cs b/scripts/loader/uiLoader/MainMenuLoader.cs index 3659e79..4e7676c 100644 --- a/scripts/loader/uiLoader/MainMenuLoader.cs +++ b/scripts/loader/uiLoader/MainMenuLoader.cs @@ -7,6 +7,7 @@ using ColdMint.scripts.deathInfo; using ColdMint.scripts.debug; using ColdMint.scripts.inventory; using ColdMint.scripts.item; +using ColdMint.scripts.loot; using ColdMint.scripts.map; using ColdMint.scripts.map.roomInjectionProcessor; @@ -43,31 +44,6 @@ public partial class MainMenuLoader : UiLoaderTemplate LogCat.MinLogLevel = LogCat.DisableAllLogLevel; } - //注册测试使用的战利品表 - if (Config.IsDebug()) - { - var testLootList = new LootList - { - Id = Config.LootListId.Test - }; - var staffOfTheUndead = new LootEntry - { - Chance = 0.05f, - MaxQuantity = 5, - MinQuantity = 1, - ResPath = "res://prefab/weapons/staffOfTheUndead.tscn" - }; - testLootList.AddLootEntry(staffOfTheUndead); - var packsack = new LootEntry - { - Chance = 1f, - MaxQuantity = 1, - MinQuantity = 1, - ResPath = "res://prefab/packsacks/packsack.tscn" - }; - testLootList.AddLootEntry(packsack); - LootListManager.RegisterLootList(testLootList); - } DeathInfoGenerator.RegisterDeathInfoHandler(new SelfDeathInfoHandler()); MapGenerator.RegisterRoomInjectionProcessor(new ChanceRoomInjectionProcessor()); @@ -82,6 +58,7 @@ public partial class MainMenuLoader : UiLoaderTemplate Directory.CreateDirectory(dataPath); } + //Registered camp //注册阵营 var defaultCamp = new Camp(Config.CampId.Default) @@ -94,13 +71,16 @@ public partial class MainMenuLoader : UiLoaderTemplate var aborigines = new Camp(Config.CampId.Aborigines); CampManager.AddCamp(aborigines); _gameScene = (PackedScene)GD.Load("res://scenes/game.tscn"); - + //Register ItemTypes from file //从文件注册物品类型 ItemTypeRegister.RegisterFromFile(); //Hardcoded ItemTypes Register //硬编码注册物品类型 - ItemTypeManager.StaticRegister(); + ItemTypeRegister.StaticRegister(); + + //静态注册掉落表 + LootRegister.StaticRegister(); } public override void InitializeUi() diff --git a/scripts/loot/LootDatum.cs b/scripts/loot/LootDatum.cs new file mode 100644 index 0000000..4053484 --- /dev/null +++ b/scripts/loot/LootDatum.cs @@ -0,0 +1,8 @@ +using Godot; + +namespace ColdMint.scripts.loot; + +public readonly record struct LootDatum(string ItemId, int Quantity) +{ + public (string id, int quantity) Value => (ItemId, Quantity); +} \ No newline at end of file diff --git a/scripts/loot/LootEntry.cs b/scripts/loot/LootEntry.cs new file mode 100644 index 0000000..77a834b --- /dev/null +++ b/scripts/loot/LootEntry.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +using ColdMint.scripts.utils; + +namespace ColdMint.scripts.loot; + +/// +/// Loot entry +/// 战利品条目 +/// +public readonly struct LootEntry(string itemId,int minQuantity=1,int maxQuantity = 1,int weight = 1) +{ + /// + /// ID of item + /// 物品ID + /// + public string ItemId { get; init; } = itemId; + + /// + /// Minimum number of generated + /// 最小生成多少个 + /// + public int MinQuantity { get; init; } = minQuantity; + + /// + /// The maximum number of files to be generated + /// 最多生成多少个 + /// + public int MaxQuantity { get; init; } = maxQuantity; + + /// + /// Weight of probability within the drop group + /// 在掉落组内的生成权重 + /// + public int Weight { get; init; } = weight; +} + +/// +/// Loot Group +/// 战利品分组 +/// +/// +/// +public readonly record struct LootGroup(double Chance, IEnumerable Entries) +{ + private int WeightSum { get; } = Entries.Sum(entry => entry.Weight); + + public LootDatum GenerateLootData() + { + var random = RandomUtils.Instance; + var w = random.Next(WeightSum); + LootEntry entry = default; + foreach (var e in Entries) + { + w -= e.Weight; + if (w < 0) + { + entry = e; + } + } + + var quantity = random.Next(entry.MinQuantity, entry.MaxQuantity + 1); + + return new(entry.ItemId, quantity); + } +} \ No newline at end of file diff --git a/scripts/loot/LootList.cs b/scripts/loot/LootList.cs new file mode 100644 index 0000000..ffba1f3 --- /dev/null +++ b/scripts/loot/LootList.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; + +using ColdMint.scripts.debug; +using ColdMint.scripts.utils; + +using Godot; + +namespace ColdMint.scripts.loot; + +/// +/// Loot list +/// 战利品表 +/// +public readonly struct LootList(string id, IList groups) +{ + public string Id { get; } = id; + private IList Groups { get; } = groups; + + private static Random Random => RandomUtils.Instance; + + /// + /// GenerateLootData + /// 生成战利品数据 + /// + /// + public LootDatum[] GenerateLootData() + { + if (Groups is []) + { + LogCat.LogWithFormat("loot_list_has_no_entries", Id); + return []; + } + + var lootDataList = new List(); + foreach (var group in Groups) + { + //If the random number is greater than the generation probability, skip the current loop. + //如果随机数大于生成概率,则跳过当前循环。 + var rd = Random.NextDouble(); + if (rd > group.Chance) continue; + + //We generate a loot data for each loot entry. + //我们为每个战利品条目生成一个战利品数据。 + var datum = group.GenerateLootData(); + lootDataList.Add(datum); + LogCat.LogWithFormat("loot_data_add", datum); + } + + LogCat.LogWithFormat("loot_data_quantity", lootDataList.Count); + return lootDataList.ToArray(); + } +} \ No newline at end of file diff --git a/scripts/loot/LootListManager.cs b/scripts/loot/LootListManager.cs new file mode 100644 index 0000000..09e7709 --- /dev/null +++ b/scripts/loot/LootListManager.cs @@ -0,0 +1,51 @@ +using System.Collections.Generic; + +using ColdMint.scripts.utils; + +using Godot; + +namespace ColdMint.scripts.loot; + +/// +/// LootListManager +/// 战利品表管理器 +/// +public static class LootListManager +{ + private static Dictionary LootListDictionary { get; } = []; + + /// + /// Register loot table + /// 注册战利品表 + /// + /// + public static bool RegisterLootList(LootList lootList) + { + var id = lootList.Id; + if (id is "") return false; + return LootListDictionary.TryAdd(id, lootList); + } + + /// + /// Remove loot list + /// 移除战利品表 + /// + /// + /// + public static bool UnregisterLootList(string id) + { + return LootListDictionary.Remove(id); + } + + /// + /// Generate an loot data. + /// 获取掉落物品 + /// + /// + /// + public static IEnumerable GenerateLootData(string id) + { + if (!LootListDictionary.TryGetValue(id, out var list)) return []; + return list.GenerateLootData(); + } +} \ No newline at end of file diff --git a/scripts/loot/LootRegister.cs b/scripts/loot/LootRegister.cs new file mode 100644 index 0000000..4ccd9da --- /dev/null +++ b/scripts/loot/LootRegister.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; + +namespace ColdMint.scripts.loot; + +public static class LootRegister +{ + /// + /// Register loots hardcoded here + /// 在这里硬编码地注册掉落表 + /// + public static void StaticRegister() + { + //注册测试使用的战利品表 + if (Config.IsDebug()) + { + IList lootGroups = []; + lootGroups.Add(new LootGroup(1, + [ + new LootEntry("packsack", weight: 2), new LootEntry("staff_of_the_undead", minQuantity: 2, maxQuantity: 4) + ])); + lootGroups.Add(new LootGroup(0.3, + [ + new LootEntry("packsack") + ])); + + var testLootList = new LootList(Config.LootListId.Test, lootGroups); + LootListManager.RegisterLootList(testLootList); + } + } +} \ No newline at end of file diff --git a/scripts/utils/RandomUtils.cs b/scripts/utils/RandomUtils.cs new file mode 100644 index 0000000..f41a5ba --- /dev/null +++ b/scripts/utils/RandomUtils.cs @@ -0,0 +1,8 @@ +using System; + +namespace ColdMint.scripts.utils; + +public static class RandomUtils +{ + public static Random Instance { get; } = new(); +} \ No newline at end of file From 40b52abb485b49fa6efdae8275f80596a21a3041 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9C=A7=E9=9B=A8=E7=83=A8?= Date: Sun, 16 Jun 2024 17:05:19 +0800 Subject: [PATCH 10/15] fixed bug, add return for CreateItem --- scripts/item/ItemTypeManager.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/scripts/item/ItemTypeManager.cs b/scripts/item/ItemTypeManager.cs index cf7261d..f91b4e2 100644 --- a/scripts/item/ItemTypeManager.cs +++ b/scripts/item/ItemTypeManager.cs @@ -67,12 +67,13 @@ public static class ItemTypeManager /// 全局坐标中的位置 /// /// - public static void CreateItem(string id, Node? parent = null, Vector2? position = null) + public static IItem? CreateItem(string id, Node? parent = null, Vector2? position = null) { var item = NewItem(id); - parent?.AddChild(item as Node); - if (item is not Node2D node) return; + parent?.CallDeferred("add_child", (item as Node)!); + if (item is not Node2D node) return item; if (position is { } pos) node.GlobalPosition = pos; + return item; } /// @@ -87,12 +88,16 @@ public static class ItemTypeManager /// 全局坐标中的位置 /// /// - public static void CreateItems(string id, int amount, Node? parent = null, Vector2? position = null) + public static IList CreateItems(string id, int amount, Node? parent = null, Vector2? position = null) { + IList result = []; for (int i = 0; i < amount; i++) { - CreateItem(id, parent, position); + if (CreateItem(id, parent, position) is { } item) + result.Add(item); } + + return result; } /// From 2d3fa08d0d635cdc2c496cf2002b6639222a484e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9C=A7=E9=9B=A8=E7=83=A8?= Date: Sun, 16 Jun 2024 17:09:40 +0800 Subject: [PATCH 11/15] =?UTF-8?q?Replaced=20all=20hardcoded=20stringName?= =?UTF-8?q?=20call.=20=E7=A7=BB=E9=99=A4=E4=BA=86=E6=89=80=E6=9C=89?= =?UTF-8?q?=E7=A1=AC=E7=BC=96=E7=A0=81=E7=9A=84StringName=E8=B0=83?= =?UTF-8?q?=E7=94=A8=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/character/CharacterTemplate.cs | 4 +--- scripts/damage/DamageNumberNodeSpawn.cs | 2 +- scripts/item/ItemTypeManager.cs | 2 +- scripts/utils/GodotStringNameUtils.cs | 8 ++++++++ 4 files changed, 11 insertions(+), 5 deletions(-) create mode 100644 scripts/utils/GodotStringNameUtils.cs diff --git a/scripts/character/CharacterTemplate.cs b/scripts/character/CharacterTemplate.cs index a5eec70..285cc90 100644 --- a/scripts/character/CharacterTemplate.cs +++ b/scripts/character/CharacterTemplate.cs @@ -454,8 +454,6 @@ public partial class CharacterTemplate : CharacterBody2D { var lootData = LootListManager.GenerateLootData(LootListId); var finalGlobalPosition = GlobalPosition; - //Todo : change name str to nameof(), like this - // CallDeferred(nameof(GenerateLootObjects), this, lootData, finalGlobalPosition); GenerateLootObjects(GetParent(), lootData, finalGlobalPosition); } @@ -651,7 +649,7 @@ public partial class CharacterTemplate : CharacterBody2D return; } - CallDeferred("NodeReparent", node2D); + CallDeferred(nameof(NodeReparent), node2D); switch (item) { case WeaponTemplate weaponTemplate: diff --git a/scripts/damage/DamageNumberNodeSpawn.cs b/scripts/damage/DamageNumberNodeSpawn.cs index 3e79491..0bc00fc 100644 --- a/scripts/damage/DamageNumberNodeSpawn.cs +++ b/scripts/damage/DamageNumberNodeSpawn.cs @@ -106,7 +106,7 @@ public partial class DamageNumberNodeSpawn : Marker2D return; } - CallDeferred("AddDamageNumberNode", damageNumber); + CallDeferred(nameof(AddDamageNumberNode), damageNumber); damageNumber.Position = GlobalPosition; if (damageTemplate.MoveLeft) { diff --git a/scripts/item/ItemTypeManager.cs b/scripts/item/ItemTypeManager.cs index f91b4e2..1e29cca 100644 --- a/scripts/item/ItemTypeManager.cs +++ b/scripts/item/ItemTypeManager.cs @@ -70,7 +70,7 @@ public static class ItemTypeManager public static IItem? CreateItem(string id, Node? parent = null, Vector2? position = null) { var item = NewItem(id); - parent?.CallDeferred("add_child", (item as Node)!); + parent?.CallDeferred(GodotStringNameUtils.AddChild, (item as Node)!); if (item is not Node2D node) return item; if (position is { } pos) node.GlobalPosition = pos; return item; diff --git a/scripts/utils/GodotStringNameUtils.cs b/scripts/utils/GodotStringNameUtils.cs new file mode 100644 index 0000000..12cc573 --- /dev/null +++ b/scripts/utils/GodotStringNameUtils.cs @@ -0,0 +1,8 @@ +using Godot; + +namespace ColdMint.scripts.utils; + +public static class GodotStringNameUtils +{ + public static StringName AddChild { get; } = new("add_chile"); +} \ No newline at end of file From 2484bff2297392c1163aa0c5c41dc08edb155a9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9C=A7=E9=9B=A8=E7=83=A8?= Date: Sun, 16 Jun 2024 17:22:43 +0800 Subject: [PATCH 12/15] Replaced a while(true); --- scripts/inventory/UniversalItemContainer.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/scripts/inventory/UniversalItemContainer.cs b/scripts/inventory/UniversalItemContainer.cs index 5d47e56..c9e7801 100644 --- a/scripts/inventory/UniversalItemContainer.cs +++ b/scripts/inventory/UniversalItemContainer.cs @@ -67,16 +67,16 @@ public class UniversalItemContainer : IItemContainer public bool AddItemStack(IItemStack itemStack) { - while (true) + ItemSlotNode? itemSlotNode = Match(itemStack); + while (itemSlotNode is not null) { - var itemSlotNode = Match(itemStack); - - if (itemSlotNode == null) - return false; - if (itemSlotNode.AddItemStack(itemStack)) return true; + + itemSlotNode = Match(itemStack); } + + return false; } public int GetSelectIndex() @@ -234,7 +234,7 @@ public class UniversalItemContainer : IItemContainer return; } - itemSlotNode.IsSelect = (_itemSlotNodes.Count ) == _selectIndex; + itemSlotNode.IsSelect = (_itemSlotNodes.Count) == _selectIndex; _itemSlotNodes.Add(itemSlotNode); } From 703c19d09f557897903d6ef30737be98cb039317 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9C=A7=E9=9B=A8=E7=83=A8?= Date: Sun, 16 Jun 2024 17:38:54 +0800 Subject: [PATCH 13/15] fix a bug from a spelling mistake --- scripts/utils/GodotStringNameUtils.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/utils/GodotStringNameUtils.cs b/scripts/utils/GodotStringNameUtils.cs index 12cc573..ff4bb5f 100644 --- a/scripts/utils/GodotStringNameUtils.cs +++ b/scripts/utils/GodotStringNameUtils.cs @@ -4,5 +4,5 @@ namespace ColdMint.scripts.utils; public static class GodotStringNameUtils { - public static StringName AddChild { get; } = new("add_chile"); + public static StringName AddChild { get; } = new("add_child"); } \ No newline at end of file From ced2618a5e167578bc3016cb5f5156260a26e365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9C=A7=E9=9B=A8=E7=83=A8?= Date: Sun, 16 Jun 2024 18:35:00 +0800 Subject: [PATCH 14/15] =?UTF-8?q?Fixed=20a=20bug=20where=20the=20last=20it?= =?UTF-8?q?em=20always=20looted=20in=20the=20same=20loot=20group=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=86=E5=90=8C=E4=B8=80=E4=B8=AA=E6=8E=89?= =?UTF-8?q?=E8=90=BD=E7=BB=84=E4=B8=AD=E6=80=BB=E6=98=AF=E6=8E=89=E8=90=BD?= =?UTF-8?q?=E6=9C=80=E5=90=8E=E4=B8=80=E9=A1=B9=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- data/itemRegs/weapons.yaml | 8 ++++++++ locals/Log.csv | 1 + prefab/weapons/staffOfTheUndead.tscn | 3 +-- scripts/item/ItemTypeRegister.cs | 9 +++++---- scripts/item/weapon/WeaponTemplate.cs | 13 +++---------- scripts/loot/LootEntry.cs | 7 +++---- scripts/loot/LootRegister.cs | 10 +++++----- scripts/pickable/PickAbleTemplate.cs | 20 ++++++++++---------- 8 files changed, 36 insertions(+), 35 deletions(-) diff --git a/data/itemRegs/weapons.yaml b/data/itemRegs/weapons.yaml index 300a9c7..3700f97 100644 --- a/data/itemRegs/weapons.yaml +++ b/data/itemRegs/weapons.yaml @@ -2,7 +2,15 @@ scene_path: res://prefab/weapons/staffOfTheUndead.tscn icon_path: res://sprites/weapon/staffOfTheUndead_icon.png max_stack_value: 1 + +- id: degraded_staff_of_the_undead + scene_path: res://prefab/weapons/staffOfTheUndead.tscn + icon_path: res://sprites/weapon/staffOfTheUndead_icon.png + max_stack_value: 1 custom_args: - name: FiringIntervalAsMillisecond type: int value: 1000 + - name: UniqueName + type: string + value: 劣化的死灵法杖 diff --git a/locals/Log.csv b/locals/Log.csv index 4a39692..60dffeb 100644 --- a/locals/Log.csv +++ b/locals/Log.csv @@ -34,5 +34,6 @@ log_warning_node_cannot_cast_to,创建的物品{0}无法被转型为类型{1},Cr log_start_item_register_from_file,开始从文件注册物品信息,Start registering item information from files,アイテム情報をファイルから登録開始 log_found_files,找到{0}个文件,Found {0} files,{0}ファイルが見つかりました log_found_item_types,从文件中找到{0}个物品类型,Found {0} item types in files,ファイルから{0}個のアイテム・タイプが見つかった +log_register_item,注册物品类型{0}结果为{1},Registered item type {0}; results in {1},登録されたアイテム・タイプ {0} の結果は {1} です。 log_error_when_open_item_regs_dir,尝试打开物品信息目录时发生错误,Error when opening itemRegs dir,アイテム情報カタログを開こうとしてエラーが発生しました。 log_wrong_custom_arg,不匹配的参数:类型为{0}而值为{1},Mismatched parameter: type {0} and value {1},パラメータの不一致:型{0}と値{1}。 \ No newline at end of file diff --git a/prefab/weapons/staffOfTheUndead.tscn b/prefab/weapons/staffOfTheUndead.tscn index ffd1bb0..01d4dc3 100644 --- a/prefab/weapons/staffOfTheUndead.tscn +++ b/prefab/weapons/staffOfTheUndead.tscn @@ -15,9 +15,8 @@ collision_layer = 8 collision_mask = 34 script = ExtResource("1_w8hhv") ProjectileScenes = [ExtResource("2_34250")] -Id = "staff_of_the_undead" FiringIntervalAsMillisecond = 300 -metadata/Projectiles = PackedStringArray("res://prefab/projectile/curseOfTheUndead.tscn") +Id = "staff_of_the_undead" [node name="DamageArea2D" type="Area2D" parent="."] collision_layer = 8 diff --git a/scripts/item/ItemTypeRegister.cs b/scripts/item/ItemTypeRegister.cs index 00b20f2..dcad2c2 100644 --- a/scripts/item/ItemTypeRegister.cs +++ b/scripts/item/ItemTypeRegister.cs @@ -22,7 +22,7 @@ public static class ItemTypeRegister /// 在这里注册物品 /// public static void StaticRegister() { } - + /// /// Register items from yaml file /// 从文件注册物品 @@ -66,7 +66,7 @@ public static class ItemTypeRegister //Read & deserialize var yamlString = yamlFile.GetAsText(); var typeInfos = deserializer.Deserialize>(yamlString); - + yamlFile.Close(); return typeInfos; } @@ -76,7 +76,7 @@ public static class ItemTypeRegister //Load scene and icon var scene = ResourceLoader.Load(typeInfo.ScenePath); var icon = ResourceLoader.Load(typeInfo.IconPath); - + //Create init delegate Func newItemFunc; if (typeInfo.CustomArgs is null or []) @@ -104,7 +104,8 @@ public static class ItemTypeRegister var itemType = new ItemType(typeInfo.Id, newItemFunc, icon, typeInfo.MaxStackValue); - ItemTypeManager.Register(itemType); + var succeed = ItemTypeManager.Register(itemType); + LogCat.LogWithFormat("register_item", itemType.Id, succeed); } //Use for yaml deserialization diff --git a/scripts/item/weapon/WeaponTemplate.cs b/scripts/item/weapon/WeaponTemplate.cs index 2f89f65..d323f0e 100644 --- a/scripts/item/weapon/WeaponTemplate.cs +++ b/scripts/item/weapon/WeaponTemplate.cs @@ -1,4 +1,5 @@ using System; + using ColdMint.scripts.character; using ColdMint.scripts.pickable; using ColdMint.scripts.damage; @@ -14,6 +15,7 @@ namespace ColdMint.scripts.item.weapon; public abstract partial class WeaponTemplate : PickAbleTemplate { private float _gravity = ProjectSettings.GetSetting("physics/2d/default_gravity").AsSingle(); + public override void Use(Node2D? owner, Vector2 targetGlobalPosition) { Fire(owner, targetGlobalPosition); @@ -49,16 +51,7 @@ public abstract partial class WeaponTemplate : PickAbleTemplate /// [Export] private Vector2 _recoil; - public override void _Ready() - { - - } - - - - - - + public override void _Ready() { } /// /// Discharge of the weapon diff --git a/scripts/loot/LootEntry.cs b/scripts/loot/LootEntry.cs index 77a834b..c4d9ea4 100644 --- a/scripts/loot/LootEntry.cs +++ b/scripts/loot/LootEntry.cs @@ -55,10 +55,9 @@ public readonly record struct LootGroup(double Chance, IEnumerable En foreach (var e in Entries) { w -= e.Weight; - if (w < 0) - { - entry = e; - } + if (w >= 0) continue; + entry = e; + break; } var quantity = random.Next(entry.MinQuantity, entry.MaxQuantity + 1); diff --git a/scripts/loot/LootRegister.cs b/scripts/loot/LootRegister.cs index 4ccd9da..208b8ec 100644 --- a/scripts/loot/LootRegister.cs +++ b/scripts/loot/LootRegister.cs @@ -14,13 +14,13 @@ public static class LootRegister if (Config.IsDebug()) { IList lootGroups = []; + lootGroups.Add(new LootGroup(0.8, + [ + new LootEntry("degraded_staff_of_the_undead", weight: 2), new LootEntry("staff_of_the_undead") + ])); lootGroups.Add(new LootGroup(1, [ - new LootEntry("packsack", weight: 2), new LootEntry("staff_of_the_undead", minQuantity: 2, maxQuantity: 4) - ])); - lootGroups.Add(new LootGroup(0.3, - [ - new LootEntry("packsack") + new LootEntry("packsack", minQuantity: 2, maxQuantity: 4) ])); var testLootList = new LootList(Config.LootListId.Test, lootGroups); diff --git a/scripts/pickable/PickAbleTemplate.cs b/scripts/pickable/PickAbleTemplate.cs index 36e2da3..0de8019 100644 --- a/scripts/pickable/PickAbleTemplate.cs +++ b/scripts/pickable/PickAbleTemplate.cs @@ -1,8 +1,10 @@ using System; + using ColdMint.scripts.camp; using ColdMint.scripts.character; using ColdMint.scripts.damage; using ColdMint.scripts.item; + using Godot; namespace ColdMint.scripts.pickable; @@ -14,12 +16,12 @@ namespace ColdMint.scripts.pickable; public partial class PickAbleTemplate : RigidBody2D, IItem { [Export] public virtual string Id { get; set; } = "ID"; - protected Texture2D? UniqueIcon { get; set; } + [Export] protected Texture2D? UniqueIcon { get; set; } public Texture2D Icon => UniqueIcon ?? ItemTypeManager.DefaultIconOf(Id); - protected string? UniqueName { get; set; } + [Export] protected string? UniqueName { get; set; } public new string Name => UniqueName ?? ItemTypeManager.DefaultNameOf(Id); - protected string? UniqueDescription { get; set; } - + [Export] protected string? UniqueDescription { get; set; } + /// /// Owner /// 主人 @@ -55,9 +57,7 @@ public partial class PickAbleTemplate : RigidBody2D, IItem /// public bool Picked { get; set; } - public virtual void Use(Node2D? owner, Vector2 targetGlobalPosition) - { - } + public virtual void Use(Node2D? owner, Vector2 targetGlobalPosition) { } public override void _Ready() { @@ -124,7 +124,7 @@ public partial class PickAbleTemplate : RigidBody2D, IItem //Determine if your side can cause damage //判断所属的阵营是否可以造成伤害 var canCauseHarm = CampManager.CanCauseHarm(CampManager.GetCamp(ownerCharacterTemplate.CampId), - CampManager.GetCamp(characterTemplate.CampId)); + CampManager.GetCamp(characterTemplate.CampId)); if (!canCauseHarm) { return; @@ -147,8 +147,8 @@ public partial class PickAbleTemplate : RigidBody2D, IItem LinearVelocity *= 1 - Config.ThrownItemsHitEnemiesReduceSpeedByPercentage; } } - - + + /// /// Flip item /// 翻转物品 From 3063680786593299e12527252e27e0add46b3d79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9C=A7=E9=9B=A8=E7=83=A8?= Date: Sun, 16 Jun 2024 18:41:26 +0800 Subject: [PATCH 15/15] Add CanPutInPack property of IItem --- scripts/item/IItem.cs | 8 ++++++++ scripts/item/Packsack.cs | 8 ++++++-- scripts/item/itemStacks/PacksackStack.cs | 7 +++---- scripts/pickable/PickAbleTemplate.cs | 1 + 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/scripts/item/IItem.cs b/scripts/item/IItem.cs index d155aa0..6ed7bbb 100644 --- a/scripts/item/IItem.cs +++ b/scripts/item/IItem.cs @@ -26,6 +26,14 @@ public interface IItem /// 当前项目的描述 /// string? Description { get; } + /// + /// + /// Whether the current item can be put into item containers like packsack.
+ /// This attribute is usually set to false for items of the backpack class to avoid pack nesting. + ///
+ /// 当前物品是否可以放入背包类的容器中。一般将背包类物品的该属性设为false来避免背包嵌套。 + ///
+ bool CanPutInPack { get; } /// /// Execute when current item is used
e.g. when player clicks left mouse button with current item in hand
diff --git a/scripts/item/Packsack.cs b/scripts/item/Packsack.cs index 8654563..a8f0bf4 100644 --- a/scripts/item/Packsack.cs +++ b/scripts/item/Packsack.cs @@ -1,6 +1,7 @@ using ColdMint.scripts.inventory; using ColdMint.scripts.pickable; using ColdMint.scripts.utils; + using Godot; namespace ColdMint.scripts.item; @@ -14,6 +15,8 @@ public partial class Packsack : PickAbleTemplate private PackedScene? _packedScene; private PacksackUi? _packsackUi; + public override bool CanPutInPack => false; + public override void Destroy() { if (ItemContainer == null) return; @@ -31,10 +34,12 @@ public partial class Packsack : PickAbleTemplate { return; } + if (_packsackUi == null) { - _packsackUi = NodeUtils.InstantiatePackedScene(_packedScene,this); + _packsackUi = NodeUtils.InstantiatePackedScene(_packedScene, this); } + _packsackUi?.Show(); } @@ -45,6 +50,5 @@ public partial class Packsack : PickAbleTemplate base._Ready(); ItemContainer = new UniversalItemContainer(); _packedScene = GD.Load("res://prefab/ui/packsackUI.tscn"); - } } \ No newline at end of file diff --git a/scripts/item/itemStacks/PacksackStack.cs b/scripts/item/itemStacks/PacksackStack.cs index 0e78007..3e96266 100644 --- a/scripts/item/itemStacks/PacksackStack.cs +++ b/scripts/item/itemStacks/PacksackStack.cs @@ -17,17 +17,16 @@ public class PacksackStack(Packsack packsack) : IItemStack public Texture2D Icon => packsack.Icon; public string Name => packsack.Name; public string? Description => packsack.Description; - - //todo: 只拒绝是背包的物品是权宜之计,应该为物品加入一个“是否可以放入背包”的属性来实现这个判断。 + public bool CanAddItem(IItem item) { - if (item is Packsack) return false; + if (!item.CanPutInPack) return false; return packsack.ItemContainer?.CanAddItem(item) ?? false; } public bool AddItem(IItem item) { - if (item is Packsack) return false; + if (!item.CanPutInPack) return false; return packsack.ItemContainer?.AddItem(item) ?? false; } diff --git a/scripts/pickable/PickAbleTemplate.cs b/scripts/pickable/PickAbleTemplate.cs index 0de8019..5d0dd9d 100644 --- a/scripts/pickable/PickAbleTemplate.cs +++ b/scripts/pickable/PickAbleTemplate.cs @@ -21,6 +21,7 @@ public partial class PickAbleTemplate : RigidBody2D, IItem [Export] protected string? UniqueName { get; set; } public new string Name => UniqueName ?? ItemTypeManager.DefaultNameOf(Id); [Export] protected string? UniqueDescription { get; set; } + public virtual bool CanPutInPack => true; /// /// Owner