Merge branch 'refs/heads/master' into loot_rebuild
# Conflicts: # data/itemRegs/weapons.yaml # locals/Log.csv # prefab/weapons/staffOfTheUndead.tscn # scripts/character/CharacterTemplate.cs # scripts/item/ItemTypeManager.cs # scripts/item/weapon/WeaponTemplate.cs # scripts/loader/uiLoader/MainMenuLoader.cs
|
@ -1,4 +1,4 @@
|
||||||
- id: packsack
|
- id: packsack
|
||||||
scene_path: res://prefab/packsacks/packsack.tscn
|
scene_path: res://prefab/packsacks/packsack.tscn
|
||||||
icon_path: res://sprites/Player.png
|
icon_path: res://sprites/packsack.png
|
||||||
max_stack_value: 1
|
max_stack_value: 1
|
|
@ -1,6 +1,6 @@
|
||||||
- id: staff_of_the_undead
|
- id: staff_of_the_undead
|
||||||
scene_path: res://prefab/weapons/staffOfTheUndead.tscn
|
scene_path: res://prefab/weapons/staffOfTheUndead.tscn
|
||||||
icon_path: res://sprites/weapon/staffOfTheUndead.png
|
icon_path: res://sprites/weapon/staffOfTheUndead_icon.png
|
||||||
max_stack_value: 1
|
max_stack_value: 1
|
||||||
custom_args:
|
custom_args:
|
||||||
- name: FiringIntervalAsMillisecond
|
- name: FiringIntervalAsMillisecond
|
||||||
|
|
|
@ -25,3 +25,11 @@ ui_room_injection_processor,房间注入处理器,Room injection processor,部
|
||||||
ui_game_over_title,游戏结束!,Game Over!,ゲームオーバー!
|
ui_game_over_title,游戏结束!,Game Over!,ゲームオーバー!
|
||||||
ui_death_info_describe,死因,death,死因
|
ui_death_info_describe,死因,death,死因
|
||||||
ui_restart,重新开始,Restart,ぶり返す
|
ui_restart,重新开始,Restart,ぶり返す
|
||||||
|
ui_contributor_tips,由{0}位贡献者共同打造,Built by {0} contributors,{0}のコントリビューターが共同で作り上げました
|
||||||
|
ui_contributor,贡献者,contributor,貢献者です
|
||||||
|
ui_coder,编程,coder,程序设计
|
||||||
|
ui_artist,美术,artist,びじゅつ
|
||||||
|
ui_musician,音乐,musician,音楽
|
||||||
|
ui_character_voice,角色配音,character_voice,キャラクターボイスです
|
||||||
|
ui_translator,翻译,translator,翻訳
|
||||||
|
ui_unordered_list_tip,排名不分先后,Ranking is not in order,順位は関係ありません
|
||||||
|
|
|
|
@ -1,20 +1,34 @@
|
||||||
[gd_scene load_steps=4 format=3 uid="uid://cn10fimoem04m"]
|
[gd_scene load_steps=5 format=3 uid="uid://cn10fimoem04m"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://scripts/item/Packsack.cs" id="1_slakl"]
|
[ext_resource type="Script" path="res://scripts/item/Packsack.cs" id="1_slakl"]
|
||||||
[ext_resource type="Texture2D" uid="uid://b1twcink38sh0" path="res://sprites/Player.png" id="2_e1ale"]
|
[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"]
|
[sub_resource type="RectangleShape2D" id="RectangleShape2D_xqyue"]
|
||||||
size = Vector2(41, 57)
|
size = Vector2(21, 29)
|
||||||
|
|
||||||
[node name="RigidBody2D" type="RigidBody2D"]
|
[node name="RigidBody2D" type="RigidBody2D"]
|
||||||
collision_layer = 8
|
collision_layer = 8
|
||||||
collision_mask = 38
|
collision_mask = 38
|
||||||
script = ExtResource("1_slakl")
|
script = ExtResource("1_slakl")
|
||||||
Id = "packsack"
|
Id = "packsack"
|
||||||
|
_minContactInjury = null
|
||||||
|
_maxContactInjury = null
|
||||||
|
|
||||||
[node name="Player" type="Sprite2D" parent="."]
|
[node name="DamageArea2D" type="Area2D" parent="."]
|
||||||
texture = ExtResource("2_e1ale")
|
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="."]
|
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
||||||
position = Vector2(-0.5, 3.5)
|
position = Vector2(-2.5, 1.5)
|
||||||
shape = SubResource("RectangleShape2D_xqyue")
|
shape = SubResource("RectangleShape2D_xqyue")
|
||||||
|
|
||||||
|
[node name="Packsack" type="Sprite2D" parent="."]
|
||||||
|
scale = Vector2(0.5, 0.5)
|
||||||
|
texture = ExtResource("2_40jca")
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
[node name="ItemSlot" type="MarginContainer"]
|
[node name="ItemSlot" type="MarginContainer"]
|
||||||
offset_right = 38.0
|
offset_right = 38.0
|
||||||
offset_bottom = 38.0
|
offset_bottom = 38.0
|
||||||
|
size_flags_vertical = 3
|
||||||
theme_override_constants/margin_left = 3
|
theme_override_constants/margin_left = 3
|
||||||
theme_override_constants/margin_top = 3
|
theme_override_constants/margin_top = 3
|
||||||
theme_override_constants/margin_right = 3
|
theme_override_constants/margin_right = 3
|
||||||
|
@ -16,16 +17,18 @@ script = ExtResource("1_fbwot")
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
texture = ExtResource("1_y2wyt")
|
texture = ExtResource("1_y2wyt")
|
||||||
|
|
||||||
[node name="CenterContainer" type="CenterContainer" parent="BackgroundTexture"]
|
[node name="IconTextureRect" type="TextureRect" parent="BackgroundTexture"]
|
||||||
layout_mode = 2
|
layout_mode = 1
|
||||||
offset_right = 160.0
|
anchors_preset = 15
|
||||||
offset_bottom = 160.0
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_left = 3.0
|
||||||
|
offset_top = 3.0
|
||||||
|
offset_right = -3.0
|
||||||
|
offset_bottom = -3.0
|
||||||
grow_horizontal = 2
|
grow_horizontal = 2
|
||||||
grow_vertical = 2
|
grow_vertical = 2
|
||||||
scale = Vector2(0.2, 0.2)
|
expand_mode = 1
|
||||||
|
|
||||||
[node name="IconTextureRect" type="TextureRect" parent="BackgroundTexture/CenterContainer"]
|
|
||||||
layout_mode = 2
|
|
||||||
|
|
||||||
[node name="Control" type="Control" parent="."]
|
[node name="Control" type="Control" parent="."]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
|
36
prefab/ui/contributorGroup.tscn
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
[gd_scene load_steps=2 format=3 uid="uid://6i7rgx3sdu1k"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://scripts/loader/uiLoader/ContributorGroupLoader.cs" id="1_xwjh1"]
|
||||||
|
|
||||||
|
[node name="ContributorGroup" type="Control"]
|
||||||
|
layout_mode = 3
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
script = ExtResource("1_xwjh1")
|
||||||
|
|
||||||
|
[node name="TitleLabel" type="Label" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 10
|
||||||
|
anchor_right = 1.0
|
||||||
|
offset_left = 20.0
|
||||||
|
offset_right = -1082.0
|
||||||
|
offset_bottom = 39.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
theme_override_font_sizes/font_size = 25
|
||||||
|
text = "组名"
|
||||||
|
|
||||||
|
[node name="HFlowContainer" type="HFlowContainer" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_left = 15.0
|
||||||
|
offset_top = 45.0
|
||||||
|
offset_right = -14.0
|
||||||
|
offset_bottom = -6.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
32
prefab/ui/packsackUI.tscn
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
[gd_scene load_steps=2 format=3 uid="uid://dsat7xk63bfg2"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://scripts/inventory/PacksackUi.cs" id="1_jgs18"]
|
||||||
|
|
||||||
|
[node name="PacksackUi" type="Control"]
|
||||||
|
layout_mode = 3
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_left = 33.0
|
||||||
|
offset_top = 81.0
|
||||||
|
offset_right = -58.0
|
||||||
|
offset_bottom = -35.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
script = ExtResource("1_jgs18")
|
||||||
|
|
||||||
|
[node name="GridContainer" type="GridContainer" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
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_left = 3.0
|
||||||
|
offset_top = -43.0
|
||||||
|
offset_right = 43.0
|
||||||
|
offset_bottom = -18.0
|
||||||
|
text = "背包"
|
|
@ -21,7 +21,7 @@ metadata/Projectiles = PackedStringArray("res://prefab/projectile/curseOfTheUnde
|
||||||
|
|
||||||
[node name="DamageArea2D" type="Area2D" parent="."]
|
[node name="DamageArea2D" type="Area2D" parent="."]
|
||||||
collision_layer = 8
|
collision_layer = 8
|
||||||
collision_mask = 71
|
collision_mask = 70
|
||||||
|
|
||||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="DamageArea2D"]
|
[node name="CollisionShape2D" type="CollisionShape2D" parent="DamageArea2D"]
|
||||||
position = Vector2(25.5, 0.5)
|
position = Vector2(25.5, 0.5)
|
||||||
|
|
|
@ -153,7 +153,7 @@ locale/translations=PackedStringArray("res://locals/DeathInfo.en.translation", "
|
||||||
2d_physics/layer_1="RoomArea"
|
2d_physics/layer_1="RoomArea"
|
||||||
2d_physics/layer_2="Ground"
|
2d_physics/layer_2="Ground"
|
||||||
2d_physics/layer_3="Player"
|
2d_physics/layer_3="Player"
|
||||||
2d_physics/layer_4="Weapon"
|
2d_physics/layer_4="PickAbleItem"
|
||||||
2d_physics/layer_5="Projectile"
|
2d_physics/layer_5="Projectile"
|
||||||
2d_physics/layer_6="Platform"
|
2d_physics/layer_6="Platform"
|
||||||
2d_physics/layer_7="Mob"
|
2d_physics/layer_7="Mob"
|
||||||
|
|
68
scenes/contributor.tscn
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
[gd_scene load_steps=2 format=3 uid="uid://ljvmhhrk1d6j"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://scripts/loader/uiLoader/ContributorLoader.cs" id="1_ia4x6"]
|
||||||
|
|
||||||
|
[node name="Contributor" type="Control"]
|
||||||
|
layout_mode = 3
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
script = ExtResource("1_ia4x6")
|
||||||
|
|
||||||
|
[node name="Panel" type="Panel" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
|
||||||
|
[node name="CenterContainer" type="CenterContainer" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 10
|
||||||
|
anchor_right = 1.0
|
||||||
|
offset_bottom = 45.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="CenterContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_font_sizes/font_size = 30
|
||||||
|
text = "ui_contributor"
|
||||||
|
|
||||||
|
[node name="ExitButton" type="Button" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 1
|
||||||
|
anchor_left = 1.0
|
||||||
|
anchor_right = 1.0
|
||||||
|
offset_left = -86.0
|
||||||
|
offset_top = 6.0
|
||||||
|
offset_right = -19.0
|
||||||
|
offset_bottom = 39.0
|
||||||
|
grow_horizontal = 0
|
||||||
|
text = "ui_close"
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_left = 20.0
|
||||||
|
offset_top = 59.0
|
||||||
|
offset_right = -18.0
|
||||||
|
offset_bottom = -20.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 2
|
||||||
|
anchor_top = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_left = 16.0
|
||||||
|
offset_top = -36.0
|
||||||
|
offset_right = 168.0
|
||||||
|
offset_bottom = -11.0
|
||||||
|
grow_vertical = 0
|
||||||
|
text = "ui_unordered_list_tip"
|
|
@ -119,6 +119,12 @@ grow_vertical = 0
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
horizontal_alignment = 2
|
horizontal_alignment = 2
|
||||||
|
|
||||||
|
[node name="ContributorButton" type="LinkButton" parent="VBoxContainer2"]
|
||||||
|
layout_direction = 3
|
||||||
|
layout_mode = 2
|
||||||
|
text = "ui_contributor_tips"
|
||||||
|
underline = 1
|
||||||
|
|
||||||
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer2"]
|
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer2"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
|
||||||
|
|
|
@ -377,7 +377,7 @@ public static class Config
|
||||||
public const int RoomArea = 1;
|
public const int RoomArea = 1;
|
||||||
public const int Ground = 2;
|
public const int Ground = 2;
|
||||||
public const int Player = 3;
|
public const int Player = 3;
|
||||||
public const int Weapon = 4;
|
public const int PickAbleItem = 4;
|
||||||
public const int Projectile = 5;
|
public const int Projectile = 5;
|
||||||
public const int Platform = 6;
|
public const int Platform = 6;
|
||||||
public const int Mob = 7;
|
public const int Mob = 7;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using ColdMint.scripts.utils;
|
using ColdMint.scripts.utils;
|
||||||
|
|
||||||
using Godot;
|
using Godot;
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ using ColdMint.scripts.item;
|
||||||
using ColdMint.scripts.utils;
|
using ColdMint.scripts.utils;
|
||||||
using ColdMint.scripts.item.weapon;
|
using ColdMint.scripts.item.weapon;
|
||||||
using ColdMint.scripts.loot;
|
using ColdMint.scripts.loot;
|
||||||
|
using ColdMint.scripts.pickable;
|
||||||
|
|
||||||
using Godot;
|
using Godot;
|
||||||
|
|
||||||
|
@ -300,14 +301,14 @@ public partial class CharacterTemplate : CharacterBody2D
|
||||||
//设置捡起物品的常规处理。
|
//设置捡起物品的常规处理。
|
||||||
//You can supplement picking up state handling for more types of objects here.
|
//You can supplement picking up state handling for more types of objects here.
|
||||||
//您可以在这里补充更多类型对象的捡起状态处理。
|
//您可以在这里补充更多类型对象的捡起状态处理。
|
||||||
if (pickAbleItem is WeaponTemplate weaponTemplate)
|
if (pickAbleItem is PickAbleTemplate pickAbleTemplate)
|
||||||
{
|
{
|
||||||
weaponTemplate.Owner = this;
|
pickAbleTemplate.Owner = this;
|
||||||
weaponTemplate.Picked = true;
|
pickAbleTemplate.Picked = true;
|
||||||
weaponTemplate.SetCollisionMaskValue(Config.LayerNumber.Platform, false);
|
pickAbleTemplate.SetCollisionMaskValue(Config.LayerNumber.Platform, false);
|
||||||
weaponTemplate.SetCollisionMaskValue(Config.LayerNumber.Ground, false);
|
pickAbleTemplate.SetCollisionMaskValue(Config.LayerNumber.Ground, false);
|
||||||
weaponTemplate.EnableContactInjury = false;
|
pickAbleTemplate.EnableContactInjury = false;
|
||||||
weaponTemplate.Sleeping = true;
|
pickAbleTemplate.Sleeping = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (itemSlotNode.GetItem() != null && itemSlotNode.GetItem() == item && _currentItem == null)
|
if (itemSlotNode.GetItem() != null && itemSlotNode.GetItem() == item && _currentItem == null)
|
||||||
|
@ -652,31 +653,31 @@ public partial class CharacterTemplate : CharacterBody2D
|
||||||
CallDeferred(nameof(NodeReparent), node2D);
|
CallDeferred(nameof(NodeReparent), node2D);
|
||||||
switch (item)
|
switch (item)
|
||||||
{
|
{
|
||||||
case WeaponTemplate weaponTemplate:
|
case PickAbleTemplate pickAbleTemplate:
|
||||||
if (GameSceneNodeHolder.WeaponContainer == null)
|
if (GameSceneNodeHolder.WeaponContainer == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
weaponTemplate.Picked = false;
|
pickAbleTemplate.Picked = false;
|
||||||
var timer = new Timer();
|
var timer = new Timer();
|
||||||
weaponTemplate.AddChild(timer);
|
pickAbleTemplate.AddChild(timer);
|
||||||
timer.WaitTime = _itemCollisionRecoveryTime;
|
timer.WaitTime = _itemCollisionRecoveryTime;
|
||||||
timer.OneShot = true;
|
timer.OneShot = true;
|
||||||
timer.Timeout += () =>
|
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.
|
//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.
|
||||||
//仍出武器时,我们不能立即恢复物理碰撞,立即恢复会导致武器更早的与地面和平台碰撞,阻止武器的飞行。
|
//仍出武器时,我们不能立即恢复物理碰撞,立即恢复会导致武器更早的与地面和平台碰撞,阻止武器的飞行。
|
||||||
weaponTemplate.EnableContactInjury = true;
|
pickAbleTemplate.EnableContactInjury = true;
|
||||||
weaponTemplate.SetCollisionMaskValue(Config.LayerNumber.Ground, true);
|
pickAbleTemplate.SetCollisionMaskValue(Config.LayerNumber.Ground, true);
|
||||||
weaponTemplate.SetCollisionMaskValue(Config.LayerNumber.Platform, true);
|
pickAbleTemplate.SetCollisionMaskValue(Config.LayerNumber.Platform, true);
|
||||||
timer.QueueFree();
|
timer.QueueFree();
|
||||||
};
|
};
|
||||||
timer.Start();
|
timer.Start();
|
||||||
weaponTemplate.Sleeping = false;
|
pickAbleTemplate.Sleeping = false;
|
||||||
//Setting an initial speed of 0 for items here prevents the problem of throwing items too fast.
|
//Setting an initial speed of 0 for items here prevents the problem of throwing items too fast.
|
||||||
//在这里给物品设置一个为0的初始速度,可防止扔出物品时速度过快的问题。
|
//在这里给物品设置一个为0的初始速度,可防止扔出物品时速度过快的问题。
|
||||||
weaponTemplate.LinearVelocity = Vector2.Zero;
|
pickAbleTemplate.LinearVelocity = Vector2.Zero;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,11 @@ using System.Threading.Tasks;
|
||||||
|
|
||||||
using ColdMint.scripts.damage;
|
using ColdMint.scripts.damage;
|
||||||
using ColdMint.scripts.deathInfo;
|
using ColdMint.scripts.deathInfo;
|
||||||
|
using ColdMint.scripts.debug;
|
||||||
using ColdMint.scripts.item;
|
using ColdMint.scripts.item;
|
||||||
using ColdMint.scripts.map.events;
|
using ColdMint.scripts.map.events;
|
||||||
using ColdMint.scripts.utils;
|
using ColdMint.scripts.utils;
|
||||||
using ColdMint.scripts.item.weapon;
|
using ColdMint.scripts.pickable;
|
||||||
|
|
||||||
using Godot;
|
using Godot;
|
||||||
|
|
||||||
namespace ColdMint.scripts.character;
|
namespace ColdMint.scripts.character;
|
||||||
|
@ -24,7 +24,7 @@ public partial class Player : CharacterTemplate
|
||||||
|
|
||||||
//Empty object projectile
|
//Empty object projectile
|
||||||
//空的物品抛射线
|
//空的物品抛射线
|
||||||
private readonly Vector2[] _emptyVector2Array = new[] { Vector2.Zero };
|
private readonly Vector2[] _emptyVector2Array = [Vector2.Zero];
|
||||||
|
|
||||||
//抛物线
|
//抛物线
|
||||||
private Line2D? _parabola;
|
private Line2D? _parabola;
|
||||||
|
@ -337,9 +337,9 @@ public partial class Player : CharacterTemplate
|
||||||
base.Flip();
|
base.Flip();
|
||||||
//If there is a weapon, flip it too
|
//If there is a weapon, flip it too
|
||||||
//如果有武器的话,也要翻转
|
//如果有武器的话,也要翻转
|
||||||
if (CurrentItem is WeaponTemplate weapon)
|
if (CurrentItem is PickAbleTemplate pickAbleTemplate)
|
||||||
{
|
{
|
||||||
weapon.Flip(FacingLeft);
|
pickAbleTemplate.Flip(FacingLeft);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,16 +408,16 @@ public partial class Player : CharacterTemplate
|
||||||
: new Vector2(0, -PromptTextDistance);
|
: new Vector2(0, -PromptTextDistance);
|
||||||
_floatLabel.RotationDegrees = 0 - rotationDegreesNode2D;
|
_floatLabel.RotationDegrees = 0 - rotationDegreesNode2D;
|
||||||
var label = _floatLabel.GetNode<Label>("Label");
|
var label = _floatLabel.GetNode<Label>("Label");
|
||||||
if (node is WeaponTemplate weapon)
|
if (node is PickAbleTemplate pickAbleTemplate)
|
||||||
{
|
{
|
||||||
var stringBuilder = new StringBuilder();
|
var stringBuilder = new StringBuilder();
|
||||||
if (weapon.Owner is CharacterTemplate characterTemplate)
|
if (pickAbleTemplate.Owner is CharacterTemplate characterTemplate)
|
||||||
{
|
{
|
||||||
stringBuilder.Append(characterTemplate.ReadOnlyCharacterName);
|
stringBuilder.Append(characterTemplate.ReadOnlyCharacterName);
|
||||||
stringBuilder.Append(TranslationServerUtils.Translate("de"));
|
stringBuilder.Append(TranslationServerUtils.Translate("de"));
|
||||||
}
|
}
|
||||||
|
|
||||||
stringBuilder.Append(TranslationServerUtils.Translate(weapon.Name));
|
stringBuilder.Append(TranslationServerUtils.Translate(pickAbleTemplate.Name));
|
||||||
label.Text = stringBuilder.ToString();
|
label.Text = stringBuilder.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
32
scripts/contribute/ContributorData.cs
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
namespace ColdMint.scripts.contribute;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Contributor information</para>
|
||||||
|
/// <para>贡献者数据</para>
|
||||||
|
/// </summary>
|
||||||
|
public class ContributorData
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Contributor's name</para>
|
||||||
|
/// <para>贡献者的名字</para>
|
||||||
|
/// </summary>
|
||||||
|
public string? Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Links to contributors' home pages</para>
|
||||||
|
/// <para>贡献者的主页链接</para>
|
||||||
|
/// </summary>
|
||||||
|
public string? Url { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>ToolTip</para>
|
||||||
|
/// <para>工具提示</para>
|
||||||
|
/// </summary>
|
||||||
|
public string? ToolTip { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Type of contribution</para>
|
||||||
|
/// <para>贡献的类型</para>
|
||||||
|
/// </summary>
|
||||||
|
public ContributorType[]? ContributorTypes { get; set; }
|
||||||
|
}
|
159
scripts/contribute/ContributorDataManager.cs
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using ColdMint.scripts.utils;
|
||||||
|
|
||||||
|
namespace ColdMint.scripts.contribute;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Contributor data Manager</para>
|
||||||
|
/// <para>贡献者数据管理器</para>
|
||||||
|
/// </summary>
|
||||||
|
public static class ContributorDataManager
|
||||||
|
{
|
||||||
|
private static Dictionary<ContributorType, List<ContributorData>>? _contributorTypeDictionary;
|
||||||
|
|
||||||
|
private static readonly ContributorData[] ContributorArray =
|
||||||
|
[
|
||||||
|
new ContributorData
|
||||||
|
{
|
||||||
|
Name = "Cold-Mint",
|
||||||
|
Url = "https://github.com/Cold-Mint",
|
||||||
|
ContributorTypes = [ContributorType.Coder],
|
||||||
|
},
|
||||||
|
new ContributorData
|
||||||
|
{
|
||||||
|
Name = "霧雨烨",
|
||||||
|
Url = "https://github.com/Web13234",
|
||||||
|
ContributorTypes = [ContributorType.Coder]
|
||||||
|
},
|
||||||
|
new ContributorData
|
||||||
|
{
|
||||||
|
Name = "[HYPERLINK BLOCKED]",
|
||||||
|
Url = "https://www.pixiv.net/users/74412798",
|
||||||
|
ContributorTypes = [ContributorType.Artist],
|
||||||
|
ToolTip = "贡献死灵法杖和背包的贴图。"
|
||||||
|
},
|
||||||
|
new ContributorData
|
||||||
|
{
|
||||||
|
Name = "\u2605如爱生",
|
||||||
|
Url = "https://space.bilibili.com/425243934",
|
||||||
|
ContributorTypes = [ContributorType.Artist],
|
||||||
|
ToolTip = "贡献了一些枪械贴图。"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Get contributor totals</para>
|
||||||
|
/// <para>获取贡献者总数</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static int GetContributorTotals()
|
||||||
|
{
|
||||||
|
return ContributorArray.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Gets a dictionary of contribution types to the contributor array</para>
|
||||||
|
/// <para>获取贡献类型到贡献者数组的字典</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
///<para>Cache the results after calling this method, as it is very expensive to generate results.</para>
|
||||||
|
///<para>调用此方法后请将结果缓存起来,因为生成结果是非常昂贵的。</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>
|
||||||
|
/// </returns>
|
||||||
|
public static Dictionary<ContributorType, ContributorData[]>? GetContributorTypeToContributorDataArray()
|
||||||
|
{
|
||||||
|
if (_contributorTypeDictionary == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = new Dictionary<ContributorType, ContributorData[]>();
|
||||||
|
foreach (var contributorType in _contributorTypeDictionary.Keys)
|
||||||
|
{
|
||||||
|
result[contributorType] = _contributorTypeDictionary[contributorType].ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Register all contributor data</para>
|
||||||
|
/// <para>注册所有的贡献者数据</para>
|
||||||
|
/// </summary>
|
||||||
|
public static void RegisterAllContributorData()
|
||||||
|
{
|
||||||
|
if (_contributorTypeDictionary!= null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
foreach (var contributorData in ContributorArray)
|
||||||
|
{
|
||||||
|
RegisterContributorData(contributorData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Gets a string description of a contribution type</para>
|
||||||
|
/// <para>获取某个贡献类型的字符串描述</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="contributorType"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="ArgumentOutOfRangeException"></exception>
|
||||||
|
public static string? ContributorTypeToString(ContributorType contributorType)
|
||||||
|
{
|
||||||
|
return contributorType switch
|
||||||
|
{
|
||||||
|
ContributorType.Coder => TranslationServerUtils.Translate("ui_coder"),
|
||||||
|
ContributorType.Artist => TranslationServerUtils.Translate("ui_artist"),
|
||||||
|
ContributorType.Musician => TranslationServerUtils.Translate("ui_musician"),
|
||||||
|
ContributorType.CharacterVoice => TranslationServerUtils.Translate("ui_character_voice"),
|
||||||
|
ContributorType.Translator => TranslationServerUtils.Translate("ui_translator"),
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(contributorType), contributorType, null)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Register contributor data to the type dictionary</para>
|
||||||
|
/// <para>注册贡献者数据到类型字典</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="contributorType"></param>
|
||||||
|
/// <param name="contributorData"></param>
|
||||||
|
private static void AddContributorDataToTypeDictionary(ContributorType contributorType,
|
||||||
|
ContributorData contributorData)
|
||||||
|
{
|
||||||
|
if (_contributorTypeDictionary == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_contributorTypeDictionary.ContainsKey(contributorType))
|
||||||
|
{
|
||||||
|
_contributorTypeDictionary[contributorType].Add(contributorData);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_contributorTypeDictionary[contributorType] = [contributorData];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Register Contributor data</para>
|
||||||
|
/// <para>注册贡献者数据</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="contributorData"></param>
|
||||||
|
private static void RegisterContributorData(ContributorData contributorData)
|
||||||
|
{
|
||||||
|
if (contributorData.Name == null || contributorData.ContributorTypes == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_contributorTypeDictionary ??= new Dictionary<ContributorType, List<ContributorData>>();
|
||||||
|
foreach (var contributorDataContributorType in contributorData.ContributorTypes)
|
||||||
|
{
|
||||||
|
AddContributorDataToTypeDictionary(contributorDataContributorType, contributorData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
54
scripts/contribute/ContributorType.cs
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
namespace ColdMint.scripts.contribute;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Contribution type</para>
|
||||||
|
/// <para>贡献类型</para>
|
||||||
|
/// </summary>
|
||||||
|
public enum ContributorType
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Coder</para>
|
||||||
|
/// <para>程序员</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
///<para>Contributed code to the project</para>
|
||||||
|
///<para>为项目贡献了代码</para>
|
||||||
|
/// </remarks>
|
||||||
|
Coder,
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Artist</para>
|
||||||
|
/// <para>美术</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
///<para>Contributed art assets to the project</para>
|
||||||
|
///<para>为项目贡献了美术资产</para>
|
||||||
|
/// </remarks>
|
||||||
|
Artist,
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Musician</para>
|
||||||
|
/// <para>音乐家</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
///<para>Contributed music, sound assets to the project</para>
|
||||||
|
///<para>为项目贡献了音乐,音效资产</para>
|
||||||
|
/// </remarks>
|
||||||
|
Musician,
|
||||||
|
/// <summary>
|
||||||
|
/// <para>CharacterVoice</para>
|
||||||
|
/// <para>角色配音</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
///<para>Contributed voice to the game character</para>
|
||||||
|
///<para>为游戏角色贡献了语音</para>
|
||||||
|
/// </remarks>
|
||||||
|
CharacterVoice,
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Translator</para>
|
||||||
|
/// <para>翻译者</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
///<para>Contribute to localization of the project(specified language)</para>
|
||||||
|
///<para>为项目的本地化做出贡献(指定的语言)</para>
|
||||||
|
/// </remarks>
|
||||||
|
Translator
|
||||||
|
}
|
|
@ -70,7 +70,9 @@ public static class LogCat
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder.Append(DateTime.Now.ToString(" yyyy-M-d HH:mm:ss : "));
|
StringBuilder.Append(DateTime.Now.ToString(" yyyy-M-d HH:mm:ss : "));
|
||||||
StringBuilder.Append(TranslationServerUtils.Translate($"log_{message}"));
|
var key = $"log_{message}";
|
||||||
|
var translationResult = TranslationServerUtils.Translate(key);
|
||||||
|
StringBuilder.Append(translationResult == key ? message : translationResult);
|
||||||
return StringBuilder;
|
return StringBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using ColdMint.scripts.item;
|
using ColdMint.scripts.item;
|
||||||
using ColdMint.scripts.item.itemStacks;
|
using ColdMint.scripts.item.itemStacks;
|
||||||
|
|
||||||
using Godot;
|
using Godot;
|
||||||
|
|
||||||
namespace ColdMint.scripts.inventory;
|
namespace ColdMint.scripts.inventory;
|
||||||
|
@ -193,7 +191,10 @@ public interface IItemContainer : IEnumerable<ItemSlotNode>
|
||||||
/// <para>Match the first item slot that satisfies the predicate</para>
|
/// <para>Match the first item slot that satisfies the predicate</para>
|
||||||
/// <para>匹配首个拥有满足指定条件的物品槽</para>
|
/// <para>匹配首个拥有满足指定条件的物品槽</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="predicate"></param>
|
/// <param name="predicate">
|
||||||
|
///<para>predicate</para>
|
||||||
|
///<para>谓语</para>
|
||||||
|
/// </param>
|
||||||
/// <returns>
|
/// <returns>
|
||||||
/// <para>Return null if there is no slot satisfies the predicate</para>
|
/// <para>Return null if there is no slot satisfies the predicate</para>
|
||||||
/// <para>若没有满足条件的槽位,返回null</para>
|
/// <para>若没有满足条件的槽位,返回null</para>
|
||||||
|
@ -210,7 +211,6 @@ public interface IItemContainer : IEnumerable<ItemSlotNode>
|
||||||
/// <para>IEnumerable for the item slot matched to, will be empty if there's no slot satisfies the predicate</para>
|
/// <para>IEnumerable for the item slot matched to, will be empty if there's no slot satisfies the predicate</para>
|
||||||
/// <para>包含匹配到的槽位的IEnumerable,当没有满足条件的槽位时为空</para>
|
/// <para>包含匹配到的槽位的IEnumerable,当没有满足条件的槽位时为空</para>
|
||||||
/// </returns>
|
/// </returns>
|
||||||
/// <seealso cref="Match(Func{IItemStack?,bool})"/>
|
|
||||||
IEnumerable<ItemSlotNode> MatchAll(Func<ItemSlotNode, bool> predicate);
|
IEnumerable<ItemSlotNode> MatchAll(Func<ItemSlotNode, bool> predicate);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@ namespace ColdMint.scripts.inventory;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class ItemSlotNode : MarginContainer
|
public partial class ItemSlotNode : MarginContainer
|
||||||
{
|
{
|
||||||
//private IItem? _item;
|
|
||||||
private IItemStack? _itemStack;
|
private IItemStack? _itemStack;
|
||||||
private TextureRect? _backgroundTextureRect;
|
private TextureRect? _backgroundTextureRect;
|
||||||
private TextureRect? _iconTextureRect;
|
private TextureRect? _iconTextureRect;
|
||||||
|
@ -328,7 +327,7 @@ public partial class ItemSlotNode : MarginContainer
|
||||||
_backgroundTextureWhenSelect = GD.Load<Texture2D>("res://sprites/ui/ItemBarFocus.png");
|
_backgroundTextureWhenSelect = GD.Load<Texture2D>("res://sprites/ui/ItemBarFocus.png");
|
||||||
_backgroundTextureRect =
|
_backgroundTextureRect =
|
||||||
GetNode<TextureRect>("BackgroundTexture");
|
GetNode<TextureRect>("BackgroundTexture");
|
||||||
_iconTextureRect = GetNode<TextureRect>("BackgroundTexture/CenterContainer/IconTextureRect");
|
_iconTextureRect = GetNode<TextureRect>("BackgroundTexture/IconTextureRect");
|
||||||
_quantityLabel = GetNode<Label>("Control/QuantityLabel");
|
_quantityLabel = GetNode<Label>("Control/QuantityLabel");
|
||||||
_control = GetNode<Control>("Control");
|
_control = GetNode<Control>("Control");
|
||||||
_quantityLabel.Hide();
|
_quantityLabel.Hide();
|
||||||
|
|
60
scripts/inventory/PacksackUi.cs
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
using ColdMint.scripts.utils;
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
namespace ColdMint.scripts.inventory;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Backpack UI</para>
|
||||||
|
/// <para>背包UI</para>
|
||||||
|
/// </summary>
|
||||||
|
public partial class PacksackUi : Control
|
||||||
|
{
|
||||||
|
private IItemContainer? _itemContainer;
|
||||||
|
|
||||||
|
private PackedScene? _packedScene;
|
||||||
|
|
||||||
|
private GridContainer? _gridContainer;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Packsack</para>
|
||||||
|
/// <para>背包</para>
|
||||||
|
/// </summary>
|
||||||
|
public IItemContainer? ItemContainer
|
||||||
|
{
|
||||||
|
get => _itemContainer;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_itemContainer = value;
|
||||||
|
PlaceItemSlot(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Place item slots according to item information</para>
|
||||||
|
/// <para>根据物品信息放置物品槽</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="itemContainer"></param>
|
||||||
|
private void PlaceItemSlot(IItemContainer? itemContainer)
|
||||||
|
{
|
||||||
|
if (_gridContainer == null || itemContainer == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeUtils.DeleteAllChild(_gridContainer);
|
||||||
|
foreach (var itemSlotNode in itemContainer)
|
||||||
|
{
|
||||||
|
itemSlotNode.Reparent(_gridContainer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
_packedScene = GD.Load<PackedScene>("res://prefab/ui/ItemSlot.tscn");
|
||||||
|
_gridContainer = GetNode<GridContainer>("GridContainer");
|
||||||
|
_gridContainer.Columns = Config.HotBarSize;
|
||||||
|
//If the item container was set before this node was placed in the node tree, load it here.
|
||||||
|
//若物品容器在此节点放置到节点树之前被设置了,那么在这里加载。
|
||||||
|
PlaceItemSlot(_itemContainer);
|
||||||
|
}
|
||||||
|
}
|
|
@ -71,10 +71,6 @@ public interface IItem
|
||||||
/// <para>If this item need a special stack type, return the special item stack instance that contains the item. If else, just leave this null.</para>
|
/// <para>If this item need a special stack type, return the special item stack instance that contains the item. If else, just leave this null.</para>
|
||||||
/// <para>如果该项目需要特殊的物品堆类型,重写此方法来返回包含该物品的特殊物品堆实例。否则,保留原本的null返回值。</para>
|
/// <para>如果该项目需要特殊的物品堆类型,重写此方法来返回包含该物品的特殊物品堆实例。否则,保留原本的null返回值。</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
|
||||||
/// <para>DO NOT use this method to create stack from item, use <see cref="IItemStack.FromItem"/> instead</para>
|
|
||||||
/// <para>不要使用此方法从一个物品创建堆,请使用 <see cref="IItemStack.FromItem"/></para>。
|
|
||||||
/// </remarks>
|
|
||||||
/// <seealso cref="CanStackWith"/>
|
/// <seealso cref="CanStackWith"/>
|
||||||
IItemStack? SpecialStack() => null;
|
IItemStack? SpecialStack() => null;
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
using ColdMint.scripts.inventory;
|
using ColdMint.scripts.inventory;
|
||||||
using ColdMint.scripts.item.itemStacks;
|
using ColdMint.scripts.pickable;
|
||||||
|
using ColdMint.scripts.utils;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
|
||||||
namespace ColdMint.scripts.item;
|
namespace ColdMint.scripts.item;
|
||||||
|
@ -9,22 +9,12 @@ namespace ColdMint.scripts.item;
|
||||||
/// <para>packsack</para>
|
/// <para>packsack</para>
|
||||||
/// <para>背包</para>
|
/// <para>背包</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class Packsack : RigidBody2D, IItem
|
public partial class Packsack : PickAbleTemplate
|
||||||
{
|
{
|
||||||
[Export] public string Id { get; protected set; } = "place_holder_id";
|
private PackedScene? _packedScene;
|
||||||
|
private PacksackUi? _packsackUi;
|
||||||
|
|
||||||
protected Texture2D? UniqueIcon { get; set; }
|
public override void Destroy()
|
||||||
public Texture2D Icon => UniqueIcon ?? ItemTypeManager.DefaultIconOf(Id);
|
|
||||||
|
|
||||||
protected string? UniqueName { get; set; }
|
|
||||||
public new string Name => UniqueName ?? ItemTypeManager.DefaultNameOf(Id);
|
|
||||||
|
|
||||||
protected string? UniqueDescription { get; set; }
|
|
||||||
public string? Description => UniqueDescription ?? ItemTypeManager.DefaultDescriptionOf(Id);
|
|
||||||
|
|
||||||
public void Use(Node2D? owner, Vector2 targetGlobalPosition) { }
|
|
||||||
|
|
||||||
public void Destroy()
|
|
||||||
{
|
{
|
||||||
if (ItemContainer == null) return;
|
if (ItemContainer == null) return;
|
||||||
foreach (var itemSlot in ItemContainer)
|
foreach (var itemSlot in ItemContainer)
|
||||||
|
@ -35,13 +25,18 @@ public partial class Packsack : RigidBody2D, IItem
|
||||||
QueueFree();
|
QueueFree();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CanStackWith(IItem item) => false;
|
public override void Use(Node2D? owner, Vector2 targetGlobalPosition)
|
||||||
|
|
||||||
public IItemStack? SpecialStack()
|
|
||||||
{
|
{
|
||||||
return new PacksackStack(this);
|
if (_packedScene == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (_packsackUi == null)
|
||||||
|
{
|
||||||
|
_packsackUi = NodeUtils.InstantiatePackedScene<PacksackUi>(_packedScene,this);
|
||||||
|
}
|
||||||
|
_packsackUi?.Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public IItemContainer? ItemContainer { get; private set; }
|
public IItemContainer? ItemContainer { get; private set; }
|
||||||
|
|
||||||
|
@ -49,8 +44,7 @@ public partial class Packsack : RigidBody2D, IItem
|
||||||
{
|
{
|
||||||
base._Ready();
|
base._Ready();
|
||||||
ItemContainer = new UniversalItemContainer();
|
ItemContainer = new UniversalItemContainer();
|
||||||
|
_packedScene = GD.Load<PackedScene>("res://prefab/ui/packsackUI.tscn");
|
||||||
|
|
||||||
//Test: Add one ItemSlot for pack
|
|
||||||
ItemContainer.AddItemSlot(this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -159,6 +159,10 @@ public interface IItemStack
|
||||||
/// <para>Create a new ItemStack with the given item as the first item</para>
|
/// <para>Create a new ItemStack with the given item as the first item</para>
|
||||||
/// <para>以给定的物品为第一个物品创建物品堆</para>
|
/// <para>以给定的物品为第一个物品创建物品堆</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
///<para>Assuming the item implements the <see cref="IItem.SpecialStack"/> method, then use the return value of the SpecialStack method, otherwise extrapolate from the maximum number of stacks of items.</para>
|
||||||
|
///<para>假设物品实现了<see cref="IItem.SpecialStack"/>方法,那么使用SpecialStack方法的返回值,否则根据物品的最大堆叠数量来推断。</para>
|
||||||
|
/// </remarks>
|
||||||
public static IItemStack FromItem(IItem item) =>
|
public static IItemStack FromItem(IItem item) =>
|
||||||
item.SpecialStack() ??
|
item.SpecialStack() ??
|
||||||
ItemTypeManager.MaxStackQuantityOf(item.Id) switch
|
ItemTypeManager.MaxStackQuantityOf(item.Id) switch
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
using ColdMint.scripts.camp;
|
|
||||||
using ColdMint.scripts.character;
|
using ColdMint.scripts.character;
|
||||||
|
using ColdMint.scripts.pickable;
|
||||||
using ColdMint.scripts.damage;
|
using ColdMint.scripts.damage;
|
||||||
|
|
||||||
using Godot;
|
using Godot;
|
||||||
|
@ -12,57 +11,14 @@ namespace ColdMint.scripts.item.weapon;
|
||||||
/// <para>WeaponTemplate</para>
|
/// <para>WeaponTemplate</para>
|
||||||
/// <para>武器模板</para>
|
/// <para>武器模板</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract partial class WeaponTemplate : RigidBody2D, IItem
|
public abstract partial class WeaponTemplate : PickAbleTemplate
|
||||||
{
|
{
|
||||||
private float _gravity = ProjectSettings.GetSetting("physics/2d/default_gravity").AsSingle();
|
private float _gravity = ProjectSettings.GetSetting("physics/2d/default_gravity").AsSingle();
|
||||||
|
public override void Use(Node2D? owner, Vector2 targetGlobalPosition)
|
||||||
//Implements IItem
|
|
||||||
[Export] public virtual string Id { get; private set; } = "ID";
|
|
||||||
|
|
||||||
protected Texture2D? UniqueIcon { get; set; }
|
|
||||||
public Texture2D Icon => UniqueIcon ?? ItemTypeManager.DefaultIconOf(Id);
|
|
||||||
|
|
||||||
protected string? UniqueName { get; set; }
|
|
||||||
public new string Name => UniqueName ?? ItemTypeManager.DefaultNameOf(Id);
|
|
||||||
|
|
||||||
protected string? UniqueDescription { get; set; }
|
|
||||||
public string? Description => UniqueDescription ?? ItemTypeManager.DefaultDescriptionOf(Id);
|
|
||||||
|
|
||||||
|
|
||||||
public void Use(Node2D? owner, Vector2 targetGlobalPosition)
|
|
||||||
{
|
{
|
||||||
Fire(owner, targetGlobalPosition);
|
Fire(owner, targetGlobalPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Destroy()
|
|
||||||
{
|
|
||||||
QueueFree();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CanStackWith(IItem item) => false;
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Whether the weapon is currently picked up</para>
|
|
||||||
/// <para>当前武器是否被捡起了</para>
|
|
||||||
/// </summary>
|
|
||||||
public bool Picked { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Owner</para>
|
|
||||||
/// <para>主人</para>
|
|
||||||
/// </summary>
|
|
||||||
public new Node2D? Owner { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Enabled contact injury</para>
|
|
||||||
/// <para>启用接触伤害</para>
|
|
||||||
/// </summary>
|
|
||||||
public bool EnableContactInjury;
|
|
||||||
|
|
||||||
[Export] private int _minContactInjury = 1;
|
|
||||||
[Export] private int _maxContactInjury = 2;
|
|
||||||
|
|
||||||
private DateTime? _lastFiringTime;
|
private DateTime? _lastFiringTime;
|
||||||
|
|
||||||
|
@ -93,113 +49,15 @@ public abstract partial class WeaponTemplate : RigidBody2D, IItem
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
[Export] private Vector2 _recoil;
|
[Export] private Vector2 _recoil;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>This area represents the collision range of the weapon, and when other nodes enter this area, they will deal damage.</para>
|
|
||||||
/// <para>这个区域表示武器的碰撞范围,当其他节点进入此区域时,会造成伤害。</para>
|
|
||||||
/// </summary>
|
|
||||||
private Area2D? _damageArea2D;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>The number of tile maps in contact with this weapon</para>
|
|
||||||
/// <para>与此武器接触的瓦片地图数量</para>
|
|
||||||
/// </summary>
|
|
||||||
private int _tileMapNumber;
|
|
||||||
|
|
||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
_damageArea2D = GetNode<Area2D>("DamageArea2D");
|
|
||||||
_damageArea2D.BodyEntered += OnBodyEnter;
|
|
||||||
_damageArea2D.BodyExited += OnBodyExited;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnBodyExited(Node node)
|
|
||||||
{
|
|
||||||
if (Picked)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//If it leaves the ground or walls.
|
|
||||||
//如果离开了地面或墙壁。
|
|
||||||
if (node is TileMap)
|
|
||||||
{
|
|
||||||
_tileMapNumber--;
|
|
||||||
if (_tileMapNumber == 0)
|
|
||||||
{
|
|
||||||
//No longer in contact with any shingles can cause injury
|
|
||||||
//不再与任何瓦片接触后,可以造成伤害
|
|
||||||
EnableContactInjury = true;
|
|
||||||
SetCollisionMaskValue(Config.LayerNumber.Player, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Use weapons against the enemy</para>
|
|
||||||
/// <para>使用武器砸敌人</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="node"></param>
|
|
||||||
private void OnBodyEnter(Node node)
|
|
||||||
{
|
|
||||||
if (Picked)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node is TileMap)
|
|
||||||
{
|
|
||||||
_tileMapNumber++;
|
|
||||||
EnableContactInjury = false;
|
|
||||||
//Items can be pushed by the player when they are on the ground
|
|
||||||
//当物品在地面上时,可被玩家推动
|
|
||||||
SetCollisionMaskValue(Config.LayerNumber.Player, true);
|
|
||||||
}
|
|
||||||
else if (node is CharacterTemplate characterTemplate)
|
|
||||||
{
|
|
||||||
if (!EnableContactInjury)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (Owner is not CharacterTemplate ownerCharacterTemplate)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Determine if your side can cause damage
|
|
||||||
//判断所属的阵营是否可以造成伤害
|
|
||||||
var canCauseHarm = CampManager.CanCauseHarm(CampManager.GetCamp(ownerCharacterTemplate.CampId),
|
|
||||||
CampManager.GetCamp(characterTemplate.CampId));
|
|
||||||
if (!canCauseHarm)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//If allowed to cause harm
|
|
||||||
//如果允许造成伤害
|
|
||||||
var damage = new Damage
|
|
||||||
{
|
|
||||||
MaxDamage = Math.Abs(_maxContactInjury),
|
|
||||||
MinDamage = Math.Abs(_minContactInjury),
|
|
||||||
Attacker = ownerCharacterTemplate
|
|
||||||
};
|
|
||||||
damage.CreateDamage();
|
|
||||||
damage.MoveLeft = LinearVelocity.X < 0;
|
|
||||||
damage.Type = Config.DamageType.Physical;
|
|
||||||
characterTemplate.Damage(damage);
|
|
||||||
//Reduce speed after hitting enemies.
|
|
||||||
//击中敌人后减少速度。
|
|
||||||
LinearVelocity *= 1 - Config.ThrownItemsHitEnemiesReduceSpeedByPercentage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>翻转武器</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="facingLeft"></param>
|
|
||||||
public void Flip(bool facingLeft) { }
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
112
scripts/loader/uiLoader/ContributorGroupLoader.cs
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
using ColdMint.scripts.contribute;
|
||||||
|
using ColdMint.scripts.utils;
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
namespace ColdMint.scripts.loader.uiLoader;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Contributor group loader</para>
|
||||||
|
/// <para>贡献者组加载器</para>
|
||||||
|
/// </summary>
|
||||||
|
public partial class ContributorGroupLoader : UiLoaderTemplate
|
||||||
|
{
|
||||||
|
private string? _title;
|
||||||
|
private ContributorData[]? _contributorDataArray;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Contributor array</para>
|
||||||
|
/// <para>贡献者数组</para>
|
||||||
|
/// </summary>
|
||||||
|
public ContributorData[]? ContributorDataArray
|
||||||
|
{
|
||||||
|
get => _contributorDataArray;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_contributorDataArray = value;
|
||||||
|
SetContributorData(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>The title of the contribution group</para>
|
||||||
|
/// <para>贡献组的标题</para>
|
||||||
|
/// </summary>
|
||||||
|
public string? Title
|
||||||
|
{
|
||||||
|
get => _title;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_title = value;
|
||||||
|
SetTitle(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Label? _titleLabel;
|
||||||
|
private HFlowContainer? _flowContainer;
|
||||||
|
|
||||||
|
public override void InitializeUi()
|
||||||
|
{
|
||||||
|
_titleLabel = GetNode<Label>("TitleLabel");
|
||||||
|
_flowContainer = GetNode<HFlowContainer>("HFlowContainer");
|
||||||
|
//If there is initial data, it is loaded at startup.
|
||||||
|
//如果有初始数据,那么在启动时加载。
|
||||||
|
SetTitle(_title);
|
||||||
|
SetContributorData(_contributorDataArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Set contributor array</para>
|
||||||
|
/// <para>设置贡献者数组</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="contributorDataArray"></param>
|
||||||
|
private void SetContributorData(ContributorData[]? contributorDataArray)
|
||||||
|
{
|
||||||
|
if (_flowContainer == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NodeUtils.DeleteAllChild(_flowContainer);
|
||||||
|
if (contributorDataArray == null || contributorDataArray.Length == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
foreach (var contributorData in contributorDataArray)
|
||||||
|
{
|
||||||
|
var linkButton = new LinkButton();
|
||||||
|
linkButton.Underline = LinkButton.UnderlineMode.OnHover;
|
||||||
|
linkButton.Text = contributorData.Name;
|
||||||
|
linkButton.Uri = contributorData.Url;
|
||||||
|
var toolTip = contributorData.ToolTip;
|
||||||
|
if (toolTip == null)
|
||||||
|
{
|
||||||
|
linkButton.TooltipText = contributorData.Url;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
linkButton.TooltipText = contributorData.ToolTip;
|
||||||
|
}
|
||||||
|
_flowContainer.AddChild(linkButton);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Set Title</para>
|
||||||
|
/// <para>设置标题</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="title"></param>
|
||||||
|
private void SetTitle(string? title)
|
||||||
|
{
|
||||||
|
if (_titleLabel != null)
|
||||||
|
{
|
||||||
|
if (title == null)
|
||||||
|
{
|
||||||
|
_titleLabel.Hide();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_titleLabel.Show();
|
||||||
|
_titleLabel.Text = title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
72
scripts/loader/uiLoader/ContributorLoader.cs
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
using ColdMint.scripts.contribute;
|
||||||
|
using ColdMint.scripts.utils;
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
namespace ColdMint.scripts.loader.uiLoader;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>ContributorLoader</para>
|
||||||
|
/// <para>贡献者页面加载器</para>
|
||||||
|
/// </summary>
|
||||||
|
public partial class ContributorLoader : UiLoaderTemplate
|
||||||
|
{
|
||||||
|
private Button? _exitButton;
|
||||||
|
private VBoxContainer? _boxContainer;
|
||||||
|
private PackedScene? _packedScene;
|
||||||
|
private PackedScene? _mainMenu;
|
||||||
|
private PackedScene? _contributorGroup;
|
||||||
|
|
||||||
|
public override void InitializeData()
|
||||||
|
{
|
||||||
|
_mainMenu = GD.Load<PackedScene>("res://scenes/mainMenu.tscn");
|
||||||
|
_packedScene = GD.Load<PackedScene>("res://prefab/ui/contributorGroup.tscn");
|
||||||
|
_contributorGroup = GD.Load<PackedScene>("res://prefab/ui/contributorGroup.tscn");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void InitializeUi()
|
||||||
|
{
|
||||||
|
_exitButton = GetNode<Button>("ExitButton");
|
||||||
|
_boxContainer = GetNode<VBoxContainer>("VBoxContainer");
|
||||||
|
var dictionary =
|
||||||
|
ContributorDataManager.GetContributorTypeToContributorDataArray();
|
||||||
|
if (dictionary != null)
|
||||||
|
{
|
||||||
|
foreach (var contributorType in dictionary.Keys)
|
||||||
|
{
|
||||||
|
AddGroup(ContributorDataManager.ContributorTypeToString(contributorType), dictionary[contributorType]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddGroup(string? title, ContributorData[] contributorDataArray)
|
||||||
|
{
|
||||||
|
if (_boxContainer == null || _contributorGroup == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var contributorGroupLoader = NodeUtils.InstantiatePackedScene<ContributorGroupLoader>(_contributorGroup);
|
||||||
|
if (contributorGroupLoader != null)
|
||||||
|
{
|
||||||
|
contributorGroupLoader.Title = title;
|
||||||
|
contributorGroupLoader.ContributorDataArray = contributorDataArray;
|
||||||
|
_boxContainer.AddChild(contributorGroupLoader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void LoadUiActions()
|
||||||
|
{
|
||||||
|
if (_exitButton != null)
|
||||||
|
{
|
||||||
|
_exitButton.Pressed += () =>
|
||||||
|
{
|
||||||
|
if (_mainMenu == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GetTree().ChangeSceneToPacked(_mainMenu);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,6 +36,7 @@ public partial class LevelGraphEditorLoader : UiLoaderTemplate
|
||||||
private PackedScene? _roomNodeScene;
|
private PackedScene? _roomNodeScene;
|
||||||
|
|
||||||
private readonly List<Node> _selectedNodes = new();
|
private readonly List<Node> _selectedNodes = new();
|
||||||
|
private PackedScene? _mainMenu;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>Displays the time to enter the suggestion</para>
|
/// <para>Displays the time to enter the suggestion</para>
|
||||||
|
@ -59,7 +60,8 @@ public partial class LevelGraphEditorLoader : UiLoaderTemplate
|
||||||
public override void InitializeData()
|
public override void InitializeData()
|
||||||
{
|
{
|
||||||
base.InitializeData();
|
base.InitializeData();
|
||||||
_roomNodeScene = (PackedScene)GD.Load("res://prefab/ui/RoomNode.tscn");
|
_mainMenu = GD.Load<PackedScene>("res://scenes/mainMenu.tscn");
|
||||||
|
_roomNodeScene = GD.Load<PackedScene>("res://prefab/ui/RoomNode.tscn");
|
||||||
_defaultRoomName = TranslationServerUtils.Translate("ui_default_room_name");
|
_defaultRoomName = TranslationServerUtils.Translate("ui_default_room_name");
|
||||||
var folder = Config.GetLevelGraphExportDirectory();
|
var folder = Config.GetLevelGraphExportDirectory();
|
||||||
if (!Directory.Exists(folder))
|
if (!Directory.Exists(folder))
|
||||||
|
@ -310,7 +312,11 @@ public partial class LevelGraphEditorLoader : UiLoaderTemplate
|
||||||
{
|
{
|
||||||
_nodeBinding.ReturnButton.Pressed += () =>
|
_nodeBinding.ReturnButton.Pressed += () =>
|
||||||
{
|
{
|
||||||
GetTree().ChangeSceneToPacked((PackedScene)GD.Load("res://scenes/mainMenu.tscn"));
|
if (_mainMenu == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GetTree().ChangeSceneToPacked(_mainMenu);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
using ColdMint.scripts.camp;
|
using ColdMint.scripts.camp;
|
||||||
|
using ColdMint.scripts.contribute;
|
||||||
using ColdMint.scripts.deathInfo;
|
using ColdMint.scripts.deathInfo;
|
||||||
using ColdMint.scripts.debug;
|
using ColdMint.scripts.debug;
|
||||||
using ColdMint.scripts.inventory;
|
using ColdMint.scripts.inventory;
|
||||||
|
@ -10,6 +11,7 @@ using ColdMint.scripts.item;
|
||||||
using ColdMint.scripts.loot;
|
using ColdMint.scripts.loot;
|
||||||
using ColdMint.scripts.map;
|
using ColdMint.scripts.map;
|
||||||
using ColdMint.scripts.map.roomInjectionProcessor;
|
using ColdMint.scripts.map.roomInjectionProcessor;
|
||||||
|
using ColdMint.scripts.utils;
|
||||||
|
|
||||||
using Godot;
|
using Godot;
|
||||||
|
|
||||||
|
@ -25,9 +27,12 @@ public partial class MainMenuLoader : UiLoaderTemplate
|
||||||
private Label? _copyrightLabel;
|
private Label? _copyrightLabel;
|
||||||
private StringBuilder? _copyrightBuilder;
|
private StringBuilder? _copyrightBuilder;
|
||||||
private PackedScene? _gameScene;
|
private PackedScene? _gameScene;
|
||||||
|
private PackedScene? _contributor;
|
||||||
|
private PackedScene? _levelGraphEditor;
|
||||||
private Label? _sloganLabel;
|
private Label? _sloganLabel;
|
||||||
private Label? _versionLabel;
|
private Label? _versionLabel;
|
||||||
private Button? _levelGraphEditorButton;
|
private Button? _levelGraphEditorButton;
|
||||||
|
private LinkButton? _contributorButton;
|
||||||
|
|
||||||
public override void InitializeData()
|
public override void InitializeData()
|
||||||
{
|
{
|
||||||
|
@ -45,6 +50,7 @@ public partial class MainMenuLoader : UiLoaderTemplate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ContributorDataManager.RegisterAllContributorData();
|
||||||
DeathInfoGenerator.RegisterDeathInfoHandler(new SelfDeathInfoHandler());
|
DeathInfoGenerator.RegisterDeathInfoHandler(new SelfDeathInfoHandler());
|
||||||
MapGenerator.RegisterRoomInjectionProcessor(new ChanceRoomInjectionProcessor());
|
MapGenerator.RegisterRoomInjectionProcessor(new ChanceRoomInjectionProcessor());
|
||||||
MapGenerator.RegisterRoomInjectionProcessor(new TimeIntervalRoomInjectorProcessor());
|
MapGenerator.RegisterRoomInjectionProcessor(new TimeIntervalRoomInjectorProcessor());
|
||||||
|
@ -70,7 +76,9 @@ public partial class MainMenuLoader : UiLoaderTemplate
|
||||||
CampManager.AddCamp(mazoku);
|
CampManager.AddCamp(mazoku);
|
||||||
var aborigines = new Camp(Config.CampId.Aborigines);
|
var aborigines = new Camp(Config.CampId.Aborigines);
|
||||||
CampManager.AddCamp(aborigines);
|
CampManager.AddCamp(aborigines);
|
||||||
_gameScene = (PackedScene)GD.Load("res://scenes/game.tscn");
|
_gameScene = GD.Load<PackedScene>("res://scenes/game.tscn");
|
||||||
|
_contributor = GD.Load<PackedScene>("res://scenes/contributor.tscn");
|
||||||
|
_levelGraphEditor = GD.Load<PackedScene>("res://scenes/levelGraphEditor.tscn");
|
||||||
|
|
||||||
//Register ItemTypes from file
|
//Register ItemTypes from file
|
||||||
//从文件注册物品类型
|
//从文件注册物品类型
|
||||||
|
@ -85,6 +93,7 @@ public partial class MainMenuLoader : UiLoaderTemplate
|
||||||
|
|
||||||
public override void InitializeUi()
|
public override void InitializeUi()
|
||||||
{
|
{
|
||||||
|
_contributorButton = GetNode<LinkButton>("VBoxContainer2/ContributorButton");
|
||||||
_startGameButton = GetNode<Button>("StartGameButton");
|
_startGameButton = GetNode<Button>("StartGameButton");
|
||||||
_levelGraphEditorButton = GetNode<Button>("levelGraphEditorButton");
|
_levelGraphEditorButton = GetNode<Button>("levelGraphEditorButton");
|
||||||
//The level map editor is only available in debug mode.
|
//The level map editor is only available in debug mode.
|
||||||
|
@ -112,6 +121,9 @@ public partial class MainMenuLoader : UiLoaderTemplate
|
||||||
_copyrightLabel.Text = _copyrightBuilder.ToString();
|
_copyrightLabel.Text = _copyrightBuilder.ToString();
|
||||||
_versionLabel.Text = "ver." + Config.GetVersion();
|
_versionLabel.Text = "ver." + Config.GetVersion();
|
||||||
_sloganLabel.Text = SloganProvider.GetSlogan();
|
_sloganLabel.Text = SloganProvider.GetSlogan();
|
||||||
|
_contributorButton.Text =
|
||||||
|
TranslationServerUtils.TranslateWithFormat("ui_contributor_tips",
|
||||||
|
ContributorDataManager.GetContributorTotals());
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadUiActions()
|
public override void LoadUiActions()
|
||||||
|
@ -121,16 +133,36 @@ public partial class MainMenuLoader : UiLoaderTemplate
|
||||||
_startGameButton.Pressed += () =>
|
_startGameButton.Pressed += () =>
|
||||||
{
|
{
|
||||||
LogCat.Log("start_game");
|
LogCat.Log("start_game");
|
||||||
|
if (_gameScene == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
GetTree().ChangeSceneToPacked(_gameScene);
|
GetTree().ChangeSceneToPacked(_gameScene);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_contributorButton!=null)
|
||||||
|
{
|
||||||
|
_contributorButton.Pressed += () =>
|
||||||
|
{
|
||||||
|
if (_contributor == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GetTree().ChangeSceneToPacked(_contributor);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (_levelGraphEditorButton != null)
|
if (_levelGraphEditorButton != null)
|
||||||
{
|
{
|
||||||
_levelGraphEditorButton.Pressed += () =>
|
_levelGraphEditorButton.Pressed += () =>
|
||||||
{
|
{
|
||||||
LogCat.Log("level_graph_editor");
|
LogCat.Log("level_graph_editor");
|
||||||
GetTree().ChangeSceneToPacked((PackedScene)GD.Load("res://scenes/levelGraphEditor.tscn"));
|
if (_levelGraphEditor == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GetTree().ChangeSceneToPacked(_levelGraphEditor);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
165
scripts/pickable/PickAbleTemplate.cs
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
using System;
|
||||||
|
using ColdMint.scripts.camp;
|
||||||
|
using ColdMint.scripts.character;
|
||||||
|
using ColdMint.scripts.damage;
|
||||||
|
using ColdMint.scripts.item;
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
namespace ColdMint.scripts.pickable;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Templates for all fallen objects</para>
|
||||||
|
/// <para>所有掉落物的模板</para>
|
||||||
|
/// </summary>
|
||||||
|
public partial class PickAbleTemplate : RigidBody2D, IItem
|
||||||
|
{
|
||||||
|
[Export] public virtual string Id { get; set; } = "ID";
|
||||||
|
protected Texture2D? UniqueIcon { get; set; }
|
||||||
|
public Texture2D Icon => UniqueIcon ?? ItemTypeManager.DefaultIconOf(Id);
|
||||||
|
protected string? UniqueName { get; set; }
|
||||||
|
public new string Name => UniqueName ?? ItemTypeManager.DefaultNameOf(Id);
|
||||||
|
protected string? UniqueDescription { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Owner</para>
|
||||||
|
/// <para>主人</para>
|
||||||
|
/// </summary>
|
||||||
|
public new Node2D? Owner { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Enabled contact injury</para>
|
||||||
|
/// <para>启用接触伤害</para>
|
||||||
|
/// </summary>
|
||||||
|
public bool EnableContactInjury;
|
||||||
|
|
||||||
|
[Export] private int _minContactInjury = 1;
|
||||||
|
[Export] private int _maxContactInjury = 2;
|
||||||
|
|
||||||
|
public string? Description => UniqueDescription ?? ItemTypeManager.DefaultDescriptionOf(Id);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>The number of tile maps that come into contact with this item</para>
|
||||||
|
/// <para>与此物品接触的瓦片地图数量</para>
|
||||||
|
/// </summary>
|
||||||
|
private int _tileMapNumber;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>This area represents the collision range of the weapon, and when other nodes enter this area, they will deal damage.</para>
|
||||||
|
/// <para>这个区域表示武器的碰撞范围,当其他节点进入此区域时,会造成伤害。</para>
|
||||||
|
/// </summary>
|
||||||
|
private Area2D? _damageArea2D;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Whether the item is currently picked up</para>
|
||||||
|
/// <para>当前物品是否被捡起了</para>
|
||||||
|
/// </summary>
|
||||||
|
public bool Picked { get; set; }
|
||||||
|
|
||||||
|
public virtual void Use(Node2D? owner, Vector2 targetGlobalPosition)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
_damageArea2D = GetNode<Area2D>("DamageArea2D");
|
||||||
|
_damageArea2D.BodyEntered += OnBodyEnter;
|
||||||
|
_damageArea2D.BodyExited += OnBodyExited;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnBodyExited(Node node)
|
||||||
|
{
|
||||||
|
if (Picked)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//If it leaves the ground or walls.
|
||||||
|
//如果离开了地面或墙壁。
|
||||||
|
if (node is TileMap)
|
||||||
|
{
|
||||||
|
_tileMapNumber--;
|
||||||
|
if (_tileMapNumber == 0)
|
||||||
|
{
|
||||||
|
//No longer in contact with any shingles can cause injury
|
||||||
|
//不再与任何瓦片接触后,可以造成伤害
|
||||||
|
EnableContactInjury = true;
|
||||||
|
SetCollisionMaskValue(Config.LayerNumber.Player, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Use objects to smash enemies</para>
|
||||||
|
/// <para>使用物品砸敌人</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="node"></param>
|
||||||
|
private void OnBodyEnter(Node node)
|
||||||
|
{
|
||||||
|
if (Picked)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node is TileMap)
|
||||||
|
{
|
||||||
|
_tileMapNumber++;
|
||||||
|
EnableContactInjury = false;
|
||||||
|
//Items can be pushed by the player when they are on the ground
|
||||||
|
//当物品在地面上时,可被玩家推动
|
||||||
|
SetCollisionMaskValue(Config.LayerNumber.Player, true);
|
||||||
|
}
|
||||||
|
else if (node is CharacterTemplate characterTemplate)
|
||||||
|
{
|
||||||
|
if (!EnableContactInjury)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (Owner is not CharacterTemplate ownerCharacterTemplate)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Determine if your side can cause damage
|
||||||
|
//判断所属的阵营是否可以造成伤害
|
||||||
|
var canCauseHarm = CampManager.CanCauseHarm(CampManager.GetCamp(ownerCharacterTemplate.CampId),
|
||||||
|
CampManager.GetCamp(characterTemplate.CampId));
|
||||||
|
if (!canCauseHarm)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//If allowed to cause harm
|
||||||
|
//如果允许造成伤害
|
||||||
|
var damage = new Damage
|
||||||
|
{
|
||||||
|
MaxDamage = Math.Abs(_maxContactInjury),
|
||||||
|
MinDamage = Math.Abs(_minContactInjury),
|
||||||
|
Attacker = ownerCharacterTemplate
|
||||||
|
};
|
||||||
|
damage.CreateDamage();
|
||||||
|
damage.MoveLeft = LinearVelocity.X < 0;
|
||||||
|
damage.Type = Config.DamageType.Physical;
|
||||||
|
characterTemplate.Damage(damage);
|
||||||
|
//Reduce speed after hitting enemies.
|
||||||
|
//击中敌人后减少速度。
|
||||||
|
LinearVelocity *= 1 - Config.ThrownItemsHitEnemiesReduceSpeedByPercentage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Flip item</para>
|
||||||
|
/// <para>翻转物品</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="facingLeft"></param>
|
||||||
|
public void Flip(bool facingLeft) { }
|
||||||
|
|
||||||
|
public virtual void Destroy()
|
||||||
|
{
|
||||||
|
QueueFree();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CanStackWith(IItem item) => false;
|
||||||
|
}
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.7 KiB |
BIN
sprites/packsack.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
34
sprites/packsack.png.import
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://dvx10dfjctn7t"
|
||||||
|
path="res://.godot/imported/packsack.png-ba078a68a3754f332c41ffcad073a395.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://sprites/packsack.png"
|
||||||
|
dest_files=["res://.godot/imported/packsack.png-ba078a68a3754f332c41ffcad073a395.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
Before Width: | Height: | Size: 159 B After Width: | Height: | Size: 136 B |
Before Width: | Height: | Size: 148 B After Width: | Height: | Size: 224 B |
Before Width: | Height: | Size: 372 B After Width: | Height: | Size: 1.0 KiB |
BIN
sprites/weapon/staffOfTheUndead_icon.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
34
sprites/weapon/staffOfTheUndead_icon.png.import
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://dg5vwprt66w4j"
|
||||||
|
path="res://.godot/imported/staffOfTheUndead_icon.png-4ca5c1341e2dac55b2ef4a0fc05b6e6c.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://sprites/weapon/staffOfTheUndead_icon.png"
|
||||||
|
dest_files=["res://.godot/imported/staffOfTheUndead_icon.png-4ca5c1341e2dac55b2ef4a0fc05b6e6c.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|