Compare commits
No commits in common. "39ca716e3dd7d431c5f025c7ca2a6afaf105eed8" and "74c85cd5a7a9e74b2b783904a79ad8db58f68422" have entirely different histories.
39ca716e3d
...
74c85cd5a7
|
@ -1,5 +0,0 @@
|
|||
id,zh,en,jp
|
||||
#kill self
|
||||
#自杀
|
||||
death_info_self_1,{0}误伤了自己。,{0} accidentally shot himself.,{0}誤って自分を傷つけました。
|
||||
death_info_self_2,{0}忘记了瞄准。,{0} forgot to aim.,{0}照準を忘れました。
|
|
|
@ -1,17 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="csv_translation"
|
||||
type="Translation"
|
||||
uid="uid://dwx0hwuy0uqio"
|
||||
|
||||
[deps]
|
||||
|
||||
files=["res://locals/DeathInfo.zh.translation", "res://locals/DeathInfo.en.translation", "res://locals/DeathInfo.jp.translation"]
|
||||
|
||||
source_file="res://locals/DeathInfo.csv"
|
||||
dest_files=["res://locals/DeathInfo.zh.translation", "res://locals/DeathInfo.en.translation", "res://locals/DeathInfo.jp.translation"]
|
||||
|
||||
[params]
|
||||
|
||||
compress=true
|
||||
delimiter=0
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -13,10 +13,10 @@ collision_layer = 0
|
|||
collision_mask = 0
|
||||
script = ExtResource("1_ib3qh")
|
||||
metadata/Speed = 500.0
|
||||
metadata/Life = 10.0
|
||||
metadata/Durability = 1.0
|
||||
metadata/DamageType = 2
|
||||
metadata/Knockback = Vector2(2, -3)
|
||||
metadata/Life = 5000
|
||||
|
||||
[node name="CurseOfTheUndead" type="Sprite2D" parent="."]
|
||||
texture = ExtResource("1_k8el6")
|
||||
|
|
|
@ -146,7 +146,7 @@ hotbar_previous={
|
|||
|
||||
[internationalization]
|
||||
|
||||
locale/translations=PackedStringArray("res://locals/UI.en.translation", "res://locals/UI.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/InputMapping.jp.translation", "res://locals/Log.jp.translation", "res://locals/UI.jp.translation", "res://locals/Weapon.jp.translation", "res://locals/Slogan.en.translation", "res://locals/Slogan.jp.translation", "res://locals/Slogan.zh.translation", "res://locals/DeathInfo.en.translation", "res://locals/DeathInfo.jp.translation", "res://locals/DeathInfo.zh.translation")
|
||||
locale/translations=PackedStringArray("res://locals/UI.en.translation", "res://locals/UI.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/InputMapping.jp.translation", "res://locals/Log.jp.translation", "res://locals/UI.jp.translation", "res://locals/Weapon.jp.translation", "res://locals/Slogan.en.translation", "res://locals/Slogan.jp.translation", "res://locals/Slogan.zh.translation")
|
||||
|
||||
[layer_names]
|
||||
|
||||
|
|
|
@ -55,6 +55,6 @@ layout_mode = 2
|
|||
theme_override_constants/margin_top = 10
|
||||
theme_override_constants/margin_bottom = 150
|
||||
|
||||
[node name="RestartButton" type="Button" parent="CenterContainer/VBoxContainer/MarginContainer2"]
|
||||
[node name="Button" type="Button" parent="CenterContainer/VBoxContainer/MarginContainer2"]
|
||||
layout_mode = 2
|
||||
text = "restart"
|
||||
|
|
|
@ -8,11 +8,7 @@ namespace ColdMint.scripts;
|
|||
|
||||
public static class Config
|
||||
{
|
||||
/// <summary>
|
||||
/// <para>ID of the behavior tree</para>
|
||||
/// <para>行为树的ID</para>
|
||||
/// </summary>
|
||||
public static class BehaviorTreeId
|
||||
public class BehaviorTreeId
|
||||
{
|
||||
/// <summary>
|
||||
/// <para>巡逻</para>
|
||||
|
@ -25,7 +21,7 @@ public static class Config
|
|||
/// <para>BehaviorTreeResult</para>
|
||||
/// <para>行为树的结果</para>
|
||||
/// </summary>
|
||||
public static class BehaviorTreeResult
|
||||
public class BehaviorTreeResult
|
||||
{
|
||||
/// <summary>
|
||||
/// <para>Running</para>
|
||||
|
@ -153,18 +149,13 @@ public static class Config
|
|||
return OS.HasFeature("editor");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Room Injector ID</para>
|
||||
/// <para>房间注入器ID</para>
|
||||
/// </summary>
|
||||
public static class RoomInjectionProcessorId
|
||||
public class RoomInjectionProcessorId
|
||||
{
|
||||
/// <summary>
|
||||
/// <para>Chance</para>
|
||||
/// <para>概率的</para>
|
||||
/// </summary>
|
||||
public const string Chance = "Chance";
|
||||
|
||||
/// <summary>
|
||||
/// <para>TimeInterval</para>
|
||||
/// <para>时间范围的</para>
|
||||
|
@ -200,7 +191,11 @@ public static class Config
|
|||
|
||||
//The host operating system is a web browser
|
||||
//宿主操作系统是网页浏览器
|
||||
Web
|
||||
Web,
|
||||
|
||||
//Editor
|
||||
//编辑器
|
||||
// Editor
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -210,6 +205,11 @@ public static class Config
|
|||
/// <returns></returns>
|
||||
public static OsEnum GetOs()
|
||||
{
|
||||
// if (OS.HasFeature("editor"))
|
||||
// {
|
||||
// return OsEnum.Editor;
|
||||
// }
|
||||
|
||||
if (OS.HasFeature("windows"))
|
||||
{
|
||||
return OsEnum.Windows;
|
||||
|
@ -239,15 +239,9 @@ public static class Config
|
|||
{
|
||||
return OsEnum.Ios;
|
||||
}
|
||||
|
||||
return OsEnum.Unknown;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Get the game version</para>
|
||||
/// <para>获取游戏版本</para>
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static string GetVersion()
|
||||
{
|
||||
var stringBuilder = new StringBuilder();
|
||||
|
@ -353,7 +347,7 @@ public static class Config
|
|||
/// <para>Physical collision layer number</para>
|
||||
/// <para>物理碰撞层 序号</para>
|
||||
/// </summary>
|
||||
public static class LayerNumber
|
||||
public class LayerNumber
|
||||
{
|
||||
public const int RoomArea = 1;
|
||||
public const int Ground = 2;
|
||||
|
@ -364,7 +358,23 @@ public static class Config
|
|||
public const int Mob = 7;
|
||||
}
|
||||
|
||||
public static class RoomDataTag
|
||||
/// <summary>
|
||||
/// <para>The event of entering the room</para>
|
||||
/// <para>进入房间的事件</para>
|
||||
/// </summary>
|
||||
public class EnterRoomEventId
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Exit the room event</para>
|
||||
/// <para>退出房间的事件</para>
|
||||
/// </summary>
|
||||
public class ExitRoomEventId
|
||||
{
|
||||
}
|
||||
|
||||
public class RoomDataTag
|
||||
{
|
||||
/// <summary>
|
||||
/// <para>Mark the starting room</para>
|
||||
|
@ -377,7 +387,7 @@ public static class Config
|
|||
/// <para>Specify the type of damage used in the game</para>
|
||||
/// <para>指定游戏内使用的伤害类型</para>
|
||||
/// </summary>
|
||||
public static class DamageType
|
||||
public class DamageType
|
||||
{
|
||||
/// <summary>
|
||||
/// <para>physical injury</para>
|
||||
|
|
|
@ -3,11 +3,7 @@ using ColdMint.scripts.map.events;
|
|||
|
||||
namespace ColdMint.scripts;
|
||||
|
||||
/// <summary>
|
||||
/// <para>EventManager</para>
|
||||
/// <para>事件管理器</para>
|
||||
/// </summary>
|
||||
public static class EventManager
|
||||
public class EventManager
|
||||
{
|
||||
/// <summary>
|
||||
/// <para>Event when the AI character is generated</para>
|
||||
|
@ -15,18 +11,8 @@ public static class EventManager
|
|||
/// </summary>
|
||||
public static Action<AiCharacterGenerateEvent>? AiCharacterGenerateEvent;
|
||||
|
||||
/// <summary>
|
||||
/// <para>Game Over Event</para>
|
||||
/// <para>游戏结束事件</para>
|
||||
/// </summary>
|
||||
public static Action<GameOverEvent>? GameOverEvent;
|
||||
|
||||
/// <summary>
|
||||
/// <para>Events when the game is replayed</para>
|
||||
/// <para>游戏重玩时的事件</para>
|
||||
/// </summary>
|
||||
public static Action<GameReplayEvent>? GameReplayEvent;
|
||||
|
||||
/// <summary>
|
||||
/// <para>Map starts generating events</para>
|
||||
/// <para>地图开始生成的事件</para>
|
||||
|
|
|
@ -8,14 +8,12 @@ namespace ColdMint.scripts;
|
|||
/// </summary>
|
||||
public partial class FpsLabel : Label
|
||||
{
|
||||
private bool _enable;
|
||||
bool _enable;
|
||||
private LabelSettings? _labelSettings;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
Text = null;
|
||||
//Enabled only in debug mode.
|
||||
//仅在调试模式启用。
|
||||
if (Config.IsDebug())
|
||||
{
|
||||
_labelSettings = new LabelSettings();
|
||||
|
|
|
@ -22,34 +22,17 @@ public static class GameSceneNodeHolder
|
|||
/// </summary>
|
||||
public static Node2D? WeaponContainer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// <para>PlayerContainer</para>
|
||||
/// <para>玩家容器</para>
|
||||
/// </summary>
|
||||
public static Node2D? PlayerContainer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// <para>AICharacterContainer</para>
|
||||
/// <para>AICharacter角色</para>
|
||||
/// </summary>
|
||||
public static Node2D? AiCharacterContainer { get; set; }
|
||||
public static Node2D? AICharacterContainer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// <para>HotBar</para>
|
||||
/// <para>快捷栏</para>
|
||||
/// </summary>
|
||||
public static HotBar? HotBar { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// <para>Health Bar UI</para>
|
||||
/// <para>健康条UI</para>
|
||||
/// </summary>
|
||||
public static HealthBarUi? HealthBarUi { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// <para>operation tip</para>
|
||||
/// <para>操作提示</para>
|
||||
/// </summary>
|
||||
public static RichTextLabel? OperationTipLabel { get; set; }
|
||||
}
|
|
@ -3,19 +3,10 @@ using Godot;
|
|||
|
||||
namespace ColdMint.scripts;
|
||||
|
||||
/// <summary>
|
||||
/// <para>HealthBarUi</para>
|
||||
/// <para>健康条UI</para>
|
||||
/// </summary>
|
||||
public partial class HealthBarUi : HBoxContainer
|
||||
{
|
||||
private int _maxHp;
|
||||
private int _currentHp;
|
||||
private Texture2D? _heartFull;
|
||||
private Texture2D? _heartEmpty;
|
||||
private Texture2D? _heartHalf;
|
||||
private Texture2D? _heartQuarter;
|
||||
private Texture2D? _heartThreeFourths;
|
||||
|
||||
public int CurrentHp
|
||||
{
|
||||
|
@ -148,6 +139,11 @@ public partial class HealthBarUi : HBoxContainer
|
|||
}
|
||||
}
|
||||
|
||||
private Texture2D? _heartFull;
|
||||
private Texture2D? _heartEmpty;
|
||||
private Texture2D? _heartHalf;
|
||||
private Texture2D? _heartQuarter;
|
||||
private Texture2D? _heartThreeFourths;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using ColdMint.scripts.utils;
|
||||
using System.Collections.Generic;
|
||||
using ColdMint.scripts.utils;
|
||||
using Godot;
|
||||
|
||||
namespace ColdMint.scripts;
|
||||
|
|
|
@ -45,7 +45,8 @@ public class AiPickNode : BehaviorTreeNodeTemplate
|
|||
{
|
||||
//If it's a weapon
|
||||
//如果是武器
|
||||
var distanceLength = weaponTemplate.GlobalPosition.DistanceTo(Character.GlobalPosition);
|
||||
var distance = weaponTemplate.GlobalPosition - Character.GlobalPosition;
|
||||
var distanceLength = distance.Length();
|
||||
if (distanceLength < closestDistance)
|
||||
{
|
||||
closestDistance = distanceLength;
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace ColdMint.scripts.camp;
|
|||
/// </summary>
|
||||
public class Camp
|
||||
{
|
||||
private readonly string _id;
|
||||
private string _id;
|
||||
private readonly List<string> _friendlyCampIdList;
|
||||
|
||||
public Camp(string id)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using ColdMint.scripts.camp;
|
||||
using ColdMint.scripts.damage;
|
||||
using ColdMint.scripts.debug;
|
||||
|
@ -101,7 +100,7 @@ public partial class CharacterTemplate : CharacterBody2D
|
|||
//角色创建后的初始血量
|
||||
private int _initialHp;
|
||||
|
||||
public int MaxHp;
|
||||
protected int MaxHp;
|
||||
|
||||
/// <summary>
|
||||
/// <para>The camp ID of the role</para>
|
||||
|
@ -122,36 +121,6 @@ public partial class CharacterTemplate : CharacterBody2D
|
|||
|
||||
public Node[] PickingRangeBodies => PickingRangeBodiesList?.ToArray() ?? Array.Empty<Node>();
|
||||
|
||||
/// <summary>
|
||||
/// <para>Resurrected character</para>
|
||||
/// <para>复活角色</para>
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
///<para>Sets the amount of Hp a character has after resurrection</para>
|
||||
///<para>设置角色复活后拥有的Hp</para>
|
||||
/// </remarks>
|
||||
public void Revive(int newHp)
|
||||
{
|
||||
//If the new Hp is less than or equal to 0, there is no need to resurrect
|
||||
//如果新的Hp小于等于0,那么不需要复活
|
||||
if (newHp <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (CurrentHp > 0)
|
||||
{
|
||||
//If the current Hp is greater than 0, there is no need to revive
|
||||
//如果当前Hp大于0,那么不需要复活
|
||||
return;
|
||||
}
|
||||
|
||||
//Check whether the new Hp is greater than the maximum Hp. If yes, set the current Hp to the maximum Hp. If no, set the current Hp to the new HP
|
||||
//判断新的Hp是否大于最大Hp,若大于那么将当前Hp设置为最大Hp,否则设置为新的Hp
|
||||
CurrentHp = newHp > MaxHp ? MaxHp : newHp;
|
||||
Visible = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Find the nearest item within the pick up area(Does not include items currently held)</para>
|
||||
/// <para>在拾捡范围内查找距离最近的物品(不包括当前持有的物品)</para>
|
||||
|
@ -354,10 +323,10 @@ public partial class CharacterTemplate : CharacterBody2D
|
|||
|
||||
//If the time difference between the last injury and the current time is greater than the time displayed in the health bar, the health bar is hidden
|
||||
//如果上次受到伤害的时间与当前时间的时间差大于健康条显示时间,则隐藏健康条
|
||||
if (_healthBar is { Visible: true })
|
||||
{
|
||||
var timeSpan = DateTime.Now - _lastDamageTime;
|
||||
if (timeSpan > Config.HealthBarDisplaysTime)
|
||||
{
|
||||
if (_healthBar != null)
|
||||
{
|
||||
_healthBar.Visible = false;
|
||||
}
|
||||
|
@ -464,7 +433,7 @@ public partial class CharacterTemplate : CharacterBody2D
|
|||
/// <para>处理角色死亡的事件</para>
|
||||
/// </summary>
|
||||
/// <param name="damageTemplate"></param>
|
||||
protected virtual Task OnDie(DamageTemplate damageTemplate)
|
||||
protected virtual void OnDie(DamageTemplate damageTemplate)
|
||||
{
|
||||
//If the attacker is not empty and the role name is not empty, then the role death message is printed
|
||||
//如果攻击者不为空,且角色名不为空,那么打印角色死亡信息
|
||||
|
@ -482,7 +451,6 @@ public partial class CharacterTemplate : CharacterBody2D
|
|||
}
|
||||
|
||||
QueueFree();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ColdMint.scripts.damage;
|
||||
using ColdMint.scripts.deathInfo;
|
||||
using ColdMint.scripts.map.events;
|
||||
using ColdMint.scripts.utils;
|
||||
using ColdMint.scripts.weapon;
|
||||
|
@ -155,11 +153,6 @@ public partial class Player : CharacterTemplate
|
|||
|
||||
protected override void HookPhysicsProcess(ref Vector2 velocity, double delta)
|
||||
{
|
||||
if (!Visible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//When the collision state between the platform detection ray and the platform changes
|
||||
//在平台检测射线与平台碰撞状态改变时
|
||||
if (_platformDetectionRayCast2D != null && _platformDetectionRayCast2D.IsColliding() != _collidingWithPlatform)
|
||||
|
@ -322,11 +315,6 @@ public partial class Player : CharacterTemplate
|
|||
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
if (!Visible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AimTheCurrentItemAtAPoint(GetGlobalMousePosition());
|
||||
var itemMarker2DPosition = Vector2.Zero;
|
||||
if (ItemMarker2D != null)
|
||||
|
@ -378,21 +366,18 @@ public partial class Player : CharacterTemplate
|
|||
}
|
||||
}
|
||||
|
||||
protected override async Task OnDie(DamageTemplate damageTemplate)
|
||||
protected override void OnDie(DamageTemplate damageTemplate)
|
||||
{
|
||||
if (EventManager.GameOverEvent != null)
|
||||
{
|
||||
var gameOverEvent = new GameOverEvent
|
||||
{
|
||||
DeathInfo = "\"白纸\"失手将自己杀死。"
|
||||
};
|
||||
EventManager.GameOverEvent(gameOverEvent);
|
||||
}
|
||||
|
||||
Visible = false;
|
||||
if (EventManager.GameOverEvent == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var gameOverEvent = new GameOverEvent();
|
||||
if (damageTemplate.Attacker != null)
|
||||
{
|
||||
gameOverEvent.DeathInfo = await DeathInfoGenerator.GenerateDeathInfo(this, damageTemplate.Attacker);
|
||||
}
|
||||
|
||||
EventManager.GameOverEvent.Invoke(gameOverEvent);
|
||||
}
|
||||
|
||||
protected override void EnterThePickingRangeBody(Node node)
|
||||
|
|
|
@ -12,16 +12,22 @@ public partial class DamageNumberNodeSpawn : Marker2D
|
|||
private Node2D? _rootNode;
|
||||
|
||||
/// <summary>
|
||||
/// <para>The vector in the negative direction</para>
|
||||
/// <para>负方向的向量</para>
|
||||
/// <para>The horizontal velocity is in the X positive direction</para>
|
||||
/// <para>水平速度的X正方向</para>
|
||||
/// </summary>
|
||||
private Vector2 _negativeVector;
|
||||
private int _horizontalVelocityPositiveDirection;
|
||||
|
||||
/// <summary>
|
||||
/// <para>Vector in the positive direction</para>
|
||||
/// <para>正方向的向量</para>
|
||||
/// <para>Horizontal velocity in the negative X direction</para>
|
||||
/// <para>水平速度的X负方向</para>
|
||||
/// </summary>
|
||||
private Vector2 _positiveVector;
|
||||
private int _horizontalVelocityNegativeDirection;
|
||||
|
||||
/// <summary>
|
||||
/// <para>vertical height</para>
|
||||
/// <para>垂直高度</para>
|
||||
/// </summary>
|
||||
private int _verticalHeight;
|
||||
|
||||
/// <summary>
|
||||
/// <para>物理渐变色</para>
|
||||
|
@ -47,31 +53,18 @@ public partial class DamageNumberNodeSpawn : Marker2D
|
|||
base._Ready();
|
||||
_damageNumberPackedScene = GD.Load("res://prefab/ui/DamageNumber.tscn") as PackedScene;
|
||||
_rootNode = GetNode<Node2D>("/root/Game/DamageNumberContainer");
|
||||
//The horizontal velocity is in the X positive direction
|
||||
//水平速度的X正方向
|
||||
var horizontalVelocityPositiveDirection = Config.CellSize * Config.HorizontalSpeedOfDamageNumbers;
|
||||
//Horizontal velocity in the negative X direction
|
||||
//水平速度的X负方向
|
||||
var horizontalVelocityNegativeDirection = -horizontalVelocityPositiveDirection;
|
||||
//vertical height
|
||||
//垂直高度
|
||||
var verticalHeight = -Config.CellSize * Config.VerticalVelocityOfDamageNumbers;
|
||||
//Compute left and right vectors
|
||||
//计算左右向量
|
||||
_negativeVector = new Vector2(horizontalVelocityNegativeDirection, verticalHeight);
|
||||
_positiveVector = new Vector2(horizontalVelocityPositiveDirection, verticalHeight);
|
||||
_horizontalVelocityPositiveDirection = Config.CellSize * Config.HorizontalSpeedOfDamageNumbers;
|
||||
_horizontalVelocityNegativeDirection = -_horizontalVelocityPositiveDirection;
|
||||
_verticalHeight = -Config.CellSize * Config.VerticalVelocityOfDamageNumbers;
|
||||
_physicalGradient = new Gradient();
|
||||
//Physical color from OpenColor2 to OpenColor6 (red)
|
||||
//物理色 从OpenColor2 到 OpenColor6(红色)
|
||||
_physicalGradient.SetColor(0, new Color("#ffc9c9"));
|
||||
_physicalGradient.SetColor(1, new Color("#fa5252"));
|
||||
_magicGradient = new Gradient();
|
||||
//Magic Color from OpenColor2 to OpenColor6(Purple)
|
||||
//魔法色 从OpenColor2 到 OpenColor6(紫色)
|
||||
_magicGradient.SetColor(0, new Color("#d0bfff"));
|
||||
_magicGradient.SetColor(1, new Color("#7950f2"));
|
||||
_defaultGradient = new Gradient();
|
||||
//default behavior
|
||||
//默认行为
|
||||
_defaultGradient.SetColor(0, new Color("#ff8787"));
|
||||
_defaultGradient.SetColor(1, new Color("#fa5252"));
|
||||
|
@ -94,7 +87,7 @@ public partial class DamageNumberNodeSpawn : Marker2D
|
|||
/// <param name="damageTemplate"></param>
|
||||
public void Display(DamageTemplate damageTemplate)
|
||||
{
|
||||
if (_rootNode == null || _damageNumberPackedScene == null)
|
||||
if (_damageNumberPackedScene == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -105,22 +98,18 @@ public partial class DamageNumberNodeSpawn : Marker2D
|
|||
}
|
||||
|
||||
CallDeferred("AddDamageNumberNode", damageNumber);
|
||||
|
||||
damageNumber.Position = GlobalPosition;
|
||||
if (damageTemplate.MoveLeft)
|
||||
{
|
||||
damageNumber.SetVelocity(_negativeVector);
|
||||
damageNumber.SetVelocity(new Vector2(_horizontalVelocityNegativeDirection, _verticalHeight));
|
||||
}
|
||||
else
|
||||
{
|
||||
damageNumber.SetVelocity(_positiveVector);
|
||||
damageNumber.SetVelocity(new Vector2(_horizontalVelocityPositiveDirection, _verticalHeight));
|
||||
}
|
||||
|
||||
var damageLabel = damageNumber.GetNode<Label>("Label");
|
||||
if (damageLabel == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
damageLabel.Text = damageTemplate.Damage.ToString();
|
||||
var labelSettings = new LabelSettings();
|
||||
var offset = damageTemplate.Damage / (float)damageTemplate.MaxDamage;
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using ColdMint.scripts.character;
|
||||
using ColdMint.scripts.utils;
|
||||
using Godot;
|
||||
|
||||
namespace ColdMint.scripts.deathInfo;
|
||||
|
||||
public static class DeathInfoGenerator
|
||||
{
|
||||
private static List<IDeathInfoHandler>? _deathInfoHandlers;
|
||||
|
||||
/// <summary>
|
||||
/// <para>Register the death message handler</para>
|
||||
/// <para>注册死亡信息处理器</para>
|
||||
/// </summary>
|
||||
/// <param name="deathInfoHandler"></param>
|
||||
public static void RegisterDeathInfoHandler(IDeathInfoHandler deathInfoHandler)
|
||||
{
|
||||
_deathInfoHandlers ??= new List<IDeathInfoHandler>();
|
||||
_deathInfoHandlers.Add(deathInfoHandler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Unregister the death message handler</para>
|
||||
/// <para>取消注册死亡信息处理器</para>
|
||||
/// </summary>
|
||||
/// <param name="deathInfoHandler"></param>
|
||||
public static void UnregisterDeathInfoHandler(IDeathInfoHandler deathInfoHandler)
|
||||
{
|
||||
if (_deathInfoHandlers == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_deathInfoHandlers.Remove(deathInfoHandler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Generate death info</para>
|
||||
/// <para>生成死亡信息</para>
|
||||
/// </summary>
|
||||
/// <param name="victim"></param>
|
||||
/// <param name="killer"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<string> GenerateDeathInfo(Player victim, Node killer)
|
||||
{
|
||||
var victimName = victim.ReadOnlyCharacterName ?? victim.Name;
|
||||
string killerName = killer.Name;
|
||||
if (killer is CharacterTemplate characterTemplate)
|
||||
{
|
||||
killerName = characterTemplate.ReadOnlyCharacterName ?? killer.Name;
|
||||
}
|
||||
if (_deathInfoHandlers == null || _deathInfoHandlers.Count == 0)
|
||||
{
|
||||
return GenerateDefaultDeathInfo(victimName, killerName) ?? string.Empty;
|
||||
}
|
||||
foreach (var deathInfoHandler in _deathInfoHandlers)
|
||||
{
|
||||
var deathInfo = await deathInfoHandler.GenerateDeathInfo(victimName, killerName, victim, killer);
|
||||
if (!string.IsNullOrEmpty(deathInfo))
|
||||
{
|
||||
return deathInfo;
|
||||
}
|
||||
}
|
||||
|
||||
return GenerateDefaultDeathInfo(victimName, killerName) ?? string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Generate a default death message</para>
|
||||
/// <para>生成默认的死亡信息</para>
|
||||
/// </summary>
|
||||
/// <param name="victimName"></param>
|
||||
/// <param name="killerName"></param>
|
||||
/// <returns></returns>
|
||||
private static string? GenerateDefaultDeathInfo(string victimName, string killerName)
|
||||
{
|
||||
return TranslationServerUtils.TranslateWithFormat("death_info", victimName, killerName);
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
using System.Threading.Tasks;
|
||||
using ColdMint.scripts.character;
|
||||
using Godot;
|
||||
|
||||
namespace ColdMint.scripts.deathInfo;
|
||||
|
||||
/// <summary>
|
||||
/// <para>Death information processor</para>
|
||||
/// <para>死亡信息处理器</para>
|
||||
/// </summary>
|
||||
public interface IDeathInfoHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// <para>Generate death info</para>
|
||||
/// <para>生成死亡信息</para>
|
||||
/// </summary>
|
||||
/// <param name="victimName">
|
||||
///<para>victimName</para>
|
||||
///<para>受害者名称</para>
|
||||
/// </param>
|
||||
/// <param name="killerName">
|
||||
///<para>KillerName</para>
|
||||
///<para>杀手名称</para>
|
||||
/// </param>
|
||||
/// <param name="victim">
|
||||
/// <para>victim</para>
|
||||
/// <para>受害者</para>
|
||||
/// </param>
|
||||
/// <param name="killer">
|
||||
/// <para>Killer</para>
|
||||
/// <para>杀手</para>
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
public Task<string?> GenerateDeathInfo(string victimName, string killerName, Player victim, Node killer);
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
using System.Threading.Tasks;
|
||||
using ColdMint.scripts.character;
|
||||
using ColdMint.scripts.utils;
|
||||
using Godot;
|
||||
|
||||
namespace ColdMint.scripts.deathInfo;
|
||||
|
||||
/// <summary>
|
||||
/// <para>Deal with the message that your game failed due to accidental injury</para>
|
||||
/// <para>处理自己误伤导致游戏失败的信息</para>
|
||||
/// </summary>
|
||||
public class SelfDeathInfoHandler : IDeathInfoHandler
|
||||
{
|
||||
private const string Prefix = "death_info_self_";
|
||||
private const int Length = 2;
|
||||
|
||||
public Task<string?> GenerateDeathInfo(string victimName, string killerName, Player victim, Node killer)
|
||||
{
|
||||
if (victim != killer) return Task.FromResult<string?>(null);
|
||||
var index = GD.Randi() % Length + 1;
|
||||
return Task.FromResult(
|
||||
TranslationServerUtils.TranslateWithFormat(Prefix + index, victimName, killerName));
|
||||
|
||||
}
|
||||
}
|
|
@ -34,7 +34,7 @@ public partial class GameSceneLoader : SceneLoaderTemplate
|
|||
//Load AICharacter container
|
||||
//加载AICharacter容器
|
||||
var aiCharacterContainer = GetNode<Node2D>("AICharacterContainer");
|
||||
GameSceneNodeHolder.AiCharacterContainer = aiCharacterContainer;
|
||||
GameSceneNodeHolder.AICharacterContainer = aiCharacterContainer;
|
||||
//Load player container
|
||||
//加载玩家容器
|
||||
var playerContainer = GetNode<Node2D>("PlayerContainer");
|
||||
|
|
|
@ -11,7 +11,6 @@ namespace ColdMint.scripts.loader.uiLoader;
|
|||
public partial class GameOverLoaderMenuLoader : UiLoaderTemplate
|
||||
{
|
||||
private Label? _deathInfoLabel;
|
||||
private Button? _restartButton;
|
||||
|
||||
public override void InitializeUi()
|
||||
{
|
||||
|
@ -20,25 +19,11 @@ public partial class GameOverLoaderMenuLoader : UiLoaderTemplate
|
|||
|
||||
public override void InitializeData()
|
||||
{
|
||||
_restartButton = GetNodeOrNull<Button>("CenterContainer/VBoxContainer/MarginContainer2/RestartButton");
|
||||
_deathInfoLabel =
|
||||
GetNode<Label>("CenterContainer/VBoxContainer/MarginContainer/CenterContainer2/DeathInfoLabel");
|
||||
EventManager.GameOverEvent += OnGameOver;
|
||||
}
|
||||
|
||||
public override void LoadUiActions()
|
||||
{
|
||||
if (_restartButton != null)
|
||||
{
|
||||
_restartButton.Pressed += () =>
|
||||
{
|
||||
var replayEvent = new GameReplayEvent();
|
||||
EventManager.GameReplayEvent?.Invoke(replayEvent);
|
||||
Visible = false;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private void OnGameOver(GameOverEvent gameOverEvent)
|
||||
{
|
||||
if (_deathInfoLabel == null)
|
||||
|
|
|
@ -2,7 +2,6 @@ using System;
|
|||
using System.IO;
|
||||
using System.Text;
|
||||
using ColdMint.scripts.camp;
|
||||
using ColdMint.scripts.deathInfo;
|
||||
using ColdMint.scripts.debug;
|
||||
using ColdMint.scripts.map;
|
||||
using ColdMint.scripts.map.roomInjectionProcessor;
|
||||
|
@ -39,7 +38,6 @@ public partial class MainMenuLoader : UiLoaderTemplate
|
|||
LogCat.MinLogLevel = LogCat.DisableAllLogLevel;
|
||||
}
|
||||
|
||||
DeathInfoGenerator.RegisterDeathInfoHandler(new SelfDeathInfoHandler());
|
||||
MapGenerator.RegisterRoomInjectionProcessor(new ChanceRoomInjectionProcessor());
|
||||
MapGenerator.RegisterRoomInjectionProcessor(new TimeIntervalRoomInjectorProcessor());
|
||||
//Register the corresponding encoding provider to solve the problem of garbled Chinese path of the compressed package
|
||||
|
|
|
@ -38,12 +38,12 @@ public partial class AiCharacterSpawn : Marker2D
|
|||
return;
|
||||
}
|
||||
|
||||
if (GameSceneNodeHolder.AiCharacterContainer == null)
|
||||
if (GameSceneNodeHolder.AICharacterContainer == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GameSceneNodeHolder.AiCharacterContainer.AddChild(aiCharacter);
|
||||
GameSceneNodeHolder.AICharacterContainer.AddChild(aiCharacter);
|
||||
aiCharacter.Position = GlobalPosition;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using ColdMint.scripts.debug;
|
||||
using ColdMint.scripts.levelGraphEditor;
|
||||
|
@ -148,9 +149,9 @@ public static class MapGenerator
|
|||
return;
|
||||
}
|
||||
|
||||
if (GameSceneNodeHolder.AiCharacterContainer != null)
|
||||
if (GameSceneNodeHolder.AICharacterContainer != null)
|
||||
{
|
||||
NodeUtils.DeleteAllChild(GameSceneNodeHolder.AiCharacterContainer);
|
||||
NodeUtils.DeleteAllChild(GameSceneNodeHolder.AICharacterContainer);
|
||||
}
|
||||
|
||||
NodeUtils.DeleteAllChild(_mapRoot);
|
||||
|
|
|
@ -18,26 +18,21 @@ public partial class PlayerSpawn : Marker2D
|
|||
base._Ready();
|
||||
_playerPackedScene = GD.Load<PackedScene>("res://prefab/entitys/Character.tscn");
|
||||
EventManager.MapGenerationCompleteEvent += MapGenerationCompleteEvent;
|
||||
EventManager.GameReplayEvent += GameReplayEvent;
|
||||
}
|
||||
|
||||
private void GameReplayEvent(GameReplayEvent gameReplayEvent)
|
||||
private void MapGenerationCompleteEvent(MapGenerationCompleteEvent mapGenerationCompleteEvent)
|
||||
{
|
||||
EventManager.MapGenerationCompleteEvent -= MapGenerationCompleteEvent;
|
||||
//After the map is generated, create the player instance.
|
||||
//当地图生成完成后,创建玩家实例。
|
||||
if (GameSceneNodeHolder.Player != null)
|
||||
{
|
||||
//An existing player instance will not be created.
|
||||
//已经存在玩家实例,不再创建。
|
||||
GameSceneNodeHolder.Player.Position = GlobalPosition;
|
||||
GameSceneNodeHolder.Player.Revive(GameSceneNodeHolder.Player.MaxHp);
|
||||
return;
|
||||
}
|
||||
SpawnPlayer();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Generate player instance</para>
|
||||
/// <para>生成玩家实例</para>
|
||||
/// </summary>
|
||||
private void SpawnPlayer()
|
||||
{
|
||||
if (GameSceneNodeHolder.PlayerContainer == null)
|
||||
{
|
||||
return;
|
||||
|
@ -62,24 +57,9 @@ public partial class PlayerSpawn : Marker2D
|
|||
LogCat.LogWithFormat("player_spawn_debug", player.ReadOnlyCharacterName, player.Position);
|
||||
}
|
||||
|
||||
private void MapGenerationCompleteEvent(MapGenerationCompleteEvent mapGenerationCompleteEvent)
|
||||
{
|
||||
//After the map is generated, create the player instance.
|
||||
//当地图生成完成后,创建玩家实例。
|
||||
if (GameSceneNodeHolder.Player != null)
|
||||
{
|
||||
//An existing player instance will not be created.
|
||||
//已经存在玩家实例,不再创建。
|
||||
return;
|
||||
}
|
||||
|
||||
SpawnPlayer();
|
||||
}
|
||||
|
||||
public override void _ExitTree()
|
||||
{
|
||||
base._ExitTree();
|
||||
EventManager.MapGenerationCompleteEvent -= MapGenerationCompleteEvent;
|
||||
EventManager.GameReplayEvent -= GameReplayEvent;
|
||||
}
|
||||
}
|
15
scripts/map/RoomAreaDetector.cs
Normal file
15
scripts/map/RoomAreaDetector.cs
Normal file
|
@ -0,0 +1,15 @@
|
|||
using Godot;
|
||||
|
||||
namespace ColdMint.scripts.map;
|
||||
|
||||
public partial class RoomAreaDetector : Node2D
|
||||
{
|
||||
private Area2D? _area2D;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
base._Ready();
|
||||
_area2D = GetNode<Area2D>("Area2D");
|
||||
}
|
||||
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
namespace ColdMint.scripts.map.events;
|
||||
|
||||
/// <summary>
|
||||
/// <para>Game replay event</para>
|
||||
/// <para>游戏重玩事件</para>
|
||||
/// </summary>
|
||||
public class GameReplayEvent
|
||||
{
|
||||
|
||||
}
|
|
@ -12,7 +12,9 @@ namespace ColdMint.scripts.projectile;
|
|||
/// </summary>
|
||||
public partial class ProjectileTemplate : CharacterBody2D
|
||||
{
|
||||
protected long Life;
|
||||
protected Timer? Timer;
|
||||
|
||||
protected double Life;
|
||||
|
||||
//The durability of the projectile
|
||||
//抛射体的耐久度
|
||||
|
@ -24,12 +26,9 @@ public partial class ProjectileTemplate : CharacterBody2D
|
|||
protected int MinDamage;
|
||||
protected int DamageType;
|
||||
|
||||
/// <summary>
|
||||
/// <para>After this time destroy the projectile</para>
|
||||
/// <para>超过此时刻销毁抛射体</para>
|
||||
/// </summary>
|
||||
private DateTime? _destructionTime;
|
||||
|
||||
//We use the Time node to specify when to destroy the projectile
|
||||
//我们用Time节点来指定何时销毁抛射体
|
||||
private Timer? _timer;
|
||||
|
||||
/// <summary>
|
||||
/// <para>The impact area of the bullet</para>
|
||||
|
@ -47,7 +46,10 @@ public partial class ProjectileTemplate : CharacterBody2D
|
|||
/// </remarks>
|
||||
protected Vector2 KnockbackForce;
|
||||
|
||||
public float Speed => GetMeta("Speed", "15").AsSingle();
|
||||
public float Speed
|
||||
{
|
||||
get => GetMeta("Speed", "15").AsSingle();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>The master of the weapon</para>
|
||||
|
@ -57,7 +59,6 @@ public partial class ProjectileTemplate : CharacterBody2D
|
|||
|
||||
public override void _Ready()
|
||||
{
|
||||
//The bullet's impact detection area
|
||||
//子弹的碰撞检测区域
|
||||
Area2D = GetNode<Area2D>("CollisionDetectionArea");
|
||||
Area2D.Monitoring = true;
|
||||
|
@ -68,17 +69,20 @@ public partial class ProjectileTemplate : CharacterBody2D
|
|||
MinDamage = GetMeta("MinDamage", "5").AsInt32();
|
||||
DamageType = GetMeta("DamageType", Config.DamageType.Physical).AsInt32();
|
||||
KnockbackForce = GetMeta("Knockback", Vector2.Zero).AsVector2();
|
||||
//life(ms)
|
||||
//子弹的存在时间(毫秒)
|
||||
Life = GetMeta("Life", "10000").AsInt64();
|
||||
//If the existence time is less than or equal to 0, then it is set to exist for 10 seconds, and projectiles that exist indefinitely are prohibited
|
||||
//子弹的存在时间
|
||||
Life = GetMeta("Life", "10").AsDouble();
|
||||
//如果存在时间小于等于0,那么设置为存在10秒,禁止无限期存在的抛射体
|
||||
if (Life <= 0)
|
||||
{
|
||||
Life = 10000;
|
||||
Life = 10;
|
||||
}
|
||||
|
||||
_destructionTime = DateTime.Now.AddMilliseconds(Life);
|
||||
Timer = new Timer();
|
||||
AddChild(Timer);
|
||||
Timer.WaitTime = Life;
|
||||
Timer.OneShot = true;
|
||||
Timer.Start();
|
||||
Timer.Timeout += OnTimeOut;
|
||||
}
|
||||
|
||||
|
||||
|
@ -137,12 +141,10 @@ public partial class ProjectileTemplate : CharacterBody2D
|
|||
|
||||
//Allow damage to be caused
|
||||
//允许造成伤害
|
||||
var damage = new Damage
|
||||
{
|
||||
Attacker = owner,
|
||||
MaxDamage = MaxDamage,
|
||||
MinDamage = MinDamage
|
||||
};
|
||||
var damage = new Damage();
|
||||
damage.Attacker = owner;
|
||||
damage.MaxDamage = MaxDamage;
|
||||
damage.MinDamage = MinDamage;
|
||||
damage.CreateDamage();
|
||||
damage.MoveLeft = Velocity.X < 0;
|
||||
damage.Type = DamageType;
|
||||
|
@ -180,7 +182,6 @@ public partial class ProjectileTemplate : CharacterBody2D
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DoDamage(Owner, node);
|
||||
//Please specify in the Mask who the bullet will collide with
|
||||
//请在Mask内配置子弹会和谁碰撞
|
||||
|
@ -214,16 +215,6 @@ public partial class ProjectileTemplate : CharacterBody2D
|
|||
QueueFree();
|
||||
}
|
||||
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
//If the existence time is exceeded, the projectile is destroyed
|
||||
//如果超过了存在时间,那么销毁抛射体
|
||||
if (DateTime.Now >= _destructionTime)
|
||||
{
|
||||
OnTimeOut();
|
||||
}
|
||||
}
|
||||
|
||||
public override void _PhysicsProcess(double delta)
|
||||
{
|
||||
MoveAndSlide();
|
||||
|
|
|
@ -5,13 +5,9 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace ColdMint.scripts.serialization;
|
||||
|
||||
/// <summary>
|
||||
/// <para>JsonSerialization</para>
|
||||
/// <para>Json序列化工具</para>
|
||||
/// </summary>
|
||||
public static class JsonSerialization
|
||||
{
|
||||
private static readonly JsonSerializerOptions Options = new()
|
||||
private static JsonSerializerOptions _options = new JsonSerializerOptions
|
||||
{
|
||||
//Case-insensitive attribute matching
|
||||
//不区分大小写的属性匹配
|
||||
|
@ -34,7 +30,7 @@ public static class JsonSerialization
|
|||
public static async Task<T?> ReadJsonFileToObj<T>(string path)
|
||||
{
|
||||
await using var openStream = File.OpenRead(path);
|
||||
return await JsonSerializer.DeserializeAsync<T>(openStream, Options);
|
||||
return await JsonSerializer.DeserializeAsync<T>(openStream, _options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -45,7 +41,7 @@ public static class JsonSerialization
|
|||
/// <returns></returns>
|
||||
public static string Serialize(object obj)
|
||||
{
|
||||
return JsonSerializer.Serialize(obj, Options);
|
||||
return JsonSerializer.Serialize(obj, _options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -57,11 +53,11 @@ public static class JsonSerialization
|
|||
/// <returns></returns>
|
||||
public static T? Deserialize<T>(string json)
|
||||
{
|
||||
return JsonSerializer.Deserialize<T>(json, Options);
|
||||
return JsonSerializer.Deserialize<T>(json, _options);
|
||||
}
|
||||
|
||||
public static async Task<T?> ReadJsonFileToObj<T>(Stream openStream)
|
||||
{
|
||||
return await JsonSerializer.DeserializeAsync<T>(openStream, Options);
|
||||
return await JsonSerializer.DeserializeAsync<T>(openStream, _options);
|
||||
}
|
||||
}
|
|
@ -2,11 +2,7 @@
|
|||
|
||||
namespace ColdMint.scripts.utils;
|
||||
|
||||
/// <summary>
|
||||
/// <para>CoordinateUtils</para>
|
||||
/// <para>坐标工具类</para>
|
||||
/// </summary>
|
||||
public static class CoordinateUtils
|
||||
public class CoordinateUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// <para>方向描述</para>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace ColdMint.scripts.utils;
|
||||
|
||||
|
@ -7,7 +6,7 @@ namespace ColdMint.scripts.utils;
|
|||
/// <para>Explorer Utils</para>
|
||||
/// <para>资源管理器工具</para>
|
||||
/// </summary>
|
||||
public static class ExplorerUtils
|
||||
public class ExplorerUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// <para>Call Explorer to open the directory</para>
|
||||
|
@ -54,12 +53,6 @@ public static class ExplorerUtils
|
|||
};
|
||||
Process.Start(startInfoAndroid);
|
||||
break;
|
||||
case Config.OsEnum.Unknown:
|
||||
case Config.OsEnum.Macos:
|
||||
case Config.OsEnum.Ios:
|
||||
case Config.OsEnum.Web:
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,10 +64,14 @@ public static class ExplorerUtils
|
|||
public static bool SupportOpenDirectory()
|
||||
{
|
||||
var osEnum = Config.GetOs();
|
||||
return osEnum switch
|
||||
switch (osEnum)
|
||||
{
|
||||
Config.OsEnum.Windows or Config.OsEnum.Linux or Config.OsEnum.Android => true,
|
||||
_ => false
|
||||
};
|
||||
case Config.OsEnum.Windows:
|
||||
case Config.OsEnum.Linux:
|
||||
case Config.OsEnum.Android:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,11 +2,7 @@
|
|||
|
||||
namespace ColdMint.scripts.utils;
|
||||
|
||||
/// <summary>
|
||||
/// <para>GuidUtils</para>
|
||||
/// <para>Guid工具</para>
|
||||
/// </summary>
|
||||
public static class GuidUtils
|
||||
public class GuidUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// <para>Get the new GUID</para>
|
||||
|
|
|
@ -2,11 +2,7 @@
|
|||
|
||||
namespace ColdMint.scripts.utils;
|
||||
|
||||
/// <summary>
|
||||
/// <para>Hash code utils</para>
|
||||
/// <para>哈希码工具</para>
|
||||
/// </summary>
|
||||
public static class HashCodeUtils
|
||||
public class HashCodeUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// <para>Gets the hash code for a string</para>
|
||||
|
@ -19,8 +15,6 @@ public static class HashCodeUtils
|
|||
/// <returns></returns>
|
||||
public static uint GetFixedHashCode(string str)
|
||||
{
|
||||
//Turn off overflow checking to improve performance
|
||||
//关闭溢出检查,以提高性能
|
||||
unchecked
|
||||
{
|
||||
return str.Aggregate(2166136261, (current, c) => (current ^ c) * 16777619);
|
||||
|
|
|
@ -15,11 +15,15 @@ public class Md5Utils
|
|||
/// <returns></returns>
|
||||
public static string GetFileMd5(string filePath)
|
||||
{
|
||||
using var md5 = MD5.Create();
|
||||
using var stream = File.OpenRead(filePath);
|
||||
using (var md5 = MD5.Create())
|
||||
{
|
||||
using (var stream = File.OpenRead(filePath))
|
||||
{
|
||||
var hash = md5.ComputeHash(stream);
|
||||
return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Calculates the Md5 value of the string</para>
|
||||
|
@ -29,8 +33,10 @@ public class Md5Utils
|
|||
/// <returns></returns>
|
||||
public static string GetStringMd5(string str)
|
||||
{
|
||||
using var md5 = MD5.Create();
|
||||
using (var md5 = MD5.Create())
|
||||
{
|
||||
var hash = md5.ComputeHash(Encoding.UTF8.GetBytes(str));
|
||||
return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,11 +4,7 @@ using Godot;
|
|||
|
||||
namespace ColdMint.scripts.utils;
|
||||
|
||||
/// <summary>
|
||||
/// <para>Node Utils</para>
|
||||
/// <para>节点工具</para>
|
||||
/// </summary>
|
||||
public static class NodeUtils
|
||||
public class NodeUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// <para>Delete all child nodes</para>
|
||||
|
@ -85,10 +81,11 @@ public static class NodeUtils
|
|||
continue;
|
||||
}
|
||||
|
||||
var distance = node2D.GlobalPosition.DistanceTo(origin.GlobalPosition);
|
||||
if (distance < closestDistance)
|
||||
var distance = node2D.GlobalPosition - origin.GlobalPosition;
|
||||
var distanceLength = distance.Length();
|
||||
if (distanceLength < closestDistance)
|
||||
{
|
||||
closestDistance = distance;
|
||||
closestDistance = distanceLength;
|
||||
closestNode = node2D;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ namespace ColdMint.scripts.utils;
|
|||
/// <para>ParabolicUtils</para>
|
||||
/// <para>抛物线工具</para>
|
||||
/// </summary>
|
||||
public static class ParabolicUtils
|
||||
public class ParabolicUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// <para>Calculated parabola</para>
|
||||
|
@ -40,7 +40,7 @@ public static class ParabolicUtils
|
|||
// 初始化结果数组
|
||||
var points = new Vector2[numSteps];
|
||||
// 计算每个采样点的位置
|
||||
for (var i = 0; i < numSteps; i++)
|
||||
for (int i = 0; i < numSteps; i++)
|
||||
{
|
||||
// 计算当前时间
|
||||
var t = i * steps;
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
namespace ColdMint.scripts.utils;
|
||||
|
||||
/// <summary>
|
||||
/// <para>StrUtils</para>
|
||||
/// <para>字符串工具</para>
|
||||
/// </summary>
|
||||
public static class StrUtils
|
||||
public class StrUtils
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -2,10 +2,6 @@
|
|||
|
||||
namespace ColdMint.scripts.utils;
|
||||
|
||||
/// <summary>
|
||||
/// <para>TileMapUtils</para>
|
||||
/// <para>TileMap工具</para>
|
||||
/// </summary>
|
||||
public static class TileMapUtils
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -3,10 +3,6 @@ using ColdMint.scripts.debug;
|
|||
|
||||
namespace ColdMint.scripts.utils;
|
||||
|
||||
/// <summary>
|
||||
/// <para>Time Utils</para>
|
||||
/// <para>时间工具</para>
|
||||
/// </summary>
|
||||
public static class TimeUtils
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -2,10 +2,6 @@
|
|||
|
||||
namespace ColdMint.scripts.utils;
|
||||
|
||||
/// <summary>
|
||||
/// <para>Translation server utils</para>
|
||||
/// <para>翻译服务器工具</para>
|
||||
/// </summary>
|
||||
public static class TranslationServerUtils
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -5,26 +5,9 @@ using Godot;
|
|||
|
||||
namespace ColdMint.scripts.weapon;
|
||||
|
||||
/// <summary>
|
||||
/// <para>Projectile weapons</para>
|
||||
/// <para>抛射体武器</para>
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
///<para>These weapons can fire projectiles to attack the enemy.For example: guns and scepters.Generate a bullet to attack the enemy.</para>
|
||||
///<para>这类武器可发射抛射体,攻击敌人。例如:枪支和法杖。生成一个子弹攻击敌人。</para>
|
||||
/// </remarks>
|
||||
public partial class ProjectileWeapon : WeaponTemplate
|
||||
{
|
||||
/// <summary>
|
||||
/// <para>The formation position of the projectile</para>
|
||||
/// <para>抛射体的生成位置</para>
|
||||
/// </summary>
|
||||
private Marker2D? _marker2D;
|
||||
|
||||
/// <summary>
|
||||
/// <para>List of projectiles</para>
|
||||
/// <para>抛射体列表</para>
|
||||
/// </summary>
|
||||
private string[]? _projectiles;
|
||||
private Dictionary<string, PackedScene>? _projectileCache;
|
||||
private Node2D? _projectileContainer;
|
||||
|
@ -38,10 +21,6 @@ public partial class ProjectileWeapon : WeaponTemplate
|
|||
foreach (var projectileItem in _projectiles)
|
||||
{
|
||||
var packedScene = GD.Load<PackedScene>(projectileItem);
|
||||
if (packedScene == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
_projectileCache.Add(projectileItem, packedScene);
|
||||
}
|
||||
|
||||
|
@ -51,25 +30,26 @@ public partial class ProjectileWeapon : WeaponTemplate
|
|||
|
||||
protected override void DoFire(Node2D? owner, Vector2 enemyGlobalPosition)
|
||||
{
|
||||
if (_projectiles.IsEmpty())
|
||||
{
|
||||
LogCat.LogError("projectiles_is_empty");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_projectileCache == null || _projectiles == null || owner == null || _projectileContainer == null ||
|
||||
_marker2D == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_projectiles.IsEmpty())
|
||||
{
|
||||
LogCat.LogError("projectiles_is_empty");
|
||||
return;
|
||||
}
|
||||
//Get the first projectile
|
||||
//获取第一个抛射体
|
||||
var projectileScene = _projectileCache[_projectiles[0]];
|
||||
var projectile = projectileScene.Instantiate() as ProjectileTemplate;
|
||||
if (projectile != null)
|
||||
{
|
||||
projectile.Owner = owner;
|
||||
projectile.Velocity = (enemyGlobalPosition - _marker2D.GlobalPosition).Normalized() * projectile.Speed;
|
||||
var vector2 = (enemyGlobalPosition - _marker2D.GlobalPosition).Normalized() * projectile.Speed;
|
||||
projectile.Velocity = vector2;
|
||||
projectile.Position = _marker2D.GlobalPosition;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace ColdMint.scripts.weapon;
|
|||
/// </summary>
|
||||
public partial class WeaponTemplate : RigidBody2D, IItem
|
||||
{
|
||||
private float _gravity = ProjectSettings.GetSetting("physics/2d/default_gravity").AsSingle();
|
||||
public float Gravity = ProjectSettings.GetSetting("physics/2d/default_gravity").AsSingle();
|
||||
|
||||
public string? Id { get; set; }
|
||||
public int Quantity { get; set; }
|
||||
|
@ -42,10 +42,7 @@ public partial class WeaponTemplate : RigidBody2D, IItem
|
|||
|
||||
private DateTime? _lastFiringTime;
|
||||
|
||||
/// <summary>
|
||||
/// <para>Firing interval</para>
|
||||
/// <para>开火间隔</para>
|
||||
/// </summary>
|
||||
//开火间隔
|
||||
private TimeSpan _firingInterval;
|
||||
|
||||
|
||||
|
@ -59,10 +56,6 @@ public partial class WeaponTemplate : RigidBody2D, IItem
|
|||
/// </remarks>
|
||||
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? _area2D;
|
||||
|
||||
protected RayCast2D? RayCast2D;
|
||||
|
@ -124,6 +117,7 @@ public partial class WeaponTemplate : RigidBody2D, IItem
|
|||
|
||||
//If allowed to cause harm
|
||||
//如果允许造成伤害
|
||||
Owner = null;
|
||||
var damage = new Damage
|
||||
{
|
||||
MaxDamage = Math.Abs(_maxContactInjury),
|
||||
|
@ -134,9 +128,6 @@ public partial class WeaponTemplate : RigidBody2D, IItem
|
|||
damage.MoveLeft = LinearVelocity.X < 0;
|
||||
damage.Type = Config.DamageType.Physical;
|
||||
characterTemplate.Damage(damage);
|
||||
//Can only cause one collision damage.
|
||||
//仅能造成一次碰撞伤害。
|
||||
EnableContactInjury = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -186,19 +177,14 @@ public partial class WeaponTemplate : RigidBody2D, IItem
|
|||
public void Fire(Node2D? owner, Vector2 enemyGlobalPosition)
|
||||
{
|
||||
var nowTime = DateTime.Now;
|
||||
//If the present time minus the time of the last fire is less than the interval between fires, it means that the fire cannot be fired yet.
|
||||
//如果现在时间减去上次开火时间小于开火间隔,说明还不能开火。
|
||||
if (_lastFiringTime != null && nowTime - _lastFiringTime < _firingInterval)
|
||||
if (_lastFiringTime == null || nowTime - _lastFiringTime > _firingInterval)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (owner is CharacterTemplate characterTemplate)
|
||||
{
|
||||
//We check the recoil of the weapon before each firing.
|
||||
//我们在每次开火之前,检查武器的后坐力。
|
||||
if (_recoil != Vector2.Zero)
|
||||
{
|
||||
//假设此武器拥有后坐力
|
||||
var force = new Vector2();
|
||||
var forceX = Math.Abs(_recoil.X);
|
||||
if (Math.Abs(RotationDegrees) < 90)
|
||||
|
@ -214,9 +200,12 @@ public partial class WeaponTemplate : RigidBody2D, IItem
|
|||
}
|
||||
}
|
||||
|
||||
//If the time difference is greater than the firing interval, then fire
|
||||
//如果可以时间差大于开火间隔,那么开火
|
||||
DoFire(owner, enemyGlobalPosition);
|
||||
_lastFiringTime = nowTime;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Execute fire</para>
|
||||
|
|
Loading…
Reference in New Issue
Block a user