diff --git a/locals/Log.csv b/locals/Log.csv index 4ccf893..ca1cd8d 100644 --- a/locals/Log.csv +++ b/locals/Log.csv @@ -4,7 +4,6 @@ log_missing_parameters,缺少参数。,Missing parameters.,パラメータが不 log_room_root_node_must_be_node2d,房间根节点必须是 Node2D。,Room root node must be an instance of Node2D.,ルートノードはNode2Dでなければなりません。 log_width_or_height_of_room_slot_must_be_1,房间槽的宽度或高度必须为1。,The width or height of the room slot must be 1.,部屋の溝の幅または高さは1でなければなりません。 log_connected_room_timeout,连接房间超时。,Timeout when connecting rooms.,接続部屋はタイムアウトです。 -log_projectiles_is_empty,未设置抛射体。,The projectile is not set.,射出体は設置されていません。 log_map_generator_missing_parameters,地图生成器缺少参数。,Map generator missing parameters.,マップジェネレータが不足しています。 log_map_generator_attempts_to_parse_empty_layout_diagrams,地图生成器尝试解析空的布局图。,Map generator attempts to parse empty layout diagrams.,マップジェネレータは空のレイアウト図を解析しようとしています。 log_map_generator_has_no_starting_room_data,地图生成器没有起点房间数据。,Map generator has no starting room data.,マップ生成器に起点部屋データはありません。 diff --git a/prefab/weapons/StaffNecromancy.tscn b/prefab/weapons/StaffNecromancy.tscn index 92893ae..0dd8ae1 100644 --- a/prefab/weapons/StaffNecromancy.tscn +++ b/prefab/weapons/StaffNecromancy.tscn @@ -1,8 +1,7 @@ -[gd_scene load_steps=8 format=3 uid="uid://dnnn2xyayiehk"] +[gd_scene load_steps=7 format=3 uid="uid://dnnn2xyayiehk"] [ext_resource type="Texture2D" uid="uid://wt50kx6bup51" path="res://sprites/weapon/StaffNecromancy.png" id="1_ms3us"] [ext_resource type="Script" path="res://scripts/weapon/ProjectileWeapon.cs" id="1_w8hhv"] -[ext_resource type="PackedScene" uid="uid://c01av43yk1q71" path="res://prefab/projectile/curseOfTheUndead.tscn" id="2_mwli5"] [ext_resource type="Texture2D" uid="uid://dg5vwprt66w4j" path="res://sprites/weapon/StaffNecromancy_Icon.png" id="3_31iau"] [ext_resource type="AudioStream" uid="uid://cak6chjjsu7wo" path="res://sounds/fire.wav" id="4_ffr2k"] @@ -17,9 +16,7 @@ collision_layer = 8 collision_mask = 34 angular_damp = -1.0 script = ExtResource("1_w8hhv") -OffsetAngle = 0.087 -ProjectileScenes = [ExtResource("2_mwli5")] -Sequentially = true +NumberSlots = 5 FiringIntervalAsMillisecond = 300 _recoilStrength = 5 UniqueIcon = ExtResource("3_31iau") diff --git a/scripts/Config.cs b/scripts/Config.cs index ffe96c9..dece38c 100644 --- a/scripts/Config.cs +++ b/scripts/Config.cs @@ -197,6 +197,45 @@ public static class Config { return OS.HasFeature("editor"); } + + /// + /// ItemType + /// 物品类型 + /// + public static class ItemType + { + /// + /// Unknown + /// 未知的 + /// + public const int Unknown = 0; + /// + /// Placeholder + /// 占位符 + /// + public const int Placeholder = 1; + /// + /// Packsack + /// 背包 + /// + public const int Packsack = 2; + + /// + /// ProjectileWeapon + /// 远程武器 + /// + public const int ProjectileWeapon = 3; + + /// + /// Magic + /// 法术 + /// + /// + ///Type of special item used in Projectile weapons + ///用于远程武器内的特殊物品类型 + /// + public const int Magic = 4; + } /// /// Room Injector ID diff --git a/scripts/inventory/HotBar.cs b/scripts/inventory/HotBar.cs index 3515b0f..6e1826a 100644 --- a/scripts/inventory/HotBar.cs +++ b/scripts/inventory/HotBar.cs @@ -11,13 +11,13 @@ public partial class HotBar : HBoxContainer { private IItemContainer? _itemContainer; private IItemContainerDisplay? _itemContainerDisplay; - + public override void _Ready() { base._Ready(); var universalItemContainer = new UniversalItemContainer(Config.HotBarSize); _itemContainer = universalItemContainer; - _itemContainer.CanContainContainer = true; + universalItemContainer.AllowItemTypesExceptPlaceholder(); _itemContainer.SupportSelect = true; _itemContainerDisplay = new ItemSlotContainerDisplay(this); _itemContainerDisplay.BindItemContainer(_itemContainer); diff --git a/scripts/inventory/IItem.cs b/scripts/inventory/IItem.cs index 38a4d69..185c316 100644 --- a/scripts/inventory/IItem.cs +++ b/scripts/inventory/IItem.cs @@ -62,6 +62,12 @@ public interface IItem /// 最大物品数量 /// int MaxQuantity { get; } + + /// + /// ItemType + /// 获取物品类型 + /// + int ItemType { get; } /// /// Check or not diff --git a/scripts/inventory/IItemContainer.cs b/scripts/inventory/IItemContainer.cs index 42bed97..2ccd95c 100644 --- a/scripts/inventory/IItemContainer.cs +++ b/scripts/inventory/IItemContainer.cs @@ -20,6 +20,20 @@ public interface IItemContainer /// 当物品的数据发生改变时,例如数量增加,减少,或者新物品被添加到容器内触发此事件 /// Action? ItemDataChangeEvent { get; set; } + + /// + /// Allow Adding Item By Type + /// 允许添加指定类型的物品 + /// + /// + void AllowAddingItemByType(int itemType); + + /// + /// Disallow Adding Item By Type + /// 禁止添加指定类型的物品 + /// + /// + void DisallowAddingItemByType(int itemType); /// /// Can the specified item be added to the container? @@ -45,13 +59,7 @@ public interface IItemContainer /// 此物品容器是否支持选中 /// bool SupportSelect { get; set; } - - /// - /// Whether this item container supports items that CanContainItems=true, such as backpacks - /// 此物品容器是否支持容纳CanContainItems=true的物品,例如背包 - /// - bool CanContainContainer { get; set; } - + /// /// Gets a placeholder object /// 获取占位符对象 diff --git a/scripts/inventory/ItemSlotNode.cs b/scripts/inventory/ItemSlotNode.cs index d9a58b8..d7e15b1 100644 --- a/scripts/inventory/ItemSlotNode.cs +++ b/scripts/inventory/ItemSlotNode.cs @@ -117,7 +117,7 @@ public partial class ItemSlotNode : MarginContainer, IItemDisplay return; } - if (Item.SelfItemContainer != null) + if (Item.SelfItemContainer != null && Item.SelfItemContainer.CanAddItem(sourceItem)) { //Use items and place them on the container. //用物品,在物品容器上放置。 @@ -138,7 +138,7 @@ public partial class ItemSlotNode : MarginContainer, IItemDisplay return; } - if (sourceItem.SelfItemContainer != null) + if (sourceItem.SelfItemContainer != null && sourceItem.SelfItemContainer.CanAddItem(Item)) { //Use containers and place on top of items. //用容器物品,在物品上放置。 diff --git a/scripts/inventory/Packsack.cs b/scripts/inventory/Packsack.cs index b0768c9..bfaf81d 100644 --- a/scripts/inventory/Packsack.cs +++ b/scripts/inventory/Packsack.cs @@ -12,6 +12,11 @@ namespace ColdMint.scripts.inventory; public partial class Packsack : PickAbleTemplate { private const string Path = "res://prefab/ui/packsackUI.tscn"; + + public override int ItemType + { + get => Config.ItemType.Packsack; + } [Export] public int NumberSlots { get; set; } public override void Use(Node2D? owner, Vector2 targetGlobalPosition) { @@ -54,7 +59,10 @@ public partial class Packsack : PickAbleTemplate base._Ready(); if (SelfItemContainer == null) { - SelfItemContainer = new UniversalItemContainer(NumberSlots); + var universalItemContainer = new UniversalItemContainer(NumberSlots); + universalItemContainer.AllowItemTypesExceptPlaceholder(); + universalItemContainer.DisallowAddingItemByType(Config.ItemType.Packsack); + SelfItemContainer = universalItemContainer; SelfItemContainer.SupportSelect = false; } GameSceneDepend.DynamicUiGroup?.RegisterControl(Path, () => diff --git a/scripts/inventory/PlaceholderItem.cs b/scripts/inventory/PlaceholderItem.cs index 4ae581d..419599c 100644 --- a/scripts/inventory/PlaceholderItem.cs +++ b/scripts/inventory/PlaceholderItem.cs @@ -13,17 +13,17 @@ public class PlaceholderItem : IItem public void ShowSelf() { - + } public void QueueFreeSelf() { - + } public void HideSelf() { - + } public Texture2D Icon { get; } @@ -31,6 +31,10 @@ public class PlaceholderItem : IItem public string? Description { get; } = null; public int Quantity { get; set; } = 1; public int MaxQuantity { get; } = 1; + public int ItemType + { + get => Config.ItemType.Placeholder; + } public bool IsSelect { get; set; } public bool CanContainItems { get; set; } = false; public IItemContainer? ItemContainer { get; set; } diff --git a/scripts/inventory/UniversalItemContainer.cs b/scripts/inventory/UniversalItemContainer.cs index a4f7d2d..179058e 100644 --- a/scripts/inventory/UniversalItemContainer.cs +++ b/scripts/inventory/UniversalItemContainer.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Reflection; using ColdMint.scripts.map.events; namespace ColdMint.scripts.inventory; @@ -32,15 +33,59 @@ public class UniversalItemContainer(int totalCapacity) : IItemContainer /// private int _nextAvailableIndex; + /// + /// The type of item that can be added to the item container + /// 物品容器允许添加的物品类型 + /// + private readonly HashSet _allowedItemTypes = new(); + public Action? SelectedItemChangeEvent { get; set; } public Action? ItemDataChangeEvent { get; set; } + /// + /// Allow Item Types Except Placeholder + /// 允许添加除占位符以外的所有物品类型 + /// + public void AllowItemTypesExceptPlaceholder() + { + var itemTypeType = typeof(Config.ItemType); + //Get all fields + //获取所有字段 + var fields = itemTypeType.GetFields(BindingFlags.Public | BindingFlags.Static); + //Traversal field + //遍历字段 + foreach (var field in fields) + { + //Gets the value of the field + //获取字段的值 + var value = field.GetValue(null); + if (value == null) + { + continue; + } + var intValue = (int)value; + if (intValue == Config.ItemType.Placeholder) + { + continue; + } + _allowedItemTypes.Add(intValue); + } + } + + public void AllowAddingItemByType(int itemType) + { + _allowedItemTypes.Add(itemType); + } + + public void DisallowAddingItemByType(int itemType) + { + _allowedItemTypes.Remove(itemType); + } + public bool CanAddItem(IItem item) { - if (item.SelfItemContainer != null && !CanContainContainer) + if (!_allowedItemTypes.Contains(item.ItemType)) { - //The item to be added can hold other items, and this item container does not allow item containers. - //要添加的物品能够容纳其他物品,且此物品容器不允许放置物品容器。 return false; } //If the capacity is not full, directly return to add items @@ -200,8 +245,6 @@ public class UniversalItemContainer(int totalCapacity) : IItemContainer } public bool SupportSelect { get; set; } - public bool CanContainContainer { get; set; } - public IItem GetPlaceHolderItem(int index) { @@ -247,7 +290,7 @@ public class UniversalItemContainer(int totalCapacity) : IItemContainer public bool CanReplaceItem(int index, IItem item) { - if (item.SelfItemContainer != null && !CanContainContainer) + if (!_allowedItemTypes.Contains(item.ItemType)) { return false; } diff --git a/scripts/pickable/MagicPickAble.cs b/scripts/pickable/MagicPickAble.cs new file mode 100644 index 0000000..6c92a8a --- /dev/null +++ b/scripts/pickable/MagicPickAble.cs @@ -0,0 +1,15 @@ +namespace ColdMint.scripts.pickable; + +/// +/// 法术 +/// +/// +///用于抛射体武器 +/// +public partial class MagicPickAble : PickAbleTemplate +{ + public override int ItemType + { + get => Config.ItemType.Magic; + } +} \ No newline at end of file diff --git a/scripts/pickable/PickAbleTemplate.cs b/scripts/pickable/PickAbleTemplate.cs index ef20605..59e0dca 100644 --- a/scripts/pickable/PickAbleTemplate.cs +++ b/scripts/pickable/PickAbleTemplate.cs @@ -92,6 +92,10 @@ public partial class PickAbleTemplate : RigidBody2D, IItem public bool Picked { get; set; } public int MaxQuantity { get; set; } = 1; + public virtual int ItemType + { + get => Config.ItemType.Unknown; + } private bool _isSelected; @@ -108,7 +112,7 @@ public partial class PickAbleTemplate : RigidBody2D, IItem OnSelectChange(value); } } - + public IItemContainer? ItemContainer { get; set; } public IItemContainer? SelfItemContainer { get; set; } @@ -121,7 +125,7 @@ public partial class PickAbleTemplate : RigidBody2D, IItem /// protected virtual void OnSelectChange(bool isSelected) { - + } public IItem? CreateItem(int number) @@ -348,11 +352,4 @@ public partial class PickAbleTemplate : RigidBody2D, IItem pickAbleTemplate.Id = Id; } - - public virtual void Destroy() - { - QueueFree(); - } - - public bool CanStackWith(IItem item) => false; } \ No newline at end of file diff --git a/scripts/projectile/IMagic.cs b/scripts/projectile/IMagic.cs new file mode 100644 index 0000000..2b9351e --- /dev/null +++ b/scripts/projectile/IMagic.cs @@ -0,0 +1,14 @@ +namespace ColdMint.scripts.projectile; + +/// +/// Magic +/// 法术 +/// +/// +///For projectile weapons +///用于抛射体武器 +/// +public interface IMagic +{ + +} \ No newline at end of file diff --git a/scripts/weapon/ProjectileWeapon.cs b/scripts/weapon/ProjectileWeapon.cs index cd82379..5c982be 100644 --- a/scripts/weapon/ProjectileWeapon.cs +++ b/scripts/weapon/ProjectileWeapon.cs @@ -1,7 +1,5 @@ using ColdMint.scripts.debug; -using ColdMint.scripts.projectile; -using ColdMint.scripts.projectile.decorator; -using ColdMint.scripts.utils; +using ColdMint.scripts.inventory; using Godot; namespace ColdMint.scripts.weapon; @@ -21,106 +19,28 @@ public partial class ProjectileWeapon : WeaponTemplate /// 抛射体的生成位置 /// private Marker2D? _marker2D; - - /// - /// Scattering radians - /// 散射弧度 - /// - [Export] protected float OffsetAngle; - - /// - /// Offset angle mode - /// 偏移角度模式 - /// - [Export] protected int OffsetAngleMode = Config.OffsetAngleMode.Random; - - /// - /// Whether the last offset angle is positive - /// 上次的偏移角度是否为正向的 - /// - private bool _positiveOffsetAngle = true; - - /// - /// The number of projectiles fired at once - /// 一次可以发射多少个子弹 - /// - [Export] protected float NumberOfProjectiles = 1; - - [Export] protected PackedScene[] ProjectileScenes { get; set; } = []; - - /// - /// Whether to launch in the order of the projectile list - /// 是否按照抛射体列表的循序发射 - /// - [Export] - protected bool Sequentially { get; set; } - + private int _projectileIndex; + + /// + /// Number of slots for ranged weapons + /// 远程武器的槽位数量 + /// + [Export] public int NumberSlots { get; set; } + 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); } - - /// - /// GetNextProjectileScene - /// 获取下一个抛射体 - /// - /// - private PackedScene GetNextProjectileScene() - { - if (Sequentially) - { - _projectileIndex = (_projectileIndex + 1) % ProjectileScenes.Length; - return ProjectileScenes[_projectileIndex]; - } - else - { - return ProjectileScenes[RandomUtils.Instance.Next(ProjectileScenes.Length)]; - } - } - - - /// - /// GetRandomAngle - /// 获取随机的偏移弧度 - /// - /// - private float GetRandomAngle() - { - if (OffsetAngle == 0) - { - //If the offset angle is 0, then return 0 - //弧度为0,不用偏移。 - return 0; - } - - if (OffsetAngleMode == Config.OffsetAngleMode.Cross) - { - float result; - if (_positiveOffsetAngle) - { - result = -OffsetAngle / 2; - } - else - { - result = OffsetAngle / 2; - } - - _positiveOffsetAngle = !_positiveOffsetAngle; - return result; - } - - if (OffsetAngleMode == Config.OffsetAngleMode.AlwaysSame) - { - return OffsetAngle; - } - - var min = -OffsetAngle / 2; - return min + RandomUtils.Instance.NextSingle() * OffsetAngle; - } - + protected override void DoFire(Node2D? owner, Vector2 enemyGlobalPosition) { @@ -141,39 +61,6 @@ public partial class ProjectileWeapon : WeaponTemplate LogCat.LogError("projectile_container_is_null"); return; } - - //Empty list check - //空列表检查 - if (ProjectileScenes is []) - { - LogCat.LogError("projectiles_is_empty"); - return; - } - - //Get the first projectile - //获取第一个抛射体 - var projectileScene = GetNextProjectileScene(); - for (int i = 0; i < NumberOfProjectiles; i++) - { - var projectile = NodeUtils.InstantiatePackedScene(projectileScene); - if (projectile == null) return; - if (Config.IsDebug()) - { - var nodeSpawnOnKillCharacterDecorator = new NodeSpawnOnKillCharacterDecorator - { - DefaultParentNode = this, - PackedScenePath = "res://prefab/entitys/BlackenedAboriginalWarrior.tscn" - }; - projectile.AddProjectileDecorator(nodeSpawnOnKillCharacterDecorator); - } - - NodeUtils.CallDeferredAddChild(GameSceneDepend.ProjectileContainer, projectile); - projectile.Owner = owner; - projectile.TargetNode = GameSceneDepend.TemporaryTargetNode; - projectile.Velocity = - (_marker2D.GlobalPosition.DirectionTo(enemyGlobalPosition) * projectile.Speed) - .Rotated(GetRandomAngle()); - projectile.Position = _marker2D.GlobalPosition; - } + } } \ No newline at end of file