Support for restarting the game.
支持重新开始游戏了。
This commit is contained in:
parent
74c85cd5a7
commit
2a836e32e6
5
locals/DeathInfo.csv
Normal file
5
locals/DeathInfo.csv
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
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}照準を忘れました。
|
|
17
locals/DeathInfo.csv.import
Normal file
17
locals/DeathInfo.csv.import
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
[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
|
BIN
locals/DeathInfo.en.translation
Normal file
BIN
locals/DeathInfo.en.translation
Normal file
Binary file not shown.
BIN
locals/DeathInfo.jp.translation
Normal file
BIN
locals/DeathInfo.jp.translation
Normal file
Binary file not shown.
BIN
locals/DeathInfo.zh.translation
Normal file
BIN
locals/DeathInfo.zh.translation
Normal file
Binary file not shown.
|
@ -146,7 +146,7 @@ hotbar_previous={
|
||||||
|
|
||||||
[internationalization]
|
[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")
|
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")
|
||||||
|
|
||||||
[layer_names]
|
[layer_names]
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,6 @@ layout_mode = 2
|
||||||
theme_override_constants/margin_top = 10
|
theme_override_constants/margin_top = 10
|
||||||
theme_override_constants/margin_bottom = 150
|
theme_override_constants/margin_bottom = 150
|
||||||
|
|
||||||
[node name="Button" type="Button" parent="CenterContainer/VBoxContainer/MarginContainer2"]
|
[node name="RestartButton" type="Button" parent="CenterContainer/VBoxContainer/MarginContainer2"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "restart"
|
text = "restart"
|
||||||
|
|
|
@ -11,8 +11,18 @@ public class EventManager
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static Action<AiCharacterGenerateEvent>? AiCharacterGenerateEvent;
|
public static Action<AiCharacterGenerateEvent>? AiCharacterGenerateEvent;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Game Over Event</para>
|
||||||
|
/// <para>游戏结束事件</para>
|
||||||
|
/// </summary>
|
||||||
public static Action<GameOverEvent>? GameOverEvent;
|
public static Action<GameOverEvent>? GameOverEvent;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Events when the game is replayed</para>
|
||||||
|
/// <para>游戏重玩时的事件</para>
|
||||||
|
/// </summary>
|
||||||
|
public static Action<GameReplayEvent>? GameReplayEvent;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>Map starts generating events</para>
|
/// <para>Map starts generating events</para>
|
||||||
/// <para>地图开始生成的事件</para>
|
/// <para>地图开始生成的事件</para>
|
||||||
|
|
|
@ -45,8 +45,7 @@ public class AiPickNode : BehaviorTreeNodeTemplate
|
||||||
{
|
{
|
||||||
//If it's a weapon
|
//If it's a weapon
|
||||||
//如果是武器
|
//如果是武器
|
||||||
var distance = weaponTemplate.GlobalPosition - Character.GlobalPosition;
|
var distanceLength = weaponTemplate.GlobalPosition.DistanceTo(Character.GlobalPosition);
|
||||||
var distanceLength = distance.Length();
|
|
||||||
if (distanceLength < closestDistance)
|
if (distanceLength < closestDistance)
|
||||||
{
|
{
|
||||||
closestDistance = distanceLength;
|
closestDistance = distanceLength;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using ColdMint.scripts.camp;
|
using ColdMint.scripts.camp;
|
||||||
using ColdMint.scripts.damage;
|
using ColdMint.scripts.damage;
|
||||||
using ColdMint.scripts.debug;
|
using ColdMint.scripts.debug;
|
||||||
|
@ -100,7 +101,7 @@ public partial class CharacterTemplate : CharacterBody2D
|
||||||
//角色创建后的初始血量
|
//角色创建后的初始血量
|
||||||
private int _initialHp;
|
private int _initialHp;
|
||||||
|
|
||||||
protected int MaxHp;
|
public int MaxHp;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>The camp ID of the role</para>
|
/// <para>The camp ID of the role</para>
|
||||||
|
@ -121,6 +122,34 @@ public partial class CharacterTemplate : CharacterBody2D
|
||||||
|
|
||||||
public Node[] PickingRangeBodies => PickingRangeBodiesList?.ToArray() ?? Array.Empty<Node>();
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
CurrentHp = newHp;
|
||||||
|
Visible = true;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>Find the nearest item within the pick up area(Does not include items currently held)</para>
|
/// <para>Find the nearest item within the pick up area(Does not include items currently held)</para>
|
||||||
/// <para>在拾捡范围内查找距离最近的物品(不包括当前持有的物品)</para>
|
/// <para>在拾捡范围内查找距离最近的物品(不包括当前持有的物品)</para>
|
||||||
|
@ -433,7 +462,7 @@ public partial class CharacterTemplate : CharacterBody2D
|
||||||
/// <para>处理角色死亡的事件</para>
|
/// <para>处理角色死亡的事件</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="damageTemplate"></param>
|
/// <param name="damageTemplate"></param>
|
||||||
protected virtual void OnDie(DamageTemplate damageTemplate)
|
protected virtual Task OnDie(DamageTemplate damageTemplate)
|
||||||
{
|
{
|
||||||
//If the attacker is not empty and the role name is not empty, then the role death message is printed
|
//If the attacker is not empty and the role name is not empty, then the role death message is printed
|
||||||
//如果攻击者不为空,且角色名不为空,那么打印角色死亡信息
|
//如果攻击者不为空,且角色名不为空,那么打印角色死亡信息
|
||||||
|
@ -451,6 +480,7 @@ public partial class CharacterTemplate : CharacterBody2D
|
||||||
}
|
}
|
||||||
|
|
||||||
QueueFree();
|
QueueFree();
|
||||||
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using ColdMint.scripts.damage;
|
using ColdMint.scripts.damage;
|
||||||
|
using ColdMint.scripts.deathInfo;
|
||||||
using ColdMint.scripts.map.events;
|
using ColdMint.scripts.map.events;
|
||||||
using ColdMint.scripts.utils;
|
using ColdMint.scripts.utils;
|
||||||
using ColdMint.scripts.weapon;
|
using ColdMint.scripts.weapon;
|
||||||
|
@ -153,6 +155,11 @@ public partial class Player : CharacterTemplate
|
||||||
|
|
||||||
protected override void HookPhysicsProcess(ref Vector2 velocity, double delta)
|
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
|
//When the collision state between the platform detection ray and the platform changes
|
||||||
//在平台检测射线与平台碰撞状态改变时
|
//在平台检测射线与平台碰撞状态改变时
|
||||||
if (_platformDetectionRayCast2D != null && _platformDetectionRayCast2D.IsColliding() != _collidingWithPlatform)
|
if (_platformDetectionRayCast2D != null && _platformDetectionRayCast2D.IsColliding() != _collidingWithPlatform)
|
||||||
|
@ -315,6 +322,11 @@ public partial class Player : CharacterTemplate
|
||||||
|
|
||||||
public override void _Process(double delta)
|
public override void _Process(double delta)
|
||||||
{
|
{
|
||||||
|
if (!Visible)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
AimTheCurrentItemAtAPoint(GetGlobalMousePosition());
|
AimTheCurrentItemAtAPoint(GetGlobalMousePosition());
|
||||||
var itemMarker2DPosition = Vector2.Zero;
|
var itemMarker2DPosition = Vector2.Zero;
|
||||||
if (ItemMarker2D != null)
|
if (ItemMarker2D != null)
|
||||||
|
@ -366,18 +378,21 @@ public partial class Player : CharacterTemplate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDie(DamageTemplate damageTemplate)
|
protected override async Task OnDie(DamageTemplate damageTemplate)
|
||||||
{
|
{
|
||||||
if (EventManager.GameOverEvent != null)
|
Visible = false;
|
||||||
|
if (EventManager.GameOverEvent == null)
|
||||||
{
|
{
|
||||||
var gameOverEvent = new GameOverEvent
|
return;
|
||||||
{
|
|
||||||
DeathInfo = "\"白纸\"失手将自己杀死。"
|
|
||||||
};
|
|
||||||
EventManager.GameOverEvent(gameOverEvent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Visible = false;
|
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)
|
protected override void EnterThePickingRangeBody(Node node)
|
||||||
|
|
81
scripts/deathInfo/DeathInfoGenerator.cs
Normal file
81
scripts/deathInfo/DeathInfoGenerator.cs
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
35
scripts/deathInfo/IDeathInfoHandler.cs
Normal file
35
scripts/deathInfo/IDeathInfoHandler.cs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
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);
|
||||||
|
}
|
25
scripts/deathInfo/SelfDeathInfoHandler.cs
Normal file
25
scripts/deathInfo/SelfDeathInfoHandler.cs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
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));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,7 @@ namespace ColdMint.scripts.loader.uiLoader;
|
||||||
public partial class GameOverLoaderMenuLoader : UiLoaderTemplate
|
public partial class GameOverLoaderMenuLoader : UiLoaderTemplate
|
||||||
{
|
{
|
||||||
private Label? _deathInfoLabel;
|
private Label? _deathInfoLabel;
|
||||||
|
private Button? _restartButton;
|
||||||
|
|
||||||
public override void InitializeUi()
|
public override void InitializeUi()
|
||||||
{
|
{
|
||||||
|
@ -19,11 +20,25 @@ public partial class GameOverLoaderMenuLoader : UiLoaderTemplate
|
||||||
|
|
||||||
public override void InitializeData()
|
public override void InitializeData()
|
||||||
{
|
{
|
||||||
|
_restartButton = GetNodeOrNull<Button>("CenterContainer/VBoxContainer/MarginContainer2/RestartButton");
|
||||||
_deathInfoLabel =
|
_deathInfoLabel =
|
||||||
GetNode<Label>("CenterContainer/VBoxContainer/MarginContainer/CenterContainer2/DeathInfoLabel");
|
GetNode<Label>("CenterContainer/VBoxContainer/MarginContainer/CenterContainer2/DeathInfoLabel");
|
||||||
EventManager.GameOverEvent += OnGameOver;
|
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)
|
private void OnGameOver(GameOverEvent gameOverEvent)
|
||||||
{
|
{
|
||||||
if (_deathInfoLabel == null)
|
if (_deathInfoLabel == null)
|
||||||
|
|
|
@ -2,6 +2,7 @@ using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using ColdMint.scripts.camp;
|
using ColdMint.scripts.camp;
|
||||||
|
using ColdMint.scripts.deathInfo;
|
||||||
using ColdMint.scripts.debug;
|
using ColdMint.scripts.debug;
|
||||||
using ColdMint.scripts.map;
|
using ColdMint.scripts.map;
|
||||||
using ColdMint.scripts.map.roomInjectionProcessor;
|
using ColdMint.scripts.map.roomInjectionProcessor;
|
||||||
|
@ -38,6 +39,7 @@ public partial class MainMenuLoader : UiLoaderTemplate
|
||||||
LogCat.MinLogLevel = LogCat.DisableAllLogLevel;
|
LogCat.MinLogLevel = LogCat.DisableAllLogLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DeathInfoGenerator.RegisterDeathInfoHandler(new SelfDeathInfoHandler());
|
||||||
MapGenerator.RegisterRoomInjectionProcessor(new ChanceRoomInjectionProcessor());
|
MapGenerator.RegisterRoomInjectionProcessor(new ChanceRoomInjectionProcessor());
|
||||||
MapGenerator.RegisterRoomInjectionProcessor(new TimeIntervalRoomInjectorProcessor());
|
MapGenerator.RegisterRoomInjectionProcessor(new TimeIntervalRoomInjectorProcessor());
|
||||||
//Register the corresponding encoding provider to solve the problem of garbled Chinese path of the compressed package
|
//Register the corresponding encoding provider to solve the problem of garbled Chinese path of the compressed package
|
||||||
|
|
|
@ -18,21 +18,26 @@ public partial class PlayerSpawn : Marker2D
|
||||||
base._Ready();
|
base._Ready();
|
||||||
_playerPackedScene = GD.Load<PackedScene>("res://prefab/entitys/Character.tscn");
|
_playerPackedScene = GD.Load<PackedScene>("res://prefab/entitys/Character.tscn");
|
||||||
EventManager.MapGenerationCompleteEvent += MapGenerationCompleteEvent;
|
EventManager.MapGenerationCompleteEvent += MapGenerationCompleteEvent;
|
||||||
|
EventManager.GameReplayEvent += GameReplayEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MapGenerationCompleteEvent(MapGenerationCompleteEvent mapGenerationCompleteEvent)
|
private void GameReplayEvent(GameReplayEvent gameReplayEvent)
|
||||||
{
|
{
|
||||||
EventManager.MapGenerationCompleteEvent -= MapGenerationCompleteEvent;
|
|
||||||
//After the map is generated, create the player instance.
|
|
||||||
//当地图生成完成后,创建玩家实例。
|
|
||||||
if (GameSceneNodeHolder.Player != null)
|
if (GameSceneNodeHolder.Player != null)
|
||||||
{
|
{
|
||||||
//An existing player instance will not be created.
|
|
||||||
//已经存在玩家实例,不再创建。
|
|
||||||
GameSceneNodeHolder.Player.Position = GlobalPosition;
|
GameSceneNodeHolder.Player.Position = GlobalPosition;
|
||||||
|
GameSceneNodeHolder.Player.Revive(GameSceneNodeHolder.Player.MaxHp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
SpawnPlayer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Generate player instance</para>
|
||||||
|
/// <para>生成玩家实例</para>
|
||||||
|
/// </summary>
|
||||||
|
private void SpawnPlayer()
|
||||||
|
{
|
||||||
if (GameSceneNodeHolder.PlayerContainer == null)
|
if (GameSceneNodeHolder.PlayerContainer == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -57,9 +62,24 @@ public partial class PlayerSpawn : Marker2D
|
||||||
LogCat.LogWithFormat("player_spawn_debug", player.ReadOnlyCharacterName, player.Position);
|
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()
|
public override void _ExitTree()
|
||||||
{
|
{
|
||||||
base._ExitTree();
|
base._ExitTree();
|
||||||
EventManager.MapGenerationCompleteEvent -= MapGenerationCompleteEvent;
|
EventManager.MapGenerationCompleteEvent -= MapGenerationCompleteEvent;
|
||||||
|
EventManager.GameReplayEvent -= GameReplayEvent;
|
||||||
}
|
}
|
||||||
}
|
}
|
10
scripts/map/events/GameReplayEvent.cs
Normal file
10
scripts/map/events/GameReplayEvent.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
namespace ColdMint.scripts.map.events;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Game replay event</para>
|
||||||
|
/// <para>游戏重玩事件</para>
|
||||||
|
/// </summary>
|
||||||
|
public class GameReplayEvent
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -177,34 +177,36 @@ public partial class WeaponTemplate : RigidBody2D, IItem
|
||||||
public void Fire(Node2D? owner, Vector2 enemyGlobalPosition)
|
public void Fire(Node2D? owner, Vector2 enemyGlobalPosition)
|
||||||
{
|
{
|
||||||
var nowTime = DateTime.Now;
|
var nowTime = DateTime.Now;
|
||||||
if (_lastFiringTime == null || nowTime - _lastFiringTime > _firingInterval)
|
//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 (owner is CharacterTemplate characterTemplate)
|
return;
|
||||||
{
|
|
||||||
//我们在每次开火之前,检查武器的后坐力。
|
|
||||||
if (_recoil != Vector2.Zero)
|
|
||||||
{
|
|
||||||
//假设此武器拥有后坐力
|
|
||||||
var force = new Vector2();
|
|
||||||
var forceX = Math.Abs(_recoil.X);
|
|
||||||
if (Math.Abs(RotationDegrees) < 90)
|
|
||||||
{
|
|
||||||
//The weapon goes to the right and we apply a recoil to the left
|
|
||||||
//武器朝向右边我们向左施加后坐力
|
|
||||||
forceX = -forceX;
|
|
||||||
}
|
|
||||||
|
|
||||||
force.X = forceX * Config.CellSize;
|
|
||||||
force.Y = _recoil.Y * Config.CellSize;
|
|
||||||
characterTemplate.AddForce(force);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//If the time difference is greater than the firing interval, then fire
|
|
||||||
//如果可以时间差大于开火间隔,那么开火
|
|
||||||
DoFire(owner, enemyGlobalPosition);
|
|
||||||
_lastFiringTime = nowTime;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
//The weapon goes to the right and we apply a recoil to the left
|
||||||
|
//武器朝向右边我们向左施加后坐力
|
||||||
|
forceX = -forceX;
|
||||||
|
}
|
||||||
|
|
||||||
|
force.X = forceX * Config.CellSize;
|
||||||
|
force.Y = _recoil.Y * Config.CellSize;
|
||||||
|
characterTemplate.AddForce(force);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DoFire(owner, enemyGlobalPosition);
|
||||||
|
_lastFiringTime = nowTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user