Add Japanese translation to improve item picking logic.

增加日语翻译,改善物品的拾捡逻辑。
This commit is contained in:
Cold-Mint 2024-05-09 21:07:14 +08:00
parent 222d26441e
commit 5cdb720d37
Signed by: Cold-Mint
GPG Key ID: C5A9BF8A98E0CE99
39 changed files with 249 additions and 176 deletions

View File

@ -1,7 +1,9 @@
id,zh,en id,zh,en,jp
Object reference not set to an instance of an object.,尝试在空对象上调用虚拟方法。,Object reference not set to an instance of an object. Object reference not set to an instance of an object.,尝试在空对象上调用虚拟方法。,Object reference not set to an instance of an object.,空のオブジェクト上で仮想メソッドを呼び出してみます。
missing_parameters,缺少参数。,Missing parameters. missing_parameters,缺少参数。,Missing parameters.,パラメータが不足しています。
room_root_node_must_be_node2d,房间根节点必须是 Node2D。,Room root node must be Node2D. room_root_node_must_be_node2d,房间根节点必须是 Node2D。,Room root node must be Node2D.,ルートードはNode2Dでなければなりません。
width_or_height_of_room_slot_must_be_1,房间槽的宽度或高度必须为1。,The width or height of the room slot must be 1. width_or_height_of_room_slot_must_be_1,房间槽的宽度或高度必须为1。,The width or height of the room slot must be 1.,部屋の溝の幅または高さは1でなければなりません。
connected_room_timeout,连接房间超时。,Connecting the room timed out. connected_room_timeout,连接房间超时。,Connecting the room timed out.,接続部屋はタイムアウトです。
projectiles_is_empty,未设置抛射体。,The projectile is not set. projectiles_is_empty,未设置抛射体。,The projectile is not set.,射出体は設置されていません。
map_generator_is_not_set_up,未设置地图生成器。,Map generator is not set up.,マップ生成器は設置されていません。
map_generator_is_not_configured,地图生成器没有有效配置。,Map Generator is not configured.,地図生成器は機能していません。
1 id zh en jp
2 Object reference not set to an instance of an object. 尝试在空对象上调用虚拟方法。 Object reference not set to an instance of an object. 空のオブジェクト上で仮想メソッドを呼び出してみます。
3 missing_parameters 缺少参数。 Missing parameters. パラメータが不足しています。
4 room_root_node_must_be_node2d 房间根节点必须是 Node2D。 Room root node must be Node2D. ルートノードはNode2Dでなければなりません。
5 width_or_height_of_room_slot_must_be_1 房间槽的宽度或高度必须为1。 The width or height of the room slot must be 1. 部屋の溝の幅または高さは1でなければなりません。
6 connected_room_timeout 连接房间超时。 Connecting the room timed out. 接続部屋はタイムアウトです。
7 projectiles_is_empty 未设置抛射体。 The projectile is not set. 射出体は設置されていません。
8 map_generator_is_not_set_up 未设置地图生成器。 Map generator is not set up. マップ生成器は設置されていません。
9 map_generator_is_not_configured 地图生成器没有有效配置。 Map Generator is not configured. 地図生成器は機能していません。

View File

@ -6,10 +6,10 @@ uid="uid://nmtkvo0t7p7n"
[deps] [deps]
files=["res://locals/Error.zh.translation", "res://locals/Error.en.translation"] files=["res://locals/Error.zh.translation", "res://locals/Error.en.translation", "res://locals/Error.jp.translation"]
source_file="res://locals/Error.csv" source_file="res://locals/Error.csv"
dest_files=["res://locals/Error.zh.translation", "res://locals/Error.en.translation"] dest_files=["res://locals/Error.zh.translation", "res://locals/Error.en.translation", "res://locals/Error.jp.translation"]
[params] [params]

Binary file not shown.

BIN
locals/Error.jp.translation Normal file

Binary file not shown.

Binary file not shown.

View File

@ -1,2 +1,2 @@
id,zh,en id,zh,en,jp
Left Mouse Button,鼠标左键,Left Mouse Button Left Mouse Button,鼠标左键,Left Mouse Button,マウスの左ボタンです
1 id zh en jp
2 Left Mouse Button 鼠标左键 Left Mouse Button マウスの左ボタンです

View File

