diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..89fafca --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 NewDerFolder + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 0d720df..0f94a17 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,104 @@ # EasyBag -⚠️ Note: The underlying architecture is in flux right now. We plan to rewrite the Quick Start guide in the upcoming v0.5 release. +## 简介 +EasyBag是Godot中的一个库存系统插件,着力于高度解耦和数据化,和可扩展性,致力于加速和稳固中大型角色扮演游戏亦或者是需要高度定制化库存系统的项目。 +配合Godot的资源类,使其可以在Godot编辑器面板中比较物品的属性或标签。实现程序员与策划人员的有序合作。 +同时EasyBag也提供了些类快速实现如物品随机掉落,物品配方合成等功能。当然你也可以自己自由扩展。 +## 快速入门 + +### 创建资源文件 +1. EasyBag基于Godot的资源文件,以此请先创建一个```EB_InventoryItem```类型的资源文件 +2. 双击你创建的资源文件,可以看到右侧的属性面板 +3. 你最好保持文件名和```item_name```属性相同,这是个潜规则 +4. ```attribute_arr```空无一物,是时候创建了,添加元素吧,来个``` EB_IntAttribute```属性 +5. 点开这个属性,可以看到```value```,```attribute_name```,```is_static``` +6. 试着更改更改属性名称为```atk```,将值改成```10``` +7. 添加一个标签吧,你得先创建一个标签 +8. 新建```EB_BaseTag```类型的资源文件,记得保存文件名称和```tag_name```属性一致 +9. 重写点回你之前创建的```EB_InventoryItem```类型资源文件,为其```tag_arr```添加tag,点击快速加载选择刚刚创建的tag + +### 加载物品到库存 +创建一个场景并且编辑其脚本 +在```_ready```函数中 +```gdscript +#加载物品 +var my_item:=load("res://resource/你的文件路径.tres") +#创建库存容器 +var my_inventory:=EB_Inventory.new() +#将物品添加进去 +my_inventory.add_item(my_item) +``` +是的这样子my_inventory中就有这个物品了 + +### 更加集中式的做法 +1. 创建一个```EB_DictionaryCodex```的资源文件 +2. 为其添加键值对,注意值应该快速加载你创建过的物品项 +3. 加载物品到库存 +```gdscript +#你可以选择用键或者是物品名称获取物品 +codex.get_InventoryItem_by_name("") +codex.get_InventoryItem_by_id("") +var new_item=codex.get_InventoryItem_by_id("你的键") +#将物品添加进去 +inventory.add_item(new_item) +``` + +### 还有很多 +当然这个快速入门比较短,EasyBag中还有许多基础用法和进阶用法,比如说掉落池或者是配方类,未来我们会进一步完善文档。 + + # EasyBag -目前底层架构处于变动中,预计于0.5版本重写新版本的快速入门. + +## Introduction +EasyBag is an inventory system plugin for Godot, focusing on high decoupling, data-driven design, and scalability. It is dedicated to accelerating and stabilizing medium-to-large RPG projects or any project requiring a highly customizable inventory system. + +By leveraging Godot's Resource system, it allows you to compare item attributes and tags directly within the Godot editor panel, facilitating an organized workflow between programmers and game designers. + +EasyBag also provides utility classes to quickly implement features like random item drops and crafting recipes. Of course, you are free to extend it however you like. + +## Quick Start + +### Creating Resource Files +1. EasyBag is built on Godot's Resource system. Start by creating a resource file of type `EB_InventoryItem`. +2. Double-click your newly created resource file to view its properties in the right-side panel. +3. **Pro Tip:** It's highly recommended to keep the file name identical to the `item_name` property. This is a widely accepted convention. +4. The `attribute_arr` is currently empty—time to create one! Add an element, such as an `EB_IntAttribute`. +5. Click on this attribute to reveal its properties: `value`, `attribute_name`, and `is_static`. +6. Try changing the attribute name to `atk` and setting the value to `10`. +7. Next, let's add a tag. First, you need to create the tag itself. +8. Create a new resource file of type `EB_BaseTag`. Remember to save the file with a name that matches the `tag_name` property. +9. Go back to your `EB_InventoryItem` resource file, add the tag to its `tag_arr`, and use the Quick Load feature to select the tag you just created. + +### Loading Items into Inventory +Create a scene and edit its script. In the `_ready` function: + +```gdscript +# Load the item +var my_item := load("res://resource/your_file_path.tres") + +# Create an inventory container +var my_inventory := EB_Inventory.new() + +# Add the item to the inventory +my_inventory.add_item(my_item) +``` + +And just like that, your item is now in `my_inventory`! + +### A More Centralized Approach +1. Create a resource file of type `EB_DictionaryCodex`. +2. Add key-value pairs to it. Note that the values should be Quick Loaded from the item resources you've previously created. +3. Load items into the inventory: + +```gdscript +# You can retrieve items using either a key or an item name +codex.get_InventoryItem_by_name("") +codex.get_InventoryItem_by_id("") + +var new_item = codex.get_InventoryItem_by_id("your_key") + +# Add the item to the inventory +inventory.add_item(new_item) +``` + +### And There's More! +Of course, this quick start guide is quite brief. EasyBag includes many basic and advanced features, such as drop pools and crafting recipes. We will continue to improve and expand the documentation in the future. diff --git a/Task/page/aaa.gd b/Task/page/aaa.gd index 5967b56..227c121 100644 --- a/Task/page/aaa.gd +++ b/Task/page/aaa.gd @@ -5,6 +5,17 @@ extends Node @export var inventory:=EB_CapacityInventory.new() func _ready() -> void: + + var my_item:=load("res://resource/eb/itmes/new_resource.tres") + var my_inventory:=EB_Inventory.new() + my_inventory.add_item(my_item) + var codex:EB_DictionaryCodex=load("res://resource/eb/codex.tres") + #你可以选择用键或者是物品名称获取物品 + codex.get_InventoryItem_by_name("") + codex.get_InventoryItem_by_id("") + var new_item=codex.get_InventoryItem_by_id("你的键") + inventory.add_item(new_item) + inventory.stack_attribute=preload("res://resource/eb/late_attribute/stack.gd").new() inventory.max_stack_attribute=preload("res://resource/eb/static_attribute/max_stack.gd").new() diff --git a/Task/page/grid_page.tscn b/Task/page/grid_page.tscn new file mode 100644 index 0000000..5f4c23d --- /dev/null +++ b/Task/page/grid_page.tscn @@ -0,0 +1,209 @@ +[gd_scene format=3 uid="uid://bywy28p0m81xm"] + +[ext_resource type="Texture2D" uid="uid://c7o37ili224i7" path="res://addons/easy_bag/asset/icon/apple.png" id="1_2k051"] +[ext_resource type="Texture2D" uid="uid://bwp5ku0hu00q8" path="res://addons/easy_bag/asset/icon/EasyBagResource.png" id="2_1x1f4"] +[ext_resource type="Texture2D" uid="uid://pdqc3qr88h6b" path="res://addons/easy_bag/asset/icon/hpIcon.png" id="3_3ulxc"] +[ext_resource type="Texture2D" uid="uid://d202aoymh587g" path="res://addons/easy_bag/asset/icon/GreenApple.png" id="4_3ulxc"] +[ext_resource type="Texture2D" uid="uid://65lwgvhknhkn" path="res://addons/easy_bag/asset/icon/book.png" id="5_ek0ie"] + +[node name="GridPage" type="Control" unique_id=873143751] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="PanelContainer" type="PanelContainer" parent="." unique_id=425836410] +layout_mode = 0 +offset_left = 668.0 +offset_top = 223.0 +offset_right = 941.0 +offset_bottom = 385.0 + +[node name="HFlowContainer" type="HFlowContainer" parent="PanelContainer" unique_id=669937720] +layout_mode = 2 + +[node name="PanelContainer" type="PanelContainer" parent="PanelContainer/HFlowContainer" unique_id=1156746990] +layout_mode = 2 + +[node name="TextureRect" type="TextureRect" parent="PanelContainer/HFlowContainer/PanelContainer" unique_id=1220313199] +custom_minimum_size = Vector2(50, 50) +layout_mode = 2 +texture = ExtResource("1_2k051") +expand_mode = 1 + +[node name="PanelContainer2" type="PanelContainer" parent="PanelContainer/HFlowContainer" unique_id=180352666] +layout_mode = 2 + +[node name="TextureRect" type="TextureRect" parent="PanelContainer/HFlowContainer/PanelContainer2" unique_id=50591591] +custom_minimum_size = Vector2(50, 50) +layout_mode = 2 +texture = ExtResource("2_1x1f4") +expand_mode = 1 + +[node name="PanelContainer3" type="PanelContainer" parent="PanelContainer/HFlowContainer" unique_id=593770944] +layout_mode = 2 + +[node name="TextureRect" type="TextureRect" parent="PanelContainer/HFlowContainer/PanelContainer3" unique_id=12606192] +custom_minimum_size = Vector2(50, 50) +layout_mode = 2 +texture = ExtResource("3_3ulxc") +expand_mode = 1 + +[node name="PanelContainer4" type="PanelContainer" parent="PanelContainer/HFlowContainer" unique_id=1420462990] +layout_mode = 2 + +[node name="TextureRect" type="TextureRect" parent="PanelContainer/HFlowContainer/PanelContainer4" unique_id=1766944062] +custom_minimum_size = Vector2(50, 50) +layout_mode = 2 +expand_mode = 1 + +[node name="PanelContainer5" type="PanelContainer" parent="PanelContainer/HFlowContainer" unique_id=479447553] +layout_mode = 2 + +[node name="TextureRect" type="TextureRect" parent="PanelContainer/HFlowContainer/PanelContainer5" unique_id=1492489588] +custom_minimum_size = Vector2(50, 50) +layout_mode = 2 +expand_mode = 1 + +[node name="PanelContainer6" type="PanelContainer" parent="PanelContainer/HFlowContainer" unique_id=1374439643] +layout_mode = 2 + +[node name="TextureRect" type="TextureRect" parent="PanelContainer/HFlowContainer/PanelContainer6" unique_id=1148355071] +custom_minimum_size = Vector2(50, 50) +layout_mode = 2 +expand_mode = 1 + +[node name="PanelContainer7" type="PanelContainer" parent="PanelContainer/HFlowContainer" unique_id=25768683] +layout_mode = 2 + +[node name="TextureRect" type="TextureRect" parent="PanelContainer/HFlowContainer/PanelContainer7" unique_id=1546133697] +custom_minimum_size = Vector2(50, 50) +layout_mode = 2 +expand_mode = 1 + +[node name="PanelContainer8" type="PanelContainer" parent="PanelContainer/HFlowContainer" unique_id=632134745] +layout_mode = 2 + +[node name="TextureRect" type="TextureRect" parent="PanelContainer/HFlowContainer/PanelContainer8" unique_id=291430643] +custom_minimum_size = Vector2(50, 50) +layout_mode = 2 +expand_mode = 1 + +[node name="PanelContainer9" type="PanelContainer" parent="PanelContainer/HFlowContainer" unique_id=322857949] +layout_mode = 2 + +[node name="TextureRect" type="TextureRect" parent="PanelContainer/HFlowContainer/PanelContainer9" unique_id=150642780] +custom_minimum_size = Vector2(50, 50) +layout_mode = 2 +expand_mode = 1 + +[node name="PanelContainer10" type="PanelContainer" parent="PanelContainer/HFlowContainer" unique_id=1082505126] +layout_mode = 2 + +[node name="TextureRect" type="TextureRect" parent="PanelContainer/HFlowContainer/PanelContainer10" unique_id=729404147] +custom_minimum_size = Vector2(50, 50) +layout_mode = 2 +expand_mode = 1 + +[node name="PanelContainer11" type="PanelContainer" parent="PanelContainer/HFlowContainer" unique_id=1575815679] +layout_mode = 2 + +[node name="TextureRect" type="TextureRect" parent="PanelContainer/HFlowContainer/PanelContainer11" unique_id=189320247] +custom_minimum_size = Vector2(50, 50) +layout_mode = 2 +expand_mode = 1 + +[node name="PanelContainer12" type="PanelContainer" parent="PanelContainer/HFlowContainer" unique_id=2047006448] +layout_mode = 2 + +[node name="TextureRect" type="TextureRect" parent="PanelContainer/HFlowContainer/PanelContainer12" unique_id=1596046235] +custom_minimum_size = Vector2(50, 50) +layout_mode = 2 +expand_mode = 1 + +[node name="PanelContainer13" type="PanelContainer" parent="PanelContainer/HFlowContainer" unique_id=144750887] +layout_mode = 2 + +[node name="TextureRect" type="TextureRect" parent="PanelContainer/HFlowContainer/PanelContainer13" unique_id=590999782] +custom_minimum_size = Vector2(50, 50) +layout_mode = 2 +expand_mode = 1 + +[node name="PanelContainer14" type="PanelContainer" parent="PanelContainer/HFlowContainer" unique_id=596743739] +layout_mode = 2 + +[node name="TextureRect" type="TextureRect" parent="PanelContainer/HFlowContainer/PanelContainer14" unique_id=275655839] +custom_minimum_size = Vector2(50, 50) +layout_mode = 2 +expand_mode = 1 + +[node name="PanelContainer15" type="PanelContainer" parent="PanelContainer/HFlowContainer" unique_id=2038510521] +layout_mode = 2 + +[node name="TextureRect" type="TextureRect" parent="PanelContainer/HFlowContainer/PanelContainer15" unique_id=329376707] +custom_minimum_size = Vector2(50, 50) +layout_mode = 2 +expand_mode = 1 + +[node name="CenterContainer" type="CenterContainer" parent="PanelContainer" unique_id=1131789826] +layout_mode = 2 + +[node name="PanelContainer2" type="PanelContainer" parent="." unique_id=1439799268] +layout_mode = 0 +offset_left = 411.0 +offset_top = 225.0 +offset_right = 542.0 +offset_bottom = 383.0 + +[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer2" unique_id=1096500789] +layout_mode = 2 + +[node name="PanelContainer" type="PanelContainer" parent="PanelContainer2/VBoxContainer" unique_id=1526053230] +layout_mode = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer2/VBoxContainer/PanelContainer" unique_id=1431859195] +layout_mode = 2 + +[node name="TextureRect" type="TextureRect" parent="PanelContainer2/VBoxContainer/PanelContainer/HBoxContainer" unique_id=1112973318] +custom_minimum_size = Vector2(50, 50) +layout_mode = 2 +texture = ExtResource("4_3ulxc") + +[node name="Label" type="Label" parent="PanelContainer2/VBoxContainer/PanelContainer/HBoxContainer" unique_id=1112073964] +layout_mode = 2 +theme_type_variation = &"HeaderLarge" +text = "Apple" + +[node name="PanelContainer2" type="PanelContainer" parent="PanelContainer2/VBoxContainer" unique_id=2054898374] +layout_mode = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer2/VBoxContainer/PanelContainer2" unique_id=1999692848] +layout_mode = 2 + +[node name="TextureRect" type="TextureRect" parent="PanelContainer2/VBoxContainer/PanelContainer2/HBoxContainer" unique_id=1177668137] +custom_minimum_size = Vector2(50, 50) +layout_mode = 2 +texture = ExtResource("2_1x1f4") + +[node name="Label" type="Label" parent="PanelContainer2/VBoxContainer/PanelContainer2/HBoxContainer" unique_id=264481604] +layout_mode = 2 +theme_type_variation = &"HeaderLarge" +text = "Box" + +[node name="PanelContainer3" type="PanelContainer" parent="PanelContainer2/VBoxContainer" unique_id=302590660] +layout_mode = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer2/VBoxContainer/PanelContainer3" unique_id=1117947507] +layout_mode = 2 + +[node name="TextureRect" type="TextureRect" parent="PanelContainer2/VBoxContainer/PanelContainer3/HBoxContainer" unique_id=1546825021] +custom_minimum_size = Vector2(50, 50) +layout_mode = 2 +texture = ExtResource("5_ek0ie") + +[node name="Label" type="Label" parent="PanelContainer2/VBoxContainer/PanelContainer3/HBoxContainer" unique_id=1888740149] +layout_mode = 2 +theme_type_variation = &"HeaderLarge" +text = "Book" diff --git a/addons/easy_bag/asset/background/EasyBagBg.png b/addons/easy_bag/asset/background/EasyBagBg.png new file mode 100644 index 0000000..0eee82d Binary files /dev/null and b/addons/easy_bag/asset/background/EasyBagBg.png differ diff --git a/addons/easy_bag/asset/background/EasyBagBg.png.import b/addons/easy_bag/asset/background/EasyBagBg.png.import new file mode 100644 index 0000000..1f29dfb --- /dev/null +++ b/addons/easy_bag/asset/background/EasyBagBg.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://c8582iad3yhqa" +path="res://.godot/imported/EasyBagBg.png-3238f94400bf6c430f10ad177852a4d7.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/easy_bag/asset/background/EasyBagBg.png" +dest_files=["res://.godot/imported/EasyBagBg.png-3238f94400bf6c430f10ad177852a4d7.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/addons/easy_bag/script/attribute/EB_BaseTag.gd b/addons/easy_bag/script/attribute/EB_BaseTag.gd index 3847248..1c73fe9 100644 --- a/addons/easy_bag/script/attribute/EB_BaseTag.gd +++ b/addons/easy_bag/script/attribute/EB_BaseTag.gd @@ -1,6 +1,7 @@ @icon("res://addons/easy_bag/asset/icon/TagIcon.png") class_name EB_BaseTag extends EasyBagResource - +## 带有名称的标签,在物品上挂载标签 +## 虽然目前除了名称外无其他属性但却相当重要 @export var tag_name: String = "new tag" #@export_multiline var tag_description: String = "a new tag" diff --git a/addons/easy_bag/script/attribute/EB_TagAttribute.gd b/addons/easy_bag/script/attribute/EB_TagAttribute.gd new file mode 100644 index 0000000..27d3f82 --- /dev/null +++ b/addons/easy_bag/script/attribute/EB_TagAttribute.gd @@ -0,0 +1,15 @@ +## @experimental +class_name EB_TagAttribute extends EB_BaseAttribute + + +@export var value:EB_BaseTag=EB_BaseTag.new() + +func get_value()->EB_BaseTag: + return value +func set_value(new_value:EB_BaseTag): + value=new_value +func compare_value(new_value:EB_BaseTag)->bool: + if value.tag_name==new_value.tag_name: + return true + else: + return false diff --git a/addons/easy_bag/script/attribute/EB_TagAttribute.gd.uid b/addons/easy_bag/script/attribute/EB_TagAttribute.gd.uid new file mode 100644 index 0000000..702b7a7 --- /dev/null +++ b/addons/easy_bag/script/attribute/EB_TagAttribute.gd.uid @@ -0,0 +1 @@ +uid://bnf01h8vw6267 diff --git a/addons/easy_bag/script/bag/EB_DictionaryCodex.gd b/addons/easy_bag/script/bag/EB_DictionaryCodex.gd index 98eda7b..5cd377b 100644 --- a/addons/easy_bag/script/bag/EB_DictionaryCodex.gd +++ b/addons/easy_bag/script/bag/EB_DictionaryCodex.gd @@ -12,7 +12,10 @@ func get_InventoryItem_by_id(target_id:String="") -> EB_InventoryItem: push_error("EB_Codex: No item found with ID '%s'" % target_id) return null else: - return item_dict[target_id].clone_with_id(target_id) + if use_id_as_item_name: + return item_dict[target_id].clone_with_id(target_id) + else: + return item_dict[target_id].clone_self() func get_InventoryItem_by_name(target_name: String) -> EB_InventoryItem: if _name_to_id_cache.has(target_name): diff --git a/addons/easy_bag/script/bag/EB_Inventory.gd b/addons/easy_bag/script/bag/EB_Inventory.gd index a4533f0..b0a31c9 100644 --- a/addons/easy_bag/script/bag/EB_Inventory.gd +++ b/addons/easy_bag/script/bag/EB_Inventory.gd @@ -5,10 +5,10 @@ class_name EB_Inventory @export var item_array:Array[EB_InventoryItem] -func get_inventory_size(): +func get_inventory_size()->int: return item_array.size() -func add_item(item:EB_InventoryItem): +func add_item(item:EB_InventoryItem)->void: item_array.append(item) func has_item_by_name(target_name:String)->bool: diff --git a/addons/easy_bag/script/bag/EB_Slot.gd b/addons/easy_bag/script/bag/EB_Slot.gd index 049e0c4..ea8e4f1 100644 --- a/addons/easy_bag/script/bag/EB_Slot.gd +++ b/addons/easy_bag/script/bag/EB_Slot.gd @@ -1,10 +1,17 @@ class_name EB_Slot extends EB_BaseInventory -var item:EB_InventoryItem=null +var item: EB_InventoryItem = null +@export var allowed_tags: Array[EB_BaseTag] = [] -func replace_item(new_item:EB_InventoryItem)->EB_InventoryItem: - var old_item=item - item=new_item +func replace_item(new_item: EB_InventoryItem) -> EB_InventoryItem: + # 如果设置了允许标签,检查新物品是否全部拥有 + if allowed_tags.size() > 0: + for tag in allowed_tags: + if not new_item.has_tag_by_name(tag.tag_name): + return new_item # 不满足条件,原路返回 + + var old_item = item + item = new_item return old_item diff --git a/addons/easy_bag/script/item/EB_DropItem.gd b/addons/easy_bag/script/item/EB_DropItem.gd index ef8c974..ff24bb0 100644 --- a/addons/easy_bag/script/item/EB_DropItem.gd +++ b/addons/easy_bag/script/item/EB_DropItem.gd @@ -1,5 +1,6 @@ @icon("res://addons/easy_bag/asset/icon/DropItem.png") class_name EB_DropItem extends EB_BaseItem +## 掉落项,通常放在 EB_DropPool 中 @export var drop_weight:int=1 @export var item:EB_InventoryItemOverride diff --git a/addons/easy_bag/script/item/EB_InventoryItem.gd b/addons/easy_bag/script/item/EB_InventoryItem.gd index b2c5b3a..56cfdff 100644 --- a/addons/easy_bag/script/item/EB_InventoryItem.gd +++ b/addons/easy_bag/script/item/EB_InventoryItem.gd @@ -1,10 +1,24 @@ class_name EB_InventoryItem extends EB_BaseItem +## 库存容器中的物品,可拥有属性和标签 + +@export var icon:Texture2D @export var item_name:String="new InventoryItem" @export var attribute_arr:Array[EB_BaseAttribute] @export var tag_arr:Array[EB_BaseTag] +## @experimental +## 允许您通过重写这个方法为物品项添加额外属性,重写的标签会在获取属性等涉及属性的方法中被检查 +func add_extra_attributes()->Array[EB_BaseAttribute]: + return [] + + +## @experimental +## 允许您通过重写这个方法为物品项添加额外标签,重写的标签会在获取标签方法中被检查 +func add_extra_tags()->Array[EB_BaseTag]: + return [] + func clone_self()->EB_InventoryItem: return self.duplicate(true) @@ -14,6 +28,7 @@ func clone_with_id(item_id: String="") -> EB_InventoryItem: ins.item_name=item_id return ins + func set_attribute_value_by_name(target_name:String,new_value): var attribute=get_attribute_by_name(target_name) attribute.set_value(new_value) @@ -22,6 +37,9 @@ func get_attribute_by_name(target_name:String)->EB_BaseAttribute: for i in attribute_arr: if i.attribute_name==target_name: return i + for i in add_extra_attributes(): + if i.attribute_name==target_name: + return i push_error("EB_InventoryItem的get_attribute_by_name未找到该名称的属性:",target_name) return @@ -29,13 +47,20 @@ func has_attribute_by_name(target_name:String)->bool: for i in attribute_arr: if i.attribute_name==target_name: return true + for i in add_extra_attributes(): + if i.attribute_name==target_name: + return true return false func get_attribute_value_by_name(target_name:String): var attribute=get_attribute_by_name(target_name) return attribute.get_value() +## 通过传入的字符串判断是否拥有此标签 func has_tag_by_name(target_name:String)->bool: for i in tag_arr: if i.tag_name==target_name: return true + for i in add_extra_tags(): + if i.tag_name==target_name: + return true return false diff --git a/addons/easy_bag/script/item/EB_ItemRequirement.gd b/addons/easy_bag/script/item/EB_ItemRequirement.gd new file mode 100644 index 0000000..bcbd3bd --- /dev/null +++ b/addons/easy_bag/script/item/EB_ItemRequirement.gd @@ -0,0 +1,47 @@ +class_name EB_ItemRequirement extends EB_BaseItem + + + +enum CompareType { + EQUAL, + GREATER_EQUAL, + LESS +} +@export var require_item:EB_InventoryItem +@export var compare_type: CompareType = CompareType.GREATER_EQUAL +@export var require_attribute_arr:Array[EB_BaseAttribute]=[] + +func consume_requirement(item: EB_InventoryItem): + if not check_requirement(item): + return false + + if compare_type == CompareType.GREATER_EQUAL: + for i in require_attribute_arr: + var attr = item.get_attribute_by_name(i.attribute_name) + attr.set_value(attr.get_value() - i.get_value()) + + return true + +func compare(a1:EB_BaseAttribute,a2:EB_BaseAttribute)->bool: + match compare_type: + CompareType.EQUAL: + return a1.compare_value(a2.get_value()) + CompareType.GREATER_EQUAL: + if a1.get_value()>=a2.get_value(): + return true + else: + return false + CompareType.LESS: + if a1.get_value()EB_InventoryItem: - pass +func craft(items: Array[EB_InventoryItem]) -> Array[EB_InventoryItem]: + # 1. 检查所有材料需求是否满足 + for i in input_item_arr: + var found := false + for a in items: + if a.item_name == i.require_item.item_name: + found = true + if not i.check_requirement(a): + return [] + if not found: + return [] + + # 2. 根据 auto_consume 决定是否扣除材料 + if auto_consume: + for i in input_item_arr: + for a in items: + if a.item_name == i.require_item.item_name: + i.consume_requirement(a) + break + + # 3. 生成产物 + var out_items: Array[EB_InventoryItem] = [] + for i in output_item_arr: + out_items.append(i.create_instance()) + return out_items diff --git a/project.godot b/project.godot index 3240f30..b36fc1b 100644 --- a/project.godot +++ b/project.godot @@ -12,7 +12,7 @@ config_version=5 config/name="EasyBag" run/main_scene="uid://cw42xfjd82bym" -config/features=PackedStringArray("4.6", "GL Compatibility") +config/features=PackedStringArray("4.7", "GL Compatibility") run/max_fps=60 config/icon="res://icon.svg" diff --git a/resource/eb/codex.tres b/resource/eb/codex.tres index 0e96836..1130a6a 100644 --- a/resource/eb/codex.tres +++ b/resource/eb/codex.tres @@ -1,14 +1,12 @@ [gd_resource type="Resource" script_class="EB_DictionaryCodex" format=3 uid="uid://bmiss5013han"] [ext_resource type="Script" uid="uid://cc30h31dhdh85" path="res://addons/easy_bag/script/item/EB_InventoryItem.gd" id="1_clg42"] +[ext_resource type="Resource" uid="uid://c8bb75fejwhhn" path="res://resource/eb/itmes/new_resource.tres" id="2_0dwkc"] [ext_resource type="Script" uid="uid://cyiac7h0q686" path="res://addons/easy_bag/script/bag/EB_DictionaryCodex.gd" id="2_h7br2"] -[ext_resource type="Resource" uid="uid://1f8tguqaa8r3" path="res://resource/eb/itmes/apple.tres" id="2_s5tuc"] -[ext_resource type="Resource" uid="uid://cajtii30imsrk" path="res://resource/eb/itmes/香蕉.tres" id="3_b2i3m"] [resource] script = ExtResource("2_h7br2") item_dict = Dictionary[String, ExtResource("1_clg42")]({ -"苹果": ExtResource("2_s5tuc"), -"香蕉": ExtResource("3_b2i3m") +"itemA": ExtResource("2_0dwkc") }) metadata/_custom_type_script = "uid://cyiac7h0q686" diff --git a/resource/eb/drop_pool/task_drop.tres b/resource/eb/drop_pool/task_drop.tres index a7f5d23..4bba31a 100644 --- a/resource/eb/drop_pool/task_drop.tres +++ b/resource/eb/drop_pool/task_drop.tres @@ -1,7 +1,7 @@ [gd_resource type="Resource" script_class="EB_DropPool" format=3 uid="uid://dmq00fqtfb614"] [ext_resource type="Script" uid="uid://gc4vf0bshm8f" path="res://addons/easy_bag/script/item/EB_DropItem.gd" id="1_7fpa0"] -[ext_resource type="Script" uid="uid://dyimly80elqea" path="res://addons/easy_bag/script/attribute/EB_BaseAttributeOverride.gd" id="3_biwy3"] +[ext_resource type="Script" uid="uid://cjywwcriyr5sh" path="res://addons/easy_bag/script/attribute/EB_BaseAttribute.gd" id="3_bof6l"] [ext_resource type="Resource" uid="uid://1f8tguqaa8r3" path="res://resource/eb/itmes/apple.tres" id="3_m42q0"] [ext_resource type="Script" uid="uid://ds8mr4dixckhb" path="res://addons/easy_bag/script/bag/EB_DropPool.gd" id="4_bof6l"] [ext_resource type="Script" uid="uid://dtcdigdcp72jj" path="res://addons/easy_bag/script/item/EB_InventoryItemOverride.gd" id="4_lwt2a"] diff --git a/resource/eb/itmes/new_resource.tres b/resource/eb/itmes/new_resource.tres new file mode 100644 index 0000000..79bed06 --- /dev/null +++ b/resource/eb/itmes/new_resource.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" script_class="EB_InventoryItem" format=3 uid="uid://c8bb75fejwhhn"] + +[ext_resource type="Script" uid="uid://cjywwcriyr5sh" path="res://addons/easy_bag/script/attribute/EB_BaseAttribute.gd" id="1_akhn5"] +[ext_resource type="Script" uid="uid://bt4ntkbkpdm3b" path="res://addons/easy_bag/script/attribute/EB_IntAttribute.gd" id="2_mkqfq"] +[ext_resource type="Script" uid="uid://cc30h31dhdh85" path="res://addons/easy_bag/script/item/EB_InventoryItem.gd" id="2_p4300"] +[ext_resource type="Script" uid="uid://dqa7ynna1qfkj" path="res://addons/easy_bag/script/attribute/EB_BaseTag.gd" id="3_mkqfq"] + +[sub_resource type="Resource" id="Resource_ykuwg"] +script = ExtResource("2_mkqfq") +metadata/_custom_type_script = "uid://bt4ntkbkpdm3b" + +[resource] +script = ExtResource("2_p4300") +attribute_arr = Array[ExtResource("1_akhn5")]([SubResource("Resource_ykuwg")]) +metadata/_custom_type_script = "uid://cc30h31dhdh85" diff --git a/resource/eb/static_attribute/max_stack.gd b/resource/eb/static_attribute/max_stack.gd index 332e2c2..a62a031 100644 --- a/resource/eb/static_attribute/max_stack.gd +++ b/resource/eb/static_attribute/max_stack.gd @@ -2,4 +2,4 @@ class_name max_stack extends EB_IntAttribute func _init() -> void: attribute_name="max_stack" - set_value(64) + set_value(64)