diff --git a/data/itemRegs/magics.yaml b/data/itemRegs/magics.yaml new file mode 100644 index 0000000..7b53fa5 --- /dev/null +++ b/data/itemRegs/magics.yaml @@ -0,0 +1,10 @@ +#Register spells used by the projectile here. +#在这里注册抛射体使用的法术。 +#Note: The id must be the same as the item id in the scene. Otherwise, an ArgumentException will be thrown. +#备注:id必须和场景内的物品id保持一致。否则会抛出ArgumentException。 +#After you declare the id of the item, add the corresponding localized text to the csv file in the locals' folder. For example, if the id is a corresponding name is item_a and the corresponding description is item_a_desc. +#当您声明物品的id后,请在locals文件夹中的csv文件中添加相应的本地化文本。例如:id为a,则对应的名称为item_a,对应的描述为item_a_desc。 +- id: necromancy + scene_path: res://prefab/magics/curseOfTheUndead.tscn + icon_path: res://sprites/projectile/curseOfTheUndead.png + max_stack_value: 1 \ No newline at end of file diff --git a/locals/Item.csv b/locals/Item.csv index 78af003..ecdd158 100644 --- a/locals/Item.csv +++ b/locals/Item.csv @@ -2,4 +2,6 @@ id,zh,en,ja item_staff_necromancy,死灵法杖,staffNecromancy,ネクロポリスの杖です item_staff_necromancy_desc,发射诅咒,可将敌人转化为邪恶的怪物。,Cast a curse that transforms enemies into evil monsters.,呪いを発射して、敵を邪悪な怪物に変えることができます。 item_portable_backpacks,便携式背包,PortableBackpacks,ポータブルバックパック -item_portable_backpacks_desc,为玩家提供9个物品槽。,Provides 9 item slots for the player.,プレイヤーに9つのアイテムスロットを提供します。 \ No newline at end of file +item_portable_backpacks_desc,为玩家提供9个物品槽。,Provides 9 item slots for the player.,プレイヤーに9つのアイテムスロットを提供します。 +item_necromancy,死灵法术,necromancy,ネクロマンシー +item_necromancy_desc,法术的实体化弹丸。,The materialized projectile of a spell.,術の実体化した弾丸です。 \ No newline at end of file diff --git a/locals/Log.csv b/locals/Log.csv index ca1cd8d..a23920f 100644 --- a/locals/Log.csv +++ b/locals/Log.csv @@ -111,4 +111,6 @@ log_hide_all_node,隐藏{0}个节点。,Hide {0} nodes.,{0}ノードを非表示 log_show_all_node,显示{0}个节点。,Show {0} nodes.,{0}ノードが表示されます。 log_enter_the_screen,进入屏幕。,Enter screen,画面に移動。 log_exit_the_screen,退出屏幕。,Exit screen,画面を終了します。 -log_failed_to_create_room_preview,创建{0}的房间预览图失败。,Failed to create a room preview of the {0}.,{0}の部屋のプレビューを作成できませんでした。 \ No newline at end of file +log_failed_to_create_room_preview,创建{0}的房间预览图失败。,Failed to create a room preview of the {0}.,{0}の部屋のプレビューを作成できませんでした。 +log_generated_item_is_empty,生成的物品{0}是空的吗{1}。,Generated item {0} is empty {1}.,生成したアイテム{0}は空ですか{1}。 +log_magics_is_null,法术列表是空的。,The spell list is empty.,スペルリストは空です。 \ No newline at end of file diff --git a/prefab/magics/curseOfTheUndead.tscn b/prefab/magics/curseOfTheUndead.tscn new file mode 100644 index 0000000..11e4248 --- /dev/null +++ b/prefab/magics/curseOfTheUndead.tscn @@ -0,0 +1,46 @@ +[gd_scene load_steps=6 format=3 uid="uid://crthy8a50a4t"] + +[ext_resource type="Script" path="res://scripts/pickable/MagicPickAble.cs" id="1_5mane"] +[ext_resource type="AudioStream" uid="uid://cak6chjjsu7wo" path="res://sounds/fire.wav" id="4_ffr2k"] +[ext_resource type="Texture2D" uid="uid://bbcjkyrsx88av" path="res://sprites/projectile/curseOfTheUndead.png" id="4_y6nkf"] + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_obcq2"] +size = Vector2(20, 21) + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_14m1g"] +size = Vector2(20, 20.75) + +[node name="curseOfTheUndead" type="RigidBody2D"] +collision_layer = 8 +collision_mask = 34 +angular_damp = -1.0 +script = ExtResource("1_5mane") +UniqueIcon = ExtResource("4_y6nkf") + +[node name="DamageArea2D" type="Area2D" parent="."] +collision_layer = 8 +collision_mask = 102 + +[node name="CollisionShape2D" type="CollisionShape2D" parent="DamageArea2D"] +position = Vector2(0, -0.5) +shape = SubResource("RectangleShape2D_obcq2") + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +position = Vector2(0, -0.625) +shape = SubResource("RectangleShape2D_14m1g") + +[node name="Marker2D" type="Marker2D" parent="."] +position = Vector2(65, 0) + +[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="Marker2D"] +stream = ExtResource("4_ffr2k") +bus = &"SoundEffect" + +[node name="TipLabel" type="Label" parent="."] +offset_left = -19.0 +offset_top = 23.0 +offset_right = 21.0 +offset_bottom = 48.0 + +[node name="CurseOfTheUndead" type="Sprite2D" parent="."] +texture = ExtResource("4_y6nkf") diff --git a/prefab/roomTemplates/dungeon/initialRoom.tscn b/prefab/roomTemplates/dungeon/initialRoom.tscn index ca37f5c..e44b0cf 100644 --- a/prefab/roomTemplates/dungeon/initialRoom.tscn +++ b/prefab/roomTemplates/dungeon/initialRoom.tscn @@ -1,11 +1,10 @@ -[gd_scene load_steps=10 format=4 uid="uid://du5ldsp613fei"] +[gd_scene load_steps=9 format=4 uid="uid://du5ldsp613fei"] [ext_resource type="TileSet" uid="uid://c4wpp12rr44hi" path="res://tileSets/dungeon.tres" id="1_rn2om"] [ext_resource type="Script" path="res://scripts/map/PlayerSpawn.cs" id="2_6p8mv"] [ext_resource type="Script" path="res://scripts/map/ItemSpawn.cs" id="3_v1tlc"] [ext_resource type="Texture2D" uid="uid://drw45jlmfo0su" path="res://sprites/light/White_100.png" id="5_4pssd"] [ext_resource type="PackedScene" uid="uid://djsh4unystlf0" path="res://prefab/furnitures/SpellEditor.tscn" id="5_7c8bh"] -[ext_resource type="PackedScene" uid="uid://bq5d2w22wnxrf" path="res://prefab/packsacks/PortableBackpacks.tscn" id="6_0iot7"] [sub_resource type="RectangleShape2D" id="RectangleShape2D_kiih8"] size = Vector2(507, 251) @@ -46,6 +45,11 @@ position = Vector2(142, 84) script = ExtResource("3_v1tlc") ItemId = "staff_necromancy" +[node name="ItemMarker2D2" type="Marker2D" parent="."] +position = Vector2(321, 118) +script = ExtResource("3_v1tlc") +ItemId = "necromancy" + [node name="NavigationRegion2D" type="NavigationRegion2D" parent="."] navigation_polygon = SubResource("NavigationPolygon_064c7") @@ -81,9 +85,3 @@ texture = ExtResource("5_4pssd") [node name="RigidBody2D" parent="." instance=ExtResource("5_7c8bh")] position = Vector2(149, 109) collision_mask = 0 - -[node name="RigidBody2D2" parent="." instance=ExtResource("6_0iot7")] -position = Vector2(338, 115) - -[node name="RigidBody2D3" parent="." instance=ExtResource("6_0iot7")] -position = Vector2(206, 123) diff --git a/scenes/game.tscn b/scenes/game.tscn index fe5936c..d6bda67 100644 --- a/scenes/game.tscn +++ b/scenes/game.tscn @@ -118,6 +118,8 @@ visible = false [node name="WeaponContainer" type="Node2D" parent="."] +[node name="MagicContainer" type="Node2D" parent="."] + [node name="PlayerContainer" type="Node2D" parent="."] [node name="AICharacterContainer" type="Node2D" parent="."] diff --git a/scripts/GameSceneDepend.cs b/scripts/GameSceneDepend.cs index 64e3efa..3821978 100644 --- a/scripts/GameSceneDepend.cs +++ b/scripts/GameSceneDepend.cs @@ -48,6 +48,12 @@ public static class GameSceneDepend /// 抛射体容器 /// public static Node2D? ProjectileContainer { get; set; } + + /// + /// MagicContainer + /// 法术容器 + /// + public static Node2D? MagicContainer { get; set; } /// /// WeaponContainer diff --git a/scripts/debug/LogCat.cs b/scripts/debug/LogCat.cs index 0a85c53..5907d05 100644 --- a/scripts/debug/LogCat.cs +++ b/scripts/debug/LogCat.cs @@ -88,6 +88,12 @@ public static class LogCat /// 房间 /// public const string Room = "Room"; + + /// + /// ItemSpawn + /// 物品生成器 + /// + public const string ItemSpawn = "ItemSpawn"; } diff --git a/scripts/inventory/ItemTypeManager.cs b/scripts/inventory/ItemTypeManager.cs index 29b759b..6dce398 100644 --- a/scripts/inventory/ItemTypeManager.cs +++ b/scripts/inventory/ItemTypeManager.cs @@ -97,16 +97,4 @@ public static class ItemTypeManager Registry.TryGetValue(id, out var itemType) ? itemType.Icon ?? DefaultTexture : DefaultTexture; - - /// - /// Gets the maximum number of stacks for an item - /// 获取某个物品的最大堆叠数量 - /// - /// - ///id - ///物品ID - /// - /// - public static int MaxStackQuantityOf(string id) => - Registry.TryGetValue(id, out var itemType) ? itemType.MaxStackQuantity : 0; } \ No newline at end of file diff --git a/scripts/loader/sceneLoader/GameSceneLoader.cs b/scripts/loader/sceneLoader/GameSceneLoader.cs index e39855d..bf56c32 100644 --- a/scripts/loader/sceneLoader/GameSceneLoader.cs +++ b/scripts/loader/sceneLoader/GameSceneLoader.cs @@ -45,6 +45,10 @@ public partial class GameSceneLoader : SceneLoaderTemplate //加载抛射体容器 var projectileContainer = GetNode("ProjectileContainer"); GameSceneDepend.ProjectileContainer = projectileContainer; + //Load magic container + //加载魔术容器 + var magicContainer = GetNode("MagicContainer"); + GameSceneDepend.MagicContainer = magicContainer; //Load Packsack container //加载背包容器 var packsackContainer = GetNode("PacksackContainer"); diff --git a/scripts/map/ItemSpawn.cs b/scripts/map/ItemSpawn.cs index 2276d18..15c6495 100644 --- a/scripts/map/ItemSpawn.cs +++ b/scripts/map/ItemSpawn.cs @@ -1,4 +1,5 @@ -using ColdMint.scripts.inventory; +using ColdMint.scripts.debug; +using ColdMint.scripts.inventory; using ColdMint.scripts.map.events; using Godot; @@ -15,7 +16,6 @@ public partial class ItemSpawn : Marker2D public override void _Ready() { base._Ready(); - EventBus.MapGenerationCompleteEvent += MapGenerationCompleteEvent; } @@ -29,6 +29,7 @@ public partial class ItemSpawn : Marker2D } var item = ItemTypeManager.CreateItem(ItemId, this); + LogCat.LogWithFormat("generated_item_is_empty",LogCat.LogLabel.ItemSpawn,true,ItemId,item == null); if (item is Node2D node2D) { node2D.GlobalPosition = GlobalPosition; diff --git a/scripts/pickable/MagicPickAble.cs b/scripts/pickable/MagicPickAble.cs index 6c92a8a..6e547cd 100644 --- a/scripts/pickable/MagicPickAble.cs +++ b/scripts/pickable/MagicPickAble.cs @@ -1,15 +1,53 @@ +using ColdMint.scripts.projectile; +using ColdMint.scripts.weapon; +using Godot; + namespace ColdMint.scripts.pickable; /// +/// magic /// 法术 /// /// +///For projectile weapons ///用于抛射体武器 /// -public partial class MagicPickAble : PickAbleTemplate +public partial class MagicPickAble : PickAbleTemplate, IMagic { + private string? _projectilePath; + + private PackedScene? _projectileScene; + public override void _Ready() + { + base._Ready(); + if (_projectilePath != null) + { + _projectileScene = GD.Load(_projectilePath); + } + } + public override int ItemType { get => Config.ItemType.Magic; } + + public PackedScene? GetProjectile() + { + return _projectileScene; + } + + public void ModifyWeapon(ProjectileWeapon projectileWeapon) + { + + } + + public void RestoreWeapon(ProjectileWeapon projectileWeapon) + { + + } + + public void ModifyProjectile(Projectile projectile) + { + + } } \ No newline at end of file diff --git a/scripts/projectile/IMagic.cs b/scripts/projectile/IMagic.cs index 2b9351e..d984f71 100644 --- a/scripts/projectile/IMagic.cs +++ b/scripts/projectile/IMagic.cs @@ -1,3 +1,6 @@ +using ColdMint.scripts.weapon; +using Godot; + namespace ColdMint.scripts.projectile; /// @@ -10,5 +13,32 @@ namespace ColdMint.scripts.projectile; /// public interface IMagic { + /// + /// GetProjectile + /// 获取抛射体 + /// + /// + PackedScene? GetProjectile(); + + /// + /// Modify Weapon + /// 修改武器 + /// + /// + void ModifyWeapon(ProjectileWeapon projectileWeapon); + + /// + /// Restores the modified weapon properties + /// 还原修改的武器属性 + /// + /// + void RestoreWeapon(ProjectileWeapon projectileWeapon); + /// + /// Modify the projectile + /// 修改抛射体 + /// + /// + void ModifyProjectile(Projectile projectile); + } \ No newline at end of file diff --git a/scripts/utils/NodeUtils.cs b/scripts/utils/NodeUtils.cs index 4761ab2..89a7e34 100644 --- a/scripts/utils/NodeUtils.cs +++ b/scripts/utils/NodeUtils.cs @@ -225,16 +225,21 @@ public static class NodeUtils /// public static Node FindContainerNode(Node childNode, Node defaultParentNode) { - if (GameSceneDepend.AiCharacterContainer!= null && childNode is AiCharacter) + if (GameSceneDepend.AiCharacterContainer != null && childNode is AiCharacter) { return GameSceneDepend.AiCharacterContainer; } - + if (GameSceneDepend.ProjectileContainer != null && childNode is Projectile) { return GameSceneDepend.ProjectileContainer; } - + + if (GameSceneDepend.MagicContainer != null && childNode is IMagic) + { + return GameSceneDepend.MagicContainer; + } + if (GameSceneDepend.WeaponContainer != null && childNode is WeaponTemplate) { return GameSceneDepend.WeaponContainer; diff --git a/scripts/weapon/ProjectileWeapon.cs b/scripts/weapon/ProjectileWeapon.cs index 5c982be..04e21ff 100644 --- a/scripts/weapon/ProjectileWeapon.cs +++ b/scripts/weapon/ProjectileWeapon.cs @@ -1,5 +1,8 @@ +using System.Collections.Generic; using ColdMint.scripts.debug; using ColdMint.scripts.inventory; +using ColdMint.scripts.map.events; +using ColdMint.scripts.projectile; using Godot; namespace ColdMint.scripts.weapon; @@ -19,28 +22,60 @@ public partial class ProjectileWeapon : WeaponTemplate /// 抛射体的生成位置 /// private Marker2D? _marker2D; - - private int _projectileIndex; - + /// /// Number of slots for ranged weapons /// 远程武器的槽位数量 /// [Export] public int NumberSlots { get; set; } + private readonly List _magics = new(); + public override int ItemType { get => Config.ItemType.ProjectileWeapon; } - + public override void _Ready() { base._Ready(); _marker2D = GetNode("Marker2D"); SelfItemContainer = new UniversalItemContainer(NumberSlots); SelfItemContainer.AllowAddingItemByType(Config.ItemType.Magic); + SelfItemContainer.ItemDataChangeEvent += OnItemDataChangeEvent; + } + + private void OnItemDataChangeEvent(ItemDataChangeEvent itemDataChangeEvent) + { + if (SelfItemContainer == null) + { + return; + } + _magics.Clear(); + var totalCapacity = SelfItemContainer.GetTotalCapacity(); + for (var i = 0; i < totalCapacity; i++) + { + var item = SelfItemContainer.GetItem(i); + if (item == null) + { + continue; + } + if (item is not IMagic magic) + { + continue; + } + _magics.Add(magic); + } + } + + public override void _ExitTree() + { + base._ExitTree(); + if (SelfItemContainer != null) + { + SelfItemContainer.ItemDataChangeEvent -= OnItemDataChangeEvent; + } } - protected override void DoFire(Node2D? owner, Vector2 enemyGlobalPosition) { @@ -61,6 +96,10 @@ public partial class ProjectileWeapon : WeaponTemplate LogCat.LogError("projectile_container_is_null"); return; } - + if (_magics.Count == 0) + { + LogCat.LogError("magics_is_null"); + return; + } } } \ No newline at end of file