@ -6,10 +6,10 @@ uid="uid://dvvc7sup2d2ii"
[deps] [deps]
files=["res://locals/InputMapping.zh.translation", "res://locals/InputMapping.en.translation"] files=["res://locals/InputMapping.zh.translation", "res://locals/InputMapping.en.translation", "res://locals/InputMapping.jp.translation"]
source_file="res://locals/InputMapping.csv" source_file="res://locals/InputMapping.csv"
dest_files=["res://locals/InputMapping.zh.translation", "res://locals/InputMapping.en.translation"] dest_files=["res://locals/InputMapping.zh.translation", "res://locals/InputMapping.en.translation", "res://locals/InputMapping.jp.translation"]
[params] [params]

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,11 +1 @@
id,zh,en id,zh,en,jp
data_packet_missing_id,位于{0}的数据包缺少Id无法加载。,"Packet at {0}, missing Id, unable to load."
index_is_up_to_date,位于{0}的数据包索引已是最新。,"The packet index at {0} is up to date."
build_an_index,为{0}构建索引。,"Build an index for {0}."
add_file_index,添加文件索引{0}。,"Add file index {0}."
index_updated,{0}索引已更新。,"{0} Index has been updated."
no_manifest_file,位于{0}的数据包,没有清单文件,无法加载。,"Packet located in {0}, no manifest file, cannot be loaded."
duplicate_at_path_id,位于{0}路径{1}的Id({2})已被占用,无法加载。,"Id({2}) in {0} path {1} is occupied and cannot be loaded."
duplicate_at_path_id,位于{0}路径{1}的Id({2})已被占用,无法加载。,"Id({2}) in {0} path {1} is occupied and cannot be loaded."
map_generator_is_not_set_up,未设置地图生成器。,Map generator is not set up.
map_generator_is_not_configured,地图生成器没有有效配置。,Map Generator is not configured.
1 id zh en jp
data_packet_missing_id 位于{0}的数据包,缺少Id,无法加载。 Packet at {0}, missing Id, unable to load.
index_is_up_to_date 位于{0}的数据包索引已是最新。 The packet index at {0} is up to date.
build_an_index 为{0}构建索引。 Build an index for {0}.
add_file_index 添加文件索引{0}。 Add file index {0}.
index_updated {0}索引已更新。 {0} Index has been updated.
no_manifest_file 位于{0}的数据包,没有清单文件,无法加载。 Packet located in {0}, no manifest file, cannot be loaded.
duplicate_at_path_id 位于{0}路径{1}的Id({2})已被占用,无法加载。 Id({2}) in {0} path {1} is occupied and cannot be loaded.
duplicate_at_path_id 位于{0}路径{1}的Id({2})已被占用,无法加载。 Id({2}) in {0} path {1} is occupied and cannot be loaded.
map_generator_is_not_set_up 未设置地图生成器。 Map generator is not set up.
map_generator_is_not_configured 地图生成器没有有效配置。 Map Generator is not configured.

View File

@ -6,10 +6,10 @@ uid="uid://btmjafjh5r6bk"
[deps] [deps]
files=["res://locals/Log.zh.translation", "res://locals/Log.en.translation"] files=["res://locals/Log.zh.translation", "res://locals/Log.en.translation", "res://locals/Log.jp.translation"]
source_file="res://locals/Log.csv" source_file="res://locals/Log.csv"
dest_files=["res://locals/Log.zh.translation", "res://locals/Log.en.translation"] dest_files=["res://locals/Log.zh.translation", "res://locals/Log.en.translation", "res://locals/Log.jp.translation"]
[params] [params]

Binary file not shown.

BIN
locals/Log.jp.translation Normal file

Binary file not shown.

Binary file not shown.

View File

@ -1,15 +1,14 @@
id,zh,en id,zh,en,jp
product_name,异界旅人,A traveler from another world product_name,异界旅人,A traveler from another world,異界の旅人です
start_game,开始游戏,Start game start_game,开始游戏,Start game,ゲームを始めます
settings,设置,Settings settings,设置,Settings,備え付け
pick_up,拾捡,Pick up pick_up,拾捡,Pick up ,拾います
move_left,向左移动,Move left move_left,向左移动,Move left,左に移動します
move_right,向右移动,Move right move_right,向右移动,Move right,右に移動します
jump,跳跃,Jump jump,跳跃,Jump,飛
throw,抛出,Throw a throw,抛出,Throw a ,ほうしゅつ
must_be_thrown,必须先抛出{0}才能拾捡{1},{0} must be thrown before {1} can be picked up. use_item,使用,Use,しよう
use_item,使用,Use jump_down,跳下平台,Jump off platform,踊り場から飛び降ります
jump_down,跳下平台,Jump off platform de,的,'s,の
de,的,'s default_player_name,白纸,blankPaper,しらかみ
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}
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}
1 id zh en jp
2 product_name 异界旅人 A traveler from another world 異界の旅人です
3 start_game 开始游戏 Start game ゲームを始めます
4 settings 设置 Settings 備え付け
5 pick_up 拾捡 Pick up 拾います
6 move_left 向左移动 Move left 左に移動します
7 move_right 向右移动 Move right 右に移動します
8 jump 跳跃 Jump
9 throw 抛出 Throw a ほうしゅつ
10 must_be_thrown use_item 必须先抛出{0}才能拾捡{1} 使用 {0} must be thrown before {1} can be picked up. Use しよう
11 use_item jump_down 使用 跳下平台 Use Jump off platform 踊り場から飛び降ります
12 jump_down de 跳下平台 Jump off platform 's
13 de default_player_name 白纸 's blankPaper しらかみ
14 default_player_name item_prompt_debug 白纸 ID:{0}\n名称:{1}\n数量:{2}\n最大叠加数量:{3}\n数据类型:{4}\n描述:{5} blankPaper 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}
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}

View File

@ -6,10 +6,10 @@ uid="uid://bpdkorm7lprma"
[deps] [deps]
files=["res://locals/UI.zh.translation", "res://locals/UI.en.translation"] files=["res://locals/UI.zh.translation", "res://locals/UI.en.translation", "res://locals/UI.jp.translation"]
source_file="res://locals/UI.csv" source_file="res://locals/UI.csv"
dest_files=["res://locals/UI.zh.translation", "res://locals/UI.en.translation"] dest_files=["res://locals/UI.zh.translation", "res://locals/UI.en.translation", "res://locals/UI.jp.translation"]
[params] [params]

Binary file not shown.

BIN
locals/UI.jp.translation Normal file

Binary file not shown.

Binary file not shown.

View File

@ -1,3 +1,3 @@
id,zh,en id,zh,en,jp
staff_of_the_undead,死灵法杖,StaffOfTheUndead staff_of_the_undead,死灵法杖,StaffOfTheUndead,ネクロポリスの杖です
staff_of_the_undead_desc,发射诅咒,可将敌人转化为邪恶的怪物。,Cast a curse that transforms enemies into evil monsters. staff_of_the_undead_desc,发射诅咒,可将敌人转化为邪恶的怪物。,Cast a curse that transforms enemies into evil monsters.,呪いを発射して、敵を邪悪な怪物に変えることができます。
1 id zh en jp
2 staff_of_the_undead 死灵法杖 StaffOfTheUndead ネクロポリスの杖です
3 staff_of_the_undead_desc 发射诅咒,可将敌人转化为邪恶的怪物。 Cast a curse that transforms enemies into evil monsters. 呪いを発射して、敵を邪悪な怪物に変えることができます。

View File

@ -6,10 +6,10 @@ uid="uid://dmhmjvtquyu16"
[deps] [deps]
files=["res://locals/Weapon.zh.translation", "res://locals/Weapon.en.translation"] files=["res://locals/Weapon.zh.translation", "res://locals/Weapon.en.translation", "res://locals/Weapon.jp.translation"]
source_file="res://locals/Weapon.csv" source_file="res://locals/Weapon.csv"
dest_files=["res://locals/Weapon.zh.translation", "res://locals/Weapon.en.translation"] dest_files=["res://locals/Weapon.zh.translation", "res://locals/Weapon.en.translation", "res://locals/Weapon.jp.translation"]
[params] [params]

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,13 +1,6 @@
id,zh,en id,zh,en,jp
slogan_1,如果是你,你会选择金钱还是荣誉?,"If it were you, would you choose money or honor?" slogan_1,游戏属于每一个人。,The game belongs to everyone.,ゲームはすべての人のものです。
slogan_2,游戏属于每一个人。,The game belongs to everyone. slogan_2,如果你想要得到爱,你就播种爱。,"If you want love, you sow love.",愛を手に入れたければ、愛の種をまきます。
slogan_3,如果你想要得到爱,你就播种爱。,"If you want love, you sow love." slogan_3,快乐?伤心?痛苦?,Happy? Sad? Pain?,楽しいですか?悲しいですか?苦しいですか?
slogan_4,作为自然法则,死亡是每一个人人生的最终归宿。,"As a law of nature, everyone will end up dead." slogan_4,0001 0011 0001 0101 0100 1111 0100,0001 0011 0001 0101 0100 1111 0100,0001 0011 0001 0101 0100 1111 0100
slogan_5,光阴似箭。,tempus fugit. slogan_5,kaWaYi!,kaWaYi!,kaWaYi!
slogan_6,快乐?伤心?痛苦?,Happy? Sad? Pain?
slogan_7,在图像和音乐中酝酿感情。,Brewing emotions in images and music.
slogan_8,罪与罚。,crime and punishment.
slogan_9,高桥李依!,Rie Takahashi!
slogan_10,0001 0011 0001 0101 0100 1111 0100,0001 0011 0001 0101 0100 1111 0100
slogan_11,恋愛偏差値上昇中!-P丸様。,恋愛偏差値上昇中!-P丸様。
slogan_12,kaWaYi!,kaWaYi!
1 id zh en jp
2 slogan_1 如果是你,你会选择金钱还是荣誉? 游戏属于每一个人。 If it were you, would you choose money or honor? The game belongs to everyone. ゲームはすべての人のものです。
3 slogan_2 游戏属于每一个人。 如果你想要得到爱,你就播种爱。 The game belongs to everyone. If you want love, you sow love. 愛を手に入れたければ、愛の種をまきます。
4 slogan_3 如果你想要得到爱,你就播种爱。 快乐?伤心?痛苦? If you want love, you sow love. Happy? Sad? Pain? 楽しいですか?悲しいですか?苦しいですか?
5 slogan_4 作为自然法则,死亡是每一个人人生的最终归宿。 0001 0011 0001 0101 0100 1111 0100 As a law of nature, everyone will end up dead. 0001 0011 0001 0101 0100 1111 0100 0001 0011 0001 0101 0100 1111 0100
6 slogan_5 光阴似箭。 kaWaYi! tempus fugit. kaWaYi! kaWaYi!
slogan_6 快乐?伤心?痛苦? Happy? Sad? Pain?
slogan_7 在图像和音乐中酝酿感情。 Brewing emotions in images and music.
slogan_8 罪与罚。 crime and punishment.
slogan_9 高桥李依! Rie Takahashi!
slogan_10 0001 0011 0001 0101 0100 1111 0100 0001 0011 0001 0101 0100 1111 0100
slogan_11 恋愛偏差値上昇中!-P丸様。 恋愛偏差値上昇中!-P丸様。
slogan_12 kaWaYi! kaWaYi!

View File

@ -6,10 +6,10 @@ uid="uid://cjtdm8ddsrd7e"
[deps] [deps]
files=["res://locals/slogan.zh.translation", "res://locals/slogan.en.translation"] files=["res://locals/slogan.zh.translation", "res://locals/slogan.en.translation", "res://locals/slogan.jp.translation"]
source_file="res://locals/slogan.csv" source_file="res://locals/slogan.csv"
dest_files=["res://locals/slogan.zh.translation", "res://locals/slogan.en.translation"] dest_files=["res://locals/slogan.zh.translation", "res://locals/slogan.en.translation", "res://locals/slogan.jp.translation"]
[params] [params]

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -146,7 +146,8 @@ hotbar_previous={
[internationalization] [internationalization]
locale/translations=PackedStringArray("res://locals/UI.en.translation", "res://locals/UI.zh.translation", "res://locals/Error.zh.translation", "res://locals/Error.en.translation", "res://locals/slogan.en.translation", "res://locals/slogan.zh.translation", "res://locals/Log.en.translation", "res://locals/Log.zh.translation", "res://locals/Weapon.en.translation", "res://locals/Weapon.zh.translation", "res://locals/InputMapping.en.translation", "res://locals/InputMapping.zh.translation") locale/translations=PackedStringArray("res://locals/UI.en.translation", "res://locals/UI.zh.translation", "res://locals/Error.zh.translation", "res://locals/Error.en.translation", "res://locals/slogan.en.translation", "res://locals/slogan.zh.translation", "res://locals/Log.en.translation", "res://locals/Log.zh.translation", "res://locals/Weapon.en.translation", "res://locals/Weapon.zh.translation", "res://locals/InputMapping.en.translation", "res://locals/InputMapping.zh.translation", "res://locals/Error.jp.translation", "res://locals/InputMapping.jp.translation", "res://locals/Log.jp.translation", "res://locals/slogan.jp.translation", "res://locals/UI.jp.translation", "res://locals/Weapon.jp.translation")
locale/test="jp"
[layer_names] [layer_names]

View File

@ -22,13 +22,15 @@ grow_vertical = 2
[node name="VBoxContainer" type="VBoxContainer" parent="CanvasLayer/Control"] [node name="VBoxContainer" type="VBoxContainer" parent="CanvasLayer/Control"]
layout_mode = 1 layout_mode = 1
anchors_preset = 2 anchors_preset = 12
anchor_top = 1.0 anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0 anchor_bottom = 1.0
offset_left = 10.0 offset_left = 20.0
offset_top = -95.0 offset_top = -85.0
offset_right = 178.0 offset_right = -20.0
offset_bottom = -10.0 offset_bottom = -20.0
grow_horizontal = 2
grow_vertical = 0 grow_vertical = 0
[node name="HealthBarUi" type="HBoxContainer" parent="CanvasLayer/Control/VBoxContainer"] [node name="HealthBarUi" type="HBoxContainer" parent="CanvasLayer/Control/VBoxContainer"]
@ -47,9 +49,11 @@ script = ExtResource("2_owrhq")
layout_mode = 2 layout_mode = 2
texture = ExtResource("2_n1yht") texture = ExtResource("2_n1yht")
[node name="OperationTip" type="Label" parent="CanvasLayer/Control/VBoxContainer"] [node name="OperationTip" type="RichTextLabel" parent="CanvasLayer/Control/VBoxContainer"]
layout_mode = 2 layout_mode = 2
text = "32323" bbcode_enabled = true
text = "OperationTip"
fit_content = true
[node name="ProjectileContainer" type="Node2D" parent="."] [node name="ProjectileContainer" type="Node2D" parent="."]

View File

@ -80,6 +80,13 @@ public static class Config
/// </summary> /// </summary>
public const int MaxStackQuantity = 99; public const int MaxStackQuantity = 99;
/// <summary>
/// <para>Operation prompts, function key text color</para>
/// <para>操作提示内,功能键文本颜色</para>
/// </summary>
public const string OperationTipActionColor = "#2b8a3e";
/// <summary> /// <summary>
/// <para>Company/Creator name</para> /// <para>Company/Creator name</para>
/// <para>公司/创作者名字</para> /// <para>公司/创作者名字</para>

View File

@ -26,5 +26,5 @@ public static class GameSceneNodeHolder
public static HealthBarUi? HealthBarUi { get; set; } public static HealthBarUi? HealthBarUi { get; set; }
public static Label? OperationTipLabel { get; set; } public static RichTextLabel? OperationTipLabel { get; set; }
} }

View File

@ -12,7 +12,7 @@ public static class SloganProvider
/// <para>Define how many banners you want to display</para> /// <para>Define how many banners you want to display</para>
/// <para>定义共有多少条标语需要展示</para> /// <para>定义共有多少条标语需要展示</para>
/// </summary> /// </summary>
private const int Total = 12; private const int Total = 5;
/// <summary> /// <summary>
/// <para>Swipe the machine to get a slogan</para> /// <para>Swipe the machine to get a slogan</para>

View File

@ -4,6 +4,7 @@ using ColdMint.scripts.camp;
using ColdMint.scripts.damage; using ColdMint.scripts.damage;
using ColdMint.scripts.health; using ColdMint.scripts.health;
using ColdMint.scripts.inventory; using ColdMint.scripts.inventory;
using ColdMint.scripts.utils;
using ColdMint.scripts.weapon; using ColdMint.scripts.weapon;
using Godot; using Godot;
@ -43,7 +44,29 @@ public partial class CharacterTemplate : CharacterBody2D
//Items currently held //Items currently held
//当前持有的物品 //当前持有的物品
public Node2D? CurrentItem; private Node2D? _currentItem;
public Node2D? CurrentItem
{
get => _currentItem;
set
{
_currentItem = value;
WhenUpdateCurrentItem(_currentItem);
}
}
/// <summary>
/// <para>When the items the character holds are updated</para>
/// <para>当角色持有的物品更新时</para>
/// </summary>
/// <param name="currentItem">
///<para>Update finished items</para>
///<para>更新完成后的物品</para>
/// </param>
protected virtual void WhenUpdateCurrentItem(Node2D? currentItem)
{
}
//Define a pick up range //Define a pick up range
//定义一个拾起范围 //定义一个拾起范围
@ -92,9 +115,32 @@ public partial class CharacterTemplate : CharacterBody2D
/// <para>Pick up all items within range</para> /// <para>Pick up all items within range</para>
/// <para>拾捡范围内的所有物品</para> /// <para>拾捡范围内的所有物品</para>
/// </summary> /// </summary>
private List<Node>? _pickingRangeBodies; protected List<Node>? PickingRangeBodiesList;
public Node[] PickingRangeBodies => _pickingRangeBodies?.ToArray() ?? Array.Empty<Node>(); public Node[] PickingRangeBodies => PickingRangeBodiesList?.ToArray() ?? Array.Empty<Node>();
/// <summary>
/// <para>Find the nearest item within the pick up area(Does not include items currently held)</para>
/// <para>在拾捡范围内查找距离最近的物品(不包括当前持有的物品)</para>
/// </summary>
/// <returns></returns>
public Node2D? FindTheNearestItem()
{
if (PickingRangeBodiesList == null || PickingRangeBodiesList.Count == 0)
{
return null;
}
HashSet<Node>? exclude = null;
if (_currentItem != null)
{
//Prevent picking up objects in your hands again.
//防止再次捡起自己手上的物品。
exclude = new HashSet<Node> { _currentItem };
}
return NodeUtils.GetTheNearestNode(this, PickingRangeBodiesList.ToArray(), exclude);
}
/// <summary> /// <summary>
@ -122,7 +168,7 @@ public partial class CharacterTemplate : CharacterBody2D
public override void _Ready() public override void _Ready()
{ {
base._Ready(); base._Ready();
_pickingRangeBodies = new List<Node>(); PickingRangeBodiesList = new List<Node>();
CharacterName = GetMeta("Name", Name).AsString(); CharacterName = GetMeta("Name", Name).AsString();
CampId = GetMeta("CampId", Config.CampId.Default).AsString(); CampId = GetMeta("CampId", Config.CampId.Default).AsString();
MaxHp = GetMeta("MaxHp", Config.DefaultMaxHp).AsInt32(); MaxHp = GetMeta("MaxHp", Config.DefaultMaxHp).AsInt32();
@ -232,7 +278,7 @@ public partial class CharacterTemplate : CharacterBody2D
weaponTemplate.Sleeping = true; weaponTemplate.Sleeping = true;
} }
if (itemSlotNode.GetItem() != null && itemSlotNode.GetItem() == item && CurrentItem == null) if (itemSlotNode.GetItem() != null && itemSlotNode.GetItem() == item && _currentItem == null)
{ {
//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. //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.
//如果物品容器内选中的物品槽是刚刚捡到的物品,且手里没有物品持有,那么我们将选中的物品放到手上。 //如果物品容器内选中的物品槽是刚刚捡到的物品,且手里没有物品持有,那么我们将选中的物品放到手上。
@ -256,12 +302,12 @@ public partial class CharacterTemplate : CharacterBody2D
/// </summary> /// </summary>
public bool UseItem(Vector2 position) public bool UseItem(Vector2 position)
{ {
if (CurrentItem == null) if (_currentItem == null)
{ {
return false; return false;
} }
if (CurrentItem is WeaponTemplate weaponTemplate) if (_currentItem is WeaponTemplate weaponTemplate)
{ {
weaponTemplate.Fire(this, position); weaponTemplate.Fire(this, position);
} }
@ -397,7 +443,12 @@ public partial class CharacterTemplate : CharacterBody2D
/// <param name="node"></param> /// <param name="node"></param>
protected virtual void EnterThePickingRangeBody(Node node) protected virtual void EnterThePickingRangeBody(Node node)
{ {
_pickingRangeBodies?.Add(node); if (node is not IItem)
{
return;
}
PickingRangeBodiesList?.Add(node);
} }
/// <summary> /// <summary>
@ -407,7 +458,12 @@ public partial class CharacterTemplate : CharacterBody2D
/// <param name="node"></param> /// <param name="node"></param>
protected virtual void ExitThePickingRangeBody(Node node) protected virtual void ExitThePickingRangeBody(Node node)
{ {
_pickingRangeBodies?.Remove(node); if (node is not IItem)
{
return;
}
PickingRangeBodiesList?.Remove(node);
} }
/// <summary> /// <summary>
@ -429,9 +485,9 @@ public partial class CharacterTemplate : CharacterBody2D
{ {
//We continuously set the position of the items to prevent them from changing as we zoom in and out of the window. //We continuously set the position of the items to prevent them from changing as we zoom in and out of the window.
//我们持续设置物品的位置,为了防止放大缩小窗口时物品位置的变化。 //我们持续设置物品的位置,为了防止放大缩小窗口时物品位置的变化。
if (CurrentItem != null) if (_currentItem != null)
{ {
CurrentItem.Position = Vector2.Zero; _currentItem.Position = Vector2.Zero;
} }
var velocity = Velocity; var velocity = Velocity;
@ -453,7 +509,7 @@ public partial class CharacterTemplate : CharacterBody2D
/// </summary> /// </summary>
public void AimTheCurrentItemAtAPoint(Vector2 position) public void AimTheCurrentItemAtAPoint(Vector2 position)
{ {
if (CurrentItem == null) if (_currentItem == null)
{ {
//Do not currently hold any items. //Do not currently hold any items.
//当前没有持有任何物品。 //当前没有持有任何物品。
@ -462,7 +518,7 @@ public partial class CharacterTemplate : CharacterBody2D
// Apply the rotation Angle to the node // Apply the rotation Angle to the node
// 将旋转角度应用于节点 // 将旋转角度应用于节点
CurrentItem.LookAt(position); _currentItem.LookAt(position);
} }

View File

@ -26,13 +26,9 @@ public partial class Player : CharacterTemplate
//用于检测玩家是否站在平台上的射线 //用于检测玩家是否站在平台上的射线
private RayCast2D? _platformDetectionRayCast2D; private RayCast2D? _platformDetectionRayCast2D;
//在拾捡范围内,可拾起的物品数量
private int _totalNumberOfPickups;
private const float PromptTextDistance = 50; private const float PromptTextDistance = 50;
//玩家可拾捡的物品
private Node2D? _pickAbleItem;
//抛出物品的飞行速度 //抛出物品的飞行速度
private float _throwingVelocity = Config.CellSize * 13; private float _throwingVelocity = Config.CellSize * 13;
@ -77,99 +73,73 @@ public partial class Player : CharacterTemplate
} }
var operationTipBuilder = new StringBuilder(); var operationTipBuilder = new StringBuilder();
if (_totalNumberOfPickups > 0)
{
//If there's anything around to pick up
//如果周围有能捡的东西
if (CurrentItem == null)
{
if (_pickAbleItem != null)
{
string? name = null;
if (_pickAbleItem is WeaponTemplate weaponTemplate)
{
//When the weapon has no owner, a pick up prompt is displayed.
//当武器没有主人时,显示捡起提示。
if (weaponTemplate.Owner == null || weaponTemplate.Owner == this)
{
name = TranslationServer.Translate(weaponTemplate.Name);
}
}
if (name != null)
{
operationTipBuilder.Append(
TranslationServer.Translate(InputMap.ActionGetEvents("pick_up")[0].AsText()));
operationTipBuilder.Append(TranslationServer.Translate("pick_up"));
operationTipBuilder.Append(name);
}
}
}
else
{
string? pickAbleItemName = null;
string? currentItemName = null;
string mustBeThrown = TranslationServer.Translate("must_be_thrown");
if (_pickAbleItem != null)
{
//可捡的物品是武器
if (_pickAbleItem is WeaponTemplate weaponTemplate)
{
pickAbleItemName = TranslationServer.Translate(weaponTemplate.Name);
}
}
if (CurrentItem != null)
{
//当前持有的物品是武器
if (CurrentItem is WeaponTemplate weaponTemplate)
{
currentItemName = TranslationServer.Translate(weaponTemplate.Name);
}
}
if (pickAbleItemName != null && currentItemName != null && mustBeThrown != "must_be_thrown")
{
operationTipBuilder.Append(string.Format(mustBeThrown, currentItemName, pickAbleItemName));
operationTipBuilder.Append(' ');
operationTipBuilder.Append(
TranslationServer.Translate(InputMap.ActionGetEvents("throw")[0].AsText()));
operationTipBuilder.Append(TranslationServer.Translate("throw"));
operationTipBuilder.Append(currentItemName);
}
}
operationTipLabel.Text = operationTipBuilder.ToString();
return;
}
operationTipBuilder.Append("[color=");
operationTipBuilder.Append(Config.OperationTipActionColor);
operationTipBuilder.Append(']');
operationTipBuilder.Append(TranslationServer.Translate(InputMap.ActionGetEvents("ui_left")[0].AsText())); operationTipBuilder.Append(TranslationServer.Translate(InputMap.ActionGetEvents("ui_left")[0].AsText()));
operationTipBuilder.Append("[/color]");
operationTipBuilder.Append(TranslationServer.Translate("move_left")); operationTipBuilder.Append(TranslationServer.Translate("move_left"));
operationTipBuilder.Append(' '); operationTipBuilder.Append(' ');
operationTipBuilder.Append("[color=");
operationTipBuilder.Append(Config.OperationTipActionColor);
operationTipBuilder.Append(']');
operationTipBuilder.Append(TranslationServer.Translate(InputMap.ActionGetEvents("ui_right")[0].AsText())); operationTipBuilder.Append(TranslationServer.Translate(InputMap.ActionGetEvents("ui_right")[0].AsText()));
operationTipBuilder.Append("[/color]");
operationTipBuilder.Append(TranslationServer.Translate("move_right")); operationTipBuilder.Append(TranslationServer.Translate("move_right"));
operationTipBuilder.Append(' '); operationTipBuilder.Append(' ');
operationTipBuilder.Append("[color=");
operationTipBuilder.Append(Config.OperationTipActionColor);
operationTipBuilder.Append(']');
operationTipBuilder.Append(TranslationServer.Translate(InputMap.ActionGetEvents("ui_up")[0].AsText())); operationTipBuilder.Append(TranslationServer.Translate(InputMap.ActionGetEvents("ui_up")[0].AsText()));
operationTipBuilder.Append("[/color]");
operationTipBuilder.Append(TranslationServer.Translate("jump")); operationTipBuilder.Append(TranslationServer.Translate("jump"));
if (_collidingWithPlatform) if (_collidingWithPlatform)
{ {
operationTipBuilder.Append(' '); operationTipBuilder.Append(' ');
operationTipBuilder.Append("[color=");
operationTipBuilder.Append(Config.OperationTipActionColor);
operationTipBuilder.Append(']');
operationTipBuilder.Append(TranslationServer.Translate(InputMap.ActionGetEvents("ui_down")[0].AsText())); operationTipBuilder.Append(TranslationServer.Translate(InputMap.ActionGetEvents("ui_down")[0].AsText()));
operationTipBuilder.Append("[/color]");
operationTipBuilder.Append(TranslationServer.Translate("jump_down")); operationTipBuilder.Append(TranslationServer.Translate("jump_down"));
} }
//If the PickingRangeBodiesList is not null and the length is greater than 0
//如果PickingRangeBodiesList不是null且长度大于0
if (PickingRangeBodiesList is { Count: > 0 })
{
operationTipBuilder.Append(' ');
operationTipBuilder.Append("[color=");
operationTipBuilder.Append(Config.OperationTipActionColor);
operationTipBuilder.Append(']');
operationTipBuilder.Append(
TranslationServer.Translate(InputMap.ActionGetEvents("pick_up")[0].AsText()));
operationTipBuilder.Append("[/color]");
operationTipBuilder.Append(TranslationServer.Translate("pick_up"));
operationTipLabel.Text = operationTipBuilder.ToString();
}
if (CurrentItem != null) if (CurrentItem != null)
{ {
operationTipBuilder.Append(' '); operationTipBuilder.Append(' ');
operationTipBuilder.Append("[color=");
operationTipBuilder.Append(Config.OperationTipActionColor);
operationTipBuilder.Append(']');
operationTipBuilder.Append(TranslationServer.Translate(InputMap.ActionGetEvents("throw")[0].AsText())); operationTipBuilder.Append(TranslationServer.Translate(InputMap.ActionGetEvents("throw")[0].AsText()));
operationTipBuilder.Append("[/color]");
operationTipBuilder.Append(TranslationServer.Translate("throw")); operationTipBuilder.Append(TranslationServer.Translate("throw"));
if (CurrentItem is WeaponTemplate weaponTemplate) if (CurrentItem is WeaponTemplate weaponTemplate)
{ {
operationTipBuilder.Append(TranslationServer.Translate(weaponTemplate.Name)); operationTipBuilder.Append(TranslationServer.Translate(weaponTemplate.Name));
//提示武器攻击 //提示武器攻击
operationTipBuilder.Append(' '); operationTipBuilder.Append(' ');
operationTipBuilder.Append("[color=");
operationTipBuilder.Append(Config.OperationTipActionColor);
operationTipBuilder.Append(']');
operationTipBuilder.Append( operationTipBuilder.Append(
TranslationServer.Translate(InputMap.ActionGetEvents("use_item")[0].AsText())); TranslationServer.Translate(InputMap.ActionGetEvents("use_item")[0].AsText()));
operationTipBuilder.Append("[/color]");
operationTipBuilder.Append(TranslationServer.Translate("use_item")); operationTipBuilder.Append(TranslationServer.Translate("use_item"));
operationTipBuilder.Append(TranslationServer.Translate(weaponTemplate.Name)); operationTipBuilder.Append(TranslationServer.Translate(weaponTemplate.Name));
} }
@ -212,18 +182,20 @@ public partial class Player : CharacterTemplate
//捡起物品 //捡起物品
if (Input.IsActionJustPressed("pick_up")) if (Input.IsActionJustPressed("pick_up"))
{ {
var success = PickItem(_pickAbleItem); var pickAbleItem = FindTheNearestItem();
var success = PickItem(pickAbleItem);
if (success) if (success)
{ {
_pickAbleItem = null; if (pickAbleItem != null)
_totalNumberOfPickups--; {
PickingRangeBodiesList?.Remove(pickAbleItem);
}
if (_floatLabel != null) if (_floatLabel != null)
{ {
_floatLabel.QueueFree(); _floatLabel.QueueFree();
_floatLabel = null; _floatLabel = null;
} }
UpdateOperationTip();
} }
} }
@ -278,6 +250,7 @@ public partial class Player : CharacterTemplate
{ {
return; return;
} }
if (_parabola != null) if (_parabola != null)
{ {
_parabola.Points = new[] { Vector2.Zero }; _parabola.Points = new[] { Vector2.Zero };
@ -319,16 +292,16 @@ public partial class Player : CharacterTemplate
rigidBody2D.LinearVelocity = GetThrowVelocity(); rigidBody2D.LinearVelocity = GetThrowVelocity();
break; break;
} }
CurrentItem = null; CurrentItem = null;
_totalNumberOfPickups++;
var hotBar = GameSceneNodeHolder.HotBar; var hotBar = GameSceneNodeHolder.HotBar;
hotBar?.RemoveItemFromItemSlotBySelectIndex(1); hotBar?.RemoveItemFromItemSlotBySelectIndex(1);
}
}
protected override void WhenUpdateCurrentItem(Node2D? currentItem)
{
UpdateOperationTip(); UpdateOperationTip();
} }
}
private Vector2 GetThrowVelocity() private Vector2 GetThrowVelocity()
{ {
@ -392,6 +365,7 @@ public partial class Player : CharacterTemplate
protected override void EnterThePickingRangeBody(Node node) protected override void EnterThePickingRangeBody(Node node)
{ {
base.EnterThePickingRangeBody(node);
if (CurrentItem == node) if (CurrentItem == node)
{ {
//If the node entering the pick range is the node held by the player, then return. //If the node entering the pick range is the node held by the player, then return.
@ -404,8 +378,6 @@ public partial class Player : CharacterTemplate
return; return;
} }
_totalNumberOfPickups++;
_pickAbleItem = node2D;
if (_floatLabelPackedScene != null) if (_floatLabelPackedScene != null)
{ {
//If there is a scene of floating text, then we generate floating text. //If there is a scene of floating text, then we generate floating text.
@ -440,19 +412,12 @@ public partial class Player : CharacterTemplate
protected override void ExitThePickingRangeBody(Node node) protected override void ExitThePickingRangeBody(Node node)
{ {
base.ExitThePickingRangeBody(node);
if (node is not Node2D) if (node is not Node2D)
{ {
return; return;
} }
_totalNumberOfPickups--;
if (_totalNumberOfPickups == 0)
{
//Set to null if there are no more items to pick up
//如果没有可捡的物品了设置为null
_pickAbleItem = null;
}
if (_floatLabel != null) if (_floatLabel != null)
{ {
_floatLabel.QueueFree(); _floatLabel.QueueFree();

View File

@ -27,7 +27,7 @@ public partial class GameSceneLoader : SceneLoaderTemplate
var hotBar = GetNode<HotBar>("CanvasLayer/Control/VBoxContainer/HotBar"); var hotBar = GetNode<HotBar>("CanvasLayer/Control/VBoxContainer/HotBar");
GameSceneNodeHolder.HotBar = hotBar; GameSceneNodeHolder.HotBar = hotBar;
//加载操作提示 //加载操作提示
var operationTip = GetNode<Label>("CanvasLayer/Control/VBoxContainer/OperationTip"); var operationTip = GetNode<RichTextLabel>("CanvasLayer/Control/VBoxContainer/OperationTip");
GameSceneNodeHolder.OperationTipLabel = operationTip; GameSceneNodeHolder.OperationTipLabel = operationTip;
//加载武器容器 //加载武器容器
var weaponContainer = GetNode<Node2D>("WeaponContainer"); var weaponContainer = GetNode<Node2D>("WeaponContainer");

View File

@ -1,4 +1,5 @@
using System.Threading.Tasks; using System.Collections.Generic;
using System.Threading.Tasks;
using Godot; using Godot;
namespace ColdMint.scripts.utils; namespace ColdMint.scripts.utils;
@ -36,4 +37,59 @@ public class NodeUtils
{ {
return await Task.Run(() => DeleteAllChild(parent)); return await Task.Run(() => DeleteAllChild(parent));
} }
/// <summary>
/// <para>Gets the node closest to the origin</para>
/// <para>获取距离原点最近的节点</para>
/// </summary>
/// <param name="origin">
///<para>origin</para>
///<para>原点</para>
/// </param>
/// <param name="array">
///<para>Node array</para>
///<para>节点数组</para>
/// </param>
/// <param name="exclude">
///<para>Which nodes are excluded</para>
///<para>排除哪些节点</para>
/// </param>
/// <param name="excludeInvisibleNodes">
///<para>Whether or not unseen nodes should be excluded</para>
///<para>是否排除不可见的节点</para>
/// </param>
/// <returns></returns>
public static Node2D? GetTheNearestNode(Node2D origin, Node[] array, HashSet<Node>? exclude = null,
bool excludeInvisibleNodes = true)
{
var closestDistance = float.MaxValue;
Node2D? closestNode = null;
foreach (var node in array)
{
if (node is not Node2D node2D) continue;
if (excludeInvisibleNodes && !node2D.Visible)
{
//If invisible nodes are excluded and the current node is invisible, then the next.
//如果排除不可见的节点,且当前节点就是不可见的,那么下一个。
continue;
}
if (exclude != null && exclude.Contains(node))
{
//If the current node, is within our exclusion project. So the next one.
//如果当前节点,在我们的排除项目内。那么下一个。
continue;
}
var distance = node2D.GlobalPosition - origin.GlobalPosition;
var distanceLength = distance.Length();
if (distanceLength < closestDistance)
{
closestDistance = distanceLength;
closestNode = node2D;
}
}
return closestNode;
}
} }