Compare commits

..

114 Commits

Author SHA1 Message Date
1f66376857
Items held by the player upon death are also destroyed.
玩家死亡后持有的物品也会被销毁。
2024-10-18 14:56:58 +08:00
5ad4c1f09d
Add audio logs.
加入音频的日志。
2024-10-18 12:44:26 +08:00
6807064bd8
The world will be generated automatically after the player dies.
玩家死亡之后会自动生成世界了。
2024-10-17 17:16:47 +08:00
9352f2c32b
No longer throws all items after the player dies, and recreates the map after the player dies.
玩家死亡后不再扔出所有物品,在玩家死亡后重新创建地图。
2024-10-17 16:08:21 +08:00
d36c909dec
Fixed an issue where players did not trigger spawns and did not spawn when entering the room again.
修复玩家没有触发刷怪,再次进入房间不刷怪的问题。
2024-10-17 11:04:43 +08:00
359d465ac9
Join the reading room.
加入阅读室。
2024-10-16 20:15:39 +08:00
15b6f34621
Join the cell.
加入牢房。
2024-10-16 16:42:32 +08:00
176e0dcb90
Add new taglines.
加入新的标语。
2024-10-16 15:17:55 +08:00
02a0e92d38
Fixed an issue where the first frame of the projectile launched by the projectile weapon was not oriented correctly. Modify the new presentation diagram.
修复抛射体武器发射的抛射体第一帧方向不对的问题。修改新的演示图。
2024-10-14 11:02:29 +08:00
e370009b18
Fixed an issue where the UI would not refresh properly when placing a weapon in slot 1 in the spell editor.
修复将槽位为1的武器放到法术编辑器上UI无法正常刷新的问题。
2024-10-13 17:53:37 +08:00
8bd7113153
Add a tracking spell.
加入跟踪法术。
2024-10-12 14:49:21 +08:00
35cb1296c7
Add Magic missile.
加入魔法飞弹。
2024-10-12 10:57:58 +08:00
16c1a8185c
Fixed an issue where triple shot spells did not work.
修复三重射击法术无效的问题。
2024-10-11 19:49:00 +08:00
e0e4c80e94
Example Remove the ability to upload logs to the server.
移除向服务器上传日志的功能。
2024-10-11 17:59:47 +08:00
94e620befd
Upgrade the dependent library.
升级依赖库。
2024-10-11 17:33:57 +08:00
1fee1cce86
Adjust when to load resources.
调整加载资源的时机。
2024-10-11 17:22:31 +08:00
e21d37edce
Fixed an issue where players were blocked by a wall when entering a room.
修复玩家进入房间时被墙挡住的问题。
2024-10-11 14:52:39 +08:00
891986f706
Thrown items no longer have collision damage.
扔出的物品不再具有碰撞伤害。
2024-10-11 10:22:28 +08:00
fc1a12acd0
Players standing on the edge of the platform can also jump down.
玩家站在平台边缘也可以向下跳跃了。
2024-10-10 16:29:54 +08:00
eb6be280e0
Fixed an issue where weapons would block projectiles.
修复武器会阻挡抛射体的问题。
2024-10-10 16:03:07 +08:00
c2e84783e8
The player will no longer always use items when interacting with the UI or furniture.
当玩家与UI或家具交互时不再一直使用持有的物品了。
2024-10-10 14:11:34 +08:00
f3c46f2668
Fixed an issue where items would not be lost after player death.
修复玩家死亡后物品不会丢失的问题。
2024-10-10 10:53:13 +08:00
88813fe837
Fixed an issue where items held in hand would not refresh when placing them in a selected slot.
修复将物品放到已选中的槽位时,手中持有的物品没刷新的问题。
2024-10-10 10:13:54 +08:00
9416993849
Give the enemy pause after the attack.
使敌人攻击后有所停顿。
2024-10-09 21:21:38 +08:00
35dc2ee1b9
Make the barrier stop pickables.
使屏障可阻止可拾捡物。
2024-10-09 17:36:59 +08:00
5b5a9ae198
Fixed an issue where Ai characters could not attack with weapons.
修复Ai角色使用武器无法攻击的问题。
2024-10-09 16:51:03 +08:00
3695a7ef11
Add beginner's wand.
加入初学者法杖。
2024-10-09 15:54:43 +08:00
929dfb5f2f
Unified Resource loading api, projectile weapon allows to configure spells.
统一资源加载的api,抛射体武器允许配置法术。
2024-10-09 10:49:10 +08:00
d1c0f1e265
Add animations to show and hide mini maps.
为迷你地图的显示和隐藏加入动画。
2024-10-09 10:21:26 +08:00
53889ef2fd
Support split-wave Spawn monsters now.
支持分波次刷出怪物了。
2024-10-08 22:04:37 +08:00
d80c49ab02
Adjust the time of spawns of items and enemies in the map to when the player first enters the room.
将地图中物品,敌人生成的时机调整到玩家首次进入房间时。
2024-10-08 16:11:51 +08:00
5371d31d99
Split the function that places the barrier.
拆分放置屏障的函数。
2024-10-08 10:52:42 +08:00
5f9961aad7
Update texture.
更新纹理。
2024-10-08 09:59:33 +08:00
dd89150026
Remove operation prompt.
移除操作提示。
2024-10-08 09:33:41 +08:00
726e2b3d00
Fixed an issue where the triple shot spell could not be used.
修复三重射击法术无法使用的问题。
2024-10-08 09:26:11 +08:00
feeb8261e3
Fixed an issue where items were overwritten using the wrong index when picking them up.
修复捡起物品时,使用错误的索引导致物品覆盖的问题。
2024-10-08 09:03:10 +08:00
291ef653f0
Added wooden boxes and tutorial levels.
加入木箱子和教程关卡。
2024-10-07 23:29:08 +08:00
a9ab4a687c
Add the Necromancy Curse spell.
加入死灵诅咒法术。
2024-10-07 15:42:54 +08:00
25ad117d6f
Add melee weapons.
加入近战武器。
2024-10-07 15:17:04 +08:00
f313240400
The discharge certificate will no longer be deducted.
离职证明不再持续扣血了。
2024-10-06 16:10:00 +08:00
02f2fa0d93
Joining and leaving certificate.
加入离职证明。
2024-10-06 12:04:59 +08:00
bfc5ee6ac9
Modify the texture.
修改纹理。
2024-10-06 09:47:36 +08:00
4a4d4a0c37
Fixed an issue where AI could not pick up weapons.
修复AI不能捡起武器的问题。
2024-10-05 20:56:50 +08:00
4e83bca579
Ignore the Android build directory.
忽略安卓的编译目录。
2024-10-05 20:02:14 +08:00
6d9b9ca7ec
Improved the loading range of spells.
改进法术的加载范围。
2024-10-05 17:15:19 +08:00
3f96519ac0
Add the triple shot spell.
加入三重射击法术。
2024-10-05 16:19:31 +08:00
407798b13b
Recoil is calculated only after successful firing.
仅在成功开火后计算后座力。
2024-10-05 10:53:07 +08:00
e718d78137
Fixed item ID and its container being lost when throwing items. Pick up the weapon again can not fire the bullet issue.
修复扔出物品时,物品的ID与自身的物品容器丢失。再次捡起武器无法发射子弹的问题。
2024-10-05 10:20:55 +08:00
b7805c5804
Fixed array subscript out of bounds issue.
修复数组下标越界的问题。
2024-10-05 09:52:53 +08:00
839d60b62a
Allows players to reload projectiles on their weapons.
允许玩家对武器装填抛射体了。
2024-10-05 09:13:14 +08:00
8a7a9bcf5d
Now supports spawning spell items.
支持生成法术物品了。
2024-10-04 20:53:34 +08:00
124c6ce0ba
The UI will be automatically closed when the player leaves the range of the furniture. The spell editor is now able to load information about items placed in it.
玩家离开家具的操作范围时会自动关闭UI了。法术编辑器现在能够加载放入的物品信息。
2024-10-04 16:13:34 +08:00
2d7985010d
Add item types. Item containers now support limiting added item types. Added spell classes for projectile weapons.
加入物品类型,物品容器支持限制添加的物品类型了。加入适用于抛射体武器的法术类。
2024-10-04 10:21:09 +08:00
bb0f582fed
Fixed an issue where the spell Editor could not remove items placed in the second time.
修复法术编辑器二次放入物品无法取出的问题。
2024-10-01 20:53:56 +08:00
81344faa3e
Add animation to spell editor.
加入法术编辑器的动画。
2024-10-01 15:01:34 +08:00
77f2bac36e
Adds UI to spell editor.
加入法术编辑器的UI。
2024-09-30 22:13:51 +08:00
67706ca9d7
Ignore the fleet directory.
忽略fleet目录。
2024-09-30 09:10:34 +08:00
bfec07a0de
Fixed When switching items, players would have multiple items stacked on their hands.
修复切换物品时,玩家手上会叠加多个物品。
2024-09-30 08:56:00 +08:00
c1c3fce58a
Allows players to drag items onto the item container for quick storage.
允许玩家将物品拖到物品容器上以便快速入库。
2024-09-29 23:30:42 +08:00
2d92a92faf
Backpacks are no longer allowed in backpacks.
不允许背包内放置背包了。
2024-09-29 22:12:54 +08:00
31a1d292d8
Fixed an issue where players could pick up items in the backpack after throwing it.Supports placing items across item containers
修复玩家扔出背包后,再捡起背包内的物品消失的问题。支持跨容器替换物品了。
2024-09-28 22:59:25 +08:00
4f2208bd60
Improving the ability to drag items, there are still some issues.
改进拖动物品的功能,仍然存在一些问题。
2024-09-27 23:24:22 +08:00
617164a4bc
Fixed an issue where the inventory icon was not updated after the player threw an item.
修复玩家扔出物品后,物品栏没有更新图标的问题。
2024-09-27 21:16:00 +08:00
efff63ddd4
Item containers no longer store items consecutively.
物品容器不再按照索引存储物品了。
2024-09-27 20:53:04 +08:00
f881d43c3b
Bind the backpack to the ui.
使背包和ui绑定。
2024-09-26 22:43:10 +08:00
b53f5bc2df
Remove the drag and drop item code.
移除拖拽物品的代码。
2024-09-25 23:01:52 +08:00
b9a9349596
Fixed an issue where two items would be selected at the same time when the player picked up the item and re-selected it.
修复玩家捡起物品后,重新选中物品,会有两个物品同时被选择的问题。
2024-09-25 21:56:54 +08:00
b7c3651462
Use placeholders to resolve the problem that an empty slot cannot be selected in the shortcut bar.
使用占位符来解决快捷栏无法选中空槽位的问题。
2024-09-23 23:17:57 +08:00
63680a9410
Add an event where item data changes.
加入物品数据改变的事件。
2024-09-23 21:03:39 +08:00
234241b74a
Bind the item container to the item container display.
将物品容器和物品容器显示器绑定。
2024-09-22 23:13:59 +08:00
32299877c6
Item containers maintain item collections, not item slots.
物品容器将维护物品集合,而不是物品槽。
2024-09-22 16:51:42 +08:00
2c6f8804ba
Do not create duplicate ui nodes in the same ui group.
禁止在同一个ui组,创建重复的ui节点。
2024-09-18 23:19:38 +08:00
899337e8e3
Fixes pickups flying out of walls, supports pushing furniture by pressing f.
修复可拾捡物飞出墙壁,支持按下f键推动家具。
2024-09-18 21:28:54 +08:00
cb19423cb0
Modifying a node Name.
修改节点名称。
2024-09-18 20:20:02 +08:00
c25d985f87
Improve the efficiency of backpack UI toggle visibility. Prepare for the upcoming workbench UI.
提升背包UI切换可见度时的效率。为即将到来的工作台UI做准备。
2024-09-14 23:38:57 +08:00
ba11bf06da
Make spell separation table.
制作法术分离工作台。
2024-09-13 23:04:39 +08:00
fc8d33b28d
Update the list of contributors.
更新贡献者名单。
2024-09-09 22:26:07 +08:00
4ae8a5d470
Fixed an issue where some room slots could not be blocked.
修复某些房间槽无法被堵住的问题。
2024-09-09 22:22:03 +08:00
1e019339d8
After the map is generated, tiles will be copied from the Barrier layer when unused slots appear. Plug the slot.
生成地图后,当出现尚未使用的插槽,将会从Barrier层拷贝瓦片。堵上插槽。
2024-09-08 21:17:05 +08:00
ce8f9121a5
No more drawing unexplored rooms.
不再绘制未探索过的房间了。
2024-09-08 09:45:14 +08:00
26c0843202
Hands over the responsibility of creating room previews to the minimap.
将创建房间预览图的职责移交给迷你地图。
2024-09-06 23:36:21 +08:00
ab0d05d16d
Makes the map follow the player's movements.
使地图跟随玩家移动。
2024-09-06 22:56:36 +08:00
Cold-Mint
ed4339f390
Merge pull request #8 from Ride-A-Pig/master
Minimap bug fix
2024-09-05 12:42:58 +08:00
Ride_A_Pig
ab10d75b24 Minimap bug fix
修复小地图错位问题
2024-09-05 12:34:41 +08:00
781c50ee30
Add debugging information to the mini map.
为迷你地图加入调试信息。
2024-09-05 11:50:05 +08:00
41a2cebf41
Improved recoil algorithm.
改进后座力算法。
2024-09-04 23:23:22 +08:00
1429b879e8
Can generate a preview and place it in the mini-map.
能够生成预览图并将其放置到迷你地图内了。
2024-09-01 23:24:35 +08:00
c1a3bfa266
Improved weapon recoil effect.
改进武器的后座力效果。
2024-09-01 22:25:20 +08:00
1ef0f08e2f
Create a map preview image.
制作地图预览图。
2024-08-27 23:06:33 +08:00
5b0803f85f
After the player leaves the room, the previous room vision is deprived and enemies are frozen.
玩家离开房间后上个房间视野将被剥夺,敌人被冻结。
2024-08-25 18:49:48 +08:00
38c0bdff2a
Join the fog of war.
加入战争迷雾。
2024-08-24 22:49:59 +08:00
4f16214885
Modified the knockback algorithm.
修改击退算法。
2024-08-22 22:03:44 +08:00
d3f2076b11
Fix the issue of picking up lost attributes after losing weapons.
修复失去武器后再捡起丢失属性的问题。
2024-08-20 22:17:07 +08:00
cff0507d25
Bullet tracking will no longer penetrate the wall.
子弹跟踪不再会穿透墙壁了。
2024-08-20 00:15:12 +08:00
2a5629fc86
Projectiles can now track enemies.
抛射体可以跟踪敌人了。
2024-08-18 16:09:31 +08:00
8c02a0548c
Upgrade to 4.3.
升级到4.3。
2024-08-15 22:58:28 +08:00
5d9643476f
Bullets can now track enemies.
子弹可以跟踪敌人了。
2024-08-14 23:08:07 +08:00
451d6d0849
Add bullet arc and number of bullets generated.
加入子弹弧度和产生子弹的数量
2024-08-13 23:07:05 +08:00
3b2ba7440c
Improved the collision logic of bullets.
改进子弹的碰撞逻辑。
2024-08-12 22:30:13 +08:00
ef58f3885b
The projectile weapon allows the projectile queue to be fired sequentially.
抛射体武器,允许循序发射抛射体队列了。
2024-08-11 23:29:23 +08:00
05ac2dec60
Join Mr. Raven.
加入乌鸦先生。
2024-08-11 00:25:00 +08:00
e10e22e3bd
Update Readme.
更新Readme。
2024-08-10 22:01:49 +08:00
56d3ae4964
Restore the database.
恢复数据库。
2024-08-06 00:27:51 +08:00
cceda0bd1f
Remove the GetMeta method.
移除GetMeta方法。
2024-08-05 22:52:20 +08:00
4459b6a88b
Added the game difficulty configuration class and added the ability to generate scenes after projectiles kill enemies.
加入游戏难度的配置类,加入抛射体杀死敌人后生成场景的功能。
2024-08-04 00:32:49 +08:00
bac2ae1992
Modifies the return value of the damage Api to whether fatal damage has been inflicted. Add the projectile decorator.
修改伤害Api的返回值为是否造成了致命伤害。加入抛射体装饰器。
2024-08-02 23:57:11 +08:00
e54b62cb82
Item ids can only be specified in yaml files.
物品的id只能在yaml文件内指定了。
2024-08-01 23:30:28 +08:00
074f11e971
Ignore the.vscode directory.
忽略.vscode目录。
2024-07-31 22:52:29 +08:00
219f207472
Remove custom parameters in yaml. Rename the resource file.
移除在yaml内的自定义参数。重命名资源文件。
2024-07-31 22:14:40 +08:00
c397aff026
Add sound effects.
加入音效。
2024-07-28 17:53:54 +08:00
d143cf8dbf
Fixed bullet through wall issue.
修复子弹穿墙的问题。
2024-07-28 11:12:53 +08:00
f4660fe581
Adjust Mod timing, temporarily disable Mod.
调整Mod时序,暂时禁用Mod。
2024-07-28 10:09:44 +08:00
d95515fdb7
ModLoader now support calling entry functions.
模组加载器现在支持调用入口函数了。
2024-07-27 22:06:10 +08:00
a7a5a309a2
Migrate TileMap to TileMapLayer. Development using version 4.3 of Godot.
迁移TileMap到TileMapLayer。使用4.3版本Godot进行研发。
2024-07-26 22:38:18 +08:00
203 changed files with 8087 additions and 3270 deletions

7
.gitignore vendored
View File

@ -1,8 +1,13 @@
# Godot 4+ specific ignores
.godot/
export_presets.cfg
.idea/
.vs/
.vscode/
.fleet/
# Ignore the Android build directory
android/
export_presets.cfg
*.translation
*.user
AppConfig.yaml
ColdMint.Traveler.csproj.old

View File

@ -1,4 +1,4 @@
<Project Sdk="Godot.NET.Sdk/4.2.2">
<Project Sdk="Godot.NET.Sdk/4.3.0">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework Condition=" '$(GodotTargetPlatform)' == 'android' ">net7.0</TargetFramework>
@ -9,7 +9,9 @@
<LangVersion>12</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2023.3.0" />
<PackageReference Include="YamlDotNet" Version="15.1.6" />
<PackageReference Include="JetBrains.Annotations" Version="2024.2.0" />
<PackageReference Include="YamlDotNet" Version="16.1.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="6.0.29" />
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.10" />
</ItemGroup>
</Project>

View File

@ -10,12 +10,12 @@ A pixel cross-platform roguelite game.
## Recent Development progress
| Task | status |
| ----------------------------------------------------------- | ------------------ |
| Randomly generated map | complete |
| loot | complete |
| Support still out of the knapsack system | complete |
| Add AI agents to creatures | In progress |
| Task | status |
|------------------------------------------|-------------|
| Randomly generated map | complete |
| loot | complete |
| Support still out of the knapsack system | complete |
| Add AI agents to creatures | In progress |
## Screenshot
@ -30,12 +30,20 @@ Level graph editor
## Run the project locally
#### Download engine
1. Download [Godot Engine .Net](https://godotengine.org/).
After downloading the engine, you will need to download an additional export template to export as an executable program.
After downloading the engine, you will need to download an additional export template to export as an executable
program.
2. Download [.NetSDK](https://dotnet.microsoft.com/download).
Ubuntu or Linux Mint install the .net 8.0 Sdk.
```
apt install dotnet-sdk-8.0
```
#### Clone project
Enter the following command in your working directory:
@ -55,44 +63,29 @@ data/*
#### Custom feature
- **disableVersionIsolation** Disable version isolation.
- **enableMod** Experimental feature, the game loads dll files and pck files in the mod directory when the mod is
enabled. Due to the isolation of AssemblyLoadContext, the main game content cannot be accessed from within the Mod for
the time being.
## Configuring Openobserve
#### Run the console on Linux
> This is optional, and the game will work even if you do not configure Openobserve.
Enter the following command in the directory where the game is located:
openobserve is used to continuously collect logs and alarm information after a game has been released.
#### Set up the openobserve server
see[openobserve](https://github.com/openobserve/openobserve)
#### Write configuration
After you have set up an openobserve server, follow the following steps to configure the file:
1. Create a configuration file named **AppConfig.yaml** in the root directory of your project.
2. Fill in the information for the remote server.
```yaml
open_observe:
address: [address]
access_token: [token]
org_id: [org_id]
stream_name: [stream_name]
```
address Indicates the address of the server in the format of http(s)://www.example.com. (Support http and https)
```
./Traveler.sh
```
## Participate in translation
The project is prepared for localization at the beginning of writing. You can edit the csv file in the locals directory. To modify and add new translations.
The project is prepared for localization at the beginning of writing. You can edit the csv file in the locals directory.
To modify and add new translations.
## License
[GPL-3.0 license](LICENSE)
Support commercial, anyone can modify, build, and sell or distribute for free. For all derivative versions of this project, under the GPL, you shall **retain the author copyright** and **publish the modified source code**.
Support commercial, anyone can modify, build, and sell or distribute for free. For all derivative versions of this
project, under the GPL, you shall **retain the author copyright** and **publish the modified source code**.
> Note: You have the right to sell the modified version, but not the original.
>

View File

@ -34,6 +34,13 @@
2. ダウンロード [.NetSDK](https://dotnet.microsoft.com/download).
UbuntuやLinux Mintに。net8.0Sdkをインストールします。
```
apt install dotnet-sdk-8.0
```
#### クローンプロジェクトです
作業リストに次の指示を入力します。
@ -53,35 +60,15 @@ data/*
#### 風習特徴
- **disableVersionIsolation** 版孤立を無効化する。
- **enableMod**実験的な機能、modが有効になっている場合、ゲームはmodディレクトリにdllファイルとpckファイルをロードします。assemblyloadcontextが分離されているため、当面の間、mod内からメインゲームのコンテンツにアクセスすることはできません。
## はいちOpenobserve
#### Linux上でコンソールを動かします
> これはオプションなので、Openobserveを設定しなくてもゲームは正常に動作します。
openobserveは、リリース後にログやアラームを継続的に収集するために使用されます。
#### 搭建openobserve衣服务器
読み過ごす:[openobserve](https://github.com/openobserve/openobserve)
#### 構成を書きます
openobserveのサーバーを構築したら、次のようにファイルを設定します。
1. プロジェクトのルートディレクトリに**AppConfig.yaml **というプロファイルを作成します。
2. リモートサーバーの情報を入力します。
```yaml
open_observe:
address: [address]
access_token: [token]
org_id: [org_id]
stream_name: [stream_name]
```
address サーバーのアドレス、フォーマットはこうなります http(s)://www.example.com。支持http和https
ゲームの存在するディレクトリに以下のコマンドを入力します:
```
./Traveler.sh
```
## 翻訳に携わります
このプロジェクトは、当初からローカライズの準備ができていました。localsディレクトリのcsvファイルを編集することができます。新しい翻訳を加えたり修正したりしています

View File

@ -10,11 +10,11 @@
## 近期研发进度
| 任务 | 状态 |
| ----------------------------------------------------------- |----|
| 随机生成地图 | 完成 |
| 战利品 | 完成 |
| 支持仍出的背包系统 | 完成 |
| 任务 | 状态 |
|-----------|-----|
| 随机生成地图 | 完成 |
| 战利品 | 完成 |
| 支持仍出的背包系统 | 完成 |
| 为生物添加AI代理 | 进行中 |
## 屏幕截图
@ -30,12 +30,19 @@
## 在本地运行项目
#### 下载引擎
1. 下载[Godot Engine .Net](https://godotengine.org/)。
下载引擎后,您需要额外下载导出模板才能导出为可执行程序。
2. 下载 [.NetSDK](https://dotnet.microsoft.com/download).
Ubuntu或Linux Mint安装.net8.0Sdk。
```
apt install dotnet-sdk-8.0
```
#### 克隆项目
在您的工作目录输入以下指令:
@ -55,34 +62,15 @@ data/*
#### 自定义特性
- **disableVersionIsolation** 禁用版本隔离。
- **enableMod** 实验性功能当启用模组时游戏会在mod目录加载dll文件和pck文件。由于AssemblyLoadContext的隔离性暂时不能从Mod内访问主游戏内容。
## 配置Openobserve
#### 在Linux上运行控制台
> 这是可选的操作即使您不配置Openobserve游戏也能正常运行。
在游戏所在目录输入以下命令:
openobserve用于在游戏发布后持续收集日志和报警信息。
#### 搭建openobserve服务器
请见:[openobserve](https://github.com/openobserve/openobserve)
#### 编写配置
在您搭建完毕openobserve的服务器后按如下步骤配置文件
1. 在项目的根目录创建名为**AppConfig.yaml**的配置文件。
2. 填入远程服务器的信息。
```yaml
open_observe:
address: [address]
access_token: [token]
org_id: [org_id]
stream_name: [stream_name]
```
address 服务器的地址,格式为 http(s)://www.example.com。支持http和https
```
./Traveler.sh
```
## 参与翻译
@ -94,7 +82,8 @@ openobserve用于在游戏发布后持续收集日志和报警信息。
查看协议的中文翻译版本:[GPL-3.0 license 简体中文](LICENSE_ZH)
支持商用任何人可修改构建并用于售卖或免费发布。对于此项目的所有衍生版本根据GPL协议您应当**保留作者版权**,以及**公开修改后的源代码**。
支持商用任何人可修改构建并用于售卖或免费发布。对于此项目的所有衍生版本根据GPL协议您应当**保留作者版权**,以及*
*公开修改后的源代码**。
> 注意:您有权售卖修改后的版本,但不能售卖原版。

10
data/itemRegs/items.yaml Normal file
View File

@ -0,0 +1,10 @@
#Register items 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: resignation_certificate
scene_path: res://prefab/items/resignationCertificate.tscn
icon_path: res://sprites/projectile/resignationCertificate.png
max_stack_value: 1

26
data/itemRegs/magics.yaml Normal file
View File

@ -0,0 +1,26 @@
#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
- id: x3
scene_path: res://prefab/magics/x3.tscn
icon_path: res://sprites/projectile/x3.png
max_stack_value: 1
- id: curse
scene_path: res://prefab/magics/curse.tscn
icon_path: res://sprites/projectile/x3.png
max_stack_value: 1
- id: magic_missile
scene_path: res://prefab/magics/magicMissile.tscn
icon_path: res://sprites/projectile/magicMissile.png
max_stack_value: 1
- id: tracking_spell
scene_path: res://prefab/magics/trackingSpell.tscn
icon_path: res://sprites/projectile/trackingSpell.png
max_stack_value: 1

View File

@ -1,4 +1,13 @@
- id: packsack
scene_path: res://prefab/packsacks/packsack.tscn
icon_path: res://sprites/packsack.png
#Register an item container 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。
#portable_backpacks
#便携式背包
- id: portable_backpacks
scene_path: res://prefab/packsacks/PortableBackpacks.tscn
icon_path: res://sprites/PortableBackpacks.png
max_stack_value: 1

View File

@ -1,20 +1,25 @@
- id: 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: UniqueName
type: string
value: 爱你!
#Register your weapon 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: degraded_staff_of_the_undead
scene_path: res://prefab/weapons/staffOfTheUndead.tscn
icon_path: res://sprites/weapon/staffOfTheUndead_icon.png
#staff_necromancy
#死灵法杖
# The Necromancy Staff will act differently on different difficulties.
#死灵法杖在不同的难度下会有不同的行为。
#The probability of generating monsters is as follows:Hard mode 100%, Normal mode 75%, easy mode 5%
#以下是在击杀敌人后生成怪物的概率困难模式100%普通模式75%简单模式5%
- id: staff_necromancy
scene_path: res://prefab/weapons/StaffNecromancy.tscn
icon_path: res://sprites/weapon/StaffNecromancy_Icon.png
max_stack_value: 1
- id: iron_axe
scene_path: res://prefab/weapons/IronAxe.tscn
icon_path: res://sprites/weapon/StaffNecromancy_Icon.png
max_stack_value: 1
- id: beginner_staff
scene_path: res://prefab/weapons/BeginnerStaff.tscn
icon_path: res://sprites/weapon/BeginnerStaff_Icon.png
max_stack_value: 1
custom_args:
- name: FiringIntervalAsMillisecond
type: int
value: 1000
- name: UniqueName
type: string
value: item_staff_of_the_undead_desc

View File

@ -1,57 +1,181 @@
connection_data_list:
- from_id: c0255eb6-2c75-44f7-9058-0921fe8fb0d8
to_id: 4ae948ea-82b7-4b2d-bec2-19ed8a9d4c03
- from_id: 5a284c6f-2ce5-4dba-b32e-f0fcb9e9940d
to_id: 4de20bd2-b557-4c29-9613-d4b35ea1f239
from_port: 0
to_port: 0
- from_id: 4ae948ea-82b7-4b2d-bec2-19ed8a9d4c03
to_id: ba32e05c-0c80-4a79-b5ce-5b8150400e05
- from_id: 4de20bd2-b557-4c29-9613-d4b35ea1f239
to_id: 3053d123-3f71-4cd0-8f05-f821aa95c702
from_port: 0
to_port: 0
- from_id: 4ae948ea-82b7-4b2d-bec2-19ed8a9d4c03
to_id: 8b3d645a-96c0-407e-871d-6f4a0b69557b
- from_id: 3053d123-3f71-4cd0-8f05-f821aa95c702
to_id: fcc9333c-e70f-4a28-9029-1b1098502049
from_port: 0
to_port: 0
- from_id: 8b3d645a-96c0-407e-871d-6f4a0b69557b
to_id: 7e3ae680-3d7e-4ae9-b82f-5bfbe1c2f613
- from_id: fcc9333c-e70f-4a28-9029-1b1098502049
to_id: 627b8abc-abb9-4117-bdea-9f818a69f972
from_port: 0
to_port: 0
- from_id: ba32e05c-0c80-4a79-b5ce-5b8150400e05
to_id: 7e3ae680-3d7e-4ae9-b82f-5bfbe1c2f613
- from_id: 627b8abc-abb9-4117-bdea-9f818a69f972
to_id: 478eee96-e8f6-4eea-82cd-a2ab3f54e015
from_port: 0
to_port: 0
- from_id: 478eee96-e8f6-4eea-82cd-a2ab3f54e015
to_id: b2dba7b5-baab-4911-be58-7f54bdf89f86
from_port: 0
to_port: 0
- from_id: fcc9333c-e70f-4a28-9029-1b1098502049
to_id: fb43e864-e7b8-4482-a43a-34612b14aa94
from_port: 0
to_port: 0
- from_id: 627b8abc-abb9-4117-bdea-9f818a69f972
to_id: fab80988-f9b6-4e53-91cd-4c063d9cb1fb
from_port: 0
to_port: 0
- from_id: fb43e864-e7b8-4482-a43a-34612b14aa94
to_id: 89805068-5b2f-4f44-92b4-58d4df704341
from_port: 0
to_port: 0
- from_id: fab80988-f9b6-4e53-91cd-4c063d9cb1fb
to_id: d28a2647-a7f3-4179-a91d-d4a1d38a7438
from_port: 0
to_port: 0
- from_id: 89805068-5b2f-4f44-92b4-58d4df704341
to_id: 53abd2f0-995f-4d37-8b2f-058c70282fbd
from_port: 0
to_port: 0
- from_id: 53abd2f0-995f-4d37-8b2f-058c70282fbd
to_id: c702286c-5f8a-417b-9220-769bdfc1ea8c
from_port: 0
to_port: 0
- from_id: c702286c-5f8a-417b-9220-769bdfc1ea8c
to_id: 310c226b-dbb2-4193-b386-7b018a725228
from_port: 0
to_port: 0
room_node_data_list:
- id: c0255eb6-2c75-44f7-9058-0921fe8fb0d8
title: 起点房间
description: 测试的起点房间。
- id: 5a284c6f-2ce5-4dba-b32e-f0fcb9e9940d
title: 房间1
description: ''
room_template_set:
- 'res://prefab/roomTemplates/dungeon/initialRoom.tscn'
- res://prefab/roomTemplates/tutorials/spellEditor.tscn
tags:
- StartingRoom
room_injection_processor_data: null
- id: ba32e05c-0c80-4a79-b5ce-5b8150400e05
room_injection_processor_data: ''
enter_room_event_handler_id:
exit_room_event_handler_id:
- id: 4de20bd2-b557-4c29-9613-d4b35ea1f239
title: 房间2
description: ''
room_template_set:
- res://prefab/roomTemplates/tutorials/tripleShotSpell.tscn
tags:
room_injection_processor_data: ''
enter_room_event_handler_id:
exit_room_event_handler_id:
- id: 3053d123-3f71-4cd0-8f05-f821aa95c702
title: 房间3
description: ''
room_template_set:
- 'res://prefab/roomTemplates/dungeon/'
tags: null
- id: 4ae948ea-82b7-4b2d-bec2-19ed8a9d4c03
title: 大厅
description: 比普通房间要大一些的房间,有多个门,用于连接到其他房间。
room_template_set:
- 'res://prefab/roomTemplates/dungeon/utilityRoom.tscn'
tags: null
room_injection_processor_data: null
- id: 8b3d645a-96c0-407e-871d-6f4a0b69557b
- res://prefab/roomTemplates/dungeon/
tags:
room_injection_processor_data: ''
enter_room_event_handler_id:
exit_room_event_handler_id:
- id: fcc9333c-e70f-4a28-9029-1b1098502049
title: 房间4
description: ''
room_template_set:
- 'res://prefab/roomTemplates/dungeon/'
tags: null
- res://prefab/roomTemplates/dungeon/
tags:
room_injection_processor_data: ''
- id: 7e3ae680-3d7e-4ae9-b82f-5bfbe1c2f613
enter_room_event_handler_id:
exit_room_event_handler_id:
- id: 627b8abc-abb9-4117-bdea-9f818a69f972
title: 房间5
description: ''
room_template_set:
- 'res://prefab/roomTemplates/dungeon/'
tags: null
- res://prefab/roomTemplates/dungeon/
tags:
room_injection_processor_data: ''
enter_room_event_handler_id:
exit_room_event_handler_id:
- id: 478eee96-e8f6-4eea-82cd-a2ab3f54e015
title: 房间6
description: ''
room_template_set:
- res://prefab/roomTemplates/dungeon/
tags:
room_injection_processor_data: ''
enter_room_event_handler_id:
exit_room_event_handler_id:
- id: b2dba7b5-baab-4911-be58-7f54bdf89f86
title: 房间7
description: ''
room_template_set:
- res://prefab/roomTemplates/dungeon/
tags:
room_injection_processor_data: ''
enter_room_event_handler_id:
exit_room_event_handler_id:
- id: fb43e864-e7b8-4482-a43a-34612b14aa94
title: 房间8
description: ''
room_template_set:
- res://prefab/roomTemplates/dungeon/
tags:
room_injection_processor_data: ''
enter_room_event_handler_id:
exit_room_event_handler_id:
- id: fab80988-f9b6-4e53-91cd-4c063d9cb1fb
title: 房间9
description: ''
room_template_set:
- res://prefab/roomTemplates/dungeon/
tags:
room_injection_processor_data: ''
enter_room_event_handler_id:
exit_room_event_handler_id:
- id: d28a2647-a7f3-4179-a91d-d4a1d38a7438
title: 房间11
description: ''
room_template_set:
- res://prefab/roomTemplates/dungeon/
tags:
room_injection_processor_data: ''
enter_room_event_handler_id:
exit_room_event_handler_id:
- id: 89805068-5b2f-4f44-92b4-58d4df704341
title: 房间10
description: ''
room_template_set:
- res://prefab/roomTemplates/dungeon/
tags:
room_injection_processor_data: ''
enter_room_event_handler_id:
exit_room_event_handler_id:
- id: c702286c-5f8a-417b-9220-769bdfc1ea8c
title: 房间13
description: ''
room_template_set:
- res://prefab/roomTemplates/dungeon/
tags:
room_injection_processor_data: ''
enter_room_event_handler_id:
exit_room_event_handler_id:
- id: 53abd2f0-995f-4d37-8b2f-058c70282fbd
title: 房间12
description: ''
room_template_set:
- res://prefab/roomTemplates/dungeon/
tags:
room_injection_processor_data: ''
enter_room_event_handler_id:
exit_room_event_handler_id:
- id: 310c226b-dbb2-4193-b386-7b018a725228
title: 房间14
description: ''
room_template_set:
- res://prefab/roomTemplates/dungeon/
tags:
room_injection_processor_data: ''
enter_room_event_handler_id:
exit_room_event_handler_id:

15
default_bus_layout.tres Normal file
View File

@ -0,0 +1,15 @@
[gd_resource type="AudioBusLayout" format=3 uid="uid://cdugntqhtcyd"]
[resource]
bus/1/name = &"BGM"
bus/1/solo = false
bus/1/mute = false
bus/1/bypass_fx = false
bus/1/volume_db = 0.0
bus/1/send = &"Master"
bus/2/name = &"SoundEffect"
bus/2/solo = false
bus/2/mute = false
bus/2/bypass_fx = false
bus/2/volume_db = -0.0127316
bus/2/send = &"Master"

View File

@ -15,6 +15,7 @@ dest_files=["res://.godot/imported/ark-pixel-12px-proportional-zh_cn.ttf-478ad47
Rendering=null
antialiasing=1
generate_mipmaps=false
disable_embedded_bitmaps=true
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48

3
locals/Character.csv Normal file
View File

@ -0,0 +1,3 @@
id,zh,en,ja
character_necromancer,死灵法师,Necromancer,ネクロマンサー
character_evil_crow,邪恶的乌鸦先生,Evil Mr. Raven,悪のミスター・レイヴン
1 id zh en ja
2 character_necromancer 死灵法师 Necromancer ネクロマンサー
3 character_evil_crow 邪恶的乌鸦先生 Evil Mr. Raven 悪のミスター・レイヴン

View File

@ -0,0 +1,17 @@
[remap]
importer="csv_translation"
type="Translation"
uid="uid://dwrygxaehoybb"
[deps]
files=["res://locals/Character.zh.translation", "res://locals/Character.en.translation", "res://locals/Character.ja.translation"]
source_file="res://locals/Character.csv"
dest_files=["res://locals/Character.zh.translation", "res://locals/Character.en.translation", "res://locals/Character.ja.translation"]
[params]
compress=true
delimiter=0

View File

@ -3,6 +3,9 @@ id,zh,en,ja
#自杀
death_info_self_1,{0}误伤了自己。,{0} accidentally shot themself.,{0}誤って自分を傷つけました。
death_info_self_2,{0}忘记了瞄准。,{0} forgot to aim.,{0}照準を忘れました。
#Died reading a separation certificate.
#死于阅读离职证明。
death_info_resignation_certificate,{0}阅读冷薄荷的离职证明被毒害了!(你知道的太多了),{0} Read Cold Mint's separation certificate was poisoned!(You know too much),{0}コールドミントの離職証明書を読んで毒されました!(あなたは知りすぎです)
#Default death message
#默认死亡信息
death_info_default,{0}被{1}杀死了。,{0} is killed by {1}.,{0}は{1}に殺されました。
1 id,zh,en,ja
3 #自杀
4 death_info_self_1,{0}误伤了自己。,{0} accidentally shot themself.,{0}誤って自分を傷つけました。
5 death_info_self_2,{0}忘记了瞄准。,{0} forgot to aim.,{0}照準を忘れました。
6 #Died reading a separation certificate.
7 #死于阅读离职证明。
8 death_info_resignation_certificate,{0}阅读冷薄荷的离职证明被毒害了!(你知道的太多了),{0} Read Cold Mint's separation certificate was poisoned!(You know too much),{0}コールドミントの離職証明書を読んで毒されました!(あなたは知りすぎです)
9 #Default death message
10 #默认死亡信息
11 death_info_default,{0}被{1}杀死了。,{0} is killed by {1}.,{0}は{1}に殺されました。

View File

@ -1,5 +1,21 @@
id,zh,en,ja
item_staff_of_the_undead,死灵法杖,StaffOfTheUndead,ネクロポリスの杖です
item_staff_of_the_undead_desc,发射诅咒,可将敌人转化为邪恶的怪物。,Cast a curse that transforms enemies into evil monsters.,呪いを発射して、敵を邪悪な怪物に変えることができます。
item_packsack,背包,Packsack,背嚢
item_packsack_desc,可以装载更多物品的背包。,A backpack that can hold more items.,より多くのアイテムを保持できるバックパックです。
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つのアイテムスロットを提供します。
item_necromancy,死灵法术,necromancy,ネクロマンシー
item_necromancy_desc,法术的实体化弹丸。,The materialized projectile of a spell.,術の実体化した弾丸です。
item_x3,三重射击法术,Triple shot spell,三重射撃術です
item_x3_desc,使发射器一次射出三颗弹丸。,Make the launcher shoot three pellets at a time.,発射機から一度に三つの弾丸を発射させます。
item_resignation_certificate,离职证明,Resignation certificate,退職証明書です
item_resignation_certificate_desc,冷薄荷,感谢您在职时为公司做出的贡献。,"Cold Mint, thank you for your service to the company.",コールドミント、現役時代のご貢献ありがとうございました。
item_iron_axe,铁斧子,Iron axe,鉄の斧です
item_iron_axe_desc,铁斧子,Iron axe,鉄の斧です
item_curse,死灵诅咒法术,The curse of the Dead,死霊呪いの術
item_curse_desc,杀死敌人后在生成死灵敌人。,Spawn Undead enemies after killing them.,敵を殺すと死霊敵が発生します。
item_beginner_staff,初学者法杖,Beginner's staff,初心者用の杖です
item_beginner_staff_desc,送给初来乍到的冒险家。,For new adventurers.,初心者の冒険家に贈ります。
item_magic_missile,魔法飞弹,Magic missile,魔法のミサイルです
item_magic_missile_desc,轻快的法术。,A light spell.,軽快な術です。
item_tracking_spell,追踪法术,Tracking spell,追跡術です
item_tracking_spell_desc,使发射的子弹追踪敌人,Let the fired bullets track the enemy,発射した弾丸で敵を追跡させます
1 id zh en ja
2 item_staff_of_the_undead item_staff_necromancy 死灵法杖 StaffOfTheUndead staffNecromancy ネクロポリスの杖です
3 item_staff_of_the_undead_desc item_staff_necromancy_desc 发射诅咒,可将敌人转化为邪恶的怪物。 Cast a curse that transforms enemies into evil monsters. 呪いを発射して、敵を邪悪な怪物に変えることができます。
4 item_packsack item_portable_backpacks 背包 便携式背包 Packsack PortableBackpacks 背嚢 ポータブルバックパック
5 item_packsack_desc item_portable_backpacks_desc 可以装载更多物品的背包。 为玩家提供9个物品槽。 A backpack that can hold more items. Provides 9 item slots for the player. より多くのアイテムを保持できるバックパックです。 プレイヤーに9つのアイテムスロットを提供します。
6 item_necromancy 死灵法术 necromancy ネクロマンシー
7 item_necromancy_desc 法术的实体化弹丸。 The materialized projectile of a spell. 術の実体化した弾丸です。
8 item_x3 三重射击法术 Triple shot spell 三重射撃術です
9 item_x3_desc 使发射器一次射出三颗弹丸。 Make the launcher shoot three pellets at a time. 発射機から一度に三つの弾丸を発射させます。
10 item_resignation_certificate 离职证明 Resignation certificate 退職証明書です
11 item_resignation_certificate_desc 冷薄荷,感谢您在职时为公司做出的贡献。 Cold Mint, thank you for your service to the company. コールドミント、現役時代のご貢献ありがとうございました。
12 item_iron_axe 铁斧子 Iron axe 鉄の斧です
13 item_iron_axe_desc 铁斧子 Iron axe 鉄の斧です
14 item_curse 死灵诅咒法术 The curse of the Dead 死霊呪いの術
15 item_curse_desc 杀死敌人后在生成死灵敌人。 Spawn Undead enemies after killing them. 敵を殺すと死霊敵が発生します。
16 item_beginner_staff 初学者法杖 Beginner's staff 初心者用の杖です
17 item_beginner_staff_desc 送给初来乍到的冒险家。 For new adventurers. 初心者の冒険家に贈ります。
18 item_magic_missile 魔法飞弹 Magic missile 魔法のミサイルです
19 item_magic_missile_desc 轻快的法术。 A light spell. 軽快な術です。
20 item_tracking_spell 追踪法术 Tracking spell 追跡術です
21 item_tracking_spell_desc 使发射的子弹追踪敌人 Let the fired bullets track the enemy 発射した弾丸で敵を追跡させます

View File

@ -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.,マップ生成器に起点部屋データはありません。
@ -36,10 +35,6 @@ log_register_item,注册物品类型{0}结果为{1},Registered item type {0}; re
log_error_when_open_item_regs_dir,尝试打开物品信息目录{0}时发生错误,错误代码:{1},"An error occurred when trying to open the item information directory {0}, error code: {1}",アイテム情報ディレクトリ{0}を開こうとしてエラーが発生しました、エラーコード:{1}
log_wrong_custom_arg,不匹配的参数:类型为{0}而值为{1},Mismatched parameter: type {0} and value {1},パラメータの不一致:型{0}と値{1}。
log_item_container_is_null,物品容器为空,Item container is null,アイテム・コンテナが空です
log_item_has_no_owner,物品没有所有者,Item has no owner,アイテムに所有者がいません
log_no_damage_between_camps,没有阵营之间的伤害,No damage between camps,陣営間のダメージはありません
log_contact_damage_disabled_during_collision,在碰撞期间禁用接触伤害,Contact damage disabled during collision,衝突中に接触ダメージが無効になります
log_owner_of_the_item_is_not_character,物品的所有者不是角色,The owner of the item is not a character,アイテムの所有者はキャラクターではありません
log_try_to_open_state_machine_that_is_on,尝试打开处于运行状态的状态机。,Try to open a state machine that is on.,実行中のステートマシンを開こうとしています。
log_state_machine_does_not_specify_context,状态机没有指定上下文。,The state machine does not specify a context.,ステートマシンはコンテキストを指定していません。
log_state_processor_already_registered,状态处理器已经注册。,State processor already registered.,ステートプロセッサは既に登録されています。
@ -51,13 +46,7 @@ log_patrol_to_next_point,下一个点{0},当前位置{1},偏移量{2},距
log_patrol_arrival_point,到达巡逻点{0}。,Arrival at patrol point {0}.,巡回ポイント{0}に到着します。
log_patrol_origin_position,巡逻路径的起始位置是{0}。,The starting position of the patrol path is {0}.,巡回路の開始位置は{0}です。
log_patrol_not_on_floor,不能将初始路径设置在空中。,The initial path cannot be set in the air.,初期パスを空中に設定できません。
log_item_container_is_null,物品容器为空。,Item container is null.,アイテム・コンテナが空です。
log_can_add_item,可以添加物品{0}。,Can add item {0}.,アイテム{0}を追加できます。
log_backpack_not_allowed,不允许添加到背包。,Not allowed to add to backpack.,バックパックに追加することは許可されていません。
log_item_is_null,物品为空。,Item is null.,アイテムが空です。
log_item_id_not_same,物品ID不同。,Item ID is different.,アイテムIDが異なります。
log_max_quantity_exceeded,超过最大数量。,Exceeded maximum quantity.,最大数量を超えました。
log_item_slot_is_selected_and_not_allowed,已选择物品槽,不允许添加。,"Item slot is selected, not allowed to add.",アイテムスロットが選択されており、追加は許可されていません。
log_patrol_enemy_detected,检测到敌人。,Enemy detected.,敵を検出しました。
log_attacker_or_target_is_null,攻击者或目标为空。,Attacker or target is null.,攻撃者またはターゲットが空です。
log_in_the_same_camp,在同一阵营。,In the same camp.,同じ陣営です。
@ -73,10 +62,6 @@ log_owner_is_not_AiCharacter,所有者不是AiCharacter。,Owner is not AiCharac
log_find_nearest_item,查找最近的物品。,Find the nearest item.,最も近いアイテムを見つけます。
log_float_label_instantiate_failed,浮动标签实例化失败。,Float label instantiation failed.,フロートラベルのインスタンス化に失敗しました。
log_pickable_picked_up,可拾捡物被捡起了,那么不显示标签。,"If the pickable item is picked up, the label is not displayed.",でも、拾得物が拾い上げられたら、ラベルは表示されません。
log_start_uploading,开始上传{0}条日志。,Start uploading {0} logs.,{0}個のログをアップロードを開始します。
log_upload_successful,上传成功,已上传{0}条日志,剩余{1}条日志待上传。,"Upload successful, {0} logs uploaded, {1} logs remaining.",アップロードが成功しました、{0}個のログがアップロードされ、{1}個のログが残っています。
log_upload_failed,上传失败,错误代码:{0},剩余{1}条日志待上传。,"Upload failed, error code: {0}, {1} logs remaining.",アップロードに失敗しました、エラーコード:{0}、{1}個のログが残っています。
log_upload_status,已记录{0}条日志,上传阈值为{1}。,"{0} logs recorded, upload threshold is {1}.",{0}個のログが記録され、アップロード閾値は{1}です。
log_weapon_detected,检测到武器。,Weapon detected.,武器が検出されました。
log_no_weapon_detected,没有检测到武器。,No weapon detected.,武器が検出されません。
log_weapon_lost,武器丢失。,Weapon lost.,武器が失われました。
@ -86,6 +71,7 @@ log_weapon_not_in_pickup_range,武器不在拾取范围内。,The weapon is not
log_weapon_picked_up,武器被拾取。,Weapon picked up.,武器が拾い取られました。
log_weapon_pickup_failed,武器拾取失败。,Weapon pickup failed.,武器の拾い取りに失敗しました。
log_enter_the_picking_range_body,进入拾取范围。,Enter the picking range.,拾い取り範囲に入ります。
log_exit_the_picking_range_body,退出拾取范围。,Exit the picking range.,ピックアップ範囲から外します。
log_search_for_weapon_timeout,搜索武器超时。,Search for weapon timeout.,武器の検索がタイムアウトしました。
log_initialize_the_context,初始化上下文环境。,Initialize the context environment.,コンテキスト環境を初期化します。
log_initialize_the_context_failed,初始化上下文环境失败。,Initialize the context environment failed.,コンテキスト環境の初期化に失敗しました。
@ -109,3 +95,38 @@ log_dll_name,已加载{0}。,Loaded {0}.,{0}をロードしました。
log_dll_does_not_register_lifecycle_processor,位于{0}的dll文件未注册生命周期处理器{1}。,"The DLL file located at {0} does not register the lifecycle processor {1}.",{0}にあるDLLファイルは、ライフサイクルプロセッサ{1}を登録していません。
log_mod_lifecycle_handler_not_implement_interface,位于{0}的dll文件生命周期处理器未实现IModLifecycleHandler接口。,"The DLL file located at {0}, the lifecycle processor does not implement the IModLifecycleHandler interface.",{0}にあるDLLファイル、ライフサイクルプロセッサはIModLifecycleHandlerインターフェースを実装していません。
log_dll_no_parameterless_constructor,位于{0}的dll文件没有无参构造函数。,"The DLL file located at {0} does not have a parameterless constructor.",{0}にあるDLLファイルにはパラメータのないコンストラクタがありません。
log_dll_type_length,位于{0}的dll文件内共包含{1}个类型。,"The DLL file located at {0} contains a total of {1} types.",{0}にあるDLLファイルには合計{1}個のタイプが含まれています。
log_after_no_longer_in_contact_with_any_tiles,不再与任何瓦片接触后,可以造成伤害。,"After no longer coming into contact with any tiles, it can cause damage",タイルと接触しなくなった後、損傷を引き起こす可能性があります。
log_contact_with_tiles_disables_damage,与瓦片接触禁用伤害。,"Disabling damage on contact with tiles",タイルとの接触によるダメージの無効化
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}の部屋のプレビューを作成できませんでした。
log_generated_item_is_empty,生成的物品{0}是空的吗{1}。,Generated item {0} is empty {1}.,生成したアイテム{0}は空ですか{1}。
log_projectile_generate_magic_is_null,没有装填可提供抛射体的法术。,There is no reload spell that provides projectiles.,射出体を提供するスペルを装填していません。
log_projectile_scene_is_null,抛射体场景为空。,Projectile scene is empty.,射出体は空です。
log_projectile_is_null,抛射体为空。,Projectile scene is empty.,射出シーンは空です。
log_projectile_weapon_range,加载法术范围{0}顺序模式吗{1}上次发射法术时采用的索引{2}。,Load spell range {0} Sequential mode {1} Index used when the spell was last fired {2}.,スペル範囲{0}順序モードですか{1}前回スペルを送信した時のインデックス{2}。
log_no_platform_detection_raycast_found,缺少必要的平台检测射线。,Lack of necessary platform detection rays.,放射線を検出するのに必要なプラットフォームが不足しています。
log_hide_display_item,项目{0}被隐藏了。,Item {0} is hidden.,アイテム{0}は非表示にされます。
log_add_display_item,添加项目{0}。,Add item {0}.,項目{0}を追加します。
log_update_display_item,更新项目{0}。,Update item {0}.,更新項目{0}です。
log_batch_update_data,批量更新数据开始为{0}结束为{1}.,Batch update data starts with {0} and ends with {1}.,一括更新データの開始を{0}、終了を{1}とします。
log_new_room_node_data_is_incomplete,新房间{0}数据不全。,New room {0} data is incomplete.,新しい部屋{0}はデータが不完全です。
log_parent_room_does_not_exist,放置房间{0}时父级房间不存在。,The parent room does not exist when room {0} is placed.,部屋{0}を置いても親部屋は存在しません。
log_room_template_does_not_exist,放置房间{0}房间模板不存在。,Room template does not exist when placing room {1}.,部屋{0}を置いた時点では部屋テンプレートは存在しません。
log_room_slot_does_not_exist,放置房间{0}房间槽位不存在。,Room slot does not exist when placing room {0}.,置き部屋{0}部屋スロットは存在しません。
log_available_rooms_are_not_available,放置房间{0}时,可用房间不存在。,"When placing room {0}, the available room does not exist.",部屋{0}を置いた場合、利用可能な部屋は存在しません。
log_room_corresponding_to_resource_is_null,放置房间{0}时,资源{1}对应的房间为null.,"When room {0} is placed, the room corresponding to resource {1} is null.",部屋{0}を置く場合、リソース{1}に対応する部屋はnullとなります。
log_slots_do_not_match,放置房间{0}时,槽位不匹配。,"When placing room {0}, the slots do not match.",部屋{0}を置く時、溝の位置が一致しません。
log_slot_incomplete,放置房间{0}时,槽位不完整。,The slot is incomplete when placing room {0}.,部屋{0}を置く場合、溝の位置が不完全です。
log_placement_position_is_empty,房间{0}放置位置为空。,The room {0} position is empty.,部屋{0}を空にします。
log_parameter_inconsistency,参数不齐。,Parameter inconsistency.,パラメーターが不揃いです。
log_room_slot_position_is_empty,房间位置描述为空。,Room location is described as empty.,部屋の位置は空です。
log_room_overlap,房间重叠。,The rooms overlap.,部屋が重なります。
log_game_over_event_is_empty,游戏结束事件为空。,End of game event is empty.,ゲームオーバーでイベントは空です。
log_cannot_resurrect_non_existent_player,不能复活不存在的玩家。,Cannot resurrect non-existent players.,存在しないプレイヤーを復活させることはできません。
log_no_audio_stream_player,没有音频播放器组件。,No audio player component.,オーディオプレーヤーキットはありません。
log_audio_stream_player_is_playing,音频播放器正在播放中。,The audio player is playing.,オーディオプレーヤーが再生中です。
log_play_audio,播放音频BUS为{0}Stream为{1}.,BUS is {0} and Stream is {1}.,再生オーディオはBUSが{0}Streamが{1}です。
1 id zh en ja
4 log_room_root_node_must_be_node2d 房间根节点必须是 Node2D。 Room root node must be an instance of Node2D. ルートノードはNode2Dでなければなりません。
5 log_width_or_height_of_room_slot_must_be_1 房间槽的宽度或高度必须为1。 The width or height of the room slot must be 1. 部屋の溝の幅または高さは1でなければなりません。
6 log_connected_room_timeout 连接房间超时。 Timeout when connecting rooms. 接続部屋はタイムアウトです。
log_projectiles_is_empty 未设置抛射体。 The projectile is not set. 射出体は設置されていません。
7 log_map_generator_missing_parameters 地图生成器缺少参数。 Map generator missing parameters. マップジェネレータが不足しています。
8 log_map_generator_attempts_to_parse_empty_layout_diagrams 地图生成器尝试解析空的布局图。 Map generator attempts to parse empty layout diagrams. マップジェネレータは空のレイアウト図を解析しようとしています。
9 log_map_generator_has_no_starting_room_data 地图生成器没有起点房间数据。 Map generator has no starting room data. マップ生成器に起点部屋データはありません。
35 log_error_when_open_item_regs_dir 尝试打开物品信息目录{0}时发生错误,错误代码:{1} An error occurred when trying to open the item information directory {0}, error code: {1} アイテム情報ディレクトリ{0}を開こうとしてエラーが発生しました、エラーコード:{1}
36 log_wrong_custom_arg 不匹配的参数:类型为{0}而值为{1} Mismatched parameter: type {0} and value {1} パラメータの不一致:型{0}と値{1}。
37 log_item_container_is_null 物品容器为空 Item container is null アイテム・コンテナが空です
log_item_has_no_owner 物品没有所有者 Item has no owner アイテムに所有者がいません
log_no_damage_between_camps 没有阵营之间的伤害 No damage between camps 陣営間のダメージはありません
log_contact_damage_disabled_during_collision 在碰撞期间禁用接触伤害 Contact damage disabled during collision 衝突中に接触ダメージが無効になります
log_owner_of_the_item_is_not_character 物品的所有者不是角色 The owner of the item is not a character アイテムの所有者はキャラクターではありません
38 log_try_to_open_state_machine_that_is_on 尝试打开处于运行状态的状态机。 Try to open a state machine that is on. 実行中のステートマシンを開こうとしています。
39 log_state_machine_does_not_specify_context 状态机没有指定上下文。 The state machine does not specify a context. ステートマシンはコンテキストを指定していません。
40 log_state_processor_already_registered 状态处理器已经注册。 State processor already registered. ステートプロセッサは既に登録されています。
46 log_patrol_arrival_point 到达巡逻点{0}。 Arrival at patrol point {0}. 巡回ポイント{0}に到着します。
47 log_patrol_origin_position 巡逻路径的起始位置是{0}。 The starting position of the patrol path is {0}. 巡回路の開始位置は{0}です。
48 log_patrol_not_on_floor 不能将初始路径设置在空中。 The initial path cannot be set in the air. 初期パスを空中に設定できません。
log_item_container_is_null 物品容器为空。 Item container is null. アイテム・コンテナが空です。
49 log_can_add_item 可以添加物品{0}。 Can add item {0}. アイテム{0}を追加できます。
log_backpack_not_allowed 不允许添加到背包。 Not allowed to add to backpack. バックパックに追加することは許可されていません。
log_item_is_null 物品为空。 Item is null. アイテムが空です。
log_item_id_not_same 物品ID不同。 Item ID is different. アイテムIDが異なります。
log_max_quantity_exceeded 超过最大数量。 Exceeded maximum quantity. 最大数量を超えました。
log_item_slot_is_selected_and_not_allowed 已选择物品槽,不允许添加。 Item slot is selected, not allowed to add. アイテムスロットが選択されており、追加は許可されていません。
50 log_patrol_enemy_detected 检测到敌人。 Enemy detected. 敵を検出しました。
51 log_attacker_or_target_is_null 攻击者或目标为空。 Attacker or target is null. 攻撃者またはターゲットが空です。
52 log_in_the_same_camp 在同一阵营。 In the same camp. 同じ陣営です。
62 log_find_nearest_item 查找最近的物品。 Find the nearest item. 最も近いアイテムを見つけます。
63 log_float_label_instantiate_failed 浮动标签实例化失败。 Float label instantiation failed. フロートラベルのインスタンス化に失敗しました。
64 log_pickable_picked_up 可拾捡物被捡起了,那么不显示标签。 If the pickable item is picked up, the label is not displayed. でも、拾得物が拾い上げられたら、ラベルは表示されません。
log_start_uploading 开始上传{0}条日志。 Start uploading {0} logs. {0}個のログをアップロードを開始します。
log_upload_successful 上传成功,已上传{0}条日志,剩余{1}条日志待上传。 Upload successful, {0} logs uploaded, {1} logs remaining. アップロードが成功しました、{0}個のログがアップロードされ、{1}個のログが残っています。
log_upload_failed 上传失败,错误代码:{0},剩余{1}条日志待上传。 Upload failed, error code: {0}, {1} logs remaining. アップロードに失敗しました、エラーコード:{0}、{1}個のログが残っています。
log_upload_status 已记录{0}条日志,上传阈值为{1}。 {0} logs recorded, upload threshold is {1}. {0}個のログが記録され、アップロード閾値は{1}です。
65 log_weapon_detected 检测到武器。 Weapon detected. 武器が検出されました。
66 log_no_weapon_detected 没有检测到武器。 No weapon detected. 武器が検出されません。
67 log_weapon_lost 武器丢失。 Weapon lost. 武器が失われました。
71 log_weapon_picked_up 武器被拾取。 Weapon picked up. 武器が拾い取られました。
72 log_weapon_pickup_failed 武器拾取失败。 Weapon pickup failed. 武器の拾い取りに失敗しました。
73 log_enter_the_picking_range_body 进入拾取范围。 Enter the picking range. 拾い取り範囲に入ります。
74 log_exit_the_picking_range_body 退出拾取范围。 Exit the picking range. ピックアップ範囲から外します。
75 log_search_for_weapon_timeout 搜索武器超时。 Search for weapon timeout. 武器の検索がタイムアウトしました。
76 log_initialize_the_context 初始化上下文环境。 Initialize the context environment. コンテキスト環境を初期化します。
77 log_initialize_the_context_failed 初始化上下文环境失败。 Initialize the context environment failed. コンテキスト環境の初期化に失敗しました。
95 log_dll_does_not_register_lifecycle_processor 位于{0}的dll文件,未注册生命周期处理器{1}。 The DLL file located at {0} does not register the lifecycle processor {1}. {0}にあるDLLファイルは、ライフサイクルプロセッサ{1}を登録していません。
96 log_mod_lifecycle_handler_not_implement_interface 位于{0}的dll文件,生命周期处理器未实现IModLifecycleHandler接口。 The DLL file located at {0}, the lifecycle processor does not implement the IModLifecycleHandler interface. {0}にあるDLLファイル、ライフサイクルプロセッサはIModLifecycleHandlerインターフェースを実装していません。
97 log_dll_no_parameterless_constructor 位于{0}的dll文件,没有无参构造函数。 The DLL file located at {0} does not have a parameterless constructor. {0}にあるDLLファイルにはパラメータのないコンストラクタがありません。
98 log_dll_type_length 位于{0}的dll文件内,共包含{1}个类型。 The DLL file located at {0} contains a total of {1} types. {0}にあるDLLファイルには合計{1}個のタイプが含まれています。
99 log_after_no_longer_in_contact_with_any_tiles 不再与任何瓦片接触后,可以造成伤害。 After no longer coming into contact with any tiles, it can cause damage タイルと接触しなくなった後、損傷を引き起こす可能性があります。
100 log_contact_with_tiles_disables_damage 与瓦片接触禁用伤害。 Disabling damage on contact with tiles タイルとの接触によるダメージの無効化
101 log_hide_all_node 隐藏{0}个节点。 Hide {0} nodes. {0}ノードを非表示にします。
102 log_show_all_node 显示{0}个节点。 Show {0} nodes. {0}ノードが表示されます。
103 log_enter_the_screen 进入屏幕。 Enter screen 画面に移動。
104 log_exit_the_screen 退出屏幕。 Exit screen 画面を終了します。
105 log_failed_to_create_room_preview 创建{0}的房间预览图失败。 Failed to create a room preview of the {0}. {0}の部屋のプレビューを作成できませんでした。
106 log_generated_item_is_empty 生成的物品{0}是空的吗{1}。 Generated item {0} is empty {1}. 生成したアイテム{0}は空ですか{1}。
107 log_projectile_generate_magic_is_null 没有装填可提供抛射体的法术。 There is no reload spell that provides projectiles. 射出体を提供するスペルを装填していません。
108 log_projectile_scene_is_null 抛射体场景为空。 Projectile scene is empty. 射出体は空です。
109 log_projectile_is_null 抛射体为空。 Projectile scene is empty. 射出シーンは空です。
110 log_projectile_weapon_range 加载法术范围{0}顺序模式吗{1}上次发射法术时采用的索引{2}。 Load spell range {0} Sequential mode {1} Index used when the spell was last fired {2}. スペル範囲{0}順序モードですか{1}前回スペルを送信した時のインデックス{2}。
111 log_no_platform_detection_raycast_found 缺少必要的平台检测射线。 Lack of necessary platform detection rays. 放射線を検出するのに必要なプラットフォームが不足しています。
112 log_hide_display_item 项目{0}被隐藏了。 Item {0} is hidden. アイテム{0}は非表示にされます。
113 log_add_display_item 添加项目{0}。 Add item {0}. 項目{0}を追加します。
114 log_update_display_item 更新项目{0}。 Update item {0}. 更新項目{0}です。
115 log_batch_update_data 批量更新数据开始为{0}结束为{1}. Batch update data starts with {0} and ends with {1}. 一括更新データの開始を{0}、終了を{1}とします。
116 log_new_room_node_data_is_incomplete 新房间{0}数据不全。 New room {0} data is incomplete. 新しい部屋{0}はデータが不完全です。
117 log_parent_room_does_not_exist 放置房间{0}时父级房间不存在。 The parent room does not exist when room {0} is placed. 部屋{0}を置いても親部屋は存在しません。
118 log_room_template_does_not_exist 放置房间{0}房间模板不存在。 Room template does not exist when placing room {1}. 部屋{0}を置いた時点では部屋テンプレートは存在しません。
119 log_room_slot_does_not_exist 放置房间{0}房间槽位不存在。 Room slot does not exist when placing room {0}. 置き部屋{0}部屋スロットは存在しません。
120 log_available_rooms_are_not_available 放置房间{0}时,可用房间不存在。 When placing room {0}, the available room does not exist. 部屋{0}を置いた場合、利用可能な部屋は存在しません。
121 log_room_corresponding_to_resource_is_null 放置房间{0}时,资源{1}对应的房间为null. When room {0} is placed, the room corresponding to resource {1} is null. 部屋{0}を置く場合、リソース{1}に対応する部屋はnullとなります。
122 log_slots_do_not_match 放置房间{0}时,槽位不匹配。 When placing room {0}, the slots do not match. 部屋{0}を置く時、溝の位置が一致しません。
123 log_slot_incomplete 放置房间{0}时,槽位不完整。 The slot is incomplete when placing room {0}. 部屋{0}を置く場合、溝の位置が不完全です。
124 log_placement_position_is_empty 房间{0}放置位置为空。 The room {0} position is empty. 部屋{0}を空にします。
125 log_parameter_inconsistency 参数不齐。 Parameter inconsistency. パラメーターが不揃いです。
126 log_room_slot_position_is_empty 房间位置描述为空。 Room location is described as empty. 部屋の位置は空です。
127 log_room_overlap 房间重叠。 The rooms overlap. 部屋が重なります。
128 log_game_over_event_is_empty 游戏结束事件为空。 End of game event is empty. ゲームオーバーでイベントは空です。
129 log_cannot_resurrect_non_existent_player 不能复活不存在的玩家。 Cannot resurrect non-existent players. 存在しないプレイヤーを復活させることはできません。
130 log_no_audio_stream_player 没有音频播放器组件。 No audio player component. オーディオプレーヤーキットはありません。
131 log_audio_stream_player_is_playing 音频播放器正在播放中。 The audio player is playing. オーディオプレーヤーが再生中です。
132 log_play_audio 播放音频BUS为{0}Stream为{1}. BUS is {0} and Stream is {1}. 再生オーディオはBUSが{0}Streamが{1}です。

View File

@ -1,4 +1,3 @@
id,zh,en,ja
de,的,"'s",の
default_player_name,白纸,blankPaper,しらかみ
item_prompt_debug,ID{0}\n名称{1}\n数量{2}\n最大叠加数量{3}\n数据类型{4}\n描述{5},ID: {0}\nName: {1}\nQuantity: {2}\nMaximum stacking quantity: {3}\nData type: {4}\nDescription{5},id:{0}\n名称:{1}\nの数は最大{2}\nシナジー数:{3}\nデータタイプ:{4}\n述べ表わす:{5}
1 id zh en ja
de 's
2 default_player_name 白纸 blankPaper しらかみ
3 item_prompt_debug ID:{0}\n名称:{1}\n数量:{2}\n最大叠加数量:{3}\n数据类型:{4}\n描述:{5} ID: {0}\nName: {1}\nQuantity: {2}\nMaximum stacking quantity: {3}\nData type: {4}\nDescription:{5} id:{0}\n名称:{1}\nの数は最大{2}\nシナジー数:{3}\nデータタイプ:{4}\n述べ表わす:{5}

View File

@ -4,3 +4,8 @@ slogan_1,Kawaii!,Kawaii!,Kawaii!
slogan_2,魔法是想象的世界。,Magic is an imaginary world.,魔法は想像の世界です。
slogan_3,也试试《Minecraft》,Also try 'Minecraft'!,「Minecraft」もやってみて
slogan_4,也试试《Terraria》,Also try 'Terraria'!,「Terraria」もやってみて
slogan_5,也试试《Terraria》,Also try 'Terraria'!,「Terraria」もやってみて
slogan_6,游戏在bug上运行。,The game runs on a bug.,ゲームはバグで動作します。
slogan_7,こんにちは!,こんにちは!,こんにちは!
slogan_7,你好!,你好!,你好!
slogan_7,Hello,Hello,Hello
1 id zh en ja
4 slogan_2 魔法是想象的世界。 Magic is an imaginary world. 魔法は想像の世界です。
5 slogan_3 也试试《Minecraft》! Also try 'Minecraft'! 「Minecraft」もやってみて!
6 slogan_4 也试试《Terraria》! Also try 'Terraria'! 「Terraria」もやってみて!
7 slogan_5 也试试《Terraria》! Also try 'Terraria'! 「Terraria」もやってみて!
8 slogan_6 游戏在bug上运行。 The game runs on a bug. ゲームはバグで動作します。
9 slogan_7 こんにちは! こんにちは! こんにちは!
10 slogan_7 你好! 你好! 你好!
11 slogan_7 Hello! Hello! Hello!

17
locals/Slogan.csv.import Normal file
View File

@ -0,0 +1,17 @@
[remap]
importer="csv_translation"
type="Translation"
uid="uid://m1i5vqn3aq7e"
[deps]
files=["res://locals/Slogan.zh.translation", "res://locals/Slogan.en.translation", "res://locals/Slogan.ja.translation"]
source_file="res://locals/Slogan.csv"
dest_files=["res://locals/Slogan.zh.translation", "res://locals/Slogan.en.translation", "res://locals/Slogan.ja.translation"]
[params]
compress=true
delimiter=0

1
locals/SloganOnMap.csv Normal file
View File

@ -0,0 +1 @@
id,zh,en,ja
1 id zh en ja

View File

@ -0,0 +1,17 @@
[remap]
importer="csv_translation"
type="Translation"
uid="uid://ckggihhjkgp20"
[deps]
files=["res://locals/SloganOnMap.zh.translation", "res://locals/SloganOnMap.en.translation", "res://locals/SloganOnMap.ja.translation"]
source_file="res://locals/SloganOnMap.csv"
dest_files=["res://locals/SloganOnMap.zh.translation", "res://locals/SloganOnMap.en.translation", "res://locals/SloganOnMap.ja.translation"]
[params]
compress=true
delimiter=0

View File

@ -34,3 +34,9 @@ ui_character_voice,角色配音,character_voice,キャラクターボイスで
ui_translator,翻译,translator,翻訳
ui_unordered_list_tip,排名不分先后,Ranking is not in order,順位は関係ありません
ui_loading,正在加载...,Loading...,読み込み中...
ui_spell_editor,法术编辑器,Spell editor,スペルエディター
ui_rebuild_the_world,正在重新构建世界...,Is reconstructing the world...,世界を再構築しています…
ui_tutorial_spellEditor,按E捡起地上的武器\n法杖需要搭配法术使用\n靠近工作台\n鼠标左键使用工作台。\n鼠标左键拖动物品\n以实现在不同的容器之间移动它们。,"Press E to pick up the weapon on the ground, \nthe wand needs to be used with the spell, \nclose to the workbench, \nthe left mouse button to use the workbench.\nDrag items with the left mouse button \nto move them between different containers.",Eを押して地面の武器を拾い上げます。\n杖は魔法と組み合わせて使います。\n作業台に近づいて、\nマウスの左ボタンで作業台を使います。\nマウスの左ボタンでモをドラッグすると、\nさまざまな容器の間を移動できます。
ui_tutorial_break_box,鼠标左键使用武器打破箱子->,"Use the left mouse button to \nbreak the box with the weapon->",マウスの左ボタンで箱を破ります->
ui_tutorial_jump_onto_platform,W跳上平台\nS从平台上跳下。,"W jumps onto the platform, \nS jumps off the platform.",Wは踊り場に、\nSは踊り場に飛び降りるのです。
ui_tutorial_combine_more_powerful_spells,组合更强力的法术->,Combine more powerful spells->,より強力な術を組み合わせます->

1 id zh en ja
34 ui_translator 翻译 translator 翻訳
35 ui_unordered_list_tip 排名不分先后 Ranking is not in order 順位は関係ありません
36 ui_loading 正在加载... Loading... 読み込み中...
37 ui_spell_editor 法术编辑器 Spell editor スペルエディター
38 ui_rebuild_the_world 正在重新构建世界... Is reconstructing the world... 世界を再構築しています…
39 ui_tutorial_spellEditor 按E捡起地上的武器,\n法杖需要搭配法术使用,\n靠近工作台,\n鼠标左键使用工作台。\n鼠标左键拖动物品,\n以实现在不同的容器之间移动它们。 Press E to pick up the weapon on the ground, \nthe wand needs to be used with the spell, \nclose to the workbench, \nthe left mouse button to use the workbench.\nDrag items with the left mouse button \nto move them between different containers. Eを押して地面の武器を拾い上げます。\n杖は魔法と組み合わせて使います。\n作業台に近づいて、\nマウスの左ボタンで作業台を使います。\nマウスの左ボタンでモノをドラッグすると、\nさまざまな容器の間を移動できます。
40 ui_tutorial_break_box 鼠标左键使用武器打破箱子-> Use the left mouse button to \nbreak the box with the weapon-> マウスの左ボタンで箱を破ります->
41 ui_tutorial_jump_onto_platform W跳上平台,\nS从平台上跳下。 W jumps onto the platform, \nS jumps off the platform. Wは踊り場に、\nSは踊り場に飛び降りるのです。
42 ui_tutorial_combine_more_powerful_spells 组合更强力的法术-> Combine more powerful spells-> より強力な術を組み合わせます->

3
prefab/MainCamera.tscn Normal file
View File

@ -0,0 +1,3 @@
[gd_scene format=3 uid="uid://briehpw3eg1i6"]
[node name="Camera2D" type="Camera2D"]

View File

@ -0,0 +1,104 @@
[gd_scene load_steps=11 format=3 uid="uid://dxx1vqpecig7i"]
[ext_resource type="Script" path="res://scripts/character/AiCharacter.cs" id="1_ubaid"]
[ext_resource type="Texture2D" uid="uid://c1yxhtiqrfvvp" path="res://sprites/character/BlackenedAboriginalWarrior.png" id="2_pcmq1"]
[ext_resource type="Script" path="res://scripts/damage/DamageNumberNodeSpawn.cs" id="3_kiam3"]
[ext_resource type="PackedScene" uid="uid://sqqfrmikmk5v" path="res://prefab/ui/HealthBar.tscn" id="4_gt388"]
[ext_resource type="Script" path="res://scripts/bubble/BubbleMarker.cs" id="5_y2fh5"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_f8frw"]
size = Vector2(40, 46)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_a3myh"]
size = Vector2(46, 65)
[sub_resource type="SpriteFrames" id="SpriteFrames_qumby"]
animations = [{
"frames": [{
"duration": 1.0,
"texture": ExtResource("2_pcmq1")
}],
"loop": true,
"name": &"default",
"speed": 5.0
}]
[sub_resource type="CircleShape2D" id="CircleShape2D_c61vr"]
radius = 220.0
[sub_resource type="CircleShape2D" id="CircleShape2D_fowd5"]
radius = 300.0
[node name="BlackenedAboriginalWarrior" type="CharacterBody2D"]
collision_layer = 64
collision_mask = 38
script = ExtResource("1_ubaid")
InitWeaponId = "staff_necromancy"
CharacterName = "character_evil_crow"
CanMutateAfterDeath = false
MaxHp = 50
CampId = "Mazoku"
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(2, 10)
shape = SubResource("RectangleShape2D_f8frw")
[node name="Area2DPickingArea" type="Area2D" parent="."]
collision_layer = 0
collision_mask = 8
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2DPickingArea"]
position = Vector2(0, 5.5)
shape = SubResource("RectangleShape2D_a3myh")
[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="."]
sprite_frames = SubResource("SpriteFrames_qumby")
[node name="ItemMarker2D" type="Marker2D" parent="."]
position = Vector2(15, 20)
[node name="AttackObstacleDetection" type="RayCast2D" parent="ItemMarker2D"]
collision_mask = 2
[node name="DamageNumber" type="Marker2D" parent="."]
position = Vector2(0, -32)
script = ExtResource("3_kiam3")
[node name="HealthBar" parent="." instance=ExtResource("4_gt388")]
visible = false
offset_left = -46.0
offset_top = 41.0
offset_right = 50.0
offset_bottom = 53.0
[node name="WallDetection" type="RayCast2D" parent="."]
position = Vector2(3, -1)
target_position = Vector2(50, 0)
collision_mask = 6
[node name="AttackArea2D" type="Area2D" parent="."]
collision_layer = 0
collision_mask = 68
[node name="CollisionShape2D" type="CollisionShape2D" parent="AttackArea2D"]
shape = SubResource("CircleShape2D_c61vr")
[node name="NavigationAgent2D" type="NavigationAgent2D" parent="."]
[node name="BubbleMarker" type="Marker2D" parent="."]
position = Vector2(0, -79)
script = ExtResource("5_y2fh5")
[node name="ScoutArea2D" type="Area2D" parent="."]
collision_layer = 0
collision_mask = 76
[node name="CollisionShape2D" type="CollisionShape2D" parent="ScoutArea2D"]
shape = SubResource("CircleShape2D_fowd5")
[node name="TipLabel" type="Label" parent="."]
offset_left = -20.0
offset_top = 46.0
offset_right = 15.0
offset_bottom = 71.0
horizontal_alignment = 1

View File

@ -22,19 +22,19 @@ animations = [{
"speed": 5.0
}]
[node name="Player" type="CharacterBody2D"]
[node name="Player" type="CharacterBody2D" node_paths=PackedStringArray("_platformDetectionRayCast2DList")]
light_mask = 2
collision_layer = 4
collision_mask = 34
collision_mask = 162
platform_floor_layers = 4294967042
platform_wall_layers = 128
script = ExtResource("1_1dlls")
metadata/CampId = "Default"
metadata/MaxHp = 32
_platformDetectionRayCast2DList = [NodePath("PlatformDetectionRayCast1"), NodePath("PlatformDetectionRayCast2"), NodePath("PlatformDetectionRayCast3")]
MaxHp = 32
CampId = "Default"
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
shape = SubResource("CapsuleShape2D_bb8wt")
debug_color = Color(0.886275, 0, 0.803922, 0.419608)
[node name="Camera2D" type="Camera2D" parent="."]
position_smoothing_enabled = true
[node name="Area2DPickingArea" type="Area2D" parent="."]
collision_layer = 0
@ -50,7 +50,15 @@ sprite_frames = SubResource("SpriteFrames_qumby")
width = 5.0
default_color = Color(0.858824, 0.65098, 0.682353, 1)
[node name="PlatformDetectionRayCast" type="RayCast2D" parent="."]
[node name="PlatformDetectionRayCast1" type="RayCast2D" parent="."]
collision_mask = 32
[node name="PlatformDetectionRayCast2" type="RayCast2D" parent="."]
position = Vector2(20, 0)
collision_mask = 32
[node name="PlatformDetectionRayCast3" type="RayCast2D" parent="."]
position = Vector2(-20, 0)
collision_mask = 32
[node name="ItemMarker2D" type="Marker2D" parent="."]
@ -59,3 +67,5 @@ position = Vector2(15, 20)
[node name="DamageNumber" type="Marker2D" parent="."]
position = Vector2(0, -47)
script = ExtResource("3_lrmsw")
[node name="AudioListener2D" type="AudioListener2D" parent="."]

View File

@ -34,17 +34,20 @@ radius = 172.29
collision_layer = 64
collision_mask = 38
script = ExtResource("1_ubaid")
InitWeaponId = null
CharacterName = "character_necromancer"
CanMutateAfterDeath = false
_initialHp = null
MaxHp = 50
CampId = "Mazoku"
LootListId = "test"
metadata/CampId = "Mazoku"
metadata/MaxHp = 50
metadata/Name = "死灵法师"
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(0, 4)
shape = SubResource("CapsuleShape2D_bb8wt")
[node name="Area2DPickingArea" type="Area2D" parent="."]
collision_layer = 0
collision_layer = 64
collision_mask = 8
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2DPickingArea"]
@ -89,13 +92,20 @@ shape = SubResource("CircleShape2D_c61vr")
position = Vector2(0, -79)
script = ExtResource("5_y2fh5")
[node name="VisibleOnScreenEnabler2D" type="VisibleOnScreenEnabler2D" parent="."]
position = Vector2(0, 5.5)
scale = Vector2(2.04, 3.05)
[node name="ScoutArea2D" type="Area2D" parent="."]
collision_layer = 0
collision_mask = 76
[node name="CollisionShape2D" type="CollisionShape2D" parent="ScoutArea2D"]
shape = SubResource("CircleShape2D_fowd5")
[node name="TipLabel" type="Label" parent="."]
anchors_preset = 5
anchor_left = 0.5
anchor_right = 0.5
offset_left = -57.0
offset_top = 57.0
offset_right = 61.0
offset_bottom = 82.0
grow_horizontal = 2
horizontal_alignment = 1

View File

@ -0,0 +1,117 @@
[gd_scene load_steps=16 format=3 uid="uid://djsh4unystlf0"]
[ext_resource type="Script" path="res://scripts/furniture/GuiFurniture.cs" id="1_t1qdg"]
[ext_resource type="Texture2D" uid="uid://cyciw4drjvrs8" path="res://sprites/furnitures/SpellEditor.png" id="2_sbshw"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_vx4tg"]
size = Vector2(31, 31)
[sub_resource type="CircleShape2D" id="CircleShape2D_in1f7"]
radius = 52.6118
[sub_resource type="AtlasTexture" id="AtlasTexture_yq6e3"]
atlas = ExtResource("2_sbshw")
region = Rect2(0, 0, 44, 43)
[sub_resource type="AtlasTexture" id="AtlasTexture_ljyfv"]
atlas = ExtResource("2_sbshw")
region = Rect2(44, 0, 44, 43)
[sub_resource type="AtlasTexture" id="AtlasTexture_46j2i"]
atlas = ExtResource("2_sbshw")
region = Rect2(88, 0, 44, 43)
[sub_resource type="AtlasTexture" id="AtlasTexture_q6a2v"]
atlas = ExtResource("2_sbshw")
region = Rect2(132, 0, 44, 43)
[sub_resource type="AtlasTexture" id="AtlasTexture_lyh2i"]
atlas = ExtResource("2_sbshw")
region = Rect2(0, 43, 44, 43)
[sub_resource type="AtlasTexture" id="AtlasTexture_84sml"]
atlas = ExtResource("2_sbshw")
region = Rect2(44, 43, 44, 43)
[sub_resource type="AtlasTexture" id="AtlasTexture_xncbb"]
atlas = ExtResource("2_sbshw")
region = Rect2(88, 43, 44, 43)
[sub_resource type="AtlasTexture" id="AtlasTexture_eaqhr"]
atlas = ExtResource("2_sbshw")
region = Rect2(132, 43, 44, 43)
[sub_resource type="AtlasTexture" id="AtlasTexture_bcdl4"]
atlas = ExtResource("2_sbshw")
region = Rect2(0, 86, 44, 43)
[sub_resource type="AtlasTexture" id="AtlasTexture_a4mgy"]
atlas = ExtResource("2_sbshw")
region = Rect2(44, 86, 44, 43)
[sub_resource type="SpriteFrames" id="SpriteFrames_mppe5"]
animations = [{
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_yq6e3")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_ljyfv")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_46j2i")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_q6a2v")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_lyh2i")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_84sml")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_xncbb")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_eaqhr")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_bcdl4")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_a4mgy")
}],
"loop": true,
"name": &"default",
"speed": 5.0
}]
[node name="RigidBody2D" type="RigidBody2D"]
collision_layer = 256
collision_mask = 160
script = ExtResource("1_t1qdg")
Path = "res://prefab/ui/SpellEditorUI.tscn"
_furnitureName = "ui_spell_editor"
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(-0.5, -0.5)
shape = SubResource("RectangleShape2D_vx4tg")
[node name="OperateArea2D" type="Area2D" parent="."]
visible = false
[node name="CollisionShape2D" type="CollisionShape2D" parent="OperateArea2D"]
shape = SubResource("CircleShape2D_in1f7")
[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="."]
scale = Vector2(0.7, 0.7)
sprite_frames = SubResource("SpriteFrames_mppe5")
autoplay = "default"
frame_progress = 0.717769
[node name="TipLabel" type="Label" parent="."]
offset_left = -17.0
offset_top = 19.0
offset_right = 23.0
offset_bottom = 44.0

View File

@ -0,0 +1,30 @@
[gd_scene load_steps=5 format=3 uid="uid://dld3qttpsdjpe"]
[ext_resource type="Script" path="res://scripts/furniture/Barrier.cs" id="1_hfnuj"]
[ext_resource type="Texture2D" uid="uid://cvlm5tmv43i8t" path="res://sprites/furnitures/wooden_box.png" id="2_24vtp"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_vx4tg"]
size = Vector2(32, 32)
[sub_resource type="CircleShape2D" id="CircleShape2D_in1f7"]
radius = 52.6118
[node name="WoodenBox" type="RigidBody2D"]
collision_layer = 256
collision_mask = 160
script = ExtResource("1_hfnuj")
_initialDurability = null
_maxDurability = 1
_furnitureName = null
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
shape = SubResource("RectangleShape2D_vx4tg")
[node name="OperateArea2D" type="Area2D" parent="."]
visible = false
[node name="CollisionShape2D" type="CollisionShape2D" parent="OperateArea2D"]
shape = SubResource("CircleShape2D_in1f7")
[node name="WoodenBox" type="Sprite2D" parent="."]
texture = ExtResource("2_24vtp")

View File

@ -0,0 +1,39 @@
[gd_scene load_steps=5 format=3 uid="uid://cj36fjtrlo03t"]
[ext_resource type="Script" path="res://scripts/inventory/ResignationCertificate.cs" id="1_nydte"]
[ext_resource type="AudioStream" uid="uid://cak6chjjsu7wo" path="res://sounds/fire.wav" id="2_ei0j2"]
[ext_resource type="Texture2D" uid="uid://dyfqdpdlq286h" path="res://sprites/projectile/resignationCertificate.png" id="3_jwff2"]
[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_xnc20"]
radius = 6.0
height = 21.0
[node name="Resignation certificate" type="RigidBody2D"]
collision_layer = 8
collision_mask = 34
angular_damp = -1.0
script = ExtResource("1_nydte")
FiringIntervalAsMillisecond = 1000
_recoilStrength = null
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(1, 0.5)
shape = SubResource("CapsuleShape2D_xnc20")
[node name="Marker2D" type="Marker2D" parent="."]
position = Vector2(65, 0)
[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="Marker2D"]
stream = ExtResource("2_ei0j2")
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="."]
[node name="X3" type="Sprite2D" parent="."]
texture = ExtResource("3_jwff2")

38
prefab/magics/curse.tscn Normal file
View File

@ -0,0 +1,38 @@
[gd_scene load_steps=5 format=3 uid="uid://m3tkjcbrrhfj"]
[ext_resource type="Script" path="res://scripts/spell/NodeSpawnOnKillCharacterSpell.cs" id="1_gg5rs"]
[ext_resource type="AudioStream" uid="uid://cak6chjjsu7wo" path="res://sounds/fire.wav" id="2_83n3c"]
[ext_resource type="Texture2D" uid="uid://mb5yijtw7sw5" path="res://sprites/projectile/x3.png" id="3_thtsv"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_i3lbq"]
size = Vector2(30, 31)
[node name="curse" type="RigidBody2D"]
collision_layer = 8
collision_mask = 34
angular_damp = -1.0
script = ExtResource("1_gg5rs")
_packedScenePath = "res://prefab/entitys/BlackenedAboriginalWarrior.tscn"
_projectilePath = null
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(0, -0.5)
shape = SubResource("RectangleShape2D_i3lbq")
[node name="Marker2D" type="Marker2D" parent="."]
position = Vector2(65, 0)
[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="Marker2D"]
stream = ExtResource("2_83n3c")
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="."]
[node name="X3" type="Sprite2D" parent="."]
texture = ExtResource("3_thtsv")

View File

@ -0,0 +1,34 @@
[gd_scene load_steps=5 format=3 uid="uid://crthy8a50a4t"]
[ext_resource type="Script" path="res://scripts/spell/SpellPickAble.cs" id="1_v0grp"]
[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="CircleShape2D" id="CircleShape2D_akp3k"]
[node name="curseOfTheUndead" type="RigidBody2D"]
collision_layer = 8
collision_mask = 34
angular_damp = -1.0
script = ExtResource("1_v0grp")
_projectilePath = "res://prefab/projectile/curseOfTheUndead.tscn"
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(0, -0.625)
shape = SubResource("CircleShape2D_akp3k")
[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")

View File

@ -0,0 +1,36 @@
[gd_scene load_steps=5 format=3 uid="uid://bt3ck8twqowke"]
[ext_resource type="Script" path="res://scripts/spell/SpellPickAble.cs" id="1_xxv2a"]
[ext_resource type="AudioStream" uid="uid://cak6chjjsu7wo" path="res://sounds/fire.wav" id="2_p1csa"]
[ext_resource type="Texture2D" uid="uid://ca3paw31aubkd" path="res://sprites/projectile/magicMissile.png" id="3_ckdw6"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_i3lbq"]
size = Vector2(20, 14)
[node name="MagicMissile" type="RigidBody2D"]
collision_layer = 8
collision_mask = 34
angular_damp = -1.0
script = ExtResource("1_xxv2a")
_projectilePath = "res://prefab/projectile/magicMissile.tscn"
UniqueIcon = ExtResource("3_ckdw6")
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
shape = SubResource("RectangleShape2D_i3lbq")
[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("2_p1csa")
bus = &"SoundEffect"
[node name="Marker2D" type="Marker2D" parent="."]
[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="."]
[node name="MagicMissile" type="Sprite2D" parent="."]
texture = ExtResource("3_ckdw6")

View File

@ -0,0 +1,36 @@
[gd_scene load_steps=5 format=3 uid="uid://cg75t3fw5c6er"]
[ext_resource type="Script" path="res://scripts/spell/TrackingSpell.cs" id="1_vhnwx"]
[ext_resource type="AudioStream" uid="uid://cak6chjjsu7wo" path="res://sounds/fire.wav" id="2_3fbv3"]
[ext_resource type="Texture2D" uid="uid://dhgbij2ifphar" path="res://sprites/projectile/trackingSpell.png" id="2_i33g0"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_i3lbq"]
size = Vector2(30, 31)
[node name="trackingSpell" type="RigidBody2D"]
collision_layer = 8
collision_mask = 34
angular_damp = -1.0
script = ExtResource("1_vhnwx")
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(0, -0.5)
shape = SubResource("RectangleShape2D_i3lbq")
[node name="Marker2D" type="Marker2D" parent="."]
position = Vector2(65, 0)
[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="Marker2D"]
stream = ExtResource("2_3fbv3")
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="."]
[node name="TrackingSpell" type="Sprite2D" parent="."]
texture = ExtResource("2_i33g0")

38
prefab/magics/x3.tscn Normal file
View File

@ -0,0 +1,38 @@
[gd_scene load_steps=5 format=3 uid="uid://cg75t3fw5c6er"]
[ext_resource type="Script" path="res://scripts/spell/MultipleFireSpell.cs" id="1_cnhod"]
[ext_resource type="Texture2D" uid="uid://mb5yijtw7sw5" path="res://sprites/projectile/x3.png" id="3_b3s8h"]
[ext_resource type="AudioStream" uid="uid://cak6chjjsu7wo" path="res://sounds/fire.wav" id="4_ffr2k"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_i3lbq"]
size = Vector2(30, 31)
[node name="x3" type="RigidBody2D"]
collision_layer = 8
collision_mask = 34
angular_damp = -1.0
script = ExtResource("1_cnhod")
RandomAngle = true
UnitRadian = 0.07
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(0, -0.5)
shape = SubResource("RectangleShape2D_i3lbq")
[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="."]
[node name="X3" type="Sprite2D" parent="."]
texture = ExtResource("3_b3s8h")

View File

@ -0,0 +1,26 @@
[gd_scene load_steps=4 format=3 uid="uid://bq5d2w22wnxrf"]
[ext_resource type="Script" path="res://scripts/inventory/Packsack.cs" id="1_slakl"]
[ext_resource type="Texture2D" uid="uid://di0sw4rgd26y0" path="res://sprites/PortableBackpacks.png" id="2_l0fbh"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_xqyue"]
size = Vector2(21, 29)
[node name="RigidBody2D" type="RigidBody2D"]
collision_layer = 8
collision_mask = 38
script = ExtResource("1_slakl")
NumberSlots = 30
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(-2.5, 1.5)
shape = SubResource("RectangleShape2D_xqyue")
[node name="Packsack" type="Sprite2D" parent="."]
scale = Vector2(0.5, 0.5)
texture = ExtResource("2_l0fbh")
[node name="TipLabel" type="Label" parent="."]
offset_top = 31.0
offset_right = 40.0
offset_bottom = 56.0

View File

@ -1,37 +0,0 @@
[gd_scene load_steps=5 format=3 uid="uid://cn10fimoem04m"]
[ext_resource type="Script" path="res://scripts/inventory/Packsack.cs" id="1_slakl"]
[ext_resource type="Texture2D" uid="uid://dvx10dfjctn7t" path="res://sprites/packsack.png" id="2_40jca"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_brthl"]
size = Vector2(21, 29)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_xqyue"]
size = Vector2(21, 29)
[node name="RigidBody2D" type="RigidBody2D"]
collision_layer = 8
collision_mask = 38
script = ExtResource("1_slakl")
NumberSlots = 30
Id = "packsack"
UniqueName = null
UniqueDescription = null
_minContactInjury = null
_maxContactInjury = null
[node name="DamageArea2D" type="Area2D" parent="."]
collision_layer = 8
collision_mask = 102
[node name="CollisionShape2D" type="CollisionShape2D" parent="DamageArea2D"]
position = Vector2(-2.5, 1.5)
shape = SubResource("RectangleShape2D_brthl")
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(-2.5, 1.5)
shape = SubResource("RectangleShape2D_xqyue")
[node name="Packsack" type="Sprite2D" parent="."]
scale = Vector2(0.5, 0.5)
texture = ExtResource("2_40jca")

View File

@ -1,22 +1,21 @@
[gd_scene load_steps=5 format=3 uid="uid://c01av43yk1q71"]
[gd_scene load_steps=4 format=3 uid="uid://c01av43yk1q71"]
[ext_resource type="Script" path="res://scripts/projectile/Projectile.cs" id="1_ib3qh"]
[ext_resource type="Texture2D" uid="uid://bbcjkyrsx88av" path="res://sprites/projectile/curseOfTheUndead.png" id="1_k8el6"]
[sub_resource type="CircleShape2D" id="CircleShape2D_dgro2"]
[sub_resource type="CircleShape2D" id="CircleShape2D_8117d"]
radius = 11.0
[node name="curseOfTheUndead" type="CharacterBody2D"]
collision_layer = 0
collision_mask = 0
script = ExtResource("1_ib3qh")
metadata/Speed = 500.0
metadata/Durability = 1.0
metadata/DamageType = 2
metadata/Knockback = Vector2(2, -3)
metadata/Life = 5000
_life = 5000
_durability = 1.0
_maxDamage = 7
_minDamage = 3
_damageType = 2
Speed = 10.0
_repelStrength = 2.5
[node name="CurseOfTheUndead" type="Sprite2D" parent="."]
texture = ExtResource("1_k8el6")
@ -24,9 +23,6 @@ texture = ExtResource("1_k8el6")
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
shape = SubResource("CircleShape2D_dgro2")
[node name="CollisionDetectionArea" type="Area2D" parent="."]
collision_layer = 16
collision_mask = 78
[node name="CollisionShape2D" type="CollisionShape2D" parent="CollisionDetectionArea"]
shape = SubResource("CircleShape2D_8117d")
[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="."]
bus = &"SoundEffect"
area_mask = 16

View File

@ -0,0 +1,31 @@
[gd_scene load_steps=4 format=3 uid="uid://dmt5gpklx8efc"]
[ext_resource type="Script" path="res://scripts/projectile/Projectile.cs" id="1_cp6hg"]
[ext_resource type="Texture2D" uid="uid://ca3paw31aubkd" path="res://sprites/projectile/magicMissile.png" id="2_6mikr"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_vfvxd"]
size = Vector2(20, 14)
[node name="MagicMissile" type="CharacterBody2D"]
collision_layer = 0
collision_mask = 0
script = ExtResource("1_cp6hg")
_life = 5000
_durability = 1.0
_maxDamage = 7
_minDamage = 3
_damageType = 2
Speed = 15.0
_repelStrength = 2.5
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(1, 0)
shape = SubResource("RectangleShape2D_vfvxd")
[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="."]
bus = &"SoundEffect"
area_mask = 16
[node name="MagicMissile" type="Sprite2D" parent="."]
position = Vector2(1, 0)
texture = ExtResource("2_6mikr")

File diff suppressed because one or more lines are too long

View File

@ -1,70 +0,0 @@
[gd_scene load_steps=8 format=3 uid="uid://b0uurp551pku"]
[ext_resource type="TileSet" uid="uid://c4wpp12rr44hi" path="res://tileSets/dungeon.tres" id="1_a15hy"]
[ext_resource type="Script" path="res://scripts/map/AiCharacterSpawn.cs" id="2_wamhd"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_kiih8"]
size = Vector2(443, 118)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_o85u0"]
size = Vector2(20, 48)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_30r3c"]
size = Vector2(20, 46)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_7tsse"]
size = Vector2(53, 24)
[sub_resource type="NavigationPolygon" id="NavigationPolygon_rh1gx"]
vertices = PackedVector2Array(501, 150, 9, 151, 11, 107, 43, 107, 170, 41, 169, 11, 217, 11, 219, 42, 42, 44, 470, 107, 499, 106, 469, 43)
polygons = Array[PackedInt32Array]([PackedInt32Array(0, 1, 2, 3), PackedInt32Array(4, 5, 6, 7), PackedInt32Array(0, 3, 8, 4, 7, 9), PackedInt32Array(9, 10, 0), PackedInt32Array(9, 7, 11)])
outlines = Array[PackedVector2Array]([PackedVector2Array(479, 34, 228, 32, 226, 1, 159, 1, 160, 31, 32, 35, 33, 97, 1, 97, -1, 162, 512, 160, 509, 96, 480, 97)])
source_geometry_group_name = &"navigation_polygon_source_group"
[node name="InitialRoom" type="Node2D"]
[node name="TileMap" type="TileMap" parent="."]
tile_set = ExtResource("1_a15hy")
format = 2
layer_0/name = "BackgroundWall"
layer_0/navigation_enabled = false
layer_0/tile_data = PackedInt32Array(65550, 393217, 5, 131086, 393217, 5, 196622, 393217, 5, 262158, 393217, 5, 262157, 393217, 5, 196621, 393217, 5, 131085, 393217, 5, 65549, 393217, 5, 65548, 393217, 5, 65547, 393217, 5, 65546, 393217, 5, 65545, 393217, 5, 65544, 393217, 5, 65543, 393217, 5, 65542, 393217, 5, 65541, 393217, 5, 65540, 393217, 5, 65539, 393217, 5, 65538, 393217, 5, 65537, 393217, 5, 131073, 393217, 5, 131074, 393217, 5, 131075, 393217, 5, 131076, 393217, 5, 131077, 393217, 5, 131078, 393217, 5, 131079, 393217, 5, 131080, 393217, 5, 131081, 393217, 5, 131082, 393217, 5, 131083, 393217, 5, 131084, 393217, 5, 196620, 393217, 5, 196619, 393217, 5, 196618, 393217, 5, 196617, 393217, 5, 196616, 262145, 5, 196615, 393217, 5, 196614, 393217, 5, 196613, 262145, 5, 196612, 393217, 5, 196611, 393217, 5, 196610, 393217, 5, 196609, 393217, 5, 262145, 393217, 5, 262146, 393217, 5, 262147, 393217, 5, 262148, 393217, 5, 262149, 393217, 5, 262150, 393217, 5, 262151, 393217, 5, 262152, 393217, 5, 262153, 393217, 5, 262154, 393217, 5, 262155, 393217, 5, 262156, 393217, 5, 196608, 393217, 5, 262144, 393217, 5, 262159, 393217, 5, 196623, 393217, 5, 5, 393217, 5, 6, 393217, 5)
layer_1/name = "BackgroundDecoration"
layer_1/tile_data = PackedInt32Array()
layer_2/name = "Ground"
layer_2/tile_data = PackedInt32Array(0, 1, 3, 65536, 131073, 1, 131072, 131073, 1, 1, 65537, 2, 2, 65537, 2, 3, 65537, 2, 4, 65537, 2, 7, 65537, 2, 8, 65537, 2, 9, 65537, 2, 10, 65537, 2, 11, 65537, 2, 12, 65537, 2, 13, 65537, 2, 14, 65537, 3, 15, 131073, 3, 65551, 131073, 4, 131087, 131073, 4, 327681, 65537, 0, 327682, 65537, 0, 327683, 65537, 0, 327684, 65537, 0, 327685, 65537, 0, 327686, 65537, 0, 327687, 65537, 0, 327688, 65537, 0, 327689, 65537, 0, 327690, 65537, 0, 327691, 65537, 0, 327692, 65537, 0, 327693, 65537, 0, 327694, 65537, 0, 327680, 1, 5, 327695, 131073, 5, 5, 262145, 4, 6, 262145, 4)
[node name="RoomArea" type="Area2D" parent="."]
collision_mask = 0
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomArea"]
position = Vector2(256.5, 95)
shape = SubResource("RectangleShape2D_kiih8")
[node name="RoomSlotList" type="Node2D" parent="."]
[node name="Area2D" type="Area2D" parent="RoomSlotList"]
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomSlotList/Area2D"]
position = Vector2(17, 129)
shape = SubResource("RectangleShape2D_o85u0")
[node name="Area2D2" type="Area2D" parent="RoomSlotList"]
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomSlotList/Area2D2"]
position = Vector2(498, 128)
shape = SubResource("RectangleShape2D_30r3c")
[node name="Area2D3" type="Area2D" parent="RoomSlotList"]
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomSlotList/Area2D3"]
position = Vector2(193, 15)
shape = SubResource("RectangleShape2D_7tsse")
[node name="Marker2D" type="Marker2D" parent="."]
position = Vector2(260, 87)
script = ExtResource("2_wamhd")
metadata/ResPath = "res://prefab/entitys/DelivererOfDarkMagic.tscn"
[node name="NavigationRegion2D" type="NavigationRegion2D" parent="."]
navigation_polygon = SubResource("NavigationPolygon_rh1gx")

View File

@ -1,71 +0,0 @@
[gd_scene load_steps=8 format=3 uid="uid://dslr5tdbp4noq"]
[ext_resource type="TileSet" uid="uid://c4wpp12rr44hi" path="res://tileSets/dungeon.tres" id="1_rn2om"]
[ext_resource type="Script" path="res://scripts/map/AiCharacterSpawn.cs" id="2_7q101"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_kiih8"]
size = Vector2(441, 122)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_o85u0"]
size = Vector2(20, 48)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_x4kt2"]
size = Vector2(46, 20)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_131jn"]
size = Vector2(20, 54)
[sub_resource type="NavigationPolygon" id="NavigationPolygon_db40i"]
vertices = PackedVector2Array(499, 108, 501, 150, 246, 149, 471, 108, 12, 149, 11, 107, 41, 107, 203, 149, 245, 180, 203, 178, 43, 43, 470, 44)
polygons = Array[PackedInt32Array]([PackedInt32Array(0, 1, 2, 3), PackedInt32Array(4, 5, 6, 7), PackedInt32Array(2, 8, 9, 7), PackedInt32Array(10, 11, 3, 2, 7, 6)])
outlines = Array[PackedVector2Array]([PackedVector2Array(34, 33, 31, 97, 1, 98, 2, 159, 193, 159, 193, 188, 255, 191, 256, 159, 512, 161, 509, 98, 481, 98, 480, 35)])
source_geometry_group_name = &"navigation_polygon_source_group"
[node name="InitialRoom" type="Node2D"]
[node name="TileMap" type="TileMap" parent="."]
tile_set = ExtResource("1_rn2om")
format = 2
layer_0/name = "BackgroundWall"
layer_0/navigation_enabled = false
layer_0/tile_data = PackedInt32Array(65550, 393217, 5, 131086, 393217, 5, 196622, 393217, 5, 262158, 393217, 5, 262157, 393217, 5, 196621, 393217, 5, 131085, 393217, 5, 65549, 393217, 5, 65548, 393217, 5, 65547, 393217, 5, 65546, 393217, 5, 65545, 393217, 5, 65544, 393217, 5, 65543, 393217, 5, 65542, 393217, 5, 65541, 393217, 5, 65540, 393217, 5, 65539, 393217, 5, 65538, 393217, 5, 65537, 393217, 5, 131073, 393217, 5, 131074, 393217, 5, 131075, 393217, 5, 131076, 393217, 5, 131077, 393217, 5, 131078, 393217, 5, 131079, 393217, 5, 131080, 393217, 5, 131081, 393217, 5, 131082, 393217, 5, 131083, 393217, 5, 131084, 393217, 5, 196620, 393217, 5, 196619, 393217, 5, 196618, 393217, 5, 196617, 393217, 5, 196616, 262145, 5, 196615, 393217, 5, 196614, 393217, 5, 196613, 262145, 5, 196612, 393217, 5, 196611, 393217, 5, 196610, 393217, 5, 196609, 393217, 5, 262145, 393217, 5, 262146, 393217, 5, 262147, 393217, 5, 262148, 393217, 5, 262149, 393217, 5, 262150, 393217, 5, 262151, 393217, 5, 262152, 393217, 5, 262153, 393217, 5, 262154, 393217, 5, 262155, 393217, 5, 262156, 393217, 5, 196608, 393217, 5, 262144, 393217, 5, 262159, 393217, 5, 196623, 393217, 5, 327686, 393217, 5, 327687, 393217, 5)
layer_1/name = "BackgroundDecoration"
layer_1/tile_data = PackedInt32Array()
layer_2/name = "Ground"
layer_2/tile_data = PackedInt32Array(0, 1, 3, 65536, 131073, 1, 131072, 131073, 1, 1, 65537, 2, 2, 65537, 2, 3, 65537, 2, 4, 65537, 2, 5, 65537, 2, 6, 65537, 2, 7, 65537, 2, 8, 65537, 2, 9, 65537, 2, 10, 65537, 2, 11, 65537, 2, 12, 65537, 2, 13, 65537, 2, 14, 65537, 3, 15, 131073, 3, 65551, 131073, 4, 131087, 131073, 4, 327681, 65537, 0, 327682, 65537, 0, 327683, 65537, 0, 327684, 65537, 0, 327685, 65537, 0, 327688, 65537, 0, 327689, 65537, 0, 327690, 65537, 0, 327691, 65537, 0, 327692, 65537, 0, 327693, 65537, 0, 327694, 65537, 0, 327680, 1, 5, 327695, 131073, 5, 327686, 262145, 4, 327687, 262145, 4)
[node name="RoomArea" type="Area2D" parent="."]
collision_mask = 0
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomArea"]
position = Vector2(255.5, 97)
shape = SubResource("RectangleShape2D_kiih8")
[node name="RoomSlotList" type="Node2D" parent="."]
[node name="Area2D" type="Area2D" parent="RoomSlotList"]
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomSlotList/Area2D"]
position = Vector2(17, 129)
shape = SubResource("RectangleShape2D_o85u0")
[node name="Area2D3" type="Area2D" parent="RoomSlotList"]
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomSlotList/Area2D3"]
position = Vector2(224, 178)
shape = SubResource("RectangleShape2D_x4kt2")
[node name="Area2D2" type="Area2D" parent="RoomSlotList"]
position = Vector2(498, 109)
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomSlotList/Area2D2"]
position = Vector2(0, 17)
shape = SubResource("RectangleShape2D_131jn")
[node name="Marker2D" type="Marker2D" parent="."]
position = Vector2(237, 69)
script = ExtResource("2_7q101")
metadata/ResPath = "res://prefab/entitys/DelivererOfDarkMagic.tscn"
[node name="NavigationRegion2D" type="NavigationRegion2D" parent="."]
navigation_polygon = SubResource("NavigationPolygon_db40i")

View File

@ -1,63 +0,0 @@
[gd_scene load_steps=8 format=3 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://b2blj0yf4ohx3" path="res://icon.svg" id="4_psvpu"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_kiih8"]
size = Vector2(450, 191)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_jxmys"]
size = Vector2(18, 57.75)
[sub_resource type="NavigationPolygon" id="NavigationPolygon_064c7"]
vertices = PackedVector2Array(468, 174, 500, 174, 499, 214, 41, 214, 45, 45, 468, 45)
polygons = Array[PackedInt32Array]([PackedInt32Array(0, 1, 2, 3), PackedInt32Array(0, 3, 4, 5)])
outlines = Array[PackedVector2Array]([PackedVector2Array(35, 35, 31, 224, 509, 225, 510, 164, 478, 164, 478, 35)])
source_geometry_group_name = &"navigation_polygon_source_group"
[node name="InitialRoom" type="Node2D"]
[node name="TileMap" type="TileMap" parent="."]
tile_set = ExtResource("1_rn2om")
format = 2
layer_0/name = "BackgroundWall"
layer_0/navigation_enabled = false
layer_0/tile_data = PackedInt32Array(393230, 393217, 5, 393229, 393217, 5, 393228, 393217, 5, 393227, 393217, 5, 393226, 393217, 5, 393225, 393217, 5, 393224, 393217, 5, 393223, 393217, 5, 393222, 393217, 5, 65550, 393217, 5, 131086, 393217, 5, 196622, 393217, 5, 262158, 393217, 5, 327694, 393217, 5, 327693, 393217, 5, 262157, 393217, 5, 196621, 393217, 5, 131085, 393217, 5, 65549, 393217, 5, 65548, 393217, 5, 65547, 393217, 5, 65546, 393217, 5, 65545, 393217, 5, 65544, 393217, 5, 65543, 393217, 5, 65542, 393217, 5, 65541, 393217, 5, 65540, 393217, 5, 65539, 393217, 5, 65538, 393217, 5, 65537, 393217, 5, 131073, 393217, 5, 131074, 393217, 5, 131075, 393217, 5, 131076, 393217, 5, 131077, 393217, 5, 131078, 393217, 5, 131079, 393217, 5, 131080, 393217, 5, 131081, 393217, 5, 131082, 393217, 5, 131083, 393217, 5, 131084, 393217, 5, 196620, 393217, 5, 196619, 393217, 5, 196618, 393217, 5, 196617, 393217, 5, 196616, 262145, 5, 196615, 393217, 5, 196614, 393217, 5, 196613, 262145, 5, 196612, 393217, 5, 196611, 393217, 5, 196610, 393217, 5, 196609, 393217, 5, 262145, 393217, 5, 262146, 393217, 5, 262147, 393217, 5, 262148, 393217, 5, 262149, 393217, 5, 262150, 393217, 5, 262151, 393217, 5, 262152, 393217, 5, 262153, 393217, 5, 262154, 393217, 5, 262155, 393217, 5, 262156, 393217, 5, 327692, 393217, 5, 327691, 393217, 5, 327690, 393217, 5, 327689, 393217, 5, 327688, 393217, 5, 327687, 393217, 5, 327686, 393217, 5, 327685, 393217, 5, 327684, 393217, 5, 327683, 393217, 5, 327682, 393217, 5, 327681, 393217, 5, 393217, 393217, 5, 393218, 393217, 5, 393219, 393217, 5, 393220, 393217, 5, 393221, 393217, 5, 393231, 393217, 5, 327695, 393217, 5)
layer_1/name = "BackgroundDecoration"
layer_1/tile_data = PackedInt32Array(393218, 458753, 5, 65550, 458753, 4)
layer_2/name = "Ground"
layer_2/tile_data = PackedInt32Array(0, 1, 3, 65536, 131073, 1, 131072, 131073, 1, 196608, 131073, 1, 262144, 131073, 1, 458752, 1, 5, 15, 131073, 3, 65551, 131073, 4, 131087, 131073, 4, 196623, 131073, 4, 262159, 131073, 4, 458767, 131073, 5, 327680, 131073, 1, 393216, 131073, 1, 1, 65537, 2, 2, 65537, 2, 3, 65537, 2, 4, 65537, 2, 5, 65537, 2, 6, 65537, 2, 7, 65537, 2, 8, 65537, 2, 9, 65537, 2, 10, 65537, 2, 11, 65537, 2, 12, 65537, 2, 13, 65537, 2, 14, 65537, 3, 458753, 65537, 0, 458754, 65537, 0, 458755, 65537, 0, 458756, 65537, 0, 458757, 65537, 0, 458758, 65537, 0, 458759, 65537, 0, 458760, 65537, 0, 458761, 65537, 0, 458762, 65537, 0, 458763, 65537, 0, 458764, 65537, 0, 458765, 65537, 0, 458766, 65537, 0)
[node name="RoomArea" type="Area2D" parent="."]
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomArea"]
position = Vector2(253, 130.5)
shape = SubResource("RectangleShape2D_kiih8")
[node name="RoomSlotList" type="Node2D" parent="."]
[node name="Slot1" type="Area2D" parent="RoomSlotList"]
position = Vector2(491, 193)
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomSlotList/Slot1"]
position = Vector2(5, 0)
shape = SubResource("RectangleShape2D_jxmys")
debug_color = Color(0, 0.6, 0.701961, 0.419608)
[node name="Marker2D" type="Marker2D" parent="."]
position = Vector2(221, 134)
script = ExtResource("2_6p8mv")
[node name="ItemMarker2D" type="Marker2D" parent="."]
position = Vector2(142, 84)
script = ExtResource("3_v1tlc")
ItemId = "staff_of_the_undead"
[node name="Icon" type="Sprite2D" parent="ItemMarker2D"]
scale = Vector2(0.3, 0.3)
texture = ExtResource("4_psvpu")
[node name="NavigationRegion2D" type="NavigationRegion2D" parent="."]
navigation_polygon = SubResource("NavigationPolygon_064c7")

View File

@ -0,0 +1,86 @@
[gd_scene load_steps=8 format=4 uid="uid://bo245qin4rl8a"]
[ext_resource type="TileSet" uid="uid://c4wpp12rr44hi" path="res://tileSets/dungeon.tres" id="1_60tbt"]
[ext_resource type="Texture2D" uid="uid://drw45jlmfo0su" path="res://sprites/light/White_100.png" id="2_w0wh3"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_o85u0"]
size = Vector2(20, 48)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_6qg1t"]
size = Vector2(20.9922, 46.5)
[sub_resource type="NavigationPolygon" id="NavigationPolygon_1qloc"]
vertices = PackedVector2Array(630, 138.672, 630, 183.008, 11, 183.977, 11, 138.672, 41.8984, 137.688, 599.203, 137.688, 597.203, 44.0078, 42.8906, 44.9766)
polygons = Array[PackedInt32Array]([PackedInt32Array(0, 1, 2, 3, 4, 5), PackedInt32Array(6, 5, 4, 7)])
outlines = Array[PackedVector2Array]([PackedVector2Array(33, 35, 607, 34, 609, 128, 640, 129, 640, 193, 1, 194, 1, 129, 32, 128)])
source_geometry_group_name = &"navigation_polygon_source_group"
[sub_resource type="RectangleShape2D" id="RectangleShape2D_kiih8"]
size = Vector2(638, 222)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_kfmgh"]
size = Vector2(579, 151.5)
[node name="InitialRoom2" type="Node2D"]
[node name="RoomSlotList" type="Node2D" parent="."]
[node name="Area2D" type="Area2D" parent="RoomSlotList"]
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomSlotList/Area2D"]
position = Vector2(14, 158)
shape = SubResource("RectangleShape2D_o85u0")
[node name="Area2D5" type="Area2D" parent="RoomSlotList"]
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomSlotList/Area2D5"]
position = Vector2(624, 157)
shape = SubResource("RectangleShape2D_6qg1t")
[node name="NavigationRegion2D" type="NavigationRegion2D" parent="."]
navigation_polygon = SubResource("NavigationPolygon_1qloc")
[node name="TileMap" type="Node2D" parent="."]
[node name="BackgroundWall" type="TileMapLayer" parent="TileMap"]
use_parent_material = true
tile_map_data = PackedByteArray("AAABAAEAAQAGAAUAAAABAAIAAQAGAAUAAAABAAMAAQAGAAUAAAABAAQAAQAGAAUAAAABAAUAAQAGAAUAAAACAAEAAQAGAAUAAAACAAIAAQAGAAUAAAACAAMAAQAGAAUAAAACAAQAAQAGAAUAAAACAAUAAQAGAAUAAAADAAEAAQAGAAUAAAADAAIAAQAGAAUAAAADAAMAAQAGAAUAAAADAAQAAQAGAAUAAAADAAUAAQAGAAUAAAAEAAEAAQAGAAUAAAAEAAIAAQAGAAUAAAAEAAMAAQAGAAUAAAAEAAQAAQAGAAUAAAAEAAUAAQAGAAUAAAAFAAEAAQAGAAUAAAAFAAIAAQAGAAUAAAAFAAMAAQAGAAUAAAAFAAQAAQAGAAUAAAAFAAUAAQAGAAUAAAAGAAEAAQAGAAUAAAAGAAIAAQAGAAUAAAAGAAMAAQAGAAUAAAAGAAQAAQAGAAUAAAAGAAUAAQAGAAUAAAAHAAEAAQAGAAUAAAAHAAIAAQAGAAUAAAAHAAMAAQAGAAUAAAAHAAQAAQAGAAUAAAAHAAUAAQAGAAUAAAAIAAEAAQAGAAUAAAAIAAIAAQAGAAUAAAAIAAMAAQAGAAUAAAAIAAQAAQAGAAUAAAAIAAUAAQAGAAUAAAAJAAEAAQAGAAUAAAAJAAIAAQAGAAUAAAAJAAMAAQAGAAUAAAAJAAQAAQAGAAUAAAAJAAUAAQAGAAUAAAAKAAEAAQAGAAUAAAAKAAIAAQAGAAUAAAAKAAMAAQAGAAUAAAAKAAQAAQAGAAUAAAAKAAUAAQAGAAUAAAALAAEAAQAGAAUAAAALAAIAAQAGAAUAAAALAAMAAQAGAAUAAAALAAQAAQAGAAUAAAALAAUAAQAGAAUAAAAMAAEAAQAGAAUAAAAMAAIAAQAGAAUAAAAMAAMAAQAGAAUAAAAMAAQAAQAGAAUAAAAMAAUAAQAGAAUAAAANAAEAAQAGAAUAAAANAAIAAQAGAAUAAAANAAMAAQAGAAUAAAANAAQAAQAGAAUAAAANAAUAAQAGAAUAAAAOAAEAAQAGAAUAAAAOAAIAAQAGAAUAAAAOAAMAAQAGAAUAAAAOAAQAAQAGAAUAAAAOAAUAAQAGAAUAAAAPAAEAAQAGAAUAAAAPAAIAAQAGAAUAAAAPAAMAAQAGAAUAAAAPAAQAAQAGAAUAAAAPAAUAAQAGAAUAAAAQAAEAAQAGAAUAAAAQAAIAAQAGAAUAAAAQAAMAAQAGAAUAAAAQAAQAAQAGAAUAAAAQAAUAAQAGAAUAAAARAAEAAQAGAAUAAAARAAIAAQAGAAUAAAARAAMAAQAGAAUAAAARAAQAAQAGAAUAAAARAAUAAQAGAAUAAAASAAEAAQAGAAUAAAASAAIAAQAGAAUAAAASAAMAAQAGAAUAAAASAAQAAQAGAAUAAAASAAUAAQAGAAUAAAAAAAUAAQAGAAUAAAAAAAQAAQAGAAUAAAATAAUAAQAGAAUAAAATAAQAAQAGAAUAAAA=")
tile_set = ExtResource("1_60tbt")
navigation_enabled = false
[node name="BackgroundDecoration" type="TileMapLayer" parent="TileMap"]
use_parent_material = true
tile_map_data = PackedByteArray("AAADAAQAAQAEAAYAAAAEAAQAAQAEAAYAAAAEAAUAAQAEAAYAAAADAAUAAQAEAAYAAAADAAMAAQAEAAYAAAAEAAMAAQAEAAYAAAAGAAMAAQAEAAYAAAAGAAQAAQAEAAYAAAAGAAUAAQAEAAYAAAAHAAUAAQAEAAYAAAAHAAQAAQAEAAYAAAAHAAMAAQAEAAYAAAAJAAMAAQAEAAYAAAAJAAQAAQAEAAYAAAAJAAUAAQAEAAYAAAAKAAUAAQAEAAYAAAAKAAQAAQAEAAYAAAAKAAMAAQAEAAYAAAAOAAUAAQABAAYAAAANAAUAAQAAAAYAAAA=")
tile_set = ExtResource("1_60tbt")
[node name="Ground" type="TileMapLayer" parent="TileMap"]
use_parent_material = true
tile_map_data = PackedByteArray("AAAAAAAAAQAAAAMAAAABAAAAAQABAAIAAAACAAAAAQABAAIAAAADAAAAAQABAAIAAAAEAAAAAQABAAIAAAAFAAAAAQABAAIAAAAGAAAAAQABAAIAAAAHAAAAAQABAAIAAAAIAAAAAQABAAIAAAAJAAAAAQABAAIAAAAKAAAAAQABAAIAAAALAAAAAQABAAIAAAAMAAAAAQABAAIAAAANAAAAAQABAAIAAAAOAAAAAQABAAIAAAAPAAAAAQABAAIAAAAQAAAAAQABAAIAAAARAAAAAQABAAIAAAAAAAEAAQACAAEAAAAAAAIAAQACAAEAAAAAAAMAAQACAAEAAAABAAYAAQABAAAAAAACAAYAAQABAAAAAAADAAYAAQABAAAAAAAEAAYAAQABAAAAAAAFAAYAAQABAAAAAAAGAAYAAQABAAAAAAAHAAYAAQABAAAAAAAIAAYAAQABAAAAAAAJAAYAAQABAAAAAAAKAAYAAQABAAAAAAALAAYAAQABAAAAAAAMAAYAAQABAAAAAAANAAYAAQABAAAAAAAOAAYAAQABAAAAAAAPAAYAAQABAAAAAAAQAAYAAQABAAAAAAARAAYAAQABAAAAAAASAAYAAQABAAAAAAASAAAAAQABAAIAAAATAAEAAQAAAAEAAAATAAIAAQAAAAEAAAATAAMAAQAAAAEAAAATAAYAAQACAAUAAAATAAAAAQACAAMAAAAAAAYAAQAAAAUAAAA=")
tile_set = ExtResource("1_60tbt")
[node name="Barrier" type="TileMapLayer" parent="TileMap"]
use_parent_material = true
tile_map_data = PackedByteArray("AAATAAQAAQAAAAEAAAATAAUAAQAAAAEAAAAAAAQAAQACAAEAAAAAAAUAAQACAAEAAAA=")
tile_set = ExtResource("1_60tbt")
[node name="PointLight2D" type="PointLight2D" parent="."]
visible = false
position = Vector2(320, 111)
scale = Vector2(20.125, 7.06253)
texture = ExtResource("2_w0wh3")
[node name="AutoSpawn" type="Node2D" parent="."]
visible = false
[node name="RoomArea" type="Area2D" parent="."]
collision_mask = 0
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomArea"]
position = Vector2(320, 112)
shape = SubResource("RectangleShape2D_kiih8")
[node name="SpawnArea" type="Area2D" parent="."]
[node name="CollisionShape2D" type="CollisionShape2D" parent="SpawnArea"]
position = Vector2(315.5, 116.25)
shape = SubResource("RectangleShape2D_kfmgh")

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,110 @@
[gd_scene load_steps=8 format=4 uid="uid://53ssan8hgcyn"]
[ext_resource type="TileSet" uid="uid://c4wpp12rr44hi" path="res://tileSets/dungeon.tres" id="1_kdit4"]
[ext_resource type="Texture2D" uid="uid://drw45jlmfo0su" path="res://sprites/light/White_100.png" id="2_g41lp"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_o85u0"]
size = Vector2(22.5, 48)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_6qg1t"]
size = Vector2(24.5, 59.75)
[sub_resource type="NavigationPolygon" id="NavigationPolygon_1qloc"]
vertices = PackedVector2Array(8, 791.953, 8, 746.922, 42, 749.922, 405.523, 790.039, 403.461, 746, 374.047, 746, 373.32, 109.617, 404.82, 107.648, 404.148, 150.32, 373.969, 151.328, 42, 341.359, 10.1719, 343.344, 10.8438, 301, 41, 301, 41, 86.2891, 11.6719, 88.2969, 10.3203, 45, 29.0078, 45, 371.289, 44.0234, 375.031, 489.672, 372.953, 537.211, 404.141, 533.18, 404.828, 490.656)
polygons = Array[PackedInt32Array]([PackedInt32Array(0, 1, 2, 3), PackedInt32Array(4, 3, 2, 5), PackedInt32Array(6, 7, 8, 9), PackedInt32Array(10, 11, 12, 13), PackedInt32Array(14, 15, 16, 17), PackedInt32Array(14, 17, 18, 6), PackedInt32Array(13, 14, 6, 9, 19, 10), PackedInt32Array(2, 10, 19, 20), PackedInt32Array(20, 5, 2), PackedInt32Array(21, 20, 19, 22)])
outlines = Array[PackedVector2Array]([PackedVector2Array(29, 35, 381, 34, 383, 99, 415, 97, 414, 160, 384, 161, 385, 480, 415, 481, 414, 542, 383, 546, 384, 736, 413, 736, 416, 800, -2, 802, -2, 736, 32, 739, 32, 352, 0, 354, 1, 291, 31, 291, 31, 97, 2, 99, 0, 35)])
source_geometry_group_name = &"navigation_polygon_source_group"
[sub_resource type="RectangleShape2D" id="RectangleShape2D_kiih8"]
size = Vector2(413, 828)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_kfmgh"]
size = Vector2(322, 765)
[node name="InitialRoom2" type="Node2D"]
[node name="RoomSlotList" type="Node2D" parent="."]
[node name="Area2D" type="Area2D" parent="RoomSlotList"]
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomSlotList/Area2D"]
position = Vector2(15, 322)
shape = SubResource("RectangleShape2D_o85u0")
[node name="Area2D2" type="Area2D" parent="RoomSlotList"]
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomSlotList/Area2D2"]
position = Vector2(16, 767)
shape = SubResource("RectangleShape2D_o85u0")
[node name="Area2D6" type="Area2D" parent="RoomSlotList"]
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomSlotList/Area2D6"]
position = Vector2(401, 516)
shape = SubResource("RectangleShape2D_o85u0")
[node name="Area2D4" type="Area2D" parent="RoomSlotList"]
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomSlotList/Area2D4"]
position = Vector2(14, 65)
shape = SubResource("RectangleShape2D_o85u0")
[node name="Area2D5" type="Area2D" parent="RoomSlotList"]
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomSlotList/Area2D5"]
position = Vector2(399, 129)
shape = SubResource("RectangleShape2D_o85u0")
[node name="Area2D3" type="Area2D" parent="RoomSlotList"]
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomSlotList/Area2D3"]
position = Vector2(399.75, 769.875)
shape = SubResource("RectangleShape2D_6qg1t")
[node name="NavigationRegion2D" type="NavigationRegion2D" parent="."]
position = Vector2(0, -1)
navigation_polygon = SubResource("NavigationPolygon_1qloc")
[node name="TileMap" type="Node2D" parent="."]
[node name="BackgroundWall" type="TileMapLayer" parent="TileMap"]
use_parent_material = true
tile_map_data = PackedByteArray("AAABABIAAQAGAAUAAAABABMAAQAGAAUAAAABABQAAQAGAAUAAAABABUAAQAGAAUAAAABABYAAQAGAAUAAAABABcAAQAGAAUAAAABABgAAQAGAAUAAAACABIAAQAGAAUAAAACABMAAQAGAAUAAAACABQAAQAGAAUAAAACABUAAQAGAAUAAAACABYAAQAGAAUAAAACABcAAQAGAAUAAAACABgAAQAGAAUAAAADABIAAQAGAAUAAAADABMAAQAGAAUAAAADABQAAQAGAAUAAAADABUAAQAGAAUAAAADABYAAQAGAAUAAAADABcAAQAGAAUAAAADABgAAQAGAAUAAAAEABIAAQAGAAUAAAAEABMAAQAGAAUAAAAEABQAAQAGAAUAAAAEABUAAQAGAAUAAAAEABYAAQAGAAUAAAAEABcAAQAGAAUAAAAEABgAAQAGAAUAAAAFABIAAQAGAAUAAAAFABMAAQAGAAUAAAAFABQAAQAGAAUAAAAFABUAAQAGAAUAAAAFABYAAQAGAAUAAAAFABcAAQAGAAUAAAAFABgAAQAGAAUAAAAGABIAAQAGAAUAAAAGABMAAQAGAAUAAAAGABQAAQAGAAUAAAAGABUAAQAGAAUAAAAGABYAAQAGAAUAAAAGABcAAQAGAAUAAAAGABgAAQAGAAUAAAAHABIAAQAGAAUAAAAHABMAAQAGAAUAAAAHABQAAQAGAAUAAAAHABUAAQAGAAUAAAAHABYAAQAGAAUAAAAHABcAAQAGAAUAAAAHABgAAQAGAAUAAAAIABIAAQAGAAUAAAAIABMAAQAGAAUAAAAIABQAAQAGAAUAAAAIABUAAQAGAAUAAAAIABYAAQAGAAUAAAAIABcAAQAGAAUAAAAIABgAAQAGAAUAAAAJABIAAQAGAAUAAAAJABMAAQAGAAUAAAAJABQAAQAGAAUAAAAJABUAAQAGAAUAAAAJABYAAQAGAAUAAAAJABcAAQAGAAUAAAAJABgAAQAGAAUAAAAKABIAAQAGAAUAAAAKABMAAQAGAAUAAAAKABQAAQAGAAUAAAAKABUAAQAGAAUAAAAKABYAAQAGAAUAAAAKABcAAQAGAAUAAAAKABgAAQAGAAUAAAALABIAAQAGAAUAAAALABMAAQAGAAUAAAALABQAAQAGAAUAAAALABUAAQAGAAUAAAALABYAAQAGAAUAAAALABcAAQAGAAUAAAALABgAAQAGAAUAAAAAAAEAAQAGAAUAAAAAAAIAAQAGAAUAAAABAAEAAQAGAAUAAAABAAIAAQAGAAUAAAABAAMAAQAGAAUAAAABAAQAAQAGAAUAAAABAAUAAQAGAAUAAAABAAYAAQAGAAUAAAABAAcAAQAGAAUAAAABAAgAAQAGAAUAAAABAAkAAQAGAAUAAAABAAoAAQAGAAUAAAABAAsAAQAGAAUAAAABAAwAAQAGAAUAAAABAA0AAQAGAAUAAAABAA4AAQAGAAUAAAABAA8AAQAGAAUAAAABABAAAQAGAAUAAAABABEAAQAGAAUAAAACAAEAAQAGAAUAAAACAAIAAQAGAAUAAAACAAMAAQAGAAUAAAACAAQAAQAGAAUAAAACAAUAAQAGAAUAAAACAAYAAQAGAAUAAAACAAcAAQAGAAUAAAACAAgAAQAGAAUAAAACAAkAAQAGAAUAAAACAAoAAQAGAAUAAAACAAsAAQAGAAUAAAACAAwAAQAGAAUAAAACAA0AAQAGAAUAAAACAA4AAQAGAAUAAAACAA8AAQAGAAUAAAACABAAAQAGAAUAAAACABEAAQAGAAUAAAADAAEAAQAGAAUAAAADAAIAAQAGAAUAAAADAAMAAQAGAAUAAAADAAQAAQAGAAUAAAADAAUAAQAGAAUAAAADAAYAAQAGAAUAAAADAAcAAQAGAAUAAAADAAgAAQAGAAUAAAADAAkAAQAGAAUAAAADAAoAAQAGAAUAAAADAAsAAQAGAAUAAAADAAwAAQAGAAUAAAADAA0AAQAGAAUAAAADAA4AAQAGAAUAAAADAA8AAQAGAAUAAAADABAAAQAGAAUAAAADABEAAQAGAAUAAAAEAAEAAQAGAAUAAAAEAAIAAQAGAAUAAAAEAAMAAQAGAAUAAAAEAAQAAQAGAAUAAAAEAAUAAQAGAAUAAAAEAAYAAQAGAAUAAAAEAAcAAQAGAAUAAAAEAAgAAQAGAAUAAAAEAAkAAQAGAAUAAAAEAAoAAQAGAAUAAAAEAAsAAQAGAAUAAAAEAAwAAQAGAAUAAAAEAA0AAQAGAAUAAAAEAA4AAQAGAAUAAAAEAA8AAQAGAAUAAAAEABAAAQAGAAUAAAAEABEAAQAGAAUAAAAFAAEAAQAGAAUAAAAFAAIAAQAGAAUAAAAFAAMAAQAGAAUAAAAFAAQAAQAGAAUAAAAFAAUAAQAGAAUAAAAFAAYAAQAGAAUAAAAFAAcAAQAGAAUAAAAFAAgAAQAGAAUAAAAFAAkAAQAGAAUAAAAFAAoAAQAGAAUAAAAFAAsAAQAGAAUAAAAFAAwAAQAGAAUAAAAFAA0AAQAGAAUAAAAFAA4AAQAGAAUAAAAFAA8AAQAGAAUAAAAFABAAAQAGAAUAAAAFABEAAQAGAAUAAAAGAAEAAQAGAAUAAAAGAAIAAQAGAAUAAAAGAAMAAQAGAAUAAAAGAAQAAQAGAAUAAAAGAAUAAQAGAAUAAAAGAAYAAQAGAAUAAAAGAAcAAQAGAAUAAAAGAAgAAQAGAAUAAAAGAAkAAQAGAAUAAAAGAAoAAQAGAAUAAAAGAAsAAQAGAAUAAAAGAAwAAQAGAAUAAAAGAA0AAQAGAAUAAAAGAA4AAQAGAAUAAAAGAA8AAQAGAAUAAAAGABAAAQAGAAUAAAAGABEAAQAGAAUAAAAHAAEAAQAGAAUAAAAHAAIAAQAGAAUAAAAHAAMAAQAGAAUAAAAHAAQAAQAGAAUAAAAHAAUAAQAGAAUAAAAHAAYAAQAGAAUAAAAHAAcAAQAGAAUAAAAHAAgAAQAGAAUAAAAHAAkAAQAGAAUAAAAHAAoAAQAGAAUAAAAHAAsAAQAGAAUAAAAHAAwAAQAGAAUAAAAHAA0AAQAGAAUAAAAHAA4AAQAGAAUAAAAHAA8AAQAGAAUAAAAHABAAAQAGAAUAAAAHABEAAQAGAAUAAAAIAAEAAQAGAAUAAAAIAAIAAQAGAAUAAAAIAAMAAQAGAAUAAAAIAAQAAQAGAAUAAAAIAAUAAQAGAAUAAAAIAAYAAQAGAAUAAAAIAAcAAQAGAAUAAAAIAAgAAQAGAAUAAAAIAAkAAQAGAAUAAAAIAAoAAQAGAAUAAAAIAAsAAQAGAAUAAAAIAAwAAQAGAAUAAAAIAA0AAQAGAAUAAAAIAA4AAQAGAAUAAAAIAA8AAQAGAAUAAAAIABAAAQAGAAUAAAAIABEAAQAGAAUAAAAJAAEAAQAGAAUAAAAJAAIAAQAGAAUAAAAJAAMAAQAGAAUAAAAJAAQAAQAGAAUAAAAJAAUAAQAGAAUAAAAJAAYAAQAGAAUAAAAJAAcAAQAGAAUAAAAJAAgAAQAGAAUAAAAJAAkAAQAGAAUAAAAJAAoAAQAGAAUAAAAJAAsAAQAGAAUAAAAJAAwAAQAGAAUAAAAJAA0AAQAGAAUAAAAJAA4AAQAGAAUAAAAJAA8AAQAGAAUAAAAJABAAAQAGAAUAAAAJABEAAQAGAAUAAAAKAAEAAQAGAAUAAAAKAAIAAQAGAAUAAAAKAAMAAQAGAAUAAAAKAAQAAQAGAAUAAAAKAAUAAQAGAAUAAAAKAAYAAQAGAAUAAAAKAAcAAQAGAAUAAAAKAAgAAQAGAAUAAAAKAAkAAQAGAAUAAAAKAAoAAQAGAAUAAAAKAAsAAQAGAAUAAAAKAAwAAQAGAAUAAAAKAA0AAQAGAAUAAAAKAA4AAQAGAAUAAAAKAA8AAQAGAAUAAAAKABAAAQAGAAUAAAAKABEAAQAGAAUAAAALAAEAAQAGAAUAAAALAAIAAQAGAAUAAAALAAMAAQAGAAUAAAALAAQAAQAGAAUAAAALAAUAAQAGAAUAAAALAAYAAQAGAAUAAAALAAcAAQAGAAUAAAALAAgAAQAGAAUAAAALAAkAAQAGAAUAAAALAAoAAQAGAAUAAAALAAsAAQAGAAUAAAALAAwAAQAGAAUAAAALAA0AAQAGAAUAAAALAA4AAQAGAAUAAAALAA8AAQAGAAUAAAALABAAAQAGAAUAAAALABEAAQAGAAUAAAAMAAMAAQAGAAUAAAAMAAQAAQAGAAUAAAAAAAkAAQAGAAUAAAAAAAoAAQAGAAUAAAAMABAAAQAGAAUAAAAMAA8AAQAGAAUAAAAMABcAAQAGAAUAAAAMABgAAQAGAAUAAAAAABcAAQAGAAUAAAAAABgAAQAGAAUAAAA=")
tile_set = ExtResource("1_kdit4")
navigation_enabled = false
[node name="BackgroundDecoration" type="TileMapLayer" parent="TileMap"]
use_parent_material = true
tile_map_data = PackedByteArray("AAALABEAAQAHAAQAAAABAAsAAQAGAAQAAAALAAEAAQAHAAQAAAADAAoAAQAHAAUAAAAHAAIAAQAHAAUAAAAKABgAAQAHAAUAAAA=")
tile_set = ExtResource("1_kdit4")
[node name="Ground" type="TileMapLayer" parent="TileMap"]
use_parent_material = true
tile_map_data = PackedByteArray("AAAAAAAAAQAAAAMAAAABAAAAAQABAAIAAAACAAAAAQABAAIAAAADAAAAAQABAAIAAAAEAAAAAQABAAIAAAAFAAAAAQABAAIAAAAGAAAAAQABAAIAAAAHAAAAAQABAAIAAAAIAAAAAQABAAIAAAAJAAAAAQABAAIAAAAKAAAAAQABAAIAAAAAAAMAAQACAAEAAAAAAAQAAQACAAEAAAAAAAUAAQACAAEAAAAAAAYAAQACAAEAAAAAAAcAAQACAAEAAAAAAAgAAQACAAEAAAAAAAsAAQACAAEAAAAAAAwAAQACAAEAAAAAAA0AAQACAAEAAAAAAA4AAQACAAEAAAAAAA8AAQACAAEAAAAAABAAAQACAAEAAAAMAA4AAQAAAAEAAAAMAA0AAQAAAAEAAAAMAAwAAQAAAAEAAAAMAAsAAQAAAAEAAAAMAAoAAQAAAAEAAAAMAAkAAQAAAAEAAAAMAAgAAQAAAAEAAAAMAAcAAQAAAAEAAAAMAAYAAQAAAAEAAAAMAAUAAQAAAAEAAAAMAAAAAQACAAMAAAAMAAEAAQAAAAEAAAAMAAIAAQAAAAEAAAALAAAAAQABAAIAAAAAABEAAQACAAEAAAAAABIAAQACAAEAAAAAABMAAQACAAEAAAAAABQAAQACAAEAAAAAABUAAQACAAEAAAAAABYAAQACAAEAAAAMABEAAQAAAAEAAAAMABIAAQAAAAEAAAAMABMAAQAAAAEAAAAMABQAAQAAAAEAAAAMABUAAQAAAAEAAAAMABYAAQAAAAEAAAABABkAAQABAAAAAAACABkAAQABAAAAAAADABkAAQABAAAAAAAEABkAAQABAAAAAAAFABkAAQABAAAAAAAGABkAAQABAAAAAAAHABkAAQABAAAAAAAIABkAAQABAAAAAAAJABkAAQABAAAAAAAKABkAAQABAAAAAAALABkAAQABAAAAAAAAABkAAQAAAAUAAAAMABkAAQACAAUAAAACABgAAQAEAAQAAAADABcAAQAEAAQAAAAEABYAAQAEAAQAAAAFABUAAQAEAAQAAAAGABQAAQAEAAQAAAAHABMAAQAEAAQAAAAIABIAAQAEAAQAAAAJABEAAQAEAAQAAAAKABEAAQAEAAQAAAALABEAAQAEAAQAAAAIABAAAQAEAAQAAAAHAA8AAQAEAAQAAAAGAA4AAQAEAAQAAAAFAA0AAQAEAAQAAAAEAAwAAQAEAAQAAAADAAsAAQAEAAQAAAACAAsAAQAEAAQAAAABAAsAAQAEAAQAAAAEAAoAAQAEAAQAAAAFAAkAAQAEAAQAAAAGAAgAAQAEAAQAAAAHAAcAAQAEAAQAAAAIAAYAAQAEAAQAAAAJAAUAAQAEAAQAAAAKAAUAAQAEAAQAAAALAAUAAQAEAAQAAAAIAAQAAQAEAAQAAAAHAAMAAQAEAAQAAAAGAAMAAQAEAAQAAAAFAAMAAQAEAAQAAAAEAAMAAQAEAAQAAAADAAMAAQAEAAQAAAACAAMAAQAEAAQAAAABAAMAAQAEAAQAAAA=")
tile_set = ExtResource("1_kdit4")
[node name="Barrier" type="TileMapLayer" parent="TileMap"]
use_parent_material = true
tile_map_data = PackedByteArray("AAAMAAMAAQAAAAEAAAAMAAQAAQAAAAEAAAAMAA8AAQAAAAEAAAAMABAAAQAAAAEAAAAMABcAAQAAAAEAAAAMABgAAQAAAAEAAAAAABcAAQACAAEAAAAAABgAAQACAAEAAAAAAAkAAQACAAEAAAAAAAoAAQACAAEAAAAAAAEAAQACAAEAAAAAAAIAAQACAAEAAAA=")
tile_set = ExtResource("1_kdit4")
[node name="PointLight2D" type="PointLight2D" parent="."]
visible = false
position = Vector2(206.5, 414.5)
scale = Vector2(12.9688, 26.0313)
texture = ExtResource("2_g41lp")
[node name="AutoSpawn" type="Node2D" parent="."]
[node name="RoomArea" type="Area2D" parent="."]
collision_mask = 0
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomArea"]
position = Vector2(207.5, 416)
shape = SubResource("RectangleShape2D_kiih8")
[node name="SpawnArea" type="Area2D" parent="."]
[node name="CollisionShape2D" type="CollisionShape2D" parent="SpawnArea"]
position = Vector2(209, 416.5)
shape = SubResource("RectangleShape2D_kfmgh")

View File

@ -0,0 +1,136 @@
[gd_scene load_steps=12 format=4 uid="uid://du5ldsp613fei"]
[ext_resource type="Script" path="res://scripts/map/PlayerSpawn.cs" id="1_q04qt"]
[ext_resource type="TileSet" uid="uid://c4wpp12rr44hi" path="res://tileSets/dungeon.tres" id="2_5bnvh"]
[ext_resource type="Texture2D" uid="uid://drw45jlmfo0su" path="res://sprites/light/White_100.png" id="3_atgj7"]
[ext_resource type="Script" path="res://scripts/map/ItemSpawn.cs" id="4_6ihp7"]
[ext_resource type="PackedScene" uid="uid://djsh4unystlf0" path="res://prefab/furnitures/SpellEditor.tscn" id="5_0kep0"]
[ext_resource type="Texture2D" uid="uid://cdjmfqp854utu" path="res://sprites/tutorials/spellEditor.png" id="6_dbg76"]
[ext_resource type="PackedScene" uid="uid://dld3qttpsdjpe" path="res://prefab/furnitures/WoodenBox.tscn" id="7_jybe6"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_jxmys"]
size = Vector2(23, 54.875)
[sub_resource type="NavigationPolygon" id="NavigationPolygon_064c7"]
vertices = PackedVector2Array(756.172, 267.297, 756.82, 306.008, 45.0312, 306.977, 723.094, 268.297, 45.9688, 42, 721.094, 42)
polygons = Array[PackedInt32Array]([PackedInt32Array(0, 1, 2, 3), PackedInt32Array(3, 2, 4, 5)])
outlines = Array[PackedVector2Array]([PackedVector2Array(36, 32, 731, 32, 733, 258, 766, 257, 767, 316, 35, 317)])
source_geometry_group_name = &"navigation_polygon_source_group"
[sub_resource type="RectangleShape2D" id="RectangleShape2D_kiih8"]
size = Vector2(758, 342)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_u54ac"]
size = Vector2(658, 284)
[node name="InitialRoom3" type="Node2D"]
[node name="RoomSlotList" type="Node2D" parent="."]
[node name="Slot1" type="Area2D" parent="RoomSlotList"]
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomSlotList/Slot1"]
position = Vector2(751.5, 289.438)
shape = SubResource("RectangleShape2D_jxmys")
debug_color = Color(0, 0.6, 0.701961, 0.419608)
[node name="PlayerSpawn" type="Marker2D" parent="."]
position = Vector2(54, 256)
script = ExtResource("1_q04qt")
[node name="NavigationRegion2D" type="NavigationRegion2D" parent="."]
navigation_polygon = SubResource("NavigationPolygon_064c7")
[node name="TileMap" type="Node2D" parent="."]
[node name="BackgroundWall" type="TileMapLayer" parent="TileMap"]
use_parent_material = true
tile_map_data = PackedByteArray("AAAOAAYAAQAGAAUAAAANAAYAAQAGAAUAAAAMAAYAAQAGAAUAAAALAAYAAQAGAAUAAAAKAAYAAQAGAAUAAAAJAAYAAQAGAAUAAAAIAAYAAQAGAAUAAAAHAAYAAQAGAAUAAAAGAAYAAQAGAAUAAAAOAAEAAQAGAAUAAAAOAAIAAQAGAAUAAAAOAAMAAQAGAAUAAAAOAAQAAQAGAAUAAAAOAAUAAQAGAAUAAAANAAUAAQAGAAUAAAANAAQAAQAGAAUAAAANAAMAAQAGAAUAAAANAAIAAQAGAAUAAAANAAEAAQAGAAUAAAAMAAEAAQAGAAUAAAALAAEAAQAGAAUAAAAKAAEAAQAGAAUAAAAJAAEAAQAGAAUAAAAIAAEAAQAGAAUAAAAHAAEAAQAGAAUAAAAGAAEAAQAGAAUAAAAFAAEAAQAGAAUAAAAEAAEAAQAGAAUAAAADAAEAAQAGAAUAAAACAAEAAQAGAAUAAAABAAEAAQAGAAUAAAABAAIAAQAGAAUAAAACAAIAAQAGAAUAAAADAAIAAQAGAAUAAAAEAAIAAQAGAAUAAAAFAAIAAQAGAAUAAAAGAAIAAQAGAAUAAAAHAAIAAQAGAAUAAAAIAAIAAQAGAAUAAAAJAAIAAQAGAAUAAAAKAAIAAQAGAAUAAAALAAIAAQAGAAUAAAAMAAIAAQAGAAUAAAAMAAMAAQAGAAUAAAALAAMAAQAGAAUAAAAKAAMAAQAGAAUAAAAJAAMAAQAGAAUAAAAIAAMAAQAGAAUAAAAHAAMAAQAGAAUAAAAGAAMAAQAGAAUAAAAFAAMAAQAGAAUAAAAEAAMAAQAGAAUAAAADAAMAAQAGAAUAAAACAAMAAQAGAAUAAAABAAMAAQAGAAUAAAABAAQAAQAGAAUAAAACAAQAAQAGAAUAAAADAAQAAQAGAAUAAAAEAAQAAQAGAAUAAAAFAAQAAQAGAAUAAAAGAAQAAQAGAAUAAAAHAAQAAQAGAAUAAAAIAAQAAQAGAAUAAAAJAAQAAQAGAAUAAAAKAAQAAQAGAAUAAAALAAQAAQAGAAUAAAAMAAQAAQAGAAUAAAAMAAUAAQAGAAUAAAALAAUAAQAGAAUAAAAKAAUAAQAGAAUAAAAJAAUAAQAGAAUAAAAIAAUAAQAGAAUAAAAHAAUAAQAGAAUAAAAGAAUAAQAGAAUAAAAFAAUAAQAGAAUAAAAEAAUAAQAGAAUAAAADAAUAAQAGAAUAAAACAAUAAQAGAAUAAAABAAUAAQAGAAUAAAABAAYAAQAGAAUAAAACAAYAAQAGAAUAAAADAAYAAQAGAAUAAAAEAAYAAQAGAAUAAAAFAAYAAQAGAAUAAAAPAAYAAQAGAAUAAAAPAAUAAQAGAAUAAAABAAcAAQAGAAUAAAABAAgAAQAGAAUAAAABAAkAAQAGAAUAAAACAAkAAQAGAAUAAAACAAgAAQAGAAUAAAACAAcAAQAGAAUAAAADAAcAAQAGAAUAAAADAAgAAQAGAAUAAAADAAkAAQAGAAUAAAAEAAkAAQAGAAUAAAAEAAgAAQAGAAUAAAAEAAcAAQAGAAUAAAAFAAcAAQAGAAUAAAAFAAgAAQAGAAUAAAAFAAkAAQAGAAUAAAAGAAkAAQAGAAUAAAAGAAgAAQAGAAUAAAAGAAcAAQAGAAUAAAAHAAgAAQAGAAUAAAAHAAkAAQAGAAUAAAAHAAcAAQAGAAUAAAAIAAcAAQAGAAUAAAAIAAgAAQAGAAUAAAAIAAkAAQAGAAUAAAAJAAkAAQAGAAUAAAAJAAgAAQAGAAUAAAAJAAcAAQAGAAUAAAAKAAcAAQAGAAUAAAAKAAgAAQAGAAUAAAAKAAkAAQAGAAUAAAALAAkAAQAGAAUAAAALAAgAAQAGAAUAAAALAAcAAQAGAAUAAAAMAAcAAQAGAAUAAAAMAAgAAQAGAAUAAAAMAAkAAQAGAAUAAAANAAkAAQAGAAUAAAANAAgAAQAGAAUAAAANAAcAAQAGAAUAAAAOAAcAAQAGAAUAAAAOAAgAAQAGAAUAAAAOAAkAAQAGAAUAAAAPAAkAAQAGAAUAAAAPAAgAAQAGAAUAAAAPAAcAAQAGAAUAAAAPAAQAAQAGAAUAAAAPAAMAAQAGAAUAAAAPAAIAAQAGAAUAAAAPAAEAAQAGAAUAAAAQAAEAAQAGAAUAAAARAAEAAQAGAAUAAAASAAEAAQAGAAUAAAATAAEAAQAGAAUAAAAUAAEAAQAGAAUAAAAVAAEAAQAGAAUAAAAWAAEAAQAGAAUAAAAWAAIAAQAGAAUAAAAVAAIAAQAGAAUAAAAUAAIAAQAGAAUAAAATAAIAAQAGAAUAAAASAAIAAQAGAAUAAAARAAIAAQAGAAUAAAAQAAIAAQAGAAUAAAAQAAMAAQAGAAUAAAARAAMAAQAGAAUAAAASAAMAAQAGAAUAAAATAAMAAQAGAAUAAAAUAAMAAQAGAAUAAAAVAAMAAQAGAAUAAAAWAAMAAQAGAAUAAAAWAAQAAQAGAAUAAAAVAAQAAQAGAAUAAAAUAAQAAQAGAAUAAAATAAQAAQAGAAUAAAASAAQAAQAGAAUAAAARAAQAAQAGAAUAAAAQAAQAAQAGAAUAAAAQAAUAAQAGAAUAAAARAAUAAQAGAAUAAAASAAUAAQAGAAUAAAATAAUAAQAGAAUAAAAUAAUAAQAGAAUAAAAVAAUAAQAGAAUAAAAWAAUAAQAGAAUAAAAWAAYAAQAGAAUAAAAVAAYAAQAGAAUAAAAUAAYAAQAGAAUAAAATAAYAAQAGAAUAAAASAAYAAQAGAAUAAAARAAYAAQAGAAUAAAAQAAYAAQAGAAUAAAAQAAcAAQAGAAUAAAARAAcAAQAGAAUAAAASAAcAAQAGAAUAAAATAAcAAQAGAAUAAAAUAAcAAQAGAAUAAAAVAAcAAQAGAAUAAAAWAAcAAQAGAAUAAAAWAAgAAQAGAAUAAAAVAAgAAQAGAAUAAAAUAAgAAQAGAAUAAAATAAgAAQAGAAUAAAASAAgAAQAGAAUAAAARAAgAAQAGAAUAAAAQAAgAAQAGAAUAAAAQAAkAAQAGAAUAAAARAAkAAQAGAAUAAAASAAkAAQAGAAUAAAATAAkAAQAGAAUAAAAUAAkAAQAGAAUAAAAVAAkAAQAGAAUAAAAWAAkAAQAGAAUAAAAXAAkAAQAGAAUAAAAXAAgAAQAGAAUAAAA=")
tile_set = ExtResource("2_5bnvh")
navigation_enabled = false
[node name="BackgroundDecoration" type="TileMapLayer" parent="TileMap"]
use_parent_material = true
tile_map_data = PackedByteArray("AAAEAAkAAQAHAAUAAAAWAAEAAQAHAAQAAAA=")
tile_set = ExtResource("2_5bnvh")
[node name="Ground" type="TileMapLayer" parent="TileMap"]
use_parent_material = true
tile_map_data = PackedByteArray("AAAAAAAAAQAAAAMAAAAAAAEAAQACAAEAAAAAAAIAAQACAAEAAAAAAAMAAQACAAEAAAAAAAQAAQACAAEAAAAAAAcAAQACAAEAAAAPAAAAAQABAAIAAAAAAAUAAQACAAEAAAAAAAYAAQACAAEAAAABAAAAAQABAAIAAAACAAAAAQABAAIAAAADAAAAAQABAAIAAAAEAAAAAQABAAIAAAAFAAAAAQABAAIAAAAGAAAAAQABAAIAAAAHAAAAAQABAAIAAAAIAAAAAQABAAIAAAAJAAAAAQABAAIAAAAKAAAAAQABAAIAAAALAAAAAQABAAIAAAAMAAAAAQABAAIAAAANAAAAAQABAAIAAAAOAAAAAQABAAMAAAAAAAgAAQACAAEAAAAAAAkAAQACAAEAAAAAAAoAAQAAAAUAAAABAAoAAQABAAAAAAACAAoAAQABAAAAAAADAAoAAQABAAAAAAAEAAoAAQABAAAAAAAFAAoAAQABAAAAAAAGAAoAAQABAAAAAAAHAAoAAQABAAAAAAAIAAoAAQABAAAAAAAJAAoAAQABAAAAAAAKAAoAAQABAAAAAAALAAoAAQABAAAAAAAMAAoAAQABAAAAAAANAAoAAQABAAAAAAAOAAoAAQABAAAAAAAPAAoAAQABAAAAAAAQAAoAAQABAAAAAAARAAoAAQABAAAAAAASAAoAAQABAAAAAAATAAoAAQABAAAAAAAUAAoAAQABAAAAAAAVAAoAAQABAAAAAAAWAAoAAQABAAAAAAAXAAoAAQACAAUAAAAQAAAAAQABAAIAAAARAAAAAQABAAIAAAASAAAAAQABAAIAAAATAAAAAQABAAIAAAAUAAAAAQABAAIAAAAXAAcAAQAAAAEAAAAXAAYAAQAAAAEAAAAXAAUAAQAAAAEAAAAXAAQAAQAAAAEAAAAXAAMAAQAAAAEAAAAXAAIAAQAAAAEAAAAXAAEAAQAAAAEAAAAXAAAAAQACAAMAAAAVAAAAAQABAAIAAAAWAAAAAQABAAIAAAA=")
tile_set = ExtResource("2_5bnvh")
[node name="Barrier" type="TileMapLayer" parent="TileMap"]
use_parent_material = true
tile_map_data = PackedByteArray("AAAXAAgAAQAAAAEAAAAXAAkAAQAAAAEAAAA=")
tile_set = ExtResource("2_5bnvh")
[node name="PointLight2D" type="PointLight2D" parent="."]
visible = false
position = Vector2(386, 178)
scale = Vector2(23.9375, 11.0625)
texture = ExtResource("3_atgj7")
[node name="Label" type="Label" parent="."]
offset_left = 37.0
offset_top = 46.0
offset_right = 200.0
offset_bottom = 71.0
text = "ui_tutorial_spellEditor"
[node name="Label2" type="Label" parent="."]
offset_left = 391.0
offset_top = 261.0
offset_right = 554.0
offset_bottom = 286.0
text = "ui_tutorial_break_box"
[node name="SpellEditor" type="Sprite2D" parent="."]
position = Vector2(621, 100)
texture = ExtResource("6_dbg76")
[node name="RigidBody2D" parent="." instance=ExtResource("5_0kep0")]
position = Vector2(227, 283)
[node name="WoodenBox" parent="." instance=ExtResource("7_jybe6")]
position = Vector2(715, 244)
_initialDurability = 0
_furnitureName = ""
[node name="WoodenBox2" parent="." instance=ExtResource("7_jybe6")]
position = Vector2(715, 200)
_initialDurability = 0
_furnitureName = ""
[node name="WoodenBox3" parent="." instance=ExtResource("7_jybe6")]
position = Vector2(715, 162)
_initialDurability = 0
_furnitureName = ""
[node name="AutoSpawn" type="Node2D" parent="."]
[node name="beginner_staff" type="Marker2D" parent="AutoSpawn"]
position = Vector2(134, 248)
script = ExtResource("4_6ihp7")
_itemIdList = PackedStringArray("beginner_staff")
[node name="magic_missile" type="Marker2D" parent="AutoSpawn"]
position = Vector2(100, 250)
script = ExtResource("4_6ihp7")
_itemIdList = PackedStringArray("magic_missile")
[node name="tracking_spell" type="Marker2D" parent="AutoSpawn"]
position = Vector2(156, 245)
script = ExtResource("4_6ihp7")
_itemIdList = PackedStringArray("tracking_spell")
[node name="RoomArea" type="Area2D" parent="."]
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomArea"]
position = Vector2(383, 175)
shape = SubResource("RectangleShape2D_kiih8")
[node name="SpawnArea" type="Area2D" parent="."]
[node name="CollisionShape2D" type="CollisionShape2D" parent="SpawnArea"]
position = Vector2(405, 178)
shape = SubResource("RectangleShape2D_u54ac")

View File

@ -0,0 +1,142 @@
[gd_scene load_steps=12 format=4 uid="uid://dodxp4mm0emj3"]
[ext_resource type="TileSet" uid="uid://c4wpp12rr44hi" path="res://tileSets/dungeon.tres" id="2_k54gk"]
[ext_resource type="Texture2D" uid="uid://drw45jlmfo0su" path="res://sprites/light/White_100.png" id="3_d6t7n"]
[ext_resource type="PackedScene" uid="uid://dld3qttpsdjpe" path="res://prefab/furnitures/WoodenBox.tscn" id="4_60glh"]
[ext_resource type="Script" path="res://scripts/map/ItemSpawn.cs" id="4_fh50l"]
[ext_resource type="PackedScene" uid="uid://djsh4unystlf0" path="res://prefab/furnitures/SpellEditor.tscn" id="5_ll4ng"]
[ext_resource type="Texture2D" uid="uid://kgodvs3ilxbs" path="res://sprites/tutorials/tripleShotSpell.png" id="6_2qcf3"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_jxmys"]
size = Vector2(23, 54.875)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_xgxoy"]
size = Vector2(26, 57)
[sub_resource type="NavigationPolygon" id="NavigationPolygon_064c7"]
vertices = PackedVector2Array(728.094, 269, 755.672, 269, 754.328, 309.062, 457.93, 310.93, 621.094, 264.742, 619.094, 45.0781, 726.078, 45.9219, 562.906, 266.273, 456.93, 150.68, 564.898, 43.0078, 42.9531, 43.9766, 404.938, 157.18, 41.9609, 265.109, 405.93, 309.023, 10, 309.969, 10, 268.102)
polygons = Array[PackedInt32Array]([PackedInt32Array(0, 1, 2, 3), PackedInt32Array(4, 5, 6, 0), PackedInt32Array(4, 0, 3, 7), PackedInt32Array(7, 3, 8, 9), PackedInt32Array(10, 9, 8, 11), PackedInt32Array(12, 10, 11, 13), PackedInt32Array(12, 13, 14, 15)])
outlines = Array[PackedVector2Array]([PackedVector2Array(33, 34, 32, 256, 0, 259, 0, 320, 416, 319, 415, 166, 447, 162, 448, 321, 764, 319, 766, 259, 738, 259, 736, 36, 609, 35, 611, 255, 573, 256, 575, 33)])
source_geometry_group_name = &"navigation_polygon_source_group"
[sub_resource type="RectangleShape2D" id="RectangleShape2D_kiih8"]
size = Vector2(755, 340)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_o4dgl"]
size = Vector2(706, 289)
[node name="InitialRoom" type="Node2D"]
[node name="RoomSlotList" type="Node2D" parent="."]
[node name="Slot1" type="Area2D" parent="RoomSlotList"]
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomSlotList/Slot1"]
position = Vector2(751.5, 289.438)
shape = SubResource("RectangleShape2D_jxmys")
debug_color = Color(0, 0.6, 0.701961, 0.419608)
[node name="Area2D" type="Area2D" parent="RoomSlotList"]
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomSlotList/Area2D"]
position = Vector2(17, 288)
shape = SubResource("RectangleShape2D_xgxoy")
[node name="NavigationRegion2D" type="NavigationRegion2D" parent="."]
navigation_polygon = SubResource("NavigationPolygon_064c7")
[node name="TileMap" type="Node2D" parent="."]
[node name="BackgroundWall" type="TileMapLayer" parent="TileMap"]
use_parent_material = true
tile_map_data = PackedByteArray("AAAOAAYAAQAGAAUAAAANAAYAAQAGAAUAAAAMAAYAAQAGAAUAAAALAAYAAQAGAAUAAAAKAAYAAQAGAAUAAAAJAAYAAQAGAAUAAAAIAAYAAQAGAAUAAAAHAAYAAQAGAAUAAAAGAAYAAQAGAAUAAAAOAAEAAQAGAAUAAAAOAAIAAQAGAAUAAAAOAAMAAQAGAAUAAAAOAAQAAQAGAAUAAAAOAAUAAQAGAAUAAAANAAUAAQAGAAUAAAANAAQAAQAGAAUAAAANAAMAAQAGAAUAAAANAAIAAQAGAAUAAAANAAEAAQAGAAUAAAAMAAEAAQAGAAUAAAALAAEAAQAGAAUAAAAKAAEAAQAGAAUAAAAJAAEAAQAGAAUAAAAIAAEAAQAGAAUAAAAHAAEAAQAGAAUAAAAGAAEAAQAGAAUAAAAFAAEAAQAGAAUAAAAEAAEAAQAGAAUAAAADAAEAAQAGAAUAAAACAAEAAQAGAAUAAAABAAEAAQAGAAUAAAABAAIAAQAGAAUAAAACAAIAAQAGAAUAAAADAAIAAQAGAAUAAAAEAAIAAQAGAAUAAAAFAAIAAQAGAAUAAAAGAAIAAQAGAAUAAAAHAAIAAQAGAAUAAAAIAAIAAQAGAAUAAAAJAAIAAQAGAAUAAAAKAAIAAQAGAAUAAAALAAIAAQAGAAUAAAAMAAIAAQAGAAUAAAAMAAMAAQAGAAUAAAALAAMAAQAGAAUAAAAKAAMAAQAGAAUAAAAJAAMAAQAGAAUAAAAIAAMAAQAGAAUAAAAHAAMAAQAGAAUAAAAGAAMAAQAGAAUAAAAFAAMAAQAGAAUAAAAEAAMAAQAGAAUAAAADAAMAAQAGAAUAAAACAAMAAQAGAAUAAAABAAMAAQAGAAUAAAABAAQAAQAGAAUAAAACAAQAAQAGAAUAAAADAAQAAQAGAAUAAAAEAAQAAQAGAAUAAAAFAAQAAQAGAAUAAAAGAAQAAQAGAAUAAAAHAAQAAQAGAAUAAAAIAAQAAQAGAAUAAAAJAAQAAQAGAAUAAAAKAAQAAQAGAAUAAAALAAQAAQAGAAUAAAAMAAQAAQAGAAUAAAAMAAUAAQAGAAUAAAALAAUAAQAGAAUAAAAKAAUAAQAGAAUAAAAJAAUAAQAGAAUAAAAIAAUAAQAGAAUAAAAHAAUAAQAGAAUAAAAGAAUAAQAGAAUAAAAFAAUAAQAGAAUAAAAEAAUAAQAGAAUAAAADAAUAAQAGAAUAAAACAAUAAQAGAAUAAAABAAUAAQAGAAUAAAABAAYAAQAGAAUAAAACAAYAAQAGAAUAAAADAAYAAQAGAAUAAAAEAAYAAQAGAAUAAAAFAAYAAQAGAAUAAAAPAAYAAQAGAAUAAAAPAAUAAQAGAAUAAAABAAcAAQAGAAUAAAABAAgAAQAGAAUAAAABAAkAAQAGAAUAAAACAAkAAQAGAAUAAAACAAgAAQAGAAUAAAACAAcAAQAGAAUAAAADAAcAAQAGAAUAAAADAAgAAQAGAAUAAAADAAkAAQAGAAUAAAAEAAkAAQAGAAUAAAAEAAgAAQAGAAUAAAAEAAcAAQAGAAUAAAAFAAcAAQAGAAUAAAAFAAgAAQAGAAUAAAAFAAkAAQAGAAUAAAAGAAkAAQAGAAUAAAAGAAgAAQAGAAUAAAAGAAcAAQAGAAUAAAAHAAgAAQAGAAUAAAAHAAkAAQAGAAUAAAAHAAcAAQAGAAUAAAAIAAcAAQAGAAUAAAAIAAgAAQAGAAUAAAAIAAkAAQAGAAUAAAAJAAkAAQAGAAUAAAAJAAgAAQAGAAUAAAAJAAcAAQAGAAUAAAAKAAcAAQAGAAUAAAAKAAgAAQAGAAUAAAAKAAkAAQAGAAUAAAALAAkAAQAGAAUAAAALAAgAAQAGAAUAAAALAAcAAQAGAAUAAAAMAAcAAQAGAAUAAAAMAAgAAQAGAAUAAAAMAAkAAQAGAAUAAAANAAkAAQAGAAUAAAANAAgAAQAGAAUAAAANAAcAAQAGAAUAAAAOAAcAAQAGAAUAAAAOAAgAAQAGAAUAAAAOAAkAAQAGAAUAAAAPAAkAAQAGAAUAAAAPAAgAAQAGAAUAAAAPAAcAAQAGAAUAAAAPAAQAAQAGAAUAAAAPAAMAAQAGAAUAAAAPAAIAAQAGAAUAAAAPAAEAAQAGAAUAAAAQAAEAAQAGAAUAAAARAAEAAQAGAAUAAAASAAEAAQAGAAUAAAATAAEAAQAGAAUAAAAUAAEAAQAGAAUAAAAVAAEAAQAGAAUAAAAWAAEAAQAGAAUAAAAWAAIAAQAGAAUAAAAVAAIAAQAGAAUAAAAUAAIAAQAGAAUAAAATAAIAAQAGAAUAAAASAAIAAQAGAAUAAAARAAIAAQAGAAUAAAAQAAIAAQAGAAUAAAAQAAMAAQAGAAUAAAARAAMAAQAGAAUAAAASAAMAAQAGAAUAAAATAAMAAQAGAAUAAAAUAAMAAQAGAAUAAAAVAAMAAQAGAAUAAAAWAAMAAQAGAAUAAAAWAAQAAQAGAAUAAAAVAAQAAQAGAAUAAAAUAAQAAQAGAAUAAAATAAQAAQAGAAUAAAASAAQAAQAGAAUAAAARAAQAAQAGAAUAAAAQAAQAAQAGAAUAAAAQAAUAAQAGAAUAAAARAAUAAQAGAAUAAAASAAUAAQAGAAUAAAATAAUAAQAGAAUAAAAUAAUAAQAGAAUAAAAVAAUAAQAGAAUAAAAWAAUAAQAGAAUAAAAWAAYAAQAGAAUAAAAVAAYAAQAGAAUAAAAUAAYAAQAGAAUAAAATAAYAAQAGAAUAAAASAAYAAQAGAAUAAAARAAYAAQAGAAUAAAAQAAYAAQAGAAUAAAAQAAcAAQAGAAUAAAARAAcAAQAGAAUAAAASAAcAAQAGAAUAAAATAAcAAQAGAAUAAAAUAAcAAQAGAAUAAAAVAAcAAQAGAAUAAAAWAAcAAQAGAAUAAAAWAAgAAQAGAAUAAAAVAAgAAQAGAAUAAAAUAAgAAQAGAAUAAAATAAgAAQAGAAUAAAASAAgAAQAGAAUAAAARAAgAAQAGAAUAAAAQAAgAAQAGAAUAAAAQAAkAAQAGAAUAAAARAAkAAQAGAAUAAAASAAkAAQAGAAUAAAATAAkAAQAGAAUAAAAUAAkAAQAGAAUAAAAVAAkAAQAGAAUAAAAWAAkAAQAGAAUAAAAXAAkAAQAGAAUAAAAXAAgAAQAGAAUAAAAAAAkAAQAGAAUAAAAAAAgAAQAGAAUAAAA=")
tile_set = ExtResource("2_k54gk")
navigation_enabled = false
[node name="BackgroundDecoration" type="TileMapLayer" parent="TileMap"]
use_parent_material = true
tile_map_data = PackedByteArray("AAAWAAEAAQAHAAQAAAACAAkAAQAHAAEAAAA=")
tile_set = ExtResource("2_k54gk")
[node name="Ground" type="TileMapLayer" parent="TileMap"]
use_parent_material = true
tile_map_data = PackedByteArray("AAAAAAAAAQAAAAMAAAAAAAEAAQACAAEAAAAAAAIAAQACAAEAAAAAAAMAAQACAAEAAAAAAAQAAQACAAEAAAAAAAcAAQACAAEAAAAPAAAAAQABAAIAAAAAAAUAAQACAAEAAAAAAAYAAQACAAEAAAABAAAAAQABAAIAAAACAAAAAQABAAIAAAADAAAAAQABAAIAAAAEAAAAAQABAAIAAAAFAAAAAQABAAIAAAAGAAAAAQABAAIAAAAHAAAAAQABAAIAAAAIAAAAAQABAAIAAAAJAAAAAQABAAIAAAAKAAAAAQABAAIAAAALAAAAAQABAAIAAAAMAAAAAQABAAIAAAANAAAAAQABAAIAAAAOAAAAAQABAAMAAAAAAAoAAQAAAAUAAAABAAoAAQABAAAAAAACAAoAAQABAAAAAAADAAoAAQABAAAAAAAEAAoAAQABAAAAAAAFAAoAAQABAAAAAAAGAAoAAQABAAAAAAAHAAoAAQABAAAAAAAIAAoAAQABAAAAAAAJAAoAAQABAAAAAAAKAAoAAQABAAAAAAALAAoAAQABAAAAAAAMAAoAAQABAAAAAAANAAoAAQABAAAAAAAOAAoAAQABAAAAAAAPAAoAAQABAAAAAAAQAAoAAQABAAAAAAARAAoAAQABAAAAAAASAAoAAQABAAAAAAATAAoAAQABAAAAAAAUAAoAAQABAAAAAAAVAAoAAQABAAAAAAAWAAoAAQABAAAAAAAXAAoAAQACAAUAAAAQAAAAAQABAAIAAAARAAAAAQABAAIAAAASAAAAAQABAAIAAAATAAAAAQABAAIAAAAUAAAAAQABAAIAAAAXAAcAAQAAAAEAAAAXAAYAAQAAAAEAAAAXAAUAAQAAAAEAAAAXAAQAAQAAAAEAAAAXAAMAAQAAAAEAAAAXAAIAAQAAAAEAAAAXAAEAAQAAAAEAAAAXAAAAAQACAAMAAAAVAAAAAQABAAIAAAAWAAAAAQABAAIAAAAEAAkAAQAEAAQAAAAFAAgAAQAEAAQAAAAGAAcAAQAEAAQAAAAHAAYAAQAEAAQAAAAIAAUAAQAEAAQAAAAKAAUAAQAEAAQAAAAMAAUAAQAEAAQAAAASAAUAAQADAAAAAAAJAAUAAQAEAAQAAAALAAUAAQAEAAQAAAANAAkAAQADAAAAAAANAAgAAQADAAAAAAANAAcAAQADAAAAAAANAAYAAQADAAAAAAANAAUAAQADAAAAAAASAAYAAQADAAAAAAASAAcAAQADAAAAAAASAAQAAQADAAAAAAASAAMAAQADAAAAAAASAAIAAQADAAAAAAASAAEAAQADAAAAAAAOAAUAAQADAAQAAAAPAAYAAQAEAAQAAAAQAAcAAQAEAAQAAAARAAgAAQAEAAQAAAAQAAkAAQAEAAQAAAA=")
tile_set = ExtResource("2_k54gk")
[node name="Barrier" type="TileMapLayer" parent="TileMap"]
use_parent_material = true
tile_map_data = PackedByteArray("AAAXAAgAAQAAAAEAAAAXAAkAAQAAAAEAAAAAAAgAAQACAAEAAAAAAAkAAQACAAEAAAA=")
tile_set = ExtResource("2_k54gk")
[node name="PointLight2D" type="PointLight2D" parent="."]
visible = false
position = Vector2(386, 178)
scale = Vector2(23.9375, 11.0625)
texture = ExtResource("3_d6t7n")
[node name="Label" type="Label" parent="."]
offset_left = 54.0
offset_top = 55.0
offset_right = 277.0
offset_bottom = 80.0
text = "ui_tutorial_jump_onto_platform"
[node name="Label2" type="Label" parent="."]
offset_left = 151.0
offset_top = 126.0
offset_right = 453.0
offset_bottom = 151.0
text = "ui_tutorial_combine_more_powerful_spells"
[node name="WoodenBox" parent="." instance=ExtResource("4_60glh")]
position = Vector2(711, 179)
[node name="WoodenBox4" parent="." instance=ExtResource("4_60glh")]
position = Vector2(676, 179)
[node name="WoodenBox5" parent="." instance=ExtResource("4_60glh")]
position = Vector2(676, 144)
[node name="WoodenBox6" parent="." instance=ExtResource("4_60glh")]
position = Vector2(675, 102)
[node name="WoodenBox7" parent="." instance=ExtResource("4_60glh")]
position = Vector2(641, 180)
[node name="WoodenBox8" parent="." instance=ExtResource("4_60glh")]
position = Vector2(640, 142)
[node name="WoodenBox9" parent="." instance=ExtResource("4_60glh")]
position = Vector2(640, 101)
[node name="WoodenBox2" parent="." instance=ExtResource("4_60glh")]
position = Vector2(712, 138)
[node name="WoodenBox3" parent="." instance=ExtResource("4_60glh")]
position = Vector2(711, 98)
[node name="RigidBody2D" parent="." instance=ExtResource("5_ll4ng")]
position = Vector2(473, 285)
[node name="TripleShotSpell" type="Sprite2D" parent="."]
position = Vector2(637, 85)
texture = ExtResource("6_2qcf3")
[node name="RoomArea" type="Area2D" parent="."]
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomArea"]
position = Vector2(383.5, 176)
shape = SubResource("RectangleShape2D_kiih8")
[node name="SpawnArea" type="Area2D" parent="."]
[node name="CollisionShape2D" type="CollisionShape2D" parent="SpawnArea"]
position = Vector2(385, 177.5)
shape = SubResource("RectangleShape2D_o4dgl")
[node name="AutoSpawn" type="Node2D" parent="."]
[node name="x3" type="Marker2D" parent="AutoSpawn"]
position = Vector2(434, 105)
script = ExtResource("4_fh50l")
_itemIdList = PackedStringArray("x3")

View File

@ -1,14 +0,0 @@
[gd_scene format=3 uid="uid://b7se73tsnlpd6"]
[node name="FloatLabel" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="Label" type="Label" parent="."]
layout_mode = 0
offset_right = 40.0
offset_bottom = 23.0

View File

@ -12,8 +12,3 @@ texture_under = ExtResource("1_sc0v3")
texture_over = ExtResource("2_ay5vh")
texture_progress = ExtResource("2_s0gle")
script = ExtResource("4_84gre")
[node name="Label" type="Label" parent="."]
layout_mode = 0
offset_right = 40.0
offset_bottom = 23.0

View File

@ -0,0 +1,53 @@
[gd_scene load_steps=3 format=3 uid="uid://h7lvaqqlsi4t"]
[ext_resource type="Script" path="res://scripts/loader/uiLoader/SpellEditorUi.cs" id="1_1pxjs"]
[ext_resource type="PackedScene" uid="uid://d2i4udh0hho41" path="res://prefab/ui/ItemSlot.tscn" id="2_3ut57"]
[node name="SpellEditorUi" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
script = ExtResource("1_1pxjs")
[node name="TitleLabel" type="Label" parent="."]
layout_mode = 1
anchors_preset = 10
anchor_right = 1.0
offset_bottom = 25.0
grow_horizontal = 2
text = "ui_spell_editor"
horizontal_alignment = 1
[node name="ExitButton" type="Button" parent="."]
layout_mode = 1
anchors_preset = 1
anchor_left = 1.0
anchor_right = 1.0
offset_left = -91.0
offset_top = 11.0
offset_right = -24.0
offset_bottom = 44.0
grow_horizontal = 0
text = "ui_close"
[node name="HFlowContainer" type="HFlowContainer" parent="."]
layout_mode = 1
anchors_preset = 10
anchor_right = 1.0
offset_left = 32.0
offset_top = 127.0
offset_right = -20.0
offset_bottom = 629.0
grow_horizontal = 2
mouse_filter = 2
[node name="ItemSlot" parent="." instance=ExtResource("2_3ut57")]
layout_mode = 1
offset_left = 34.0
offset_top = 73.0
offset_right = 72.0
offset_bottom = 111.0

View File

@ -0,0 +1,40 @@
[gd_scene load_steps=6 format=3 uid="uid://cg2jmn7cs8m2c"]
[ext_resource type="Script" path="res://scripts/weapon/ProjectileWeapon.cs" id="1_w4b6p"]
[ext_resource type="Texture2D" uid="uid://pf2ilanjwino" path="res://sprites/weapon/BeginnerStaff_Icon.png" id="2_ip8xd"]
[ext_resource type="Texture2D" uid="uid://b4g1mkvjf7uns" path="res://sprites/weapon/BeginnerStaff.png" id="3_rhhwp"]
[ext_resource type="AudioStream" uid="uid://cak6chjjsu7wo" path="res://sounds/fire.wav" id="4_p12sk"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_14m1g"]
size = Vector2(48, 5)
[node name="BeginnerStaff" type="RigidBody2D"]
collision_layer = 8
collision_mask = 34
script = ExtResource("1_w4b6p")
_numberSlots = 5
_fireSequentially = true
FiringIntervalAsMillisecond = 280
_recoilStrength = 5
UniqueIcon = ExtResource("2_ip8xd")
[node name="StaffOfTheUndead2" type="Sprite2D" parent="."]
position = Vector2(30, 0)
texture = ExtResource("3_rhhwp")
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(26, 0.5)
shape = SubResource("RectangleShape2D_14m1g")
[node name="Marker2D" type="Marker2D" parent="."]
position = Vector2(65, 0)
[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="Marker2D"]
stream = ExtResource("4_p12sk")
bus = &"SoundEffect"
[node name="TipLabel" type="Label" parent="."]
offset_left = 6.0
offset_top = 48.0
offset_right = 46.0
offset_bottom = 73.0

View File

@ -0,0 +1,46 @@
[gd_scene load_steps=6 format=3 uid="uid://g1jrthe4ojdd"]
[ext_resource type="Script" path="res://scripts/weapon/MeleeWeapon.cs" id="1_snmy1"]
[ext_resource type="Texture2D" uid="uid://wt50kx6bup51" path="res://sprites/weapon/StaffNecromancy.png" id="3_cm7e6"]
[ext_resource type="AudioStream" uid="uid://cak6chjjsu7wo" path="res://sounds/fire.wav" id="4_qimud"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_14m1g"]
size = Vector2(49, 5.25)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_2u0n7"]
size = Vector2(102, 94)
[node name="IronAxe" type="RigidBody2D"]
collision_layer = 8
collision_mask = 34
angular_damp = -1.0
script = ExtResource("1_snmy1")
[node name="StaffOfTheUndead2" type="Sprite2D" parent="."]
position = Vector2(30, 0)
texture = ExtResource("3_cm7e6")
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(25.5, 0.375)
shape = SubResource("RectangleShape2D_14m1g")
[node name="Marker2D" type="Marker2D" parent="."]
position = Vector2(65, 0)
[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="Marker2D"]
stream = ExtResource("4_qimud")
bus = &"SoundEffect"
[node name="TipLabel" type="Label" parent="."]
offset_left = 6.0
offset_top = 48.0
offset_right = 46.0
offset_bottom = 73.0
[node name="WeaponDamageArea" type="Area2D" parent="."]
collision_layer = 512
collision_mask = 0
[node name="CollisionShape2D" type="CollisionShape2D" parent="WeaponDamageArea"]
position = Vector2(127, 1)
shape = SubResource("RectangleShape2D_2u0n7")

View File

@ -0,0 +1,41 @@
[gd_scene load_steps=6 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="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"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_14m1g"]
size = Vector2(49, 5.25)
[node name="StaffOfTheUndead" type="RigidBody2D"]
collision_layer = 8
collision_mask = 34
script = ExtResource("1_w8hhv")
_numberSlots = 1
_spellList = PackedStringArray("necromancy")
_fireSequentially = true
FiringIntervalAsMillisecond = 350
_recoilStrength = 5
UniqueIcon = ExtResource("3_31iau")
[node name="StaffOfTheUndead2" type="Sprite2D" parent="."]
position = Vector2(30, 0)
texture = ExtResource("1_ms3us")
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(25.5, 0.375)
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 = 6.0
offset_top = 48.0
offset_right = 46.0
offset_bottom = 73.0

View File

@ -1,43 +0,0 @@
[gd_scene load_steps=6 format=3 uid="uid://dnnn2xyayiehk"]
[ext_resource type="Texture2D" uid="uid://e6670ykyq145" path="res://sprites/weapon/staffOfTheUndead.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_34250"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_obcq2"]
size = Vector2(49, 5)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_14m1g"]
size = Vector2(49, 5.25)
[node name="StaffOfTheUndead" type="RigidBody2D"]
collision_layer = 8
collision_mask = 34
script = ExtResource("1_w8hhv")
ProjectileScenes = [ExtResource("2_34250")]
FiringIntervalAsMillisecond = 300
_recoil = null
Id = "staff_of_the_undead"
UniqueName = null
UniqueDescription = null
_minContactInjury = null
_maxContactInjury = null
[node name="DamageArea2D" type="Area2D" parent="."]
collision_layer = 8
collision_mask = 70
[node name="CollisionShape2D" type="CollisionShape2D" parent="DamageArea2D"]
position = Vector2(25.5, 0.5)
shape = SubResource("RectangleShape2D_obcq2")
[node name="StaffOfTheUndead2" type="Sprite2D" parent="."]
position = Vector2(30, 0)
texture = ExtResource("1_ms3us")
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(25.5, 0.375)
shape = SubResource("RectangleShape2D_14m1g")
[node name="Marker2D" type="Marker2D" parent="."]
position = Vector2(65, 0)

View File

@ -13,7 +13,7 @@ config_version=5
config/name="Traveler"
config/version="0.0.1"
run/main_scene="res://scenes/splashScreen.tscn"
config/features=PackedStringArray("4.2", "C#", "Mobile")
config/features=PackedStringArray("4.3", "C#", "Mobile")
boot_splash/show_image=false
config/icon="res://icon.svg"
@ -40,124 +40,141 @@ theme/custom_font="res://fonts/ark-pixel-12px-proportional-zh_cn.ttf"
ui_accept={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":32,"physical_keycode":0,"key_label":0,"unicode":32,"echo":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194310,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null)
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":32,"physical_keycode":0,"key_label":0,"unicode":32,"location":0,"echo":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194310,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":1,"pressure":0.0,"pressed":true,"script":null)
]
}
ui_left={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":65,"physical_keycode":0,"key_label":0,"unicode":97,"echo":false,"script":null)
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":65,"physical_keycode":0,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":13,"pressure":0.0,"pressed":false,"script":null)
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":-1.0,"script":null)
]
}
ui_right={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":68,"physical_keycode":0,"key_label":0,"unicode":100,"echo":false,"script":null)
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":68,"physical_keycode":0,"key_label":0,"unicode":100,"location":0,"echo":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":14,"pressure":0.0,"pressed":false,"script":null)
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":1.0,"script":null)
]
}
ui_up={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":87,"physical_keycode":0,"key_label":0,"unicode":119,"echo":false,"script":null)
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":87,"physical_keycode":0,"key_label":0,"unicode":119,"location":0,"echo":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":11,"pressure":0.0,"pressed":false,"script":null)
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":-1.0,"script":null)
]
}
ui_down={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":83,"physical_keycode":0,"key_label":0,"unicode":115,"echo":false,"script":null)
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":83,"physical_keycode":0,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":12,"pressure":0.0,"pressed":false,"script":null)
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":1.0,"script":null)
]
}
pick_up={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":69,"physical_keycode":0,"key_label":0,"unicode":101,"echo":false,"script":null)
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":69,"physical_keycode":0,"key_label":0,"unicode":101,"location":0,"echo":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":9,"pressure":0.0,"pressed":true,"script":null)
]
}
throw={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":81,"physical_keycode":0,"key_label":0,"unicode":113,"echo":false,"script":null)
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":81,"physical_keycode":0,"key_label":0,"unicode":113,"location":0,"echo":false,"script":null)
]
}
use_item={
"deadzone": 0.5,
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":1,"position":Vector2(211, 16),"global_position":Vector2(215, 57),"factor":1.0,"button_index":1,"canceled":false,"pressed":true,"double_click":false,"script":null)
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":1,"position":Vector2(206, 22),"global_position":Vector2(215, 68),"factor":1.0,"button_index":1,"canceled":false,"pressed":true,"double_click":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":10,"pressure":0.0,"pressed":true,"script":null)
]
}
hotbar_1={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":49,"physical_keycode":0,"key_label":0,"unicode":49,"echo":false,"script":null)
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":49,"physical_keycode":0,"key_label":0,"unicode":49,"location":0,"echo":false,"script":null)
]
}
hotbar_2={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":50,"physical_keycode":0,"key_label":0,"unicode":50,"echo":false,"script":null)
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":50,"physical_keycode":0,"key_label":0,"unicode":50,"location":0,"echo":false,"script":null)
]
}
hotbar_3={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":51,"physical_keycode":0,"key_label":0,"unicode":51,"echo":false,"script":null)
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":51,"physical_keycode":0,"key_label":0,"unicode":51,"location":0,"echo":false,"script":null)
]
}
hotbar_4={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":52,"physical_keycode":0,"key_label":0,"unicode":52,"echo":false,"script":null)
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":52,"physical_keycode":0,"key_label":0,"unicode":52,"location":0,"echo":false,"script":null)
]
}
hotbar_5={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":53,"physical_keycode":0,"key_label":0,"unicode":53,"echo":false,"script":null)
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":53,"physical_keycode":0,"key_label":0,"unicode":53,"location":0,"echo":false,"script":null)
]
}
hotbar_6={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":54,"physical_keycode":0,"key_label":0,"unicode":54,"echo":false,"script":null)
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":54,"physical_keycode":0,"key_label":0,"unicode":54,"location":0,"echo":false,"script":null)
]
}
hotbar_7={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":55,"physical_keycode":0,"key_label":0,"unicode":55,"echo":false,"script":null)
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":55,"physical_keycode":0,"key_label":0,"unicode":55,"location":0,"echo":false,"script":null)
]
}
hotbar_8={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":56,"physical_keycode":0,"key_label":0,"unicode":56,"echo":false,"script":null)
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":56,"physical_keycode":0,"key_label":0,"unicode":56,"location":0,"echo":false,"script":null)
]
}
hotbar_9={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":57,"physical_keycode":0,"key_label":0,"unicode":57,"echo":false,"script":null)
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":57,"physical_keycode":0,"key_label":0,"unicode":57,"location":0,"echo":false,"script":null)
]
}
hotbar_next={
"deadzone": 0.5,
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":16,"position":Vector2(241, 17),"global_position":Vector2(245, 58),"factor":1.0,"button_index":5,"canceled":false,"pressed":true,"double_click":false,"script":null)
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":16,"position":Vector2(257, 22),"global_position":Vector2(266, 68),"factor":1.0,"button_index":5,"canceled":false,"pressed":true,"double_click":false,"script":null)
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":5,"axis_value":1.0,"script":null)
]
}
hotbar_previous={
"deadzone": 0.5,
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":8,"position":Vector2(169, 17),"global_position":Vector2(173, 58),"factor":1.0,"button_index":4,"canceled":false,"pressed":true,"double_click":false,"script":null)
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":4,"axis_value":1.0,"script":null)
]
}
push={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":70,"physical_keycode":0,"key_label":0,"unicode":102,"location":0,"echo":false,"script":null)
]
}
[internationalization]
locale/translations=PackedStringArray("res://locals/DeathInfo.en.translation", "res://locals/DeathInfo.ja.translation", "res://locals/DeathInfo.zh.translation", "res://locals/InputMapping.en.translation", "res://locals/InputMapping.ja.translation", "res://locals/InputMapping.zh.translation", "res://locals/Log.en.translation", "res://locals/Log.ja.translation", "res://locals/Log.zh.translation", "res://locals/Slogan.en.translation", "res://locals/Slogan.ja.translation", "res://locals/Slogan.zh.translation", "res://locals/UI.en.translation", "res://locals/UI.ja.translation", "res://locals/UI.zh.translation", "res://locals/Item.en.translation", "res://locals/Item.ja.translation", "res://locals/Item.zh.translation", "res://locals/Action.en.translation", "res://locals/Action.ja.translation", "res://locals/Action.zh.translation", "res://locals/Misc.en.translation", "res://locals/Misc.ja.translation", "res://locals/Misc.zh.translation")
locale/translations=PackedStringArray("res://locals/DeathInfo.en.translation", "res://locals/DeathInfo.ja.translation", "res://locals/DeathInfo.zh.translation", "res://locals/InputMapping.en.translation", "res://locals/InputMapping.ja.translation", "res://locals/InputMapping.zh.translation", "res://locals/Log.en.translation", "res://locals/Log.ja.translation", "res://locals/Log.zh.translation", "res://locals/Slogan.en.translation", "res://locals/Slogan.ja.translation", "res://locals/Slogan.zh.translation", "res://locals/UI.en.translation", "res://locals/UI.ja.translation", "res://locals/UI.zh.translation", "res://locals/Item.en.translation", "res://locals/Item.ja.translation", "res://locals/Item.zh.translation", "res://locals/Action.en.translation", "res://locals/Action.ja.translation", "res://locals/Action.zh.translation", "res://locals/Misc.en.translation", "res://locals/Misc.ja.translation", "res://locals/Misc.zh.translation", "res://locals/Character.en.translation", "res://locals/Character.ja.translation", "res://locals/Character.zh.translation", "res://locals/SloganOnMap.en.translation", "res://locals/SloganOnMap.ja.translation", "res://locals/SloganOnMap.zh.translation")
[layer_names]
2d_physics/layer_1="RoomArea"
2d_physics/layer_2="Ground"
2d_physics/layer_2="Floor"
2d_physics/layer_3="Player"
2d_physics/layer_4="PickAbleItem"
2d_physics/layer_5="Projectile"
2d_physics/layer_6="Platform"
2d_physics/layer_7="Mob"
2d_physics/layer_8="Wall"
2d_physics/layer_9="Furniture"
2d_physics/layer_10="WeaponDamageArea"
2d_physics/layer_11="Barrier"
[physics]
2d/default_gravity=480.0
[rendering]
textures/canvas_textures/default_texture_filter=0

View File

@ -1,11 +1,13 @@
[gd_scene load_steps=7 format=3 uid="uid://bnftvkj2cido7"]
[gd_scene load_steps=9 format=3 uid="uid://bnftvkj2cido7"]
[ext_resource type="Script" path="res://scripts/loader/sceneLoader/GameSceneLoader.cs" id="1_mqdgt"]
[ext_resource type="Texture2D" uid="uid://cs6e0af876ss5" path="res://sprites/ui/HeartEmpty.png" id="2_n1yht"]
[ext_resource type="Script" path="res://scripts/inventory/HotBar.cs" id="2_owrhq"]
[ext_resource type="Script" path="res://scripts/HealthBarUi.cs" id="2_xrm3v"]
[ext_resource type="Script" path="res://scripts/FpsLabel.cs" id="5_dis4v"]
[ext_resource type="PackedScene" uid="uid://c74180dtf7j7a" path="res://scenes/mapContainer.tscn" id="6_ljdj4"]
[ext_resource type="PackedScene" uid="uid://bb188382q7btp" path="res://scenes/gameOverMenu.tscn" id="6_yjmrv"]
[ext_resource type="Script" path="res://scripts/utils/UiGroup.cs" id="7_p0u6a"]
[node name="Game" type="Node2D"]
script = ExtResource("1_mqdgt")
@ -21,6 +23,7 @@ anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
[node name="VBoxContainer" type="VBoxContainer" parent="CanvasLayer/Control"]
layout_mode = 1
@ -34,28 +37,28 @@ offset_right = -20.0
offset_bottom = -20.0
grow_horizontal = 2
grow_vertical = 0
mouse_filter = 2
[node name="HealthBarUi" type="HBoxContainer" parent="CanvasLayer/Control/VBoxContainer"]
layout_mode = 2
mouse_filter = 2
script = ExtResource("2_xrm3v")
[node name="TextureRect3" type="TextureRect" parent="CanvasLayer/Control/VBoxContainer/HealthBarUi"]
layout_mode = 2
mouse_filter = 2
texture = ExtResource("2_n1yht")
[node name="HotBar" type="HBoxContainer" parent="CanvasLayer/Control/VBoxContainer"]
layout_mode = 2
mouse_filter = 2
script = ExtResource("2_owrhq")
[node name="TextureRect3" type="TextureRect" parent="CanvasLayer/Control/VBoxContainer/HotBar"]
layout_mode = 2
mouse_filter = 2
texture = ExtResource("2_n1yht")
[node name="OperationTip" type="RichTextLabel" parent="CanvasLayer/Control/VBoxContainer"]
layout_mode = 2
bbcode_enabled = true
fit_content = true
[node name="FPSLabel" type="Label" parent="CanvasLayer/Control"]
layout_mode = 1
anchors_preset = 1
@ -75,15 +78,21 @@ text = "ui_re_create_map"
[node name="SeedLabel" type="Label" parent="CanvasLayer/Control"]
layout_mode = 1
anchors_preset = 5
anchor_left = 0.5
anchor_right = 0.5
offset_left = -20.0
offset_right = 20.0
offset_bottom = 25.0
grow_horizontal = 2
anchors_preset = 3
anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -45.0
offset_top = -16.0
grow_horizontal = 0
grow_vertical = 0
theme_override_font_sizes/font_size = 10
[node name="BackpackUIContainer" type="Control" parent="CanvasLayer"]
[node name="MapContainer" parent="CanvasLayer/Control" instance=ExtResource("6_ljdj4")]
layout_mode = 1
[node name="DynamicUiGroup" type="Control" parent="CanvasLayer"]
visible = false
layout_mode = 3
anchors_preset = 15
@ -92,6 +101,7 @@ anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
script = ExtResource("7_p0u6a")
[node name="GameOverMenu" parent="CanvasLayer" instance=ExtResource("6_yjmrv")]
visible = false
@ -102,8 +112,15 @@ visible = false
[node name="WeaponContainer" type="Node2D" parent="."]
[node name="SpellContainer" type="Node2D" parent="."]
[node name="PickAbleContainer" type="Node2D" parent="."]
[node name="PlayerContainer" type="Node2D" parent="."]
[node name="AICharacterContainer" type="Node2D" parent="."]
[node name="PacksackContainer" type="Node2D" parent="."]
[node name="CanvasModulate" type="CanvasModulate" parent="."]
color = Color(0, 0, 0, 1)

View File

@ -9,6 +9,7 @@ anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
script = ExtResource("1_vj6du")
[node name="ColorRect" type="ColorRect" parent="."]
@ -18,6 +19,7 @@ anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
color = Color(0.941176, 0.243137, 0.243137, 0.258824)
[node name="CenterContainer" type="CenterContainer" parent="."]
@ -27,12 +29,15 @@ anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
[node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer"]
layout_mode = 2
mouse_filter = 2
[node name="CenterContainer" type="CenterContainer" parent="CenterContainer/VBoxContainer"]
layout_mode = 2
mouse_filter = 2
[node name="GameOverLabel" type="Label" parent="CenterContainer/VBoxContainer/CenterContainer"]
layout_mode = 2
@ -41,10 +46,12 @@ text = "ui_game_over_title"
[node name="MarginContainer" type="MarginContainer" parent="CenterContainer/VBoxContainer"]
layout_mode = 2
mouse_filter = 2
theme_override_constants/margin_top = 18
[node name="CenterContainer2" type="CenterContainer" parent="CenterContainer/VBoxContainer/MarginContainer"]
layout_mode = 2
mouse_filter = 2
[node name="DeathInfoLabel" type="Label" parent="CenterContainer/VBoxContainer/MarginContainer/CenterContainer2"]
layout_mode = 2
@ -52,9 +59,13 @@ text = "ui_death_info_describe"
[node name="MarginContainer2" type="MarginContainer" parent="CenterContainer/VBoxContainer"]
layout_mode = 2
mouse_filter = 2
theme_override_constants/margin_top = 10
theme_override_constants/margin_bottom = 150
[node name="RestartButton" type="Button" parent="CenterContainer/VBoxContainer/MarginContainer2"]
[node name="CenterContainer" type="CenterContainer" parent="CenterContainer/VBoxContainer/MarginContainer2"]
layout_mode = 2
text = "ui_restart"
[node name="Label" type="Label" parent="CenterContainer/VBoxContainer/MarginContainer2/CenterContainer"]
layout_mode = 2
text = "ui_rebuild_the_world"

View File

@ -1,6 +1,6 @@
[gd_scene load_steps=2 format=3 uid="uid://ckl23uwxrjat4"]
[ext_resource type="Script" path="res://scripts/loader/uiLoader/LevelGraphEditorLoader.cs" id="1_g1axq"]
[ext_resource type="Script" path="res://scripts/loader/uiLoader/LevelGraphEditorLoader.cs" id="1_qgo7w"]
[node name="LevelGraphEditor" type="Control"]
layout_mode = 3
@ -9,7 +9,7 @@ anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_g1axq")
script = ExtResource("1_qgo7w")
[node name="GraphEdit" type="GraphEdit" parent="."]
layout_mode = 1

View File

@ -35,6 +35,7 @@ offset_top = 215.0
offset_right = 50.5
offset_bottom = 248.0
grow_horizontal = 2
disabled = true
text = "ui_settings"
[node name="levelGraphEditorButton" type="Button" parent="."]

150
scenes/mapContainer.tscn Normal file
View File

@ -0,0 +1,150 @@
[gd_scene load_steps=8 format=3 uid="uid://c74180dtf7j7a"]
[ext_resource type="Texture2D" uid="uid://c35bsle7thcnh" path="res://sprites/ui/MiniMapBg.png" id="1_h88bi"]
[ext_resource type="Script" path="res://scripts/map/miniMap/MiniMap.cs" id="2_ltp8b"]
[ext_resource type="Texture2D" uid="uid://cfpcm0hkmpu38" path="res://sprites/ui/mark.png" id="3_x80y0"]
[sub_resource type="Animation" id="Animation_dkx17"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Control/MiniMap:position")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(983, 480)]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Control/MiniMap:visible")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
[sub_resource type="Animation" id="Animation_jdj6o"]
resource_name = "hide"
length = 0.3
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Control/MiniMap:position")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.3),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [Vector2(0, 0), Vector2(0, 300)]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Control/MiniMap:visible")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.3),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [true, false]
}
[sub_resource type="Animation" id="Animation_icaqa"]
resource_name = "show"
length = 0.3
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Control/MiniMap:visible")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Control/MiniMap:position")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.3),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [Vector2(0, 300), Vector2(0, 0)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_d5o4b"]
_data = {
"RESET": SubResource("Animation_dkx17"),
"hide": SubResource("Animation_jdj6o"),
"show": SubResource("Animation_icaqa")
}
[node name="MapContainer" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
[node name="MiniMapAnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_d5o4b")
}
[node name="ColorRect" type="ColorRect" parent="."]
visible = false
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
[node name="Control" type="Control" parent="."]
layout_mode = 1
anchors_preset = 3
anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -163.0
offset_top = -163.0
offset_right = -123.0
offset_bottom = -123.0
grow_horizontal = 0
grow_vertical = 0
[node name="MiniMap" type="NinePatchRect" parent="Control"]
layout_mode = 1
offset_right = 150.0
offset_bottom = 150.0
texture = ExtResource("1_h88bi")
patch_margin_left = 7
patch_margin_top = 7
patch_margin_right = 7
patch_margin_bottom = 7
script = ExtResource("2_ltp8b")
[node name="RoomPreviewContainer" type="Node2D" parent="Control/MiniMap"]
[node name="Mark" type="Sprite2D" parent="Control/MiniMap"]
position = Vector2(75, 75)
texture = ExtResource("3_x80y0")

View File

@ -1,92 +0,0 @@
using ColdMint.scripts.debug;
using ColdMint.scripts.openObserve;
using ColdMint.scripts.serialization;
using Godot;
namespace ColdMint.scripts;
public class AppConfig
{
/// <summary>
/// <para>Load configuration from file</para>
/// <para>从文件加载配置</para>
/// </summary>
public static AppConfigData? LoadFromFile()
{
var appConfigExists = FileAccess.FileExists(Config.AppConfigPath);
if (!appConfigExists)
{
LogCat.LogWarning("appConfig_not_exist");
return null;
}
var appConfigFileAccess = FileAccess.Open(Config.AppConfigPath, FileAccess.ModeFlags.Read);
var yamlData = appConfigFileAccess.GetAsText();
appConfigFileAccess.Close();
return YamlSerialization.Deserialize<AppConfigData>(yamlData);
}
/// <summary>
/// <para>ApplyAppConfig</para>
/// <para>应用配置</para>
/// </summary>
/// <param name="appConfigData"></param>
public static void ApplyAppConfig(AppConfigData appConfigData)
{
if (appConfigData.OpenObserve != null)
{
LogCollector.UpdateHttpClient(appConfigData.OpenObserve);
}
}
}
public class AppConfigData
{
/// <summary>
/// <para>OpenObserve configuration information</para>
/// <para>OpenObserve的配置信息</para>
/// </summary>
// ReSharper disable UnusedAutoPropertyAccessor.Global
public OpenObserve? OpenObserve { get; set; }
// ReSharper restore UnusedAutoPropertyAccessor.Global
}
/// <summary>
/// <para>OpenObserve Configuration information</para>
/// <para>OpenObserve配置信息</para>
/// </summary>
public class OpenObserve
{
/// <summary>
/// <para>server address</para>
/// <para>服务器地址</para>
/// </summary>
// ReSharper disable UnusedAutoPropertyAccessor.Global
public string? Address { get; set; }
// ReSharper restore UnusedAutoPropertyAccessor.Global
/// <summary>
/// <para>Access Token</para>
/// <para>访问密匙</para>
/// </summary>
// ReSharper disable UnusedAutoPropertyAccessor.Global
public string? AccessToken { get; set; }
// ReSharper restore UnusedAutoPropertyAccessor.Global
/// <summary>
/// <para>Organization ID</para>
/// <para>组织ID</para>
/// </summary>
// ReSharper disable UnusedAutoPropertyAccessor.Global
public string? OrgId { get; set; }
// ReSharper restore UnusedAutoPropertyAccessor.Global
/// <summary>
/// <para>Stream Name</para>
/// <para>流名称</para>
/// </summary>
// ReSharper disable UnusedAutoPropertyAccessor.Global
public string? StreamName { get; set; }
// ReSharper restore UnusedAutoPropertyAccessor.Global
}

23
scripts/AssetHolder.cs Normal file
View File

@ -0,0 +1,23 @@
using Godot;
namespace ColdMint.scripts;
/// <summary>
/// <para>AssetHolder</para>
/// <para>资产持有者</para>
/// </summary>
public static class AssetHolder
{
public static Texture2D? White25;
public static Texture2D? White100;
/// <summary>
/// <para>Loading the game's static assets</para>
/// <para>加载游戏的静态资产</para>
/// </summary>
public static void LoadStaticAsset()
{
White25 = ResourceLoader.Load<Texture2D>("res://sprites/light/White_25.png");
White100 = ResourceLoader.Load<Texture2D>("res://sprites/light/White_100.png");
}
}

View File

@ -21,6 +21,31 @@ public static class Config
public const string Test = "test";
}
/// <summary>
/// <para>Difficulty</para>
/// <para>游戏难度</para>
/// </summary>
public static class Difficulty
{
/// <summary>
/// <para>Simple mode</para>
/// <para>简单模式</para>
/// </summary>
public const int Easy = 0;
/// <summary>
/// <para>Normal mode</para>
/// <para>正常模式</para>
/// </summary>
public const int Normal = 1;
/// <summary>
/// <para>Hard mode</para>
/// <para>困难模式</para>
/// </summary>
public const int Hard = 2;
}
/// <summary>
/// <para>Camp ID</para>
@ -59,6 +84,12 @@ public static class Config
/// </summary>
public const float ThrownItemsHitEnemiesReduceSpeedByPercentage = 0.5f;
/// <summary>
/// <para>Scale of the room preview view</para>
/// <para>房间预览图的缩放</para>
/// </summary>
public const float RoomPreviewScale = 3f;
/// <summary>
/// <para>How much blood does a heart represent</para>
/// <para>一颗心代表多少血量</para>
@ -71,25 +102,12 @@ public static class Config
/// </summary>
public const string ModManifestFileName = "ModManifest.yaml";
/// <summary>
/// <para>The maximum number of stacked items in a single inventory</para>
/// <para>单个物品栏最大堆叠的物品数量</para>
/// </summary>
public const int MaxStackQuantity = 99;
/// <summary>
/// <para>Text change buffering Time How long does it take to execute the actual event after an event with a text change listener is triggered? (Anti-shake processing time), unit: milliseconds</para>
/// <para>当添加了文本改变监听器的事件被触发后,多长时间后执行实际事件?(防抖处理时长),单位:毫秒</para>
/// </summary>
public const long TextChangesBuffetingDuration = 300;
/// <summary>
/// <para>Operation prompts, function key text color</para>
/// <para>操作提示内,功能键文本颜色</para>
/// </summary>
public const string OperationTipActionColor = "#2b8a3e";
/// <summary>
/// <para>Company/Creator name</para>
/// <para>公司/创作者名字</para>
@ -115,12 +133,6 @@ public static class Config
public const int HotBarSize = 9;
/// <summary>
/// <para>UserID</para>
/// <para>用户ID</para>
/// </summary>
public const string UserId = "DefaultUser";
/// <summary>
/// <para>Whether version isolation is enabled</para>
/// <para>是否启用版本隔离</para>
@ -132,6 +144,16 @@ public static class Config
return !OS.HasFeature("disableVersionIsolation");
}
/// <summary>
/// <para>Whether to enable Mod</para>
/// <para>是否启用Mod</para>
/// </summary>
/// <returns></returns>
public static bool EnableMod()
{
return OS.HasFeature("enableMod");
}
/// <summary>
/// <para>Default version name</para>
/// <para>默认的版本名称</para>
@ -142,6 +164,18 @@ public static class Config
/// </remarks>
public const string DefaultVersionName = "Default";
/// <summary>
/// <para>EmptyVariant</para>
/// <para>空变量</para>
/// </summary>
public static readonly Variant EmptyVariant = new();
/// <summary>
/// <para>Blank string</para>
/// <para>空白字符串</para>
/// </summary>
public static readonly string? EmptyString = null;
/// <summary>
/// <para>IsDebug</para>
@ -163,6 +197,51 @@ public static class Config
return OS.HasFeature("editor");
}
/// <summary>
/// <para>ItemType</para>
/// <para>物品类型</para>
/// </summary>
public static class ItemType
{
/// <summary>
/// <para>Unknown</para>
/// <para>未知的</para>
/// </summary>
public const int Unknown = 0;
/// <summary>
/// <para>Placeholder</para>
/// <para>占位符</para>
/// </summary>
public const int Placeholder = 1;
/// <summary>
/// <para>Packsack</para>
/// <para>背包</para>
/// </summary>
public const int Packsack = 2;
/// <summary>
/// <para>ProjectileWeapon</para>
/// <para>远程武器</para>
/// </summary>
public const int ProjectileWeapon = 3;
/// <summary>
/// <para>Spell</para>
/// <para>法术</para>
/// </summary>
/// <remarks>
///<para>Type of special item used in Projectile weapons</para>
///<para>用于远程武器内的特殊物品类型</para>
/// </remarks>
public const int Spell = 4;
/// <summary>
/// <para>Common item types</para>
/// <para>普通的物品类型</para>
/// </summary>
public const int Item = 5;
}
/// <summary>
/// <para>Room Injector ID</para>
/// <para>房间注入器ID</para>
@ -182,6 +261,49 @@ public static class Config
public const string TimeInterval = "TimeInterval";
}
public class ZIndexManager
{
/// <summary>
/// <para>Floating icon</para>
/// <para>悬浮图标</para>
/// </summary>
public const int FloatingIcon = 1;
}
/// <summary>
/// <para>Item data changes the event type</para>
/// <para>物品数据改变事件类型</para>
/// </summary>
public enum ItemDataChangeEventType
{
/// <summary>
/// <para>add</para>
/// <para>添加</para>
/// </summary>
Add,
/// <summary>
/// <para>Quantity Added</para>
/// <para>物品数量增加</para>
/// </summary>
QuantityAdded,
/// <summary>
/// <para>remove</para>
/// <para>移除</para>
/// </summary>
Remove,
/// <summary>
/// <para>Replace</para>
/// <para>被替换</para>
/// </summary>
Replace,
/// <summary>
/// <para>Clear</para>
/// <para>被清空</para>
/// </summary>
Clear
}
public enum OsEnum
{
//unknown
@ -289,17 +411,27 @@ public static class Config
if (EnableVersionIsolation())
{
return Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), CompanyName,
ProjectSettings.GetSetting("application/config/name").AsString(), UserId,
ProjectSettings.GetSetting("application/config/name").AsString(),
ProjectSettings.GetSetting("application/config/version").AsString());
}
else
{
return Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), CompanyName,
ProjectSettings.GetSetting("application/config/name").AsString(), UserId,
ProjectSettings.GetSetting("application/config/name").AsString(),
DefaultVersionName);
}
}
/// <summary>
/// <para>GetDataBaseDirectory</para>
/// <para>获取数据库文件夹</para>
/// </summary>
/// <returns></returns>
public static string GetDataBaseDirectory()
{
return Path.Join(GetGameDataDirectory(), "Databases");
}
/// <summary>
/// <para>GetModDataDirectory</para>
/// <para>获取模组文件夹</para>
@ -338,6 +470,12 @@ public static class Config
/// </summary>
public const int DefaultMaxHp = 100;
/// <summary>
/// <para>The default durability of furniture</para>
/// <para>家具的默认耐久度</para>
/// </summary>
public const int DefaultMaxDurability = 50;
/// <summary>
/// <para>When a creature takes damage, how long to hide the bloodline again</para>
/// <para>生物受到伤害时,要在多长时间后再次隐藏血条</para>
@ -381,6 +519,27 @@ public static class Config
public const int VerticalVelocityOfDamageNumbers = 5;
public static class OffsetAngleMode
{
/// <summary>
/// <para>Random(Default)</para>
/// <para>随机的(默认)</para>
/// </summary>
public const int Random = 0;
/// <summary>
/// <para>AlwaysSame</para>
/// <para>永远不变的偏移角度</para>
/// </summary>
public const int AlwaysSame = 1;
/// <summary>
/// <para>Cross</para>
/// <para>交叉变换</para>
/// </summary>
public const int Cross = 2;
}
/// <summary>
/// <para>Physical collision layer number</para>
/// <para>物理碰撞层 序号</para>
@ -388,12 +547,71 @@ public static class Config
public static class LayerNumber
{
public const int RoomArea = 1;
public const int Ground = 2;
/// <summary>
/// <para>Floor</para>
/// <para>地板</para>
/// </summary>
public const int Floor = 2;
public const int Player = 3;
public const int PickAbleItem = 4;
public const int Projectile = 5;
/// <summary>
/// <para>Platform</para>
/// <para>平台</para>
/// </summary>
public const int Platform = 6;
public const int Mob = 7;
/// <summary>
/// <para>Wall</para>
/// <para>墙壁</para>
/// </summary>
public const int Wall = 8;
/// <summary>
/// <para>Furniture</para>
/// <para>家具</para>
/// </summary>
public const int Furniture = 9;
/// <summary>
/// <para>WeaponDamageArea</para>
/// <para>武器伤害区域</para>
/// </summary>
public const int WeaponDamageArea = 10;
public const int Barrier = 11;
}
/// <summary>
/// <para>TileMapLayerName</para>
/// <para>瓦片节点名称</para>
/// </summary>
public static class TileMapLayerName
{
/// <summary>
/// <para>Ground Layer</para>
/// <para>地面层</para>
/// </summary>
/// <remarks>
///<para>There are collision nodes on which players and creatures can stand.</para>
///<para>拥有碰撞节点,玩家和生物可以站在上面。</para>
/// </remarks>
public const string Ground = "Ground";
/// <summary>
/// <para>Barrier</para>
/// <para>屏障</para>
/// </summary>
public const string Barrier = "Barrier";
/// <summary>
/// <para>Background decorative layer</para>
/// <para>背景装饰层</para>
/// </summary>
public const string BackgroundDecoration = "BackgroundDecoration";
/// <summary>
/// <para>Background wall layer</para>
/// <para>背景墙</para>
/// </summary>
public const string BackgroundWall = "BackgroundWall";
}
public static class RoomDataTag

View File

@ -4,17 +4,11 @@ using ColdMint.scripts.map.events;
namespace ColdMint.scripts;
/// <summary>
/// <para>EventManager</para>
/// <para>事件管理器</para>
/// <para>EventBus</para>
/// <para>事件总线</para>
/// </summary>
public static class EventManager
public static class EventBus
{
/// <summary>
/// <para>Event when the AI character is generated</para>
/// <para>AI角色生成事件</para>
/// </summary>
public static Action<AiCharacterGenerateEvent>? AiCharacterGenerateEvent;
/// <summary>
/// <para>Game Over Event</para>
/// <para>游戏结束事件</para>
@ -38,10 +32,4 @@ public static class EventManager
/// <para>地图生成完成事件</para>
/// </summary>
public static Action<MapGenerationCompleteEvent>? MapGenerationCompleteEvent;
/// <summary>
/// <para>Player Instance Change Event</para>
/// <para>玩家实例改变事件</para>
/// </summary>
public static Action<PlayerInstanceChangeEvent>? PlayerInstanceChangeEvent;
}

165
scripts/GameSceneDepend.cs Normal file
View File

@ -0,0 +1,165 @@
using ColdMint.scripts.character;
using ColdMint.scripts.inventory;
using ColdMint.scripts.map.miniMap;
using ColdMint.scripts.utils;
using Godot;
namespace ColdMint.scripts;
/// <summary>
/// <para>Dependencies on the runtime of the game scene</para>
/// <para>游戏场景运行时的依赖</para>
/// </summary>
public static class GameSceneDepend
{
/// <summary>
/// <para>MiniMap</para>
/// <para>迷你地图</para>
/// </summary>
public static MiniMap? MiniMap { get; set; }
/// <summary>
/// <para>MiniMapAnimationPlayer</para>
/// <para>迷你地图的动画节点</para>
/// </summary>
public static AnimationPlayer? MiniMapAnimationPlayer { get; set; }
private static Player? _player;
/// <summary>
/// <para>Player instances within the game scene</para>
/// <para>游戏场景内的玩家实例</para>
/// </summary>
public static Player? Player
{
get => _player;
set
{
_player = value;
if (MiniMap != null)
{
MiniMap.OwnerNode = _player;
}
}
}
/// <summary>
/// <para>When the mouse enters the scope of a character, it is considered a target</para>
/// <para>鼠标进入到某个角色的范围内时,会将其视作目标</para>
/// </summary>
public static Node2D? TemporaryTargetNode { get; set; }
/// <summary>
/// <para>ProjectileContainer</para>
/// <para>抛射体容器</para>
/// </summary>
public static Node2D? ProjectileContainer { get; set; }
/// <summary>
/// <para>SpellContainer</para>
/// <para>法术容器</para>
/// </summary>
public static Node2D? SpellContainer { get; set; }
/// <summary>
/// <para>WeaponContainer</para>
/// <para>武器容器</para>
/// </summary>
public static Node2D? WeaponContainer { get; set; }
/// <summary>
/// <para>PacksackContainer</para>
/// <para>背包容器</para>
/// </summary>
public static Node2D? PacksackContainer { get; set; }
/// <summary>
/// <para>PlayerContainer</para>
/// <para>玩家容器</para>
/// </summary>
public static Node2D? PlayerContainer { get; set; }
/// <summary>
/// <para>PickAbleContainer</para>
/// <para>可拾捡物容器</para>
/// </summary>
public static Node2D? PickAbleContainer { get; set; }
/// <summary>
/// <para>AICharacterContainer</para>
/// <para>AICharacter角色</para>
/// </summary>
public static Node2D? AiCharacterContainer { get; set; }
/// <summary>
/// <para>HotBar</para>
/// <para>快捷栏</para>
/// </summary>
public static HotBar? HotBar { get; set; }
/// <summary>
/// <para>Health Bar UI</para>
/// <para>健康条UI</para>
/// </summary>
public static HealthBarUi? HealthBarUi { get; set; }
/// <summary>
/// <para>DynamicUiGroup</para>
/// <para>动态生成的Ui组</para>
/// </summary>
/// <remarks>
///<para>Dynamically generated Ui objects will be placed under this node</para>
///<para>动态生成的Ui对象将放置在此节点下</para>
/// </remarks>
public static UiGroup? DynamicUiGroup { get; set; }
/// <summary>
/// <para>Whether the player's mouse is hovering over GUI furniture</para>
/// <para>玩家的鼠标是否悬浮在GUI家具上</para>
/// </summary>
public static bool IsMouseOverFurnitureGui;
/// <summary>
/// <para>Whether the mouse is suspended over the item slot</para>
/// <para>鼠标是否悬浮在物品槽上</para>
/// </summary>
public static bool IsMouseOverItemSlotNode;
/// <summary>
/// <para>ShowMiniMap</para>
/// <para>显示迷你地图</para>
/// </summary>
public static void ShowMiniMap()
{
if (MiniMap == null)
{
return;
}
if (MiniMap.Visible)
{
return;
}
MiniMapAnimationPlayer?.Play(name: "show");
}
/// <summary>
/// <para>HideMiniMap</para>
/// <para>隐藏迷你地图</para>
/// </summary>
public static void HideMiniMap()
{
if (MiniMap == null)
{
return;
}
if (MiniMap.Visible)
{
MiniMapAnimationPlayer?.Play(name: "hide");
}
}
}

View File

@ -1,128 +0,0 @@
using ColdMint.scripts.character;
using ColdMint.scripts.inventory;
using ColdMint.scripts.loader.uiLoader;
using ColdMint.scripts.map.events;
using ColdMint.scripts.utils;
using Godot;
namespace ColdMint.scripts;
/// <summary>
/// <para>The node holder within the game scene</para>
/// <para>游戏场景内的节点持有者</para>
/// </summary>
public static class GameSceneNodeHolder
{
private static Player? _player;
/// <summary>
/// <para>Player instances within the game scene</para>
/// <para>游戏场景内的玩家实例</para>
/// </summary>
public static Player? Player
{
get => _player;
set
{
_player = value;
//Broadcast the event to the outside when the player instance changes.
//当玩家实例改变时,向外广播事件。
var playerInstanceChangeEvent = new PlayerInstanceChangeEvent
{
PlayerInstance = _player
};
EventManager.PlayerInstanceChangeEvent?.Invoke(playerInstanceChangeEvent);
}
}
/// <summary>
/// <para>ProjectileContainer</para>
/// <para>抛射体容器</para>
/// </summary>
public static Node2D? ProjectileContainer { get; set; }
/// <summary>
/// <para>WeaponContainer</para>
/// <para>武器容器</para>
/// </summary>
public static Node2D? WeaponContainer { get; set; }
/// <summary>
/// <para>PacksackContainer</para>
/// <para>背包容器</para>
/// </summary>
public static Node2D? PacksackContainer { get; set; }
/// <summary>
/// <para>PlayerContainer</para>
/// <para>玩家容器</para>
/// </summary>
public static Node2D? PlayerContainer { get; set; }
/// <summary>
/// <para>AICharacterContainer</para>
/// <para>AICharacter角色</para>
/// </summary>
public static Node2D? AiCharacterContainer { get; set; }
/// <summary>
/// <para>HotBar</para>
/// <para>快捷栏</para>
/// </summary>
public static HotBar? HotBar { get; set; }
/// <summary>
/// <para>Health Bar UI</para>
/// <para>健康条UI</para>
/// </summary>
public static HealthBarUi? HealthBarUi { get; set; }
/// <summary>
/// <para>operation tip</para>
/// <para>操作提示</para>
/// </summary>
public static RichTextLabel? OperationTipLabel { get; set; }
/// <summary>
/// <para>BackpackUiContainer</para>
/// <para>背包Ui容器</para>
/// </summary>
/// <remarks>
///<para>The knapsack Ui container houses the container of the knapsack ui node. When a user uses a backpack, the node to which his backpack is attached is displayed from within the backpack ui container.</para>
///<para>背包Ui容器内存放的是背包ui节点的容器。当用户使用背包时会从背包ui容器内将其背包对于的节点展示出来。</para>
/// </remarks>
public static Control? BackpackUiContainer { get; set; }
/// <summary>
/// <para>Hide the knapsack node in the knapsack Ui if the knapsack UI is displayed</para>
/// <para>如果背包Ui处于显示状态那么隐藏背包UI内的背包节点</para>
/// </summary>
public static void HideBackpackUiContainerIfVisible()
{
if (BackpackUiContainer == null)
{
return;
}
if (!BackpackUiContainer.Visible)
{
return;
}
NodeUtils.ForEachNode<PacksackUi>(BackpackUiContainer, node =>
{
//If the child node is not visible, the traversal continues.
//如果子节点不可见,则继续遍历。
if (!node.Visible)
return false;
//Until you find a visible node, hide it, and return true, ending the loop.
//直到找到可见的节点隐藏该节点然后返回true结束遍历。
node.Hide();
return true;
});
}
}

View File

@ -153,10 +153,10 @@ public partial class HealthBarUi : HBoxContainer
{
base._Ready();
NodeUtils.DeleteAllChild(this);
_heartEmpty = GD.Load<Texture2D>("res://sprites/ui/HeartEmpty.png");
_heartQuarter = GD.Load<Texture2D>("res://sprites/ui/HeartQuarter.png");
_heartHalf = GD.Load<Texture2D>("res://sprites/ui/HeartHalf.png");
_heartThreeFourths = GD.Load<Texture2D>("res://sprites/ui/HeartThreeFourths.png");
_heartFull = GD.Load<Texture2D>("res://sprites/ui/HeartFull.png");
_heartEmpty = ResourceLoader.Load<Texture2D>("res://sprites/ui/HeartEmpty.png");
_heartQuarter = ResourceLoader.Load<Texture2D>("res://sprites/ui/HeartQuarter.png");
_heartHalf = ResourceLoader.Load<Texture2D>("res://sprites/ui/HeartHalf.png");
_heartThreeFourths = ResourceLoader.Load<Texture2D>("res://sprites/ui/HeartThreeFourths.png");
_heartFull = ResourceLoader.Load<Texture2D>("res://sprites/ui/HeartFull.png");
}
}

View File

@ -45,7 +45,7 @@ public partial class BubbleMarker : Marker2D
{
if (!_bubbleDictionary.TryGetValue(id, out var value))
{
LogCat.LogErrorWithFormat("bubble_not_found", LogCat.LogLabel.BubbleMarker, LogCat.UploadFormat,id);
LogCat.LogErrorWithFormat("bubble_not_found", LogCat.LogLabel.BubbleMarker,id);
return;
}
@ -60,7 +60,7 @@ public partial class BubbleMarker : Marker2D
{
if (!_bubbleDictionary.TryGetValue(id, out var value))
{
LogCat.LogErrorWithFormat("bubble_not_found", LogCat.LogLabel.BubbleMarker, LogCat.UploadFormat,id);
LogCat.LogErrorWithFormat("bubble_not_found", LogCat.LogLabel.BubbleMarker,id);
return;
}

View File

@ -9,7 +9,7 @@ namespace ColdMint.scripts.camp;
/// </summary>
public static class CampManager
{
private static readonly Dictionary<string, Camp?> Camps = new Dictionary<string, Camp?>();
private static readonly Dictionary<string, Camp?> Camps = new();
/// <summary>
/// <para>The default camp is returned if no corresponding camp is obtained</para>
@ -40,7 +40,7 @@ public static class CampManager
if (camp.Id != Config.CampId.Default) return false;
_defaultCamp = camp;
AddCamp(camp);
LogCat.LogWithFormat("set_default_camp", label: LogCat.LogLabel.CampManager, LogCat.UploadFormat, camp.Id);
LogCat.LogWithFormat("set_default_camp", label: LogCat.LogLabel.CampManager, camp.Id);
return true;
}

View File

@ -62,9 +62,6 @@ public sealed partial class AiCharacter : CharacterTemplate
/// </remarks>
private RayCast2D? _attackObstacleDetection;
private VisibleOnScreenEnabler2D? _screenEnabler2D;
/// <summary>
/// <para>Navigation agent</para>
/// <para>导航代理</para>
@ -109,42 +106,29 @@ public sealed partial class AiCharacter : CharacterTemplate
private BubbleMarker? _bubbleMarker;
/// <summary>
/// <para>The initial weapons scene</para>
/// <para>初始的武器场景</para>
/// <para>Initial weapon ID</para>
/// <para>初始的武器ID</para>
/// </summary>
[Export] public string? InitWeaponRes;
[Export] public string? InitWeaponId;
public override void _Ready()
{
base._Ready();
_enemyInTheAttackRange = new List<CharacterTemplate>();
_enemyInTheScoutRange = new List<CharacterTemplate>();
_weaponInTheScoutRange = new List<WeaponTemplate>();
_screenEnabler2D = GetNode<VisibleOnScreenEnabler2D>("VisibleOnScreenEnabler2D");
_screenEnabler2D.ScreenEntered += () =>
{
//When the character enters the screen.
//当角色进入屏幕。
ProcessMode = ProcessModeEnum.Disabled;
};
_screenEnabler2D.ScreenExited += () =>
{
//When the character leaves the screen.
//当角色离开屏幕。
ProcessMode = ProcessModeEnum.Inherit;
};
_enemyInTheAttackRange = [];
_enemyInTheScoutRange = [];
_weaponInTheScoutRange = [];
_bubbleMarker = GetNode<BubbleMarker>("BubbleMarker");
if (_bubbleMarker != null)
{
using var plaintScene = GD.Load<PackedScene>("res://prefab/ui/plaint.tscn");
using var plaintScene = ResourceLoader.Load<PackedScene>("res://prefab/ui/plaint.tscn");
var plaint = NodeUtils.InstantiatePackedScene<Control>(plaintScene);
if (plaint != null)
{
_bubbleMarker.AddBubble(PlaintBubbleId, plaint);
}
using var queryScene = GD.Load<PackedScene>("res://prefab/ui/query.tscn");
using var queryScene = ResourceLoader.Load<PackedScene>("res://prefab/ui/query.tscn");
var query = NodeUtils.InstantiatePackedScene<Control>(queryScene);
if (query != null)
{
@ -195,36 +179,31 @@ public sealed partial class AiCharacter : CharacterTemplate
//You must create an item container for the character before you can pick up the item.
//必须为角色创建物品容器后才能拾起物品。
var universalItemContainer = new UniversalItemContainer();
var itemSlotNode = universalItemContainer.AddItemSlot(this);
itemSlotNode?.Hide();
var universalItemContainer = new UniversalItemContainer(1);
universalItemContainer.AllowAddingItemByType(Config.ItemType.ProjectileWeapon);
ProtectedItemContainer = universalItemContainer;
//Add initial weapon
//添加初始武器
AddInitialWeapon(InitWeaponRes);
AddInitialWeapon(InitWeaponId);
}
/// <summary>
/// <para>Adds an initial weapon to the character</para>
/// <para>为角色添加初始的武器</para>
/// </summary>
private void AddInitialWeapon(string? initWeaponRes)
private void AddInitialWeapon(string? initWeaponId)
{
if (initWeaponRes == null)
if (string.IsNullOrEmpty(initWeaponId))
{
return;
}
//Set the resource path of the initial weapon and try to create the object of the initial weapon.
//设置了初始武器的资源路径,尝试创建初始武器的对象。
var packedScene = GD.Load<PackedScene>(initWeaponRes);
var weaponTemplate = NodeUtils.InstantiatePackedScene<WeaponTemplate>(packedScene);
if (weaponTemplate == null)
var item = ItemTypeManager.CreateItem(initWeaponId, this);
if (item is not WeaponTemplate weaponTemplate)
{
return;
}
NodeUtils.CallDeferredAddChild(this, weaponTemplate);
NodeUtils.CallDeferredReparent(this, weaponTemplate);
PickItem(weaponTemplate);
}
@ -341,7 +320,7 @@ public sealed partial class AiCharacter : CharacterTemplate
if (NavigationAgent2D != null && IsOnFloor())
{
var nextPathPosition = NavigationAgent2D.GetNextPathPosition();
var direction = (nextPathPosition - GlobalPosition).Normalized();
var direction = GlobalPosition.DirectionTo(nextPathPosition);
velocity = direction * Config.CellSize * Speed * ProtectedSpeedScale;
}
}

View File

@ -9,6 +9,7 @@ using ColdMint.scripts.inventory;
using ColdMint.scripts.utils;
using ColdMint.scripts.loot;
using ColdMint.scripts.pickable;
using ColdMint.scripts.weapon;
using Godot;
using WeaponTemplate = ColdMint.scripts.weapon.WeaponTemplate;
@ -69,13 +70,16 @@ public partial class CharacterTemplate : CharacterBody2D
}
protected const float JumpVelocity = -240;
public string? ReadOnlyCharacterName => TranslationServerUtils.Translate(CharacterName);
//物品被扔出后多长时间恢复与地面和平台的碰撞(单位:秒)
private readonly double _itemCollisionRecoveryTime = 0.045f;
[Export] public string? CharacterName;
public string? ReadOnlyCharacterName => CharacterName;
protected string? CharacterName;
/// <summary>
/// <para>Can mutate after death</para>
/// <para>是否允许死后变异</para>
/// </summary>
[Export]
public bool CanMutateAfterDeath { get; set; } = true;
protected IItemContainer? ProtectedItemContainer;
@ -156,21 +160,29 @@ public partial class CharacterTemplate : CharacterBody2D
//The initial health of the character after creation
//角色创建后的初始血量
private int _initialHp;
[Export] private int _initialHp;
public int MaxHp;
[Export] protected int MaxHp;
/// <summary>
/// <para>The camp ID of the role</para>
/// <para>角色的阵营ID</para>
/// </summary>
public string CampId = null!;
[Export] public string? CampId;
private DamageNumberNodeSpawn? _damageNumber;
/// <summary>
/// <para>indestructible</para>
/// <para>是否为无敌的</para>
/// </summary>
[Export]
private bool _indestructible;
[Export] public string LootListId { get; private set; } = "";
private HealthBar? _healthBar;
private Label? _tipLabel;
private DateTime _lastDamageTime;
/// <summary>
@ -181,6 +193,16 @@ public partial class CharacterTemplate : CharacterBody2D
public Node[] PickingRangeBodies => PickingRangeBodiesList?.ToArray() ?? [];
/// <summary>
/// <para>Full Hp Revive</para>
/// <para>满血复活</para>
/// </summary>
public void FullHpRevive()
{
Revive(MaxHp);
}
/// <summary>
/// <para>Resurrected character</para>
/// <para>复活角色</para>
@ -244,27 +266,23 @@ public partial class CharacterTemplate : CharacterBody2D
{
continue;
}
weaponTemplates.Add(weaponTemplate);
}
return weaponTemplates.ToArray();
}
public override void _Ready()
{
base._Ready();
PickingRangeBodiesList = new List<Node>();
CharacterName = GetMeta("Name", Name).AsString();
CampId = GetMeta("CampId", Config.CampId.Default).AsString();
MaxHp = GetMeta("MaxHp", Config.DefaultMaxHp).AsInt32();
PickingRangeBodiesList = [];
if (MaxHp <= 0)
{
//If Max blood volume is 0 or less, set Max blood volume to 10
//若最大血量为0或小于0则将最大血量设置为10
MaxHp = Config.DefaultMaxHp;
}
_initialHp = GetMeta("InitialHp", "0").AsInt32();
if (_initialHp <= 0 || _initialHp > MaxHp)
{
//If the initial health is less than or equal to 0 or greater than the maximum health, then set it to the maximum health
@ -281,12 +299,12 @@ public partial class CharacterTemplate : CharacterBody2D
_healthBar.MaxValue = MaxHp;
}
ItemMarker2D = GetNode<Marker2D>("ItemMarker2D");
_itemMarkerOriginalX = ItemMarker2D.Position.X;
_animatedSprite2D = GetNode<AnimatedSprite2D>("AnimatedSprite2D");
_pickingArea = GetNode<Area2D>("Area2DPickingArea");
_damageNumber = GetNode<Marker2D>("DamageNumber") as DamageNumberNodeSpawn;
_tipLabel = GetNodeOrNull<Label>("TipLabel");
if (_pickingArea != null)
{
//If true, the zone will detect objects or areas entering and leaving the zone.
@ -298,6 +316,55 @@ public partial class CharacterTemplate : CharacterBody2D
_pickingArea.BodyEntered += EnterThePickingRangeBody;
_pickingArea.BodyExited += ExitThePickingRangeBody;
}
//The character cannot pass through the wall and floor
//角色不能穿过墙壁和地板
SetCollisionMaskValue(Config.LayerNumber.Wall, true);
SetCollisionMaskValue(Config.LayerNumber.Floor, true);
SetCollisionMaskValue(Config.LayerNumber.Barrier, true);
InputPickable = true;
}
public override void _ExitTree()
{
base._ExitTree();
if (GameSceneDepend.TemporaryTargetNode == this)
{
GameSceneDepend.TemporaryTargetNode = null;
}
}
public override void _MouseEnter()
{
if (GameSceneDepend.Player != null)
{
var targetCamp = CampManager.GetCamp(CampId);
var playerCamp = CampManager.GetCamp(GameSceneDepend.Player.CampId);
if (CampManager.CanCauseHarm(targetCamp, playerCamp))
{
GameSceneDepend.TemporaryTargetNode = this;
}
}
if (_tipLabel != null)
{
_tipLabel.Visible = true;
_tipLabel.Text = CharacterName;
//Vertical Centering Tip
//垂直居中提示
var oldPosition = _tipLabel.Position;
oldPosition.X = -_tipLabel.Size.X / 2;
_tipLabel.Position = oldPosition;
}
}
public override void _MouseExit()
{
if (_tipLabel != null)
{
_tipLabel.Visible = false;
}
}
/// <summary>
@ -343,7 +410,6 @@ public partial class CharacterTemplate : CharacterBody2D
return false;
}
//The item store is marked null, or the item container is null.
//物品存放的标记为null或者物品容器为null。
if (ItemMarker2D == null || ItemContainer == null)
@ -351,14 +417,6 @@ public partial class CharacterTemplate : CharacterBody2D
return false;
}
//Get the currently selected node
//拿到当前选择的节点
var selectItemSlotNode = ItemContainer.GetSelectItemSlotNode();
if (selectItemSlotNode == null)
{
return false;
}
//Check to see if you can fit the item into the container first.
//先检查是否能将物品放入容器。
var canAddItem = ItemContainer.CanAddItem(item);
@ -369,8 +427,8 @@ public partial class CharacterTemplate : CharacterBody2D
//Is it successfully added to the container?
//再检查是否成功的添加到容器内了?
var addSuccess = ItemContainer.AddItem(item);
if (!addSuccess)
var addSuccessNumber = ItemContainer.AddItem(item);
if (addSuccessNumber <= 0)
{
return false;
}
@ -381,16 +439,19 @@ public partial class CharacterTemplate : CharacterBody2D
//您可以在这里补充更多类型对象的捡起状态处理。
if (pickAbleItemNode2D is PickAbleTemplate pickAbleTemplate)
{
pickAbleTemplate.LoadResource();
pickAbleTemplate.Owner = this;
pickAbleTemplate.Picked = true;
pickAbleTemplate.SetCollisionMaskValue(Config.LayerNumber.Platform, false);
pickAbleTemplate.SetCollisionMaskValue(Config.LayerNumber.Ground, false);
pickAbleTemplate.EnableContactInjury = false;
pickAbleTemplate.Sleeping = true;
pickAbleTemplate.Freeze = true;
pickAbleTemplate.DisabledCollisionShape2D();
}
if (pickAbleItemNode2D is ProjectileWeapon projectileWeapon)
{
projectileWeapon.UpdateSpellCache();
}
if (_currentItem == null && selectItemSlotNode.GetItem() == item)
if (_currentItem == null && ItemContainer.GetSelectItem() == item)
{
//If the selected item slot in the item container is a newly picked item, and there is no item in the hand, then we put the selected item into the hand.
//如果物品容器内选中的物品槽是刚刚捡到的物品,且手里没有物品持有,那么我们将选中的物品放到手上。
@ -403,7 +464,6 @@ public partial class CharacterTemplate : CharacterBody2D
}
NodeUtils.CallDeferredReparent(ItemMarker2D, pickAbleItemNode2D);
pickAbleItemNode2D.Position = Vector2.Zero;
return true;
}
@ -421,10 +481,10 @@ public partial class CharacterTemplate : CharacterBody2D
if (_currentItem is IItem item)
{
item.Use(this, position);
return item.Use(this, position);
}
return true;
return false;
}
public override void _Process(double delta)
@ -454,7 +514,7 @@ public partial class CharacterTemplate : CharacterBody2D
return;
}
if (GameSceneNodeHolder.Player == null)
if (GameSceneDepend.Player == null)
{
//We didn't know who the player was, so we showed it as a hostile color
//我们不知道玩家是谁,所以我们将其显示为敌对颜色
@ -465,7 +525,7 @@ public partial class CharacterTemplate : CharacterBody2D
//If we set up a player node, then compare the injured party ID to the player's party ID
//如果我们设置了玩家节点那么将受伤者的阵营ID与玩家的阵营ID进行比较
var targetCamp = CampManager.GetCamp(CampId);
var playerCamp = CampManager.GetCamp(GameSceneNodeHolder.Player.CampId);
var playerCamp = CampManager.GetCamp(GameSceneDepend.Player.CampId);
if (CampManager.CanCauseHarm(targetCamp, playerCamp))
{
if (targetCamp != null && playerCamp != null)
@ -503,11 +563,15 @@ public partial class CharacterTemplate : CharacterBody2D
///<para>伤害模板</para>
/// </param>
/// <returns>
///<para>Return whether the damage was done successfully</para>
///<para>返回是否成功造成了伤害</para>
///<para>Return whether the character is dead</para>
///<para>返回本次伤害是否导致角色死亡。</para>
/// </returns>
public bool Damage(DamageTemplate damageTemplate)
{
if (_indestructible)
{
return false;
}
_lastDamageTime = DateTime.Now;
_damageNumber?.Display(damageTemplate);
CurrentHp -= damageTemplate.Damage;
@ -517,13 +581,11 @@ public partial class CharacterTemplate : CharacterBody2D
//Character death
//角色死亡
OnDie(damageTemplate);
ThrowAllItemOnDie();
return true;
}
UpDataHealthBar();
return true;
return false;
}
/// <summary>
@ -562,6 +624,11 @@ public partial class CharacterTemplate : CharacterBody2D
/// <param name="force"></param>
public void AddForce(Vector2 force)
{
if (_additionalForce != Vector2.Zero)
{
return;
}
_additionalForce = force;
}
@ -583,16 +650,16 @@ public partial class CharacterTemplate : CharacterBody2D
if (damageTemplate.Attacker is CharacterTemplate characterTemplate &&
!string.IsNullOrEmpty(characterTemplate.CharacterName))
{
LogCat.LogWithFormat("death_info", LogCat.LogLabel.Default, LogCat.UploadFormat, CharacterName,
LogCat.LogWithFormat("death_info", LogCat.LogLabel.Default, CharacterName,
characterTemplate.CharacterName);
}
else
{
LogCat.LogWithFormat("death_info", LogCat.LogLabel.Default, LogCat.UploadFormat, CharacterName,
LogCat.LogWithFormat("death_info", LogCat.LogLabel.Default, CharacterName,
damageTemplate.Attacker.Name);
}
}
ThrowAllItemOnDie();
CreateLootObject();
QueueFree();
return Task.CompletedTask;
@ -626,6 +693,7 @@ public partial class CharacterTemplate : CharacterBody2D
return;
}
LogCat.Log("exit_the_picking_range_body");
PickingRangeBodiesList?.Remove(node);
}
@ -656,7 +724,7 @@ public partial class CharacterTemplate : CharacterBody2D
return;
}
var len = ItemContainer.GetItemSlotCount();
var len = ItemContainer.GetTotalCapacity();
if (len == 0)
{
return;
@ -695,21 +763,19 @@ public partial class CharacterTemplate : CharacterBody2D
/// </param>
protected void ThrowItem(int index, int number, Vector2 velocity)
{
var itemSlotNode = ItemContainer?.GetItemSlotNode(index);
if (itemSlotNode is null) return;
if (number < 0)
if (number == 0)
{
while (!itemSlotNode.IsEmpty())
{
ThrowOneItem(itemSlotNode, velocity);
}
return;
}
else
var item = ItemContainer?.GetItem(index);
if (item is null) return;
//Less than 0, throw everything
//小于0,扔出所有物品
var actualQuantity = number < 0 ? item.Quantity : Math.Min(item.Quantity, number);
for (var i = 0; i < actualQuantity; i++)
{
for (var i = 0; i < number && !itemSlotNode.IsEmpty(); i++)
{
ThrowOneItem(itemSlotNode, velocity);
}
ThrowOneItem(index, item, velocity);
}
}
@ -717,50 +783,39 @@ public partial class CharacterTemplate : CharacterBody2D
/// <para>Throw item</para>
/// <para>抛出物品</para>
/// </summary>
/// <param name="itemSlotNode"></param>
/// <param name="index"></param>
/// <param name="originalItem"></param>
/// <param name="velocity">
/// <para>The speed to be applied to the item</para>
/// <para>要施加到物品上的速度</para>
/// </param>
private void ThrowOneItem(ItemSlotNode itemSlotNode, Vector2 velocity)
private void ThrowOneItem(int index, IItem originalItem, Vector2 velocity)
{
//Remove the item from the item container
//从物品容器内取出物品
var item = itemSlotNode.CreateItemInstance(1);
originalItem.OnThrow(velocity);
var item = originalItem.CreateItem(1);
if (item is not Node2D node2D)
{
return;
}
item.ItemContainer = null;
NodeUtils.CallDeferredAddChild(NodeUtils.FindContainerNode(node2D, GetNode("/root")), node2D);
switch (item)
{
case PickAbleTemplate pickAbleTemplate:
if (GameSceneNodeHolder.WeaponContainer == null)
if (GameSceneDepend.WeaponContainer == null)
{
return;
}
pickAbleTemplate.Sleeping = false;
pickAbleTemplate.LoadResource();
pickAbleTemplate.Owner = this;
pickAbleTemplate.Picked = false;
var timer = new Timer();
pickAbleTemplate.AddChild(timer);
timer.WaitTime = _itemCollisionRecoveryTime;
timer.Autostart = true;
timer.OneShot = true;
timer.Timeout += () =>
{
//We cannot immediately resume the physical collision when the weapon is discharged, which will cause the weapon to collide with the ground and platform earlier, preventing the weapon from flying.
//仍出武器时,我们不能立即恢复物理碰撞,立即恢复会导致武器更早的与地面和平台碰撞,阻止武器的飞行。
pickAbleTemplate.EnableContactInjury = true;
pickAbleTemplate.SetCollisionMaskValue(Config.LayerNumber.Ground, true);
pickAbleTemplate.SetCollisionMaskValue(Config.LayerNumber.Platform, true);
timer.QueueFree();
};
//Setting an initial speed of 0 for items here prevents the problem of throwing items too fast.
//在这里给物品设置一个为0的初始速度可防止扔出物品时速度过快的问题。
pickAbleTemplate.LinearVelocity = Vector2.Zero;
pickAbleTemplate.EnabledCollisionShape2D();
pickAbleTemplate.Freeze = false;
break;
}
@ -778,7 +833,8 @@ public partial class CharacterTemplate : CharacterBody2D
break;
}
itemSlotNode.RemoveItem(1);
ProtectedItemContainer?.RemoveItem(index, 1);
originalItem.QueueFreeSelf();
}

View File

@ -1,5 +1,3 @@
using System;
using System.Text;
using System.Threading.Tasks;
using ColdMint.scripts.damage;
using ColdMint.scripts.deathInfo;
@ -17,8 +15,6 @@ namespace ColdMint.scripts.character;
/// </summary>
public partial class Player : CharacterTemplate
{
private Control? _floatLabel;
//Empty object projectile
//空的物品抛射线
private readonly Vector2[] _emptyVector2Array = [Vector2.Zero];
@ -27,11 +23,7 @@ public partial class Player : CharacterTemplate
private Line2D? _parabola;
//用于检测玩家是否站在平台上的射线
private RayCast2D? _platformDetectionRayCast2D;
private const float PromptTextDistance = 50;
[Export] private RayCast2D[]? _platformDetectionRayCast2DList;
//抛出物品的飞行速度
private float _throwingVelocity = Config.CellSize * 13;
@ -39,6 +31,8 @@ public partial class Player : CharacterTemplate
//射线是否与平台碰撞
private bool _collidingWithPlatform;
private bool _canUseItem;
//How long does it take for the character to recover from a collision with the platform after jumping off the platform (in seconds)
//角色从平台上跳下后,多少时间后恢复与平台的碰撞(单位:秒)
private double _platformCollisionRecoveryTime = 0.2f;
@ -47,29 +41,30 @@ public partial class Player : CharacterTemplate
public override void _Ready()
{
base._Ready();
CharacterName = TranslationServerUtils.Translate("default_player_name");
LogCat.LogWithFormat("player_spawn_debug", LogCat.LogLabel.Default, LogCat.UploadFormat, ReadOnlyCharacterName,
GlobalPosition);
var floatLabelPackedScene = GD.Load<PackedScene>("res://prefab/ui/FloatLabel.tscn");
//Initializes the float label.
//初始化悬浮标签。
_floatLabel = NodeUtils.InstantiatePackedScene<Control>(floatLabelPackedScene);
if (_floatLabel == null)
if (_platformDetectionRayCast2DList == null || _platformDetectionRayCast2DList.Length == 0)
{
throw new NullReferenceException(TranslationServer.Translate("float_label_instantiate_failed"));
LogCat.LogError("no_platform_detection_raycast_found");
return;
}
_floatLabel.Hide();
NodeUtils.CallDeferredAddChild(this, _floatLabel);
CharacterName = TranslationServerUtils.Translate("default_player_name");
LogCat.LogWithFormat("player_spawn_debug", LogCat.LogLabel.Default, ReadOnlyCharacterName,
GlobalPosition);
_parabola = GetNode<Line2D>("Parabola");
_platformDetectionRayCast2D = GetNode<RayCast2D>("PlatformDetectionRayCast");
UpdateOperationTip();
var healthBarUi = GameSceneNodeHolder.HealthBarUi;
var healthBarUi = GameSceneDepend.HealthBarUi;
if (healthBarUi != null)
{
healthBarUi.MaxHp = MaxHp;
healthBarUi.CurrentHp = CurrentHp;
}
//Mount the camera.
//挂载相机。
var mainCameraPackedScene = ResourceLoader.Load<PackedScene>("res://prefab/MainCamera.tscn");
var camera2D = NodeUtils.InstantiatePackedScene<Camera2D>(mainCameraPackedScene);
if (camera2D != null)
{
NodeUtils.CallDeferredAddChild(this, camera2D);
}
}
protected override void WhenBindItemContainer(IItemContainer? itemContainer)
@ -81,7 +76,7 @@ public partial class Player : CharacterTemplate
//Subscribe to events when the item container is bound to the player.
//在物品容器与玩家绑定时订阅事件。
itemContainer.SelectedItemSlotChangeEvent += SelectedItemSlotChangeEvent;
itemContainer.SelectedItemChangeEvent += SelectedItemChangeEvent;
}
public override void _ExitTree()
@ -91,14 +86,13 @@ public partial class Player : CharacterTemplate
{
//Unsubscribe to events when this object is destroyed.
//此节点被销毁时,取消订阅事件。
ProtectedItemContainer.SelectedItemSlotChangeEvent -= SelectedItemSlotChangeEvent;
ProtectedItemContainer.SelectedItemChangeEvent -= SelectedItemChangeEvent;
}
}
private void SelectedItemSlotChangeEvent(SelectedItemSlotChangeEvent selectedItemSlotChangeEvent)
private void SelectedItemChangeEvent(SelectedItemChangeEvent selectedItemChangeEvent)
{
var item = selectedItemSlotChangeEvent.NewItemSlotNode?.GetItem();
GameSceneNodeHolder.HideBackpackUiContainerIfVisible();
var item = selectedItemChangeEvent.NewItem;
if (item is Node2D node2D)
{
CurrentItem = node2D;
@ -109,111 +103,35 @@ public partial class Player : CharacterTemplate
}
}
/// <summary>
/// <para>Update operation prompt</para>
/// <para>更新操作提示</para>
/// </summary>
private void UpdateOperationTip()
public override void _MouseEnter()
{
var operationTipLabel = GameSceneNodeHolder.OperationTipLabel;
if (operationTipLabel == null)
{
return;
}
var operationTipBuilder = new StringBuilder();
operationTipBuilder.Append("[color=");
operationTipBuilder.Append(Config.OperationTipActionColor);
operationTipBuilder.Append(']');
operationTipBuilder.Append(TranslationServerUtils.Translate(InputMap.ActionGetEvents("ui_left")[0].AsText()));
operationTipBuilder.Append("[/color]");
operationTipBuilder.Append(TranslationServerUtils.Translate("action_move_left"));
operationTipBuilder.Append(' ');
operationTipBuilder.Append("[color=");
operationTipBuilder.Append(Config.OperationTipActionColor);
operationTipBuilder.Append(']');
operationTipBuilder.Append(TranslationServerUtils.Translate(InputMap.ActionGetEvents("ui_right")[0].AsText()));
operationTipBuilder.Append("[/color]");
operationTipBuilder.Append(TranslationServerUtils.Translate("action_move_right"));
operationTipBuilder.Append(' ');
operationTipBuilder.Append("[color=");
operationTipBuilder.Append(Config.OperationTipActionColor);
operationTipBuilder.Append(']');
operationTipBuilder.Append(TranslationServerUtils.Translate(InputMap.ActionGetEvents("ui_up")[0].AsText()));
operationTipBuilder.Append("[/color]");
operationTipBuilder.Append(TranslationServerUtils.Translate("action_jump"));
if (_collidingWithPlatform)
{
operationTipBuilder.Append(' ');
operationTipBuilder.Append("[color=");
operationTipBuilder.Append(Config.OperationTipActionColor);
operationTipBuilder.Append(']');
operationTipBuilder.Append(
TranslationServerUtils.Translate(InputMap.ActionGetEvents("ui_down")[0].AsText()));
operationTipBuilder.Append("[/color]");
operationTipBuilder.Append(TranslationServerUtils.Translate("action_jump_down"));
}
var nearestItem = FindTheNearestItem();
if (nearestItem != null)
{
operationTipBuilder.Append(' ');
operationTipBuilder.Append("[color=");
operationTipBuilder.Append(Config.OperationTipActionColor);
operationTipBuilder.Append(']');
operationTipBuilder.Append(
TranslationServerUtils.Translate(InputMap.ActionGetEvents("pick_up")[0].AsText()));
operationTipBuilder.Append("[/color]");
operationTipBuilder.Append(TranslationServerUtils.Translate("action_pick_up"));
if (nearestItem is IItem item)
{
operationTipBuilder.Append(item.Name);
}
operationTipLabel.Text = operationTipBuilder.ToString();
}
if (CurrentItem != null)
{
operationTipBuilder.Append(' ');
operationTipBuilder.Append("[color=");
operationTipBuilder.Append(Config.OperationTipActionColor);
operationTipBuilder.Append(']');
operationTipBuilder.Append(TranslationServerUtils.Translate(InputMap.ActionGetEvents("throw")[0].AsText()));
operationTipBuilder.Append("[/color]");
operationTipBuilder.Append(TranslationServerUtils.Translate("action_throw"));
if (CurrentItem is IItem item)
{
operationTipBuilder.Append(TranslationServerUtils.Translate(item.Name));
operationTipBuilder.Append(' ');
operationTipBuilder.Append("[color=");
operationTipBuilder.Append(Config.OperationTipActionColor);
operationTipBuilder.Append(']');
operationTipBuilder.Append(
TranslationServerUtils.Translate(InputMap.ActionGetEvents("use_item")[0].AsText()));
operationTipBuilder.Append("[/color]");
operationTipBuilder.Append(TranslationServerUtils.Translate("action_use_item"));
operationTipBuilder.Append(TranslationServerUtils.Translate(item.Name));
}
}
operationTipLabel.Text = operationTipBuilder.ToString();
}
public override void _MouseExit()
{
}
protected override void HookPhysicsProcess(ref Vector2 velocity, double delta)
/// <summary>
/// <para>UpdateCollidingWithPlatform</para>
/// <para>更新与平台发生碰撞的状态</para>
/// </summary>
private void UpdateCollidingWithPlatform()
{
//When the collision state between the platform detection ray and the platform changes
//在平台检测射线与平台碰撞状态改变时
if (_platformDetectionRayCast2D != null && _platformDetectionRayCast2D.IsColliding() != _collidingWithPlatform)
if (_platformDetectionRayCast2DList is not { Length: > 0 }) return;
foreach (var rayCast2D in _platformDetectionRayCast2DList)
{
//When the state changes, update the action hint
//当状态改变时,更新操作提示
_collidingWithPlatform = _platformDetectionRayCast2D.IsColliding();
UpdateOperationTip();
if (!rayCast2D.IsColliding()) continue;
_collidingWithPlatform = true;
return;
}
_collidingWithPlatform = false;
}
protected override void HookPhysicsProcess(ref Vector2 velocity, double delta)
{
UpdateCollidingWithPlatform();
//If the character is on the ground, give an upward velocity when the jump button is pressed
//如果角色正在地面上,按下跳跃键时,给予一个向上的速度
if (Input.IsActionJustPressed("ui_up") && IsOnFloor())
@ -224,13 +142,20 @@ public partial class Player : CharacterTemplate
var axis = Input.GetAxis("ui_left", "ui_right");
velocity.X = axis * Speed * Config.CellSize * ProtectedSpeedScale;
if (Input.IsActionJustPressed("use_item"))
{
_canUseItem = !GameSceneDepend.IsMouseOverFurnitureGui && !GameSceneDepend.IsMouseOverItemSlotNode;
}
//Use items
//使用物品
if (Input.IsActionPressed("use_item"))
{
UseItem(GetGlobalMousePosition());
if (_canUseItem)
{
UseItem(GetGlobalMousePosition());
}
}
//Pick up an item
//捡起物品
if (Input.IsActionJustPressed("pick_up"))
@ -243,8 +168,6 @@ public partial class Player : CharacterTemplate
{
PickingRangeBodiesList?.Remove(pickAbleItem);
}
RecycleFloatLabel();
}
}
@ -306,16 +229,10 @@ public partial class Player : CharacterTemplate
}
ThrowItem(ItemContainer.GetSelectIndex(), 1, GetThrowVelocity());
GameSceneNodeHolder.HideBackpackUiContainerIfVisible();
CurrentItem = null;
}
}
protected override void WhenUpdateCurrentItem(Node2D? currentItem)
{
UpdateOperationTip();
}
/// <summary>
/// <para>当玩家手动抛出物品时,施加到物品上的速度值</para>
/// </summary>
@ -388,13 +305,15 @@ public partial class Player : CharacterTemplate
public override void Revive(int newHp)
{
base.Revive(newHp);
var healthBarUi = GameSceneNodeHolder.HealthBarUi;
var healthBarUi = GameSceneDepend.HealthBarUi;
if (healthBarUi != null)
{
//The purpose of setting Hp to the current Hp is to cause the life bar to refresh.
//将Hp设置为当前Hp的目的是使生命条刷新。
healthBarUi.CurrentHp = CurrentHp;
}
ProcessMode = ProcessModeEnum.Inherit;
Show();
}
/// <summary>
@ -406,8 +325,10 @@ public partial class Player : CharacterTemplate
{
Hide();
ProcessMode = ProcessModeEnum.Disabled;
if (EventManager.GameOverEvent == null)
ProtectedItemContainer?.ClearAllItems();
if (EventBus.GameOverEvent == null)
{
LogCat.Log("game_over_event_is_empty");
return;
}
@ -417,95 +338,14 @@ public partial class Player : CharacterTemplate
gameOverEvent.DeathInfo = await DeathInfoGenerator.GenerateDeathInfo(this, damageTemplate.Attacker);
}
EventManager.GameOverEvent.Invoke(gameOverEvent);
EventBus.GameOverEvent.Invoke(gameOverEvent);
}
protected override void EnterThePickingRangeBody(Node node)
{
base.EnterThePickingRangeBody(node);
if (CurrentItem == node)
{
//If the node entering the pick range is the node held by the player, then return.
//如果说进入拾捡范围的节点是玩家所持有的节点,那么返回。
return;
}
if (node is not Node2D node2D)
{
return;
}
if (_floatLabel != null)
{
if (node is not PickAbleTemplate pickAbleTemplate)
{
return;
}
if (pickAbleTemplate.Picked)
{
//If the pickables are picked up, the label is not displayed.
//如果可拾捡物被捡起了,那么不显示标签。
LogCat.LogWarning("pickable_picked_up");
return;
}
NodeUtils.CallDeferredReparent(node, _floatLabel);
var rotationDegreesNode2D = node2D.RotationDegrees;
var rotationDegreesNode2DAbs = Math.Abs(rotationDegreesNode2D);
_floatLabel.GlobalPosition = node2D.GlobalPosition;
_floatLabel.Position = rotationDegreesNode2DAbs > 90
? new Vector2(0, PromptTextDistance)
: new Vector2(0, -PromptTextDistance);
_floatLabel.RotationDegrees = 0 - rotationDegreesNode2D;
var label = _floatLabel.GetNode<Label>("Label");
var stringBuilder = new StringBuilder();
if (pickAbleTemplate.Owner is CharacterTemplate characterTemplate)
{
stringBuilder.Append(characterTemplate.ReadOnlyCharacterName);
stringBuilder.Append(TranslationServerUtils.Translate("de"));
}
stringBuilder.Append(TranslationServerUtils.Translate(pickAbleTemplate.Name));
label.Text = stringBuilder.ToString();
_floatLabel.Show();
}
UpdateOperationTip();
}
protected override void ExitThePickingRangeBody(Node node)
{
base.ExitThePickingRangeBody(node);
if (node is not Node2D)
{
return;
}
RecycleFloatLabel();
UpdateOperationTip();
}
/// <summary>
/// <para>Recycle Float Label</para>
/// <para>回收悬浮标签</para>
/// </summary>
private void RecycleFloatLabel()
{
if (_floatLabel == null)
{
return;
}
_floatLabel.Hide();
NodeUtils.CallDeferredReparent(this, _floatLabel);
}
protected override void OnHit(DamageTemplate damageTemplate)
{
base.OnHit(damageTemplate);
var healthBarUi = GameSceneNodeHolder.HealthBarUi;
var healthBarUi = GameSceneDepend.HealthBarUi;
if (healthBarUi != null)
{
healthBarUi.CurrentHp = CurrentHp;

View File

@ -14,31 +14,37 @@ public static class ContributorDataManager
private static readonly ContributorData[] ContributorArray =
[
new ContributorData
new()
{
Name = "Cold-Mint",
Url = "https://github.com/Cold-Mint",
ContributorTypes = [ContributorType.Coder],
},
new ContributorData
new()
{
Name = "霧雨烨",
Url = "https://github.com/Web13234",
ContributorTypes = [ContributorType.Coder]
},
new ContributorData
new()
{
Name = "[HYPERLINK BLOCKED]",
Url = "https://www.pixiv.net/users/74412798",
ContributorTypes = [ContributorType.Artist],
ToolTip = "贡献死灵法杖和背包的贴图。"
},
new ContributorData
new()
{
Name = "\u2605如爱生",
Url = "https://space.bilibili.com/425243934",
ContributorTypes = [ContributorType.Artist],
ToolTip = "贡献了一些枪械贴图。"
},
new()
{
Name = "Ride-A-Pig",
Url = "https://github.com/Ride-A-Pig",
ContributorTypes = [ContributorType.Coder],
}
];

View File

@ -27,7 +27,7 @@ public partial class DamageNumber : CharacterBody2D
private bool _enableGravity;
public void SetVelocity(Vector2 velocity)
public new void SetVelocity(Vector2 velocity)
{
Velocity = velocity;
_enableGravity = true;

View File

@ -46,7 +46,7 @@ public partial class DamageNumberNodeSpawn : Marker2D
public override void _Ready()
{
base._Ready();
_damageNumberPackedScene = GD.Load("res://prefab/ui/DamageNumber.tscn") as PackedScene;
_damageNumberPackedScene = ResourceLoader.Load("res://prefab/ui/DamageNumber.tscn") as PackedScene;
_rootNode = GetNode<Node2D>("/root/Game/DamageNumberContainer");
//The horizontal velocity is in the X positive direction
//水平速度的X正方向

View File

@ -0,0 +1,48 @@
using System;
using System.IO;
namespace ColdMint.scripts.database;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
/// <summary>
/// <para>Game database manager</para>
/// <para>游戏数据库管理器</para>
/// </summary>
public class DataBaseManager
{
private static ServiceProvider? _serviceProvider;
/// <summary>
/// <para>Initialize database</para>
/// <para>初始化数据库</para>
/// </summary>
public static void InitDataBases(string databasePath)
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddDbContext<GameDbContext>(options =>
options.UseSqlite($"Data Source={Path.Join(databasePath, Config.SolutionName + ".db")}"));
_serviceProvider = serviceCollection.BuildServiceProvider();
var dataPackDbContext = GetRequiredService<GameDbContext>();
dataPackDbContext.Database.EnsureCreated();
}
/// <summary>
/// <para>Get database service</para>
/// <para>获取数据库服务</para>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static T GetRequiredService<T>() where T : notnull
{
if (_serviceProvider == null)
{
throw new NullReferenceException("service provider is null");
}
var scope = _serviceProvider.CreateScope();
return scope.ServiceProvider.GetRequiredService<T>();
}
}

View File

@ -0,0 +1,42 @@
using ColdMint.scripts.database.gameDbTables;
using Microsoft.EntityFrameworkCore;
namespace ColdMint.scripts.database;
/// <summary>
/// <para>Game database</para>
/// <para>游戏数据库</para>
/// </summary>
public class GameDbContext(DbContextOptions<GameDbContext> options) : DbContext(options)
{
// ReSharper disable UnusedAutoPropertyAccessor.Global
public DbSet<ErrorRecord> ErrorRecords { get; set; }
// ReSharper restore UnusedAutoPropertyAccessor.Global
/// <summary>
/// <para>Async add error record</para>
/// <para>异步添加错误信息</para>
/// </summary>
/// <param name="errorRecord"></param>
public async void AddOrUpdateErrorRecordAsync(ErrorRecord errorRecord)
{
if (errorRecord.Message == null)
{
return;
}
var oldErrorRecord = await ErrorRecords.FindAsync(errorRecord.Message);
if (oldErrorRecord == null)
{
ErrorRecords.Add(errorRecord);
}
else
{
oldErrorRecord.Count++;
oldErrorRecord.LastDateTime = errorRecord.LastDateTime;
ErrorRecords.Update(oldErrorRecord);
}
await SaveChangesAsync();
}
}

View File

@ -0,0 +1,33 @@
using System;
using System.ComponentModel.DataAnnotations;
namespace ColdMint.scripts.database.gameDbTables;
/// <summary>
/// <para>Error record</para>
/// <para>错误记录</para>
/// </summary>
public class ErrorRecord
{
/// <summary>
/// <para>Message</para>
/// <para>错误消息</para>
/// </summary>
[Key]
[MaxLength(255)]
// ReSharper disable UnusedAutoPropertyAccessor.Global
public string? Message { get; set; }
// ReSharper restore UnusedAutoPropertyAccessor.Global
/// <summary>
/// <para>Count</para>
/// <para>出现次数</para>
/// </summary>
public int Count { get; set; } = 1;
/// <summary>
/// <para>DateTime</para>
/// <para>时间</para>
/// </summary>
public DateTime LastDateTime { get; set; } = DateTime.Now;
}

View File

@ -0,0 +1,20 @@
using System.Threading.Tasks;
using ColdMint.scripts.character;
using ColdMint.scripts.inventory;
using ColdMint.scripts.utils;
using Godot;
namespace ColdMint.scripts.deathInfo;
public class ResignationCertificateDeathInfoHandler: IDeathInfoHandler
{
public Task<string?> GenerateDeathInfo(string victimName, string killerName, Player victim, Node killer)
{
if (killer is ResignationCertificate)
{
return Task.FromResult(
TranslationServerUtils.TranslateWithFormat("death_info_resignation_certificate", victimName));
}
return Task.FromResult(Config.EmptyString);
}
}

View File

@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Text;
using ColdMint.scripts.openObserve;
using ColdMint.scripts.utils;
using Godot;
@ -16,6 +15,14 @@ public static class LogCat
/// <para>默认的日志标签</para>
/// </summary>
public const string Default = "Default";
public const string Debug = "Debug";
public const string PatchworkRoomPlacementStrategy = "PatchworkRoomPlacementStrategy";
/// <summary>
/// <para>ItemContainerDisplay</para>
/// <para>项目容器显示器</para>
/// </summary>
public const string ItemContainerDisplay = "ItemContainerDisplay";
/// <summary>
/// <para>LookForWeaponProcessor</para>
@ -64,11 +71,42 @@ public static class LogCat
/// <para>日志收集器</para>
/// </summary>
public const string LogCollector = "LogCollector";
/// <summary>
/// <para>Mod Loader</para>
/// <para>模组加载器</para>
/// </summary>
public const string ModLoader = "ModLoader";
/// <summary>
/// <para>PickAble Template</para>
/// <para>可拾取物模板</para>
/// </summary>
public const string PickAbleTemplate = "PickAbleTemplate";
/// <summary>
/// <para>ContactInjury</para>
/// <para>物品碰撞伤害</para>
/// </summary>
public const string ContactInjury = "ContactInjury";
/// <summary>
/// <para>Room</para>
/// <para>房间</para>
/// </summary>
public const string Room = "Room";
/// <summary>
/// <para>ItemSpawn</para>
/// <para>物品生成器</para>
/// </summary>
public const string ItemSpawn = "ItemSpawn";
/// <summary>
/// <para>MeleeWeapon</para>
/// <para>近战武器</para>
/// </summary>
public const string MeleeWeapon = "MeleeWeapon";
}
@ -112,11 +150,6 @@ public static class LogCat
set => _minLogLevel = value;
}
/// <summary>
/// <para>Whether to upload logs that need to be formatted by default</para>
/// <para>是否默认上传需要格式化的日志</para>
/// </summary>
public static bool UploadFormat { get; set; } = true;
private static readonly StringBuilder StringBuilder = new StringBuilder();
@ -218,14 +251,12 @@ public static class LogCat
/// </param>
/// <param name="label">
/// </param>
/// <param name="upload">
/// </param>
public static void Log(string message, string label = LogLabel.Default, bool upload = true)
public static void Log(string message, string label = LogLabel.Default)
{
PrintLog(InfoLogLevel, HandleMessage(InfoLogLevel, message, label).ToString(), label, upload);
PrintLog(InfoLogLevel, HandleMessage(InfoLogLevel, message, label).ToString(), label);
}
private static void PrintLog(int level, string concreteLog, string label, bool upload)
private static void PrintLog(int level, string concreteLog, string label)
{
if (!IsEnabledLogLabel(label))
{
@ -237,28 +268,16 @@ public static class LogCat
return;
}
if (LogCollector.CanUploadLog && upload)
{
var logData = new LogData
{
Level = level,
Message = concreteLog
};
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
LogCollector.Push(logData);
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
}
switch (level)
{
case WarningLogLevel:
GD.PrintRich("[color=#FFDE66]"+concreteLog+"[/color]");
GD.Print(concreteLog);
break;
case ErrorLogLevel:
GD.PrintRich("[color=#FF4E39]"+concreteLog+"[/color]");
GD.PrintErr(concreteLog);
break;
default:
GD.PrintRich("[color=#CCCED1]"+concreteLog+"[/color]");
GD.Print(concreteLog);
break;
}
}
@ -274,34 +293,30 @@ public static class LogCat
/// <para>这个消息支持本地化输出假设已存在翻译keyHello = 你好传入Hello则会输出你好。</para>
/// </param>
/// <param name="label"></param>
/// <param name="upload"></param>
public static void LogError(string message, string label = LogLabel.Default, bool upload = true)
public static void LogError(string message, string label = LogLabel.Default)
{
PrintLog(ErrorLogLevel, HandleMessage(ErrorLogLevel, message, label).ToString(), label, upload);
PrintLog(ErrorLogLevel, HandleMessage(ErrorLogLevel, message, label).ToString(), label);
}
public static void LogWarning(string message, string label = LogLabel.Default, bool upload = true)
public static void LogWarning(string message, string label = LogLabel.Default)
{
PrintLog(WarningLogLevel, HandleMessage(WarningLogLevel, message, label).ToString(), label, upload);
PrintLog(WarningLogLevel, HandleMessage(WarningLogLevel, message, label).ToString(), label);
}
public static void LogErrorWithFormat(string message, string label, bool upload, params object?[] args)
public static void LogErrorWithFormat(string message, string label, params object?[] args)
{
PrintLog(ErrorLogLevel, string.Format(HandleMessage(ErrorLogLevel, message, label).ToString(), args), label,
upload);
PrintLog(ErrorLogLevel, string.Format(HandleMessage(ErrorLogLevel, message, label).ToString(), args), label);
}
public static void LogWithFormat(string message, string label, bool upload, params object?[] args)
public static void LogWithFormat(string message, string label, params object?[] args)
{
PrintLog(InfoLogLevel, string.Format(HandleMessage(InfoLogLevel, message, label).ToString(), args), label,
upload);
PrintLog(InfoLogLevel, string.Format(HandleMessage(InfoLogLevel, message, label).ToString(), args), label);
}
public static void LogWarningWithFormat(string message, string label, bool upload, params object?[] args)
public static void LogWarningWithFormat(string message, string label, params object?[] args)
{
PrintLog(WarningLogLevel, string.Format(HandleMessage(WarningLogLevel, message, label).ToString(), args), label,
upload);
PrintLog(WarningLogLevel, string.Format(HandleMessage(WarningLogLevel, message, label).ToString(), args), label);
}
/// <summary>
@ -320,6 +335,6 @@ public static class LogCat
//Log an exception here or send it to the server.
//请在这里记录异常或将异常发送至服务器。
PrintLog(ErrorLogLevel,
HandleMessage(ErrorLogLevel, e.Message, label).Append('\n').Append(e.StackTrace).ToString(), label, true);
HandleMessage(ErrorLogLevel, e.Message, label).Append('\n').Append(e.StackTrace).ToString(), label);
}
}

View File

@ -0,0 +1,18 @@
namespace ColdMint.scripts.furniture;
/// <summary>
/// <para>Barrier</para>
/// <para>屏障型家具</para>
/// </summary>
public partial class Barrier : Furniture
{
public override void _Ready()
{
base._Ready();
CanSleep = false;
SetCollisionLayerValue(Config.LayerNumber.Barrier, true);
SetCollisionLayerValue(Config.LayerNumber.Furniture, false);
SetCollisionMaskValue(Config.LayerNumber.Furniture, true);
SetCollisionMaskValue(Config.LayerNumber.Barrier, true);
}
}

View File

@ -0,0 +1,108 @@
using ColdMint.scripts.damage;
using ColdMint.scripts.utils;
using Godot;
namespace ColdMint.scripts.furniture;
/// <summary>
/// <para>FurnitureTemplate</para>
/// <para>家具模板</para>
/// </summary>
public partial class Furniture : RigidBody2D
{
[Export] private int _initialDurability;
[Export] private int _maxDurability;
[Export]
private string? _furnitureName;
private Label? _tipLabel;
public override void _MouseEnter()
{
if (_tipLabel == null || string.IsNullOrEmpty(_furnitureName))
{
return;
}
var translation = TranslationServerUtils.Translate(_furnitureName);
if (string.IsNullOrEmpty(translation))
{
return;
}
_tipLabel.Visible = true;
_tipLabel.Text = translation;
//Vertical Centering Tip
//垂直居中提示
var oldPosition = _tipLabel.Position;
oldPosition.X = -_tipLabel.Size.X / 2;
_tipLabel.Rotation = -Rotation;
_tipLabel.Position = oldPosition;
}
public override void _MouseExit()
{
if (_tipLabel == null)
{
return;
}
_tipLabel.Visible = false;
}
/// <summary>
/// <para></para>
/// <para>家具的耐久度</para>
/// </summary>
private int _durability;
public override void _Ready()
{
if (_maxDurability <= 0)
{
_maxDurability = Config.DefaultMaxDurability;
}
if (_initialDurability <= 0 || _initialDurability > _maxDurability)
{
_initialDurability = _maxDurability;
}
_tipLabel = GetNodeOrNull<Label>("TipLabel");
InputPickable = true;
_durability = _initialDurability;
SetCollisionLayerValue(Config.LayerNumber.Furniture, true);
SetCollisionMaskValue(Config.LayerNumber.Wall, true);
SetCollisionMaskValue(Config.LayerNumber.Platform, true);
SetCollisionMaskValue(Config.LayerNumber.Floor, true);
}
public override void _PhysicsProcess(double delta)
{
if (Input.IsActionJustReleased("push"))
{
SetCollisionMaskValue(Config.LayerNumber.Player, false);
}
if (Input.IsActionJustPressed("push"))
{
SetCollisionMaskValue(Config.LayerNumber.Player, true);
}
}
/// <summary>
/// <para>This method is called when furniture is damaged</para>
/// <para>当家具损害时调用此方法</para>
/// </summary>
/// <param name="damageTemplate"></param>
/// <returns>
///<para>Return whether the damage completely destroyed the furniture</para>
///<para>返回本次伤害是否彻底破坏了家具</para>
/// </returns>
public bool Damage(DamageTemplate damageTemplate)
{
_durability -= damageTemplate.Damage;
if (_durability <= 0)
{
QueueFree();
}
return true;
}
}

View File

@ -0,0 +1,124 @@
using ColdMint.scripts.character;
using ColdMint.scripts.loader.uiLoader;
using ColdMint.scripts.utils;
using Godot;
namespace ColdMint.scripts.furniture;
/// <summary>
/// <para>GUIFurnitureTemplate</para>
/// <para>带有图形用户页面的家居模板</para>
/// </summary>
public partial class GuiFurniture : Furniture
{
/// <summary>
/// <para>Operating range of furniture</para>
/// <para>家具的操作范围</para>
/// </summary>
/// <remarks>
///<para>For furniture with graphical user pages, the player must enter the action range and press the shortcut key to display the UI page.</para>
///<para>对于带有图形用户页面的家具来说玩家必须进入操作范围内按下快捷键才能显示UI页面。</para>
/// </remarks>
private Area2D? _operateArea2D;
/// <summary>
/// <para>Whether the player is within range of the operation</para>
/// <para>玩家是否在操作范围内</para>
/// </summary>
private bool _playerInRange;
[Export]
public string? Path;
/// <summary>
/// <para>There's a mouse hover</para>
/// <para>有鼠标悬停</para>
/// </summary>
private bool _hasMouseOver;
public override void _Ready()
{
base._Ready();
_operateArea2D = GetNode<Area2D>("OperateArea2D");
_operateArea2D.BodyEntered += OnBodyEntered;
_operateArea2D.BodyExited += OnBodyExited;
_operateArea2D.SetCollisionMaskValue(Config.LayerNumber.Player, true);
if (Path != null)
{
GameSceneDepend.DynamicUiGroup?.RegisterControl(Path, () =>
{
var packedScene = ResourceLoader.Load<PackedScene>(Path);
return NodeUtils.InstantiatePackedScene<SpellEditorUi>(packedScene);
});
}
}
/// <summary>
/// <para>Use furniture</para>
/// <para>使用家具</para>
/// </summary>
/// <param name="player"></param>
private void Use(Player player)
{
if (Path == null)
{
return;
}
GameSceneDepend.DynamicUiGroup?.ShowControl(Path);
}
public override void _MouseEnter()
{
base._MouseEnter();
_hasMouseOver = true;
GameSceneDepend.IsMouseOverFurnitureGui = true;
}
public override void _MouseExit()
{
base._MouseExit();
_hasMouseOver = false;
GameSceneDepend.IsMouseOverFurnitureGui = false;
}
private void OnBodyEntered(Node node)
{
if (node is Player)
{
_playerInRange = true;
}
}
public override void _PhysicsProcess(double delta)
{
base._PhysicsProcess(delta);
if (GameSceneDepend.Player == null || !_playerInRange || !_hasMouseOver)
{
return;
}
if (Input.IsActionJustPressed("use_item"))
{
Use(GameSceneDepend.Player);
}
}
private void OnBodyExited(Node2D node2D)
{
if (node2D is Player)
{
_playerInRange = false;
if (Path != null)
{
GameSceneDepend.DynamicUiGroup?.HideControl(Path);
}
}
}
public override void _ExitTree()
{
if (_operateArea2D != null)
{
_operateArea2D.BodyEntered -= OnBodyEntered;
_operateArea2D.BodyExited -= OnBodyExited;
}
}
}

View File

@ -10,22 +10,18 @@ namespace ColdMint.scripts.inventory;
public partial class HotBar : HBoxContainer
{
private IItemContainer? _itemContainer;
private IItemContainerDisplay? _itemContainerDisplay;
public override void _Ready()
{
base._Ready();
_itemContainer = new UniversalItemContainer();
var universalItemContainer = new UniversalItemContainer(Config.HotBarSize);
_itemContainer = universalItemContainer;
universalItemContainer.AllowItemTypesExceptPlaceholder();
_itemContainer.SupportSelect = true;
_itemContainerDisplay = new ItemSlotContainerDisplay(this);
_itemContainerDisplay.BindItemContainer(_itemContainer);
NodeUtils.DeleteAllChild(this);
for (var i = 0; i < Config.HotBarSize; i++)
{
var itemSlotNode = _itemContainer.AddItemSlot(this);
if (itemSlotNode != null)
{
itemSlotNode.BackpackAllowed = true;
}
}
}
@ -36,14 +32,14 @@ public partial class HotBar : HBoxContainer
{
//Mouse wheel down
//鼠标滚轮向下
_itemContainer?.SelectTheNextItemSlot();
_itemContainer?.SelectNextItem();
}
if (Input.IsActionJustPressed("hotbar_previous"))
{
//Mouse wheel up
//鼠标滚轮向上
_itemContainer?.SelectThePreviousItemSlot();
_itemContainer?.SelectPreviousItem();
}
if (Input.IsActionJustPressed("hotbar_1"))
@ -106,7 +102,7 @@ public partial class HotBar : HBoxContainer
return;
}
_itemContainer.SelectItemSlot(shortcutKeyIndex);
_itemContainer.SelectItem(shortcutKeyIndex);
}
public IItemContainer? GetItemContainer()

View File

@ -5,10 +5,33 @@ namespace ColdMint.scripts.inventory;
public interface IItem
{
/// <summary>
/// <para>ID of current item</para>
/// <para>当前项目的ID</para>
/// <para>The position of the item in the container</para>
/// <para>物品在容器内的位置</para>
/// </summary>
string Id { get; }
public int Index { get; set; }
/// <summary>
/// <para>ID of current item</para>
/// <para>当前物品的ID</para>
/// </summary>
string Id { get; set; }
/// <summary>
/// <para>ShowSelf</para>
/// <para>显示自身</para>
/// </summary>
void ShowSelf();
/// <summary>
/// <para>QueueFreeSelf</para>
/// <para>销毁自身</para>
/// </summary>
void QueueFreeSelf();
/// <summary>
/// <para>HideSelf</para>
/// <para>隐藏自身</para>
/// </summary>
void HideSelf();
/// <summary>
/// <para>Icon of current item</para>
@ -40,11 +63,79 @@ public interface IItem
/// </summary>
int MaxQuantity { get; }
/// <summary>
/// <para>ItemType</para>
/// <para>获取物品类型</para>
/// </summary>
int ItemType { get; }
/// <summary>
/// <para>Check or not</para>
/// <para>是否选中</para>
/// </summary>
bool IsSelect { get; set; }
/// <summary>
/// <para>The container in which the item is located</para>
/// <para>物品所在的物品容器</para>
/// </summary>
IItemContainer? ItemContainer { get; set; }
/// <summary>
/// <para>Its own container of items</para>
/// <para>自身的物品容器</para>
/// </summary>
/// <remarks>
/// <para>Returns a non-null value if the item itself can hold other items</para>
/// <para>物品本身可容纳其他物品,则返回非空值</para>
/// </remarks>
public IItemContainer? SelfItemContainer { get; set; }
/// <summary>
/// <para>Calculate how many items can be merged with other items</para>
/// <para>计算当前物品可与其他物品合并多少个</para>
/// </summary>
/// <param name="other"></param>
/// <param name="unallocatedQuantity">
///<para>The amount yet to be allocated(This method doesn't actually change the number of iitems, so you need to allocate an int variable to keep track of how many items remain unallocated.)</para>
///<para>尚未分配的数量在此方法并不会实际改变IItem的数量故您需要分配一个int型变量记录还有多少个物品尚未分配</para>
/// </param>
/// <returns>
///<para>Number of mergable numbers. 0 indicates that the number cannot be merged. Greater than 0 indicates that the number can be merged.</para>
///<para>可合并的数量0为不能合并大于0可合并。</para>
/// </returns>
int MergeableItemCount(IItem other, int unallocatedQuantity);
/// <summary>
/// <para>Create a new item instance</para>
/// <para>创建新的物品实例</para>
/// </summary>
/// <param name="number">
///<para>Quantity (pass in a value less than 0 to create an instance using all the quantities of built-in items)</para>
///<para>数量传入小于0的值使用内置物品的所有数量创建实例</para>
/// </param>
/// <returns>
///<para>Newly created item</para>
///<para>新创建的物品</para>
/// </returns>
IItem? CreateItem(int number);
/// <summary>
/// <para>Execute when current item is used <br/> e.g. when player clicks left mouse button with current item in hand</para>
/// <para>当前项被使用时执行 <br/> e.g. 当玩家用鼠标左键点击当前物品时</para>
/// </summary>
/// <param name="owner">Owner of current item, if any</param>
/// <param name="targetGlobalPosition">Target position, such as the position of the cursor when used by the player</param>
void Use(Node2D? owner, Vector2 targetGlobalPosition);
/// <returns>
///<para>Whether it was successfully executed</para>
///<para>是否成功被执行了</para>
/// </returns>
bool Use(Node2D? owner, Vector2 targetGlobalPosition);
/// <summary>
/// <para>When the item is thrown</para>
/// <para>当物品被抛出时</para>
/// </summary>
/// <param name="velocity"></param>
void OnThrow(Vector2 velocity);
}

View File

@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using ColdMint.scripts.map.events;
using Godot;
namespace ColdMint.scripts.inventory;
@ -9,17 +7,33 @@ namespace ColdMint.scripts.inventory;
/// <para>item container</para>
/// <para>物品容器</para>
/// </summary>
/// <remarks>
///<para>Item containers can store items. Things like backpacks and Hotbars are containers with visual pages.</para>
///<para>物品容器可以储存物品。像背包和hotbar是具有可视化页面的容器。</para>
/// </remarks>
public interface IItemContainer : IEnumerable<ItemSlotNode>
public interface IItemContainer
{
/// <summary>
/// <para>This event is triggered when the selected item slot changes</para>
/// <para>当选中的物品改变时,触发此事件</para>
/// <para>This event is triggered when the selected item changes</para>
/// <para>当选中的物品改变时,触发此事件</para>
/// </summary>
Action<SelectedItemSlotChangeEvent>? SelectedItemSlotChangeEvent { get; set; }
Action<SelectedItemChangeEvent>? SelectedItemChangeEvent { get; set; }
/// <summary>
/// <para>This event is triggered when the item's data changes, such as the number increases, decreases, or new items are added to the container</para>
/// <para>当物品的数据发生改变时,例如数量增加,减少,或者新物品被添加到容器内触发此事件</para>
/// </summary>
Action<ItemDataChangeEvent>? ItemDataChangeEvent { get; set; }
/// <summary>
/// <para>Allow Adding Item By Type</para>
/// <para>允许添加指定类型的物品</para>
/// </summary>
/// <param name="itemType"></param>
void AllowAddingItemByType(int itemType);
/// <summary>
/// <para>Disallow Adding Item By Type</para>
/// <para>禁止添加指定类型的物品</para>
/// </summary>
/// <param name="itemType"></param>
void DisallowAddingItemByType(int itemType);
/// <summary>
/// <para>Can the specified item be added to the container?</para>
@ -34,15 +48,28 @@ public interface IItemContainer : IEnumerable<ItemSlotNode>
/// <para>实现添加物品的方法</para>
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
bool AddItem(IItem item);
/// <returns>
///<para>How many items were successfully added. The addition failed, and 0 was returned.</para>
///<para>有多少个物品被成功添加了。添加失败返回0</para>
/// </returns>
int AddItem(IItem item);
/// <summary>
/// <para>Whether this item container supports checking</para>
/// <para>此物品容器是否支持选中</para>
/// </summary>
public bool SupportSelect { get; set; }
bool SupportSelect { get; set; }
/// <summary>
/// <para>Gets a placeholder object</para>
/// <para>获取占位符对象</para>
/// </summary>
/// <param name="index">
///<para>index</para>
///<para>占位符代替的索引</para>
/// </param>
/// <returns></returns>
IItem GetPlaceHolderItem(int index);
/// <summary>
/// <para>Gets the selected location</para>
@ -52,104 +79,127 @@ public interface IItemContainer : IEnumerable<ItemSlotNode>
int GetSelectIndex();
/// <summary>
/// <para>Gets the currently selected node</para>
/// <para>获取当前选中的节点</para>
/// <para>Gets the currently selected item</para>
/// <para>获取当前选中的物品</para>
/// </summary>
/// <returns></returns>
ItemSlotNode? GetSelectItemSlotNode();
IItem? GetSelectItem();
/// <summary>
/// <para>Removes an item from the inventory at the currently selected location</para>
/// <para>移除当前选中位置物品栏内的物品</para>
/// </summary>
/// <param name="number">
/// <para>Quantity to be removed, inputs below zero represent all items</para>
/// <para>要删除的数量小于0的输入代表全部物品</para>
/// </param>
/// <returns>
/// <para>The remaining number, if the number of items in the current item stack is less than the specified number. Otherwise,0</para>
/// <para>若物品槽内物品少于指定的数量返回相差的数量。否则返回0</para>
/// </returns>
int RemoveItemFromItemSlotBySelectIndex(int number);
/// <summary>
/// <para>Gets the number of item slots</para>
/// <para>获取物品槽的数量</para>
/// </summary>
/// <returns></returns>
int GetItemSlotCount();
/// <summary>
/// <para>Gets the item slot for the specified location</para>
/// <para>获取指定位置的物品槽</para>
/// <para>Gets the item in the specified location</para>
/// <para>获取指定位置的物品</para>
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
ItemSlotNode? GetItemSlotNode(int index);
IItem? GetItem(int index);
/// <summary>
/// <para>Gets the item slot for the specified location, equals to <see cref="GetItemSlotNode"/></para>
/// <para>获取指定位置的物品槽,等同于<see cref="GetItemSlotNode"/></para>
/// <para>ReplaceItem</para>
/// <para>替换物品</para>
/// </summary>
/// <remarks>
///<para>Even if the item corresponding to the index is null, it can be successfully replaced.</para>
///<para>即使索引对应的物品为null也可以成功的替换。</para>
/// </remarks>
/// <param name="index"></param>
/// <returns></returns>
ItemSlotNode? this[int index] => GetItemSlotNode(index);
/// <summary>
/// <para>Removes an item from the item slot in the specified location</para>
/// <para>在指定位置的物品槽内移除物品</para>
/// </summary>
/// <param name="itemSlotIndex"></param>
/// <param name="number">
/// <para>Quantity to be removed, inputs below zero represent all items</para>
/// <para>要删除的数量小于0的输入代表全部物品</para>
/// </param>
/// <returns>
/// <para>The remaining number, if the number of items in the current item stack is less than the specified number. Otherwise,0</para>
/// <para>若物品槽内物品少于指定的数量返回相差的数量。否则返回0</para>
/// </returns>
int RemoveItemFromItemSlot(int itemSlotIndex, int number);
/// <summary>
/// <para>Based on the given item, match the item slots where it can be added to </para>
/// <para>根据给定的物品,匹配可放置它的物品槽</para>
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
bool ReplaceItem(int index, IItem item);
/// <summary>
/// <para>Whether items are replaceable</para>
/// <para>是否可替换物品</para>
/// </summary>
/// <param name="index"></param>
/// <param name="item"></param>
/// <returns></returns>
bool CanReplaceItem(int index, IItem item);
/// <summary>
/// <para>ClearItem</para>
/// <para>清理物品</para>
/// </summary>
/// <param name="index"></param>
/// <returns>
/// <para>Return null if there is no slot to place the item in</para>
/// <para>若没有槽可放置此物品则返回null</para>
///<para>Returns the item to be cleaned, or null if the item to be cleaned cannot be found</para>
///<para>返回要清理的物品如果找不到要清理的物品则返回null</para>
/// </returns>
ItemSlotNode? Match(IItem item);
IItem? ClearItem(int index);
/// <summary>
/// <para>ClearAllItems</para>
/// <para>清理全部物品</para>
/// </summary>
void ClearAllItems();
/// <summary>
/// <para>Gets the item in the specified location, equivalent to <see cref="GetItem"/></para>
/// <para>获取指定位置的物品,等同于<see cref="GetItem"/></para>
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
IItem? this[int index] => GetItem(index);
/// <summary>
/// <para>AddItemSlot</para>
/// <para>添加物品槽</para>
/// <para>Removes the item from the currently selected location</para>
/// <para>移除当前选中位置的物品</para>
/// </summary>
/// <param name="rootNode"></param>
ItemSlotNode? AddItemSlot(Node rootNode);
/// <param name="number">
/// <para>Quantity to be removed, inputs below zero represent all items</para>
/// <para>要删除的数量小于0的输入代表全部物品</para>
/// </param>
/// <returns>
///<para>How many items were actually removed</para>
///<para>实际移除了多少个物品</para>
/// </returns>
int RemoveSelectItem(int number);
/// <summary>
/// <para>SelectTheNextItemSlot</para>
/// <para>选择下一个物品槽</para>
/// <para>Deduct the number of items in the specified location</para>
/// <para>扣除指定位置的物品数量</para>
/// </summary>
void SelectTheNextItemSlot();
/// <param name="itemIndex"></param>
/// <param name="number">
/// <para>Quantity to be removed, inputs below zero represent all items</para>
/// <para>要删除的数量小于0的输入代表全部物品</para>
/// </param>
/// <returns>
///<para>How many items were actually removed</para>
///<para>实际移除了多少个物品</para>
/// </returns>
int RemoveItem(int itemIndex, int number);
/// <summary>
/// <para>SelectThePreviousItemSlot</para>
/// <para>选择上一个物品槽</para>
/// <para>Gets the used capacity of the item container</para>
/// <para>获取物品容器已使用的容量</para>
/// </summary>
void SelectThePreviousItemSlot();
/// <returns></returns>
int GetUsedCapacity();
/// <summary>
/// <para>选择物品槽</para>
/// <para>SelectItemSlot</para>
/// <para>Gets the total capacity of the item container</para>
/// <para>获取物品容器的总容量</para>
/// </summary>
/// <param name="newSelectIndex"></param>
void SelectItemSlot(int newSelectIndex);
/// <returns></returns>
int GetTotalCapacity();
/// <summary>
/// <para>Select the next item</para>
/// <para>选择下一个物品</para>
/// </summary>
void SelectNextItem();
/// <summary>
/// <para>Select the previous item</para>
/// <para>选择上一个物品</para>
/// </summary>
void SelectPreviousItem();
/// <summary>
/// <para>选择物品</para>
/// <para>Select item</para>
/// </summary>
/// <param name="index"></param>
void SelectItem(int index);
}

View File

@ -0,0 +1,13 @@
using System.Collections.Generic;
namespace ColdMint.scripts.inventory;
public interface IItemContainerDisplay : IEnumerable<IItemDisplay>
{
/// <summary>
/// <para>Bind an item container to the item container display</para>
/// <para>为物品容器显示器绑定物品容器</para>
/// </summary>
/// <param name="itemContainer"></param>
void BindItemContainer(IItemContainer? itemContainer);
}

View File

@ -0,0 +1,40 @@
namespace ColdMint.scripts.inventory;
/// <summary>
/// <para>IItemDisplay</para>
/// <para>物品显示器</para>
/// </summary>
public interface IItemDisplay
{
/// <summary>
/// <para>Call this method to refresh the display when the item's information changes</para>
/// <para>物品的信息发生变更时,调用此方法刷新显示器</para>
/// </summary>
/// <remarks>
///<param name="item">
///<para>New data for items after changes</para>
///<para>发生改变后的物品新数据</para>
/// </param>
/// </remarks>
void Update(IItem? item);
/// <summary>
/// <para>Gets the item that is being displayed</para>
/// <para>获取正在显示的物品</para>
/// </summary>
IItem? Item { get; }
/// <summary>
/// <para>Show item Display</para>
/// <para>显示物品显示器</para>
/// </summary>
void ShowSelf();
/// <summary>
/// <para>Hide item Display</para>
/// <para>隐藏物品显示器</para>
/// </summary>
void HideSelf();
}

View File

@ -0,0 +1,165 @@
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using ColdMint.scripts.debug;
using ColdMint.scripts.map.events;
namespace ColdMint.scripts.inventory;
public abstract class ItemContainerDisplayTemplate : IItemContainerDisplay
{
protected readonly List<IItemDisplay> ItemDisplayList = [];
private IItemContainer? _itemContainer;
public async void BindItemContainer(IItemContainer? itemContainer)
{
if (_itemContainer == itemContainer)
{
return;
}
if (_itemContainer != null)
{
_itemContainer.SelectedItemChangeEvent -= OnSelectedItemChangeEvent;
_itemContainer.ItemDataChangeEvent -= OnItemDataChangeEvent;
}
_itemContainer = itemContainer;
if (itemContainer == null)
{
//Set empty items container to hide all ui.
//设置空物品容器隐藏全部ui。
for (var i = 0; i < ItemDisplayList.Count; i++)
{
var itemDisplay = ItemDisplayList[i];
LogCat.LogWithFormat("hide_display_item", LogCat.LogLabel.ItemContainerDisplay, i);
itemDisplay.Update(null);
itemDisplay.HideSelf();
}
return;
}
itemContainer.SelectedItemChangeEvent += OnSelectedItemChangeEvent;
itemContainer.ItemDataChangeEvent += OnItemDataChangeEvent;
var totalCapacity = itemContainer.GetTotalCapacity();
var currentCapacity = ItemDisplayList.Count;
var capacityDifference = totalCapacity - currentCapacity;
if (capacityDifference > 0)
{
//There are those that need to be added, and we create them.
//有需要添加的,我们创建他们。
for (var i = 0; i < capacityDifference; i++)
{
LogCat.LogWithFormat("add_display_item", LogCat.LogLabel.ItemContainerDisplay, i);
AddItemDisplay();
}
}
else if (capacityDifference < 0)
{
//There are things that need to be hidden
//有需要被隐藏的
for (var i = currentCapacity - 1; i >= totalCapacity; i--)
{
LogCat.LogWithFormat("hide_display_item", LogCat.LogLabel.ItemContainerDisplay, i);
var itemDisplay = ItemDisplayList[i];
itemDisplay.Update(null);
itemDisplay.HideSelf();
}
}
await Task.Yield();
UpdateData(itemContainer, totalCapacity);
}
private void OnItemDataChangeEvent(ItemDataChangeEvent itemDataChangeEvent)
{
if (_itemContainer == null)
{
return;
}
UpdateDataForSingleLocation(_itemContainer, itemDataChangeEvent.NewIndex);
}
private void OnSelectedItemChangeEvent(SelectedItemChangeEvent selectedItemChangeEvent)
{
if (_itemContainer == null)
{
return;
}
UpdateDataForSingleLocation(_itemContainer, selectedItemChangeEvent.OldIndex);
UpdateDataForSingleLocation(_itemContainer, selectedItemChangeEvent.NewIndex);
}
/// <summary>
/// <para>Update data</para>
/// <para>更新数据</para>
/// </summary>
/// <remarks>
///<para>Used to batch update the Item data in itemContainer to the display.</para>
///<para>用于将itemContainer内的Item数据批量更新到显示器内。</para>
/// </remarks>
/// <param name="itemContainer">
///<para>Item container data</para>
///<para>物品容器数据</para>
/// </param>
/// <param name="endIndex">
///<para>endIndex</para>
///<para>结束位置</para>
/// </param>
/// <param name="startIndex">
///<para>startIndex</para>
///<para>起始位置</para>
/// </param>
private void UpdateData(IItemContainer itemContainer, int endIndex, int startIndex = 0)
{
LogCat.LogWithFormat("batch_update_data", LogCat.LogLabel.ItemContainerDisplay, startIndex, endIndex);
for (var i = startIndex; i < endIndex; i++)
{
UpdateDataForSingleLocation(itemContainer, i);
}
}
/// <summary>
/// <para>Update data for a single location</para>
/// <para>更新单个位置的数据</para>
/// </summary>
/// <param name="itemContainer"></param>
/// <param name="index"></param>
private void UpdateDataForSingleLocation(IItemContainer itemContainer, int index)
{
LogCat.LogWithFormat("update_display_item", LogCat.LogLabel.ItemContainerDisplay, index);
var itemDisplay = ItemDisplayList[index];
var item = itemContainer.GetItem(index);
if (item == null)
{
item = itemContainer.GetPlaceHolderItem(index);
}
if (itemContainer.SupportSelect)
{
item.IsSelect = index == itemContainer.GetSelectIndex();
}
else
{
item.IsSelect = false;
}
itemDisplay.Update(item);
itemDisplay.ShowSelf();
}
/// <summary>
/// <para>Add item display</para>
/// <para>添加物品显示器</para>
/// </summary>
protected abstract void AddItemDisplay();
public IEnumerator<IItemDisplay> GetEnumerator()
{
return ItemDisplayList.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}

View File

@ -0,0 +1,26 @@
using ColdMint.scripts.utils;
using Godot;
namespace ColdMint.scripts.inventory;
public class ItemSlotContainerDisplay(Node rootNode) : ItemContainerDisplayTemplate
{
private readonly PackedScene? _packedScene = ResourceLoader.Load<PackedScene>("res://prefab/ui/ItemSlot.tscn");
protected override void AddItemDisplay()
{
if (_packedScene == null)
{
return;
}
var itemSlotNode = NodeUtils.InstantiatePackedScene<ItemSlotNode>(_packedScene);
if (itemSlotNode == null)
{
return;
}
ItemDisplayList.Add(itemSlotNode);
NodeUtils.CallDeferredAddChild(rootNode, itemSlotNode);
}
}

View File

@ -1,5 +1,3 @@
using System;
using ColdMint.scripts.debug;
using ColdMint.scripts.utils;
using Godot;
@ -9,281 +7,198 @@ namespace ColdMint.scripts.inventory;
/// <para>A slot in the inventory</para>
/// <para>物品栏内的一个插槽</para>
/// </summary>
public partial class ItemSlotNode : MarginContainer
public partial class ItemSlotNode : MarginContainer, IItemDisplay
{
private TextureRect? _backgroundTextureRect;
private TextureRect? _iconTextureRect;
private Label? _quantityLabel;
private Control? _control;
private bool _isSelect;
private Texture2D? _backgroundTexture;
private Texture2D? _backgroundTextureWhenSelect;
private IItem? _item;
public IItem? Item { get; private set; }
public IItem? Item
{
set
{
//Set item
//设置物品
_item = value;
UpdateAllDisplay();
}
}
public override void _Ready()
{
_backgroundTexture = GD.Load<Texture2D>("res://sprites/ui/ItemBarEmpty.png");
_backgroundTextureWhenSelect = GD.Load<Texture2D>("res://sprites/ui/ItemBarFocus.png");
_backgroundTexture = ResourceLoader.Load<Texture2D>("res://sprites/ui/ItemBarEmpty.png");
_backgroundTextureWhenSelect = ResourceLoader.Load<Texture2D>("res://sprites/ui/ItemBarFocus.png");
_backgroundTextureRect =
GetNode<TextureRect>("BackgroundTexture");
_iconTextureRect = GetNode<TextureRect>("BackgroundTexture/IconTextureRect");
_quantityLabel = GetNode<Label>("Control/QuantityLabel");
_control = GetNode<Control>("Control");
_quantityLabel.Hide();
UpdateBackground(_isSelect);
}
public override void _EnterTree()
{
MouseEntered += OnMouseEntered;
MouseExited += OnMouseExited;
}
public override void _ExitTree()
{
MouseEntered -= OnMouseEntered;
MouseExited -= OnMouseExited;
}
private void OnMouseExited()
{
GameSceneDepend.IsMouseOverItemSlotNode = false;
}
private void OnMouseEntered()
{
GameSceneDepend.IsMouseOverItemSlotNode = true;
}
public override Variant _GetDragData(Vector2 atPosition)
{
if (_isSelect || _iconTextureRect == null)
switch (Item)
{
//Drag is not allowed if there is no icon or no pile of items.
//如果没有图标或者没有物品堆,那么不允许拖动。
return new Variant();
case null:
return Config.EmptyVariant;
case PlaceholderItem:
return Config.EmptyVariant;
}
if (_iconTextureRect == null)
{
return Config.EmptyVariant;
}
var textureRect = new TextureRect();
textureRect.ExpandMode = _iconTextureRect.ExpandMode;
textureRect.Size = _iconTextureRect.Size;
textureRect.Texture = _iconTextureRect.Texture;
textureRect.ZIndex = Config.ZIndexManager.FloatingIcon;
SetDragPreview(textureRect);
return Variant.CreateFrom(this);
}
public override bool _CanDropData(Vector2 atPosition, Variant data)
{
if (_isSelect)
{
//Do not place items in the selected item slot, even if the item slot is empty.
//禁止在已选中的物品槽内放置物品,即使物品槽是空的。
LogCat.Log("item_slot_is_selected_and_not_allowed");
return false;
}
//If the preplaced slot does not have an icon, the preplaced slot is not allowed.
//如果预放置的槽位没有图标,那么不允许放置。
if (_iconTextureRect == null)
{
return false;
}
var type = data.VariantType;
if (type == Variant.Type.Nil)
{
//The preplaced data is null.
//预放置的数据为null。
return false;
}
var itemSlotNode = data.As<ItemSlotNode>();
var item = itemSlotNode.GetItem();
if (item == null)
var sourceItem = itemSlotNode.Item;
if (sourceItem == null)
{
//Return null when trying to get the source item.
//尝试获取源物品时返回null。
return false;
}
if (item is Packsack packsack)
switch (Item)
{
if (_item == null)
{
//If the dragged item is a backpack and there are no items in the current slot, return whether the backpack is allowed.
//如果拖拽的物品是背包,且当前槽位没有物品,那么返回是否允许放置背包。
return BackpackAllowed;
}
if (packsack.ItemContainer == null)
{
LogCat.Log("item_container_is_null");
return false;
}
return packsack.ItemContainer.CanAddItem(_item);
case null:
return true;
case PlaceholderItem placeholderItem:
var placeholderItemContainer = placeholderItem.ItemContainer;
if (placeholderItemContainer == null)
{
return true;
}
return placeholderItemContainer.CanReplaceItem(placeholderItem.Index, sourceItem);
default:
var sourceItemSelfContainer = sourceItem.SelfItemContainer;
if (sourceItemSelfContainer != null)
{
//Place the container on the item.
//将容器放在物品上。
return sourceItemSelfContainer.CanAddItem(Item);
}
var itemSelfContainer = Item.SelfItemContainer;
if (itemSelfContainer != null)
{
//Drag the item onto the container.
//将物品拖到容器上。
return itemSelfContainer.CanAddItem(sourceItem);
}
return Item.MergeableItemCount(sourceItem, sourceItem.Quantity) > 0;
}
if (_item is Packsack currentPacksack)
{
if (currentPacksack.ItemContainer == null)
{
LogCat.Log("item_container_is_null");
return false;
}
return currentPacksack.ItemContainer.CanAddItem(item);
}
return CanAddItem(item);
}
/// <summary>
/// <para>Get the items in the item container</para>
/// <para>获取物品容器内的物品</para>
/// </summary>
/// <returns>
///<para>There may be multiple quantities</para>
///<para>数量可能有多个</para>
/// </returns>
public IItem? GetItem()
{
return _item;
}
/// <summary>
/// <para>CreateItemInstance</para>
/// <para>创建物品槽内的物品实例</para>
/// </summary>
/// <param name="number">
///<para>Quantity (pass in a value less than 0 to create an instance using all the quantities of built-in items)</para>
///<para>数量传入小于0的值使用内置物品的所有数量创建实例</para>
/// </param>
/// <returns>
///<para>Newly created item</para>
///<para>新创建的物品</para>
/// </returns>
public IItem? CreateItemInstance(int number)
{
if (number == 0)
{
return null;
}
if (_item is not Node2D node2D)
{
return null;
}
var duplicate = node2D.Duplicate();
if (duplicate is not Node2D newNode2D)
{
return null;
}
newNode2D.GlobalPosition = node2D.GlobalPosition;
if (duplicate is not IItem newItem)
{
return null;
}
if (number < 0)
{
newItem.Quantity = _item.Quantity;
}
else
{
newItem.Quantity = number >= _item.Quantity ? _item.Quantity : number;
}
return newItem;
}
/// <summary>
/// <para>Clean out the items in the item slot</para>
/// <para>清理物品槽内的物品</para>
/// </summary>
/// <param name="queueFree">
///<para>Whether to release a node</para>
///<para>是否释放节点</para>
/// </param>
/// <remarks>
///<para>Clean up item object references in item slots.</para>
///<para>清理物品槽内的物品对象引用。</para>
/// </remarks>
public void ClearItem(bool queueFree = true)
{
if (_item == null)
{
return;
}
if (queueFree && _item is Node node)
{
node.QueueFree();
}
_item = null;
UpdateAllDisplay();
}
public override void _DropData(Vector2 atPosition, Variant data)
{
if (_iconTextureRect == null)
//The item is empty and the corresponding item container cannot be retrieved.
//物品为空,无法获取对应的物品容器。
if (Item is null)
{
return;
}
var type = data.VariantType;
if (type == Variant.Type.Nil)
{
//The passed variable is null.
//传入的变量为null。
return;
}
var itemSlotNode = data.As<ItemSlotNode>();
var sourceItem = itemSlotNode.GetItem();
var sourceItem = itemSlotNode.Item;
if (sourceItem == null)
{
//Return null when trying to get the source item.
//尝试获取源物品时返回null。
return;
}
if (sourceItem is Packsack packsack)
if (Item.SelfItemContainer != null && Item.SelfItemContainer.CanAddItem(sourceItem))
{
//If the source item is a backpack.
//如果源物品是背包。
if (packsack.ItemContainer != null && _item != null)
//Use items and place them on the container.
//用物品,在物品容器上放置。
var oldIndex = sourceItem.Index;
var oldItemContainer = sourceItem.ItemContainer;
var addNumber = Item.SelfItemContainer.AddItem(sourceItem);
if (addNumber >= 0)
{
packsack.ItemContainer.AddItem(_item);
ClearItem(false);
return;
if (addNumber == sourceItem.Quantity)
{
oldItemContainer?.ClearItem(oldIndex);
}
else
{
oldItemContainer?.RemoveItem(oldIndex, addNumber);
}
}
}
if (_item is Packsack customPacksack)
{
if (customPacksack.ItemContainer == null)
{
return;
}
customPacksack.ItemContainer.AddItem(sourceItem);
itemSlotNode.ClearItem(false);
return;
}
AddItem(sourceItem);
itemSlotNode.ClearItem(false);
}
/// <summary>
/// <para>Whether to place a backpack in the current slot</para>
/// <para>当前槽位是否允许放置背包</para>
/// </summary>
public bool BackpackAllowed { get; set; }
public bool IsSelect
{
get => _isSelect;
set
if (sourceItem.SelfItemContainer != null && sourceItem.SelfItemContainer.CanAddItem(Item))
{
UpdateBackground(value);
_isSelect = value;
//Use containers and place on top of items.
//用容器物品,在物品上放置。
var oldIndex = Item.Index;
var oldItemContainer = Item.ItemContainer;
var addNumber = sourceItem.SelfItemContainer.AddItem(Item);
if (addNumber >= 0)
{
if (addNumber == Item.Quantity)
{
oldItemContainer?.ClearItem(oldIndex);
}
else
{
oldItemContainer?.RemoveItem(oldIndex, addNumber);
}
}
return;
}
if (Item is PlaceholderItem placeholderItem)
{
var placeholderItemContainer = placeholderItem.ItemContainer;
var sourceItemContainer = sourceItem.ItemContainer;
var sourceItemIndex = sourceItem.Index;
var replaceResult = false;
if (placeholderItemContainer != null)
{
replaceResult = placeholderItemContainer.ReplaceItem(placeholderItem.Index, sourceItem);
}
if (replaceResult && sourceItemContainer != null)
{
sourceItemContainer.ClearItem(sourceItemIndex);
}
}
}
private void UpdateBackground(bool isSelect)
{
if (_backgroundTextureRect == null)
@ -296,24 +211,6 @@ public partial class ItemSlotNode : MarginContainer
public TextureRect? BackgroundTextureRect => _backgroundTextureRect;
/// <summary>
/// <para>Whether the item in this node is empty</para>
/// <para>此节点内的物品是否为空的</para>
/// </summary>
/// <returns>
///<para>Return true if the number of items is 0 or the item object does not exist</para>
///<para>当物品数量为0或物品对象不存在时返回true</para>
/// </returns>
public bool IsEmpty()
{
if (_item == null || _item.Quantity == 0)
{
return true;
}
return false;
}
/// <summary>
/// <para>Update all displays of this slot</para>
@ -332,7 +229,7 @@ public partial class ItemSlotNode : MarginContainer
/// </summary>
private void UpdateTooltipText()
{
if (_item == null)
if (Item is PlaceholderItem or null)
{
TooltipText = null;
return;
@ -343,16 +240,16 @@ public partial class ItemSlotNode : MarginContainer
var debugText = TranslationServerUtils.Translate("item_prompt_debug");
if (debugText != null)
{
TooltipText = string.Format(debugText, _item.Id,
TranslationServerUtils.Translate(_item.Name),
_item.Quantity, _item.MaxQuantity, _item.GetType().Name,
TranslationServerUtils.Translate(_item.Description));
TooltipText = string.Format(debugText, Item.Id,
TranslationServerUtils.Translate(Item.Name),
Item.Quantity, Item.MaxQuantity, Item.GetType().Name,
TranslationServerUtils.Translate(Item.Description));
}
}
else
{
TooltipText = TranslationServerUtils.Translate(_item.Name) + "\n" +
TranslationServerUtils.Translate(_item.Description);
TooltipText = TranslationServerUtils.Translate(Item.Name) + "\n" +
TranslationServerUtils.Translate(Item.Description);
}
}
@ -367,7 +264,13 @@ public partial class ItemSlotNode : MarginContainer
return;
}
switch (_item?.Quantity)
if (Item is PlaceholderItem or null)
{
_quantityLabel.Hide();
return;
}
switch (Item?.Quantity)
{
case null or 1:
_quantityLabel.Hide();
@ -375,7 +278,7 @@ public partial class ItemSlotNode : MarginContainer
default:
//When the quantity is not null or 1, we display the quantity.
//当数量不为null或1时我们显示数量
_quantityLabel.Text = _item?.Quantity.ToString();
_quantityLabel.Text = Item?.Quantity.ToString();
_quantityLabel.Show();
break;
}
@ -390,94 +293,24 @@ public partial class ItemSlotNode : MarginContainer
{
if (_iconTextureRect != null)
{
_iconTextureRect.Texture = _item?.Icon;
_iconTextureRect.Texture = Item?.Icon;
}
}
public bool CanAddItem(IItem item)
public void Update(IItem? item)
{
if (!BackpackAllowed && item is Packsack)
{
//如果禁止放置背包,且新物品是背包
LogCat.Log("backpack_not_allowed");
return false;
}
if (_item == null)
{
//If there is no item in the current item slot, it is allowed to add.
//如果当前物品槽内没物品,那么允许添加。
LogCat.Log("item_is_null");
return true;
}
if (item.Id != _item.Id)
{
//If the item ID you want to add is different from the current item ID, disable.
//如果要添加的物品ID和当前的物品ID不一样那么禁止。
LogCat.Log("item_id_not_same");
return false;
}
var newQuantity = item.Quantity + _item.Quantity;
if (newQuantity > _item.MaxQuantity)
{
//The maximum number is exceeded and items cannot be added.
//超过了最大数量,无法添加物品。
LogCat.Log("max_quantity_exceeded");
return false;
}
return true;
Item = item;
UpdateAllDisplay();
UpdateBackground(item is { IsSelect: true });
}
/// <summary>
/// <para>Remove items from the item slot</para>
/// <para>从物品槽内移除物品</para>
/// </summary>
/// <param name="number">
///<para>number(Less than 0, remove all items)</para>
///<para>物品数量(小于0则移除全部物品)</para>
/// </param>
/// <returns>
///<para>How many items were actually removed</para>
///<para>实际移除了多少个物品</para>
/// </returns>
public int RemoveItem(int number)
public void ShowSelf()
{
if (_item == null)
{
return 0;
}
//The number of actual removals
//实际移除的数量
var removeNumber = number < 0 ? _item.Quantity : number;
_item.Quantity -= removeNumber;
if (_item.Quantity <= 0)
{
ClearItem();
}
return removeNumber;
Show();
}
public bool AddItem(IItem item)
public void HideSelf()
{
if (_item == null)
{
Item = item;
return true;
}
var newQuantity = item.Quantity + _item.Quantity;
_item.Quantity = Math.Min(newQuantity, _item.MaxQuantity);
if (item is Node2D node2D)
{
node2D.QueueFree();
}
UpdateQuantityLabel();
return true;
Hide();
}
}

View File

@ -5,9 +5,10 @@ namespace ColdMint.scripts.inventory;
public readonly struct ItemType(
string id,
Func<Node?,IItem?> createItemFunc,
Texture2D? icon,
int maxStackQuantity)
int maxStackQuantity,
Func<Node?, IItem?> createItemFunc
)
{
/// <summary>
/// <para>Item id of this type</para>
@ -19,7 +20,7 @@ public readonly struct ItemType(
/// <para>A function returns a new item instance of this type</para>
/// <para>用于创建该类型的物品实例的函数</para>
/// </summary>
public Func<Node?,IItem?> CreateItemFunc { get; init; } = createItemFunc;
public Func<Node?, IItem?> CreateItemFunc { get; init; } = createItemFunc;
/// <summary>
/// <para>Default icon of items of this type</para>

View File

@ -1,5 +1,4 @@
using System.Collections.Generic;
using ColdMint.scripts.utils;
using Godot;
namespace ColdMint.scripts.inventory;
@ -49,7 +48,7 @@ public static class ItemTypeManager
/// <summary>
/// <para>Create multiple new item instances for the given item Id</para>
/// <para>Create multiple new item instances for the given item ID</para>
/// <para>创建多个给定物品Id的新物品实例</para>
/// </summary>
/// <param name="id"></param>
@ -85,23 +84,6 @@ public static class ItemTypeManager
return items.ToArray();
}
/// <summary>
/// <para>Get the translated default name of the item type for the given id</para>
/// <para>获取指定物品id翻译后的物品名</para>
/// </summary>
/// <returns>
/// Translated default name of the item id if it exists. Else, return the id itself
/// </returns>
public static string DefaultNameOf(string id) => TranslationServerUtils.Translate($"item_{id}") ?? id;
/// <summary>
/// <para>Get the translated default description of the item type for the given id</para>
/// <para>获取指定物品id翻译后的描述</para>
/// </summary>
/// <returns>
/// Translated default description of the item id if it exists. Else, return null
/// </returns>
public static string? DefaultDescriptionOf(string id) => TranslationServerUtils.Translate($"item_{id}_desc");
/// <summary>
/// <para>Get the default icon of the item type for the given id</para>
@ -115,16 +97,4 @@ public static class ItemTypeManager
Registry.TryGetValue(id, out var itemType)
? itemType.Icon ?? DefaultTexture
: DefaultTexture;
/// <summary>
/// <para>Gets the maximum number of stacks for an item</para>
/// <para>获取某个物品的最大堆叠数量</para>
/// </summary>
/// <param name="id">
///<para>id</para>
///<para>物品ID</para>
/// </param>
/// <returns></returns>
public static int MaxStackQuantityOf(string id) =>
Registry.TryGetValue(id, out var itemType) ? itemType.MaxStackQuantity : 0;
}

View File

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using ColdMint.scripts.debug;
using ColdMint.scripts.serialization;
using ColdMint.scripts.utils;
@ -30,12 +29,12 @@ public static class ItemTypeRegister
LogCat.Log("start_item_register_from_file");
//初始化文件目录
//initialize file dir
var itemRegsDirPath = "res://data/itemRegs";
const string itemRegsDirPath = "res://data/itemRegs";
var itemRegsDir = DirAccess.Open(itemRegsDirPath);
var error = DirAccess.GetOpenError();
if (error is not Error.Ok)
{
LogCat.LogErrorWithFormat("error_when_open_item_regs_dir", LogCat.LogLabel.Default, true, itemRegsDirPath,
LogCat.LogErrorWithFormat("error_when_open_item_regs_dir", LogCat.LogLabel.Default, itemRegsDirPath,
error.ToString());
return;
}
@ -45,11 +44,11 @@ public static class ItemTypeRegister
var files = itemRegsDir.GetFiles();
if (files == null)
{
LogCat.LogWithFormat("found_files", LogCat.LogLabel.Default, LogCat.UploadFormat, 0);
LogCat.LogWithFormat("found_files", LogCat.LogLabel.Default, 0);
return;
}
LogCat.LogWithFormat("found_files", LogCat.LogLabel.Default, LogCat.UploadFormat, files.Length);
LogCat.LogWithFormat("found_files", LogCat.LogLabel.Default, files.Length);
//将文件解析为项目类型信息
//parse files to item type infos
var count = 0;
@ -69,7 +68,7 @@ public static class ItemTypeRegister
count++;
}
LogCat.LogWithFormat("found_item_types", LogCat.LogLabel.Default, LogCat.UploadFormat, count);
LogCat.LogWithFormat("found_item_types", LogCat.LogLabel.Default, count);
}
/// <summary>
@ -103,24 +102,10 @@ public static class ItemTypeRegister
//加载场景和图标
var scene = ResourceLoader.Load<PackedScene>(typeInfo.ScenePath);
var icon = ResourceLoader.Load<Texture2D>(typeInfo.IconPath);
//Create init delegate
//创建初始化委托
Action<Node?>? setArgs = null;
if (typeInfo.CustomArgs != null && typeInfo.CustomArgs.Count > 0)
{
foreach (var arg in typeInfo.CustomArgs)
{
setArgs +=
node => node?.SetDeferred(arg.Name, arg.ParseValue());
}
}
//构造项目类型,寄存器
//construct item type, register
var itemType = new ItemType(typeInfo.Id,
defaultParentNode =>
icon, typeInfo.MaxStackValue, defaultParentNode =>
{
var newItem = NodeUtils.InstantiatePackedScene<IItem>(scene);
if (newItem is not Node node) return newItem;
@ -130,13 +115,12 @@ public static class ItemTypeRegister
return null;
}
setArgs?.Invoke(node);
newItem.Id = typeInfo.Id;
NodeUtils.CallDeferredAddChild(NodeUtils.FindContainerNode(node, defaultParentNode), node);
return newItem;
},
icon, typeInfo.MaxStackValue);
});
var succeed = ItemTypeManager.Register(itemType);
LogCat.LogWithFormat("register_item", label: LogCat.LogLabel.Default, LogCat.UploadFormat, itemType.Id,
LogCat.LogWithFormat("register_item", label: LogCat.LogLabel.Default, itemType.Id,
succeed);
}
@ -146,44 +130,5 @@ public static class ItemTypeRegister
string Id,
string ScenePath,
string IconPath,
int MaxStackValue,
IList<CustomArg>? 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.Bool => bool.Parse(Value),
CustomArgType.Texture => ResourceLoader.Load<Texture2D>("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", LogCat.LogLabel.Default, LogCat.UploadFormat, "Vector2",
s);
return Vector2.Zero;
}
return new Vector2(float.Parse(ss[0]), float.Parse(ss[1]));
}
}
private enum CustomArgType
{
String,
Int,
Float,
Vector2,
Texture,
Bool,
}
int MaxStackValue);
}

View File

@ -1,4 +1,4 @@
using ColdMint.scripts.pickable;
using ColdMint.scripts.pickable;
using ColdMint.scripts.utils;
using Godot;
using PacksackUi = ColdMint.scripts.loader.uiLoader.PacksackUi;
@ -11,66 +11,59 @@ namespace ColdMint.scripts.inventory;
/// </summary>
public partial class Packsack : PickAbleTemplate
{
private PackedScene? _packedScene;
private PacksackUi? _packsackUi;
[Export] public int NumberSlots { get; set; }
private const string Path = "res://prefab/ui/packsackUI.tscn";
/// <summary>
/// <para>Whether to allow backpacks</para>
/// <para>是否允许放置背包</para>
/// </summary>
/// <remarks>
///<para>Can a new backpack be placed in the slot of the backpack?</para>
///<para>即此背包的槽位内是否可以再放置新的背包?</para>
/// </remarks>
[Export] public bool BackpackAllowed { get; set; }
public override bool CanPutInPack => false;
public override void Use(Node2D? owner, Vector2 targetGlobalPosition)
public override int ItemType
{
if (_packedScene == null)
get => Config.ItemType.Packsack;
}
[Export] public int NumberSlots { get; set; }
public override bool Use(Node2D? owner, Vector2 targetGlobalPosition)
{
if (GameSceneDepend.DynamicUiGroup == null)
{
return false;
}
return GameSceneDepend.DynamicUiGroup.ShowControl(Path, control =>
{
if (control is PacksackUi packsackUi)
{
packsackUi.Title = Name;
packsackUi.ItemContainer = SelfItemContainer;
}
});
}
protected override void OnSelectChange(bool isSelected)
{
if (isSelected)
{
return;
}
if (_packsackUi == null)
{
_packsackUi = NodeUtils.InstantiatePackedScene<PacksackUi>(_packedScene);
if (_packsackUi != null)
{
NodeUtils.CallDeferredAddChild(NodeUtils.FindContainerNode(_packsackUi, this), _packsackUi);
_packsackUi.Title = Name;
_packsackUi.ItemContainer = ItemContainer;
}
}
GameSceneNodeHolder.BackpackUiContainer?.Show();
_packsackUi?.Show();
GameSceneDepend.DynamicUiGroup?.HideControl(Path);
}
public IItemContainer? ItemContainer { get; private set; }
public override void _Ready()
public override void OnThrow(Vector2 velocity)
{
base._Ready();
ItemContainer = new UniversalItemContainer();
ItemContainer.SupportSelect = false;
//When the backpack is created, the item slot is generated.
//当背包被创建时,物品槽就被生成出来了。
for (var i = 0; i < NumberSlots; i++)
GameSceneDepend.DynamicUiGroup?.HideControl(Path);
}
public override void LoadResource()
{
base.LoadResource();
if (SelfItemContainer == null)
{
var itemSlotNode = ItemContainer.AddItemSlot(this);
if (itemSlotNode == null)
{
continue;
}
itemSlotNode.BackpackAllowed = BackpackAllowed;
itemSlotNode.Hide();
var universalItemContainer = new UniversalItemContainer(NumberSlots);
universalItemContainer.AllowItemTypesExceptPlaceholder();
universalItemContainer.DisallowAddingItemByType(Config.ItemType.Packsack);
SelfItemContainer = universalItemContainer;
SelfItemContainer.SupportSelect = false;
}
_packedScene = GD.Load<PackedScene>("res://prefab/ui/packsackUI.tscn");
GameSceneDepend.DynamicUiGroup?.RegisterControl(Path, () =>
{
var packedScene = ResourceLoader.Load<PackedScene>(Path);
return NodeUtils.InstantiatePackedScene<PacksackUi>(packedScene);
});
}
}

View File

@ -0,0 +1,61 @@
using Godot;
namespace ColdMint.scripts.inventory;
/// <summary>
/// <para>PlaceholderItem</para>
/// <para>占位物品</para>
/// </summary>
public class PlaceholderItem : IItem
{
public int Index { get; set; }
public string Id { get; set; }
public void ShowSelf()
{
}
public void QueueFreeSelf()
{
}
public void HideSelf()
{
}
public Texture2D Icon { get; }
public string Name { get; }
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; }
public IItemContainer? SelfItemContainer { get; set; }
public int MergeableItemCount(IItem other, int unallocatedQuantity)
{
return 0;
}
public IItem? CreateItem(int number)
{
return null;
}
public bool Use(Node2D? owner, Vector2 targetGlobalPosition)
{
return false;
}
public void OnThrow(Vector2 velocity)
{
}
}

View File

@ -0,0 +1,40 @@
using ColdMint.scripts.character;
using ColdMint.scripts.damage;
using ColdMint.scripts.weapon;
using Godot;
namespace ColdMint.scripts.inventory;
/// <summary>
/// <para>ResignationCertificate</para>
/// <para>离职证明</para>
/// </summary>
public partial class ResignationCertificate : WeaponTemplate
{
private readonly Damage _damage = new()
{
MaxDamage = 1,
MinDamage = 1,
Type = Config.DamageType.Magic
};
public override void LoadResource()
{
base.LoadResource();
_damage.CreateDamage();
_damage.Attacker = this;
}
public override int ItemType
{
get => Config.ItemType.Item;
}
protected override bool DoFire(Node2D? owner, Vector2 enemyGlobalPosition)
{
if (Owner is CharacterTemplate characterTemplate)
{
return characterTemplate.Damage(_damage);
}
return false;
}
}

View File

@ -1,11 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using ColdMint.scripts.map.events;
using ColdMint.scripts.utils;
using Godot;
using JetBrains.Annotations;
namespace ColdMint.scripts.inventory;
@ -13,11 +9,9 @@ namespace ColdMint.scripts.inventory;
/// <para>UniversalItemContainer</para>
/// <para>通用的物品容器</para>
/// </summary>
public class UniversalItemContainer : IItemContainer
public class UniversalItemContainer(int totalCapacity) : IItemContainer
{
private readonly List<ItemSlotNode>? _itemSlotNodes = [];
private readonly PackedScene? _itemSlotPackedScene = GD.Load<PackedScene>("res://prefab/ui/ItemSlot.tscn");
private readonly Dictionary<int, IItem> _itemDictionary = [];
/// <summary>
/// <para>UnknownIndex</para>
@ -25,167 +19,401 @@ public class UniversalItemContainer : IItemContainer
/// </summary>
private const int UnknownIndex = -1;
//_selectIndex defaults to 0.
//_selectIndex默认为0.
private int _selectIndex;
[MustDisposeResource]
public IEnumerator<ItemSlotNode> GetEnumerator()
/// <summary>
/// <para>The type of item that can be added to the item container</para>
/// <para>物品容器允许添加的物品类型</para>
/// </summary>
private readonly HashSet<int> _allowedItemTypes = new();
public Action<SelectedItemChangeEvent>? SelectedItemChangeEvent { get; set; }
public Action<ItemDataChangeEvent>? ItemDataChangeEvent { get; set; }
/// <summary>
/// <para>Allow Item Types Except Placeholder</para>
/// <para>允许添加除占位符以外的所有物品类型</para>
/// </summary>
public void AllowItemTypesExceptPlaceholder()
{
return _itemSlotNodes?.GetEnumerator() ?? Enumerable.Empty<ItemSlotNode>().GetEnumerator();
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);
}
}
[MustDisposeResource]
IEnumerator IEnumerable.GetEnumerator()
public void AllowAddingItemByType(int itemType)
{
return GetEnumerator();
_allowedItemTypes.Add(itemType);
}
public Action<SelectedItemSlotChangeEvent>? SelectedItemSlotChangeEvent { get; set; }
public void DisallowAddingItemByType(int itemType)
{
_allowedItemTypes.Remove(itemType);
}
public bool CanAddItem(IItem item)
{
return Match(item) != null;
}
public bool AddItem(IItem item)
{
var itemSlotNode = Match(item);
if (itemSlotNode == null)
if (!_allowedItemTypes.Contains(item.ItemType))
{
return false;
}
//If the capacity is not full, directly return to add items
//如果未占满容量,直接返回可添加物品
if (GetUsedCapacity() < totalCapacity)
{
return true;
}
return itemSlotNode.AddItem(item);
if (item.MaxQuantity == 1)
{
//New items do not support overlay, capacity is full, return cannot add.
//新物品不支持叠加,容量已满,返回不能添加。
return false;
}
//If the capacity is full, we calculate whether we can spread the new items evenly among the existing items.
//如果容量占满了,我们计算是否能将新物品均摊在已有的物品内。
var unallocatedQuantity = item.Quantity;
foreach (var unitItem in _itemDictionary.Values)
{
var number = unitItem.MergeableItemCount(item, unallocatedQuantity);
if (number == 0)
{
continue;
}
unallocatedQuantity -= number;
if (unallocatedQuantity < 1)
{
return true;
}
}
return unallocatedQuantity < 1;
}
private void UpdateSelectStatus(int index, IItem item)
{
item.IsSelect = index == _selectIndex;
}
/// <summary>
/// <para>Update the next available index location</para>
/// <para>更新下个可用的索引位置</para>
/// </summary>
/// <remarks>
///<para>For example, the variable [1,2,3,5,6] represents 4, or the variable [1,2,3,4,5,6,7] represents 8.</para>
///<para>例如[1,2,3,5,6]这个变量表示4再或者[1,2,3,4,5,6,7]这个变量表示8。</para>
/// </remarks>
/// <returns>
///<para>The next available index is returned after obtaining failure<see cref="UnknownIndex"/></para>
///<para>下次可用的索引,获取失败返回<see cref="UnknownIndex"/></para>
/// </returns>
private int GetNextAvailableIndex()
{
if (totalCapacity <= 0)
{
return UnknownIndex;
}
for (var i = 0; i < totalCapacity; i++)
{
var contains = _itemDictionary.ContainsKey(i);
if (!contains)
{
return i;
}
}
return UnknownIndex;
}
public int AddItem(IItem item)
{
var nextAvailableIndex = GetNextAvailableIndex();
if (item.MaxQuantity == 1)
{
if (nextAvailableIndex == UnknownIndex)
{
return 0;
}
_itemDictionary[nextAvailableIndex] = item;
item.Index = nextAvailableIndex;
item.ItemContainer = this;
if (nextAvailableIndex != _selectIndex)
{
item.HideSelf();
}
UpdateSelectStatus(nextAvailableIndex, item);
ItemDataChangeEvent?.Invoke(new ItemDataChangeEvent
{
NewItem = item,
NewIndex = nextAvailableIndex,
Type = Config.ItemDataChangeEventType.Add
});
return item.Quantity;
}
//There can be more than one item, try to share equally.
//物品可有多个,尝试均摊。
var originalQuantity = item.Quantity;
var temporarilyQuantity = item.Quantity;
var index = 0;
foreach (var unitItem in _itemDictionary.Values)
{
var number = unitItem.MergeableItemCount(item, temporarilyQuantity);
if (number == 0)
{
continue;
}
temporarilyQuantity -= number;
unitItem.Quantity += number;
ItemDataChangeEvent?.Invoke(new ItemDataChangeEvent
{
NewItem = unitItem,
NewIndex = index,
Type = Config.ItemDataChangeEventType.QuantityAdded
});
if (item.Quantity < 1)
{
//New items are fully shared.
//新物品完全被均摊。
item.HideSelf();
return originalQuantity;
}
index++;
}
//New items have some left over.
//新物品有一些剩余。
if (GetUsedCapacity() >= totalCapacity)
{
//The capacity is full. The remaining capacity cannot be stored.
//容量已满,无法存放剩余。
return originalQuantity - temporarilyQuantity;
}
//Add the rest to the container.
//添加剩余到容器内。
if (nextAvailableIndex == UnknownIndex)
{
return 0;
}
_itemDictionary[nextAvailableIndex] = item;
item.Index = nextAvailableIndex;
item.ItemContainer = this;
if (nextAvailableIndex != _selectIndex)
{
item.HideSelf();
}
UpdateSelectStatus(nextAvailableIndex, item);
ItemDataChangeEvent?.Invoke(new ItemDataChangeEvent
{
NewItem = item,
NewIndex = nextAvailableIndex,
Type = Config.ItemDataChangeEventType.Add
});
return originalQuantity;
}
public bool SupportSelect { get; set; }
public IItem GetPlaceHolderItem(int index)
{
var placeholderItem = new PlaceholderItem
{
Index = index,
ItemContainer = this
};
return placeholderItem;
}
public int GetSelectIndex()
{
return _selectIndex;
}
public ItemSlotNode? GetSelectItemSlotNode()
public IItem? GetSelectItem()
{
if (_itemSlotNodes == null || _itemSlotNodes.Count == 0)
return _itemDictionary.TryGetValue(_selectIndex, out var item) ? item : null;
}
public IItem? GetItem(int index)
{
return _itemDictionary.TryGetValue(index, out var item) ? item : null;
}
public bool ReplaceItem(int index, IItem item)
{
var oldItem = GetItem(index);
_itemDictionary[index] = item;
item.Index = index;
item.ItemContainer = this;
ItemDataChangeEvent?.Invoke(new ItemDataChangeEvent
{
NewItem = item,
NewIndex = index,
OldIndex = index,
OldItem = oldItem,
Type = Config.ItemDataChangeEventType.Replace
});
if (SupportSelect && index == _selectIndex)
{
oldItem?.HideSelf();
item.ShowSelf();
SelectedItemChangeEvent?.Invoke(new SelectedItemChangeEvent
{
NewIndex = index,
OldIndex = index,
NewItem = item,
OldItem = oldItem
});
}
return true;
}
public bool CanReplaceItem(int index, IItem item)
{
if (!_allowedItemTypes.Contains(item.ItemType))
{
return false;
}
return true;
}
public IItem? ClearItem(int index)
{
if (!_itemDictionary.TryGetValue(index, out var item))
{
return null;
}
if (_selectIndex < _itemSlotNodes.Count)
if (!_itemDictionary.Remove(index))
{
//Prevent subscripts from going out of bounds.
//防止下标越界。
return _itemSlotNodes[_selectIndex];
return null;
}
return null;
ItemDataChangeEvent?.Invoke(new ItemDataChangeEvent
{
NewItem = null,
NewIndex = index,
OldIndex = index,
OldItem = null,
Type = Config.ItemDataChangeEventType.Clear
});
if (SupportSelect && index == _selectIndex)
{
item.HideSelf();
SelectedItemChangeEvent?.Invoke(new SelectedItemChangeEvent
{
NewIndex = index,
OldIndex = index,
NewItem = null,
OldItem = null
});
}
return item;
}
public int RemoveItemFromItemSlotBySelectIndex(int number) => RemoveItemFromItemSlot(_selectIndex, number);
public int GetItemSlotCount()
public void ClearAllItems()
{
if (_itemSlotNodes == null)
foreach (var itemDictionaryKey in _itemDictionary.Keys)
{
var item = ClearItem(itemDictionaryKey);
if (item == null)
{
continue;
}
item.SelfItemContainer?.ClearAllItems();
item.QueueFreeSelf();
}
}
public int RemoveSelectItem(int number)
{
return RemoveItem(_selectIndex, number);
}
public int RemoveItem(int itemIndex, int number)
{
if (number == 0)
{
return 0;
}
return _itemSlotNodes.Count;
if (!_itemDictionary.TryGetValue(itemIndex, out var item))
{
return 0;
}
var originalQuantity = item.Quantity;
if (number < 0)
{
//If the number entered is less than 0, all items are removed.
//输入的数量小于0,则移除全部物品。
item.Quantity = 0;
_itemDictionary.Remove(itemIndex);
ItemDataChangeEvent?.Invoke(new ItemDataChangeEvent
{
NewItem = item,
NewIndex = itemIndex,
Type = Config.ItemDataChangeEventType.Remove
});
return originalQuantity;
}
var removed = Math.Min(number, item.Quantity);
item.Quantity -= removed;
if (item.Quantity < 1)
{
_itemDictionary.Remove(itemIndex);
ItemDataChangeEvent?.Invoke(new ItemDataChangeEvent
{
NewItem = item,
NewIndex = itemIndex,
Type = Config.ItemDataChangeEventType.Remove
});
}
return removed;
}
public ItemSlotNode? GetItemSlotNode(int index)
public int GetUsedCapacity()
{
if (_itemSlotNodes == null)
{
return null;
}
var safeIndex = GetSafeIndex(index);
return _itemSlotNodes[safeIndex];
return _itemDictionary.Count;
}
public int RemoveItemFromItemSlot(int itemSlotIndex, int number)
public int GetTotalCapacity()
{
if (_itemSlotNodes == null) return number;
var safeIndex = GetSafeIndex(itemSlotIndex);
if (safeIndex == UnknownIndex)
{
return number;
}
var itemSlot = _itemSlotNodes[safeIndex];
return itemSlot.RemoveItem(number);
return totalCapacity;
}
/// <summary>
/// <para>Gets a secure subscript index</para>
/// <para>获取安全的下标索引</para>
/// </summary>
/// <param name="itemSlotIndex"></param>
/// <returns>
/// <para>-1 is returned on failure, and the index that does not result in an out-of-bounds subscript is returned on success</para>
/// <para>失败返回-1成功返回不会导致下标越界的索引</para>
/// </returns>
private int GetSafeIndex(int itemSlotIndex)
public void SelectNextItem()
{
if (_itemSlotNodes == null)
{
return UnknownIndex;
}
var count = _itemSlotNodes.Count;
if (count == 0)
{
//Prevents the dividend from being 0
//防止被除数为0
return UnknownIndex;
}
return itemSlotIndex % count;
}
public ItemSlotNode? Match(IItem item)
{
//Find and return the first slot that can hold this item, if the list is null or not found, return null
//寻找并返回第一个遇到的可放置此物品的物品槽若列表为空或不存在将返回null
return _itemSlotNodes?.FirstOrDefault(itemSlotNode => itemSlotNode.CanAddItem(item));
}
public ItemSlotNode? AddItemSlot(Node rootNode)
{
if (_itemSlotNodes == null || _itemSlotPackedScene == null)
{
return null;
}
var itemSlotNode = NodeUtils.InstantiatePackedScene<ItemSlotNode>(_itemSlotPackedScene);
if (itemSlotNode == null)
{
return null;
}
NodeUtils.CallDeferredAddChild(rootNode, itemSlotNode);
if (SupportSelect)
{
itemSlotNode.IsSelect = _itemSlotNodes.Count == _selectIndex;
}
else
{
itemSlotNode.IsSelect = false;
}
_itemSlotNodes.Add(itemSlotNode);
return itemSlotNode;
}
public void SelectTheNextItemSlot()
{
if (_itemSlotNodes == null)
{
return;
}
var count = _itemSlotNodes.Count;
var count = totalCapacity;
if (count == 0)
{
return;
@ -198,17 +426,12 @@ public class UniversalItemContainer : IItemContainer
newSelectIndex = 0;
}
PrivateSelectItemSlot(oldSelectIndex, newSelectIndex);
PrivateSelectItem(oldSelectIndex, newSelectIndex);
}
public void SelectThePreviousItemSlot()
public void SelectPreviousItem()
{
if (_itemSlotNodes == null)
{
return;
}
var count = _itemSlotNodes.Count;
var count = totalCapacity;
if (count == 0)
{
return;
@ -221,77 +444,57 @@ public class UniversalItemContainer : IItemContainer
newSelectIndex = count - 1;
}
PrivateSelectItemSlot(oldSelectIndex, newSelectIndex);
PrivateSelectItem(oldSelectIndex, newSelectIndex);
}
/// <summary>
/// <para>Select an item slot</para>
/// <para>选中某个物品槽</para>
/// <para>Private methods for selecting items</para>
/// <para>选择物品的私有方法</para>
/// </summary>
private void PrivateSelectItemSlot(int oldSelectIndex, int newSelectIndex)
/// <param name="oldIndex"></param>
/// <param name="newIndex"></param>
private void PrivateSelectItem(int oldIndex, int newIndex)
{
if (!SupportSelect || _itemSlotNodes == null || oldSelectIndex == newSelectIndex)
if (!SupportSelect || oldIndex == newIndex)
{
return;
}
var oldItemSlotNode = _itemSlotNodes[oldSelectIndex];
oldItemSlotNode.IsSelect = false;
var newItemSlotNode = _itemSlotNodes[newSelectIndex];
newItemSlotNode.IsSelect = true;
HideItem(oldSelectIndex);
DisplayItem(newSelectIndex);
SelectedItemSlotChangeEvent?.Invoke(new SelectedItemSlotChangeEvent
//There is no need to broadcast placeholders when an event is invoked.
//在调用事件时,无需广播占位符。
var oldItem = GetItem(oldIndex);
if (oldItem != null)
{
NewItemSlotNode = newItemSlotNode,
OldItemSlotNode = oldItemSlotNode
oldItem.HideSelf();
oldItem.IsSelect = false;
}
//There is no need to broadcast placeholders when an event is invoked.
//在调用事件时,无需广播占位符。
var newItem = GetItem(newIndex);
if (newItem != null)
{
newItem.ShowSelf();
newItem.IsSelect = true;
}
_selectIndex = newIndex;
SelectedItemChangeEvent?.Invoke(new SelectedItemChangeEvent
{
NewIndex = newIndex,
OldIndex = oldIndex,
NewItem = newItem,
OldItem = oldItem
});
_selectIndex = newSelectIndex;
}
/// <summary>
/// <para>HideItem</para>
/// <para>隐藏某个物品</para>
/// </summary>
/// <param name="index"></param>
private void HideItem(int index)
{
var oldItem = _itemSlotNodes?[index].GetItem();
if (oldItem is not Node2D oldNode2D) return;
oldNode2D.ProcessMode = Node.ProcessModeEnum.Disabled;
oldNode2D.Hide();
}
/// <summary>
/// <para>Displays the items in an item slot</para>
/// <para>显示某个物品槽内的物品</para>
/// </summary>
/// <remarks>
///<para>This method can also be used to refresh items held by the character, for example when a new item is dragged to the current display location, then call this method to refresh items held by the character.</para>
///<para>此方法也可用于刷新角色手上持有的物品,例如当新的物品被拖动到当前显示位置,那么请调用此方法刷新角色持有的物品。</para>
/// </remarks>
/// <param name="index"></param>
private void DisplayItem(int index)
public void SelectItem(int index)
{
var item = _itemSlotNodes?[index].GetItem();
if (item is not Node2D newNode2D) return;
newNode2D.ProcessMode = Node.ProcessModeEnum.Inherit;
newNode2D.Show();
}
public void SelectItemSlot(int newSelectIndex)
{
if (newSelectIndex == _selectIndex)
if (totalCapacity == 0 || index < 0)
{
return;
}
var safeIndex = GetSafeIndex(newSelectIndex);
if (safeIndex == UnknownIndex)
{
return;
}
PrivateSelectItemSlot(_selectIndex, newSelectIndex);
PrivateSelectItem(_selectIndex, index % totalCapacity);
}
}

View File

@ -1,8 +1,10 @@
using System.Threading.Tasks;
using ColdMint.scripts.inventory;
using ColdMint.scripts.map;
using ColdMint.scripts.map.events;
using ColdMint.scripts.map.LayoutParsingStrategy;
using ColdMint.scripts.map.layoutStrategy;
using ColdMint.scripts.map.miniMap;
using ColdMint.scripts.map.RoomPlacer;
using ColdMint.scripts.utils;
using Godot;
@ -19,42 +21,55 @@ public partial class GameSceneLoader : SceneLoaderTemplate
public override Task InitializeData()
{
RenderingServer.SetDefaultClearColor(Color.FromHsv(0, 0, 0));
//Loading the blood bar scene
//加载血条场景
var healthBarUi = GetNode<HealthBarUi>("CanvasLayer/Control/VBoxContainer/HealthBarUi");
GameSceneNodeHolder.HealthBarUi = healthBarUi;
GameSceneDepend.HealthBarUi = healthBarUi;
//Load HotBar
//加载HotBar
var hotBar = GetNode<HotBar>("CanvasLayer/Control/VBoxContainer/HotBar");
GameSceneNodeHolder.HotBar = hotBar;
GameSceneDepend.HotBar = hotBar;
//Backpack Ui container
//背包Ui容器
var backpackUiContainer = GetNode<Control>("CanvasLayer/BackpackUIContainer");
GameSceneNodeHolder.BackpackUiContainer = backpackUiContainer;
//Load operation prompt
//加载操作提示
var operationTip = GetNode<RichTextLabel>("CanvasLayer/Control/VBoxContainer/OperationTip");
GameSceneNodeHolder.OperationTipLabel = operationTip;
var backpackUiContainer = GetNode<UiGroup>("CanvasLayer/DynamicUiGroup");
GameSceneDepend.DynamicUiGroup = backpackUiContainer;
//Loaded weapon container
//加载武器容器
var weaponContainer = GetNode<Node2D>("WeaponContainer");
GameSceneNodeHolder.WeaponContainer = weaponContainer;
GameSceneDepend.WeaponContainer = weaponContainer;
//Load projectile container
//加载抛射体容器
var projectileContainer = GetNode<Node2D>("ProjectileContainer");
GameSceneNodeHolder.ProjectileContainer = projectileContainer;
GameSceneDepend.ProjectileContainer = projectileContainer;
//Load magic container
//加载魔术容器
var magicContainer = GetNode<Node2D>("SpellContainer");
GameSceneDepend.SpellContainer = magicContainer;
//Load Packsack container
//加载背包容器
var packsackContainer = GetNode<Node2D>("PacksackContainer");
GameSceneNodeHolder.PacksackContainer = packsackContainer;
GameSceneDepend.PacksackContainer = packsackContainer;
//Load AICharacter container
//加载AICharacter容器
var aiCharacterContainer = GetNode<Node2D>("AICharacterContainer");
GameSceneNodeHolder.AiCharacterContainer = aiCharacterContainer;
GameSceneDepend.AiCharacterContainer = aiCharacterContainer;
//Load player container
//加载玩家容器
var playerContainer = GetNode<Node2D>("PlayerContainer");
GameSceneNodeHolder.PlayerContainer = playerContainer;
GameSceneDepend.PlayerContainer = playerContainer;
//Load the pickable container
//加载可拾捡物容器
var pickAbleContainer = GetNode<Node2D>("PickAbleContainer");
GameSceneDepend.PickAbleContainer = pickAbleContainer;
//Setting up the mini map
//设置迷你地图
var miniMap = GetNode<MiniMap>("CanvasLayer/Control/MapContainer/Control/MiniMap");
GameSceneDepend.MiniMap = miniMap;
//Set the mini map animation
//设置迷你地图动画
var miniMapAnimationPlayer = GetNode<AnimationPlayer>("CanvasLayer/Control/MapContainer/MiniMapAnimationPlayer");
GameSceneDepend.MiniMapAnimationPlayer = miniMapAnimationPlayer;
return Task.CompletedTask;
}
@ -78,9 +93,34 @@ public partial class GameSceneLoader : SceneLoaderTemplate
MapGenerator.LayoutStrategy = new TestLayoutStrategy();
MapGenerator.LayoutParsingStrategy = new SequenceLayoutParsingStrategy();
MapGenerator.RoomPlacementStrategy = new PatchworkRoomPlacementStrategy();
EventBus.GameOverEvent += OnGameOverEvent;
await GenerateMap();
}
private async void OnGameOverEvent(GameOverEvent gameOverEvent)
{
if (GameSceneDepend.WeaponContainer != null)
{
NodeUtils.DeleteAllChild(GameSceneDepend.WeaponContainer);
}
if (GameSceneDepend.PacksackContainer != null)
{
NodeUtils.DeleteAllChild(GameSceneDepend.PacksackContainer);
}
if (GameSceneDepend.SpellContainer != null)
{
NodeUtils.DeleteAllChild(GameSceneDepend.SpellContainer);
}
await GenerateMap();
var replayEvent = new GameReplayEvent();
EventBus.GameReplayEvent?.Invoke(replayEvent);
}
public override void _ExitTree()
{
EventBus.GameOverEvent -= OnGameOverEvent;
}
/// <summary>
/// <para>Generate map</para>
/// <para>生成地图</para>
@ -95,6 +135,7 @@ public partial class GameSceneLoader : SceneLoaderTemplate
var seedInfo = TranslationServerUtils.TranslateWithFormat("ui_seed_info", MapGenerator.Seed);
_seedLabel.Text = seedInfo ?? $"Seed: {MapGenerator.Seed}";
}
await MapGenerator.GenerateMap();
}
}

Some files were not shown because too many files have changed in this diff Show More