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]
|
||||
|
||||
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]
|
||||
|
||||
|
|
|
@ -55,6 +55,6 @@ layout_mode = 2
|
|||
theme_override_constants/margin_top = 10
|
||||
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
|
||||
text = "restart"
|
||||
|
|
|
@ -11,8 +11,18 @@ public 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>
|
||||
|
|
|
@ -45,8 +45,7 @@ public class AiPickNode : BehaviorTreeNodeTemplate
|
|||
{
|
||||
//If it's a weapon
|
||||
//如果是武器
|
||||
var distance = weaponTemplate.GlobalPosition - Character.GlobalPosition;
|
||||
var distanceLength = distance.Length();
|
||||
var distanceLength = weaponTemplate.GlobalPosition.DistanceTo(Character.GlobalPosition);
|
||||
if (distanceLength < closestDistance)
|
||||
{
|
||||
closestDistance = distanceLength;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using ColdMint.scripts.camp;
|
||||
using ColdMint.scripts.damage;
|
||||
using ColdMint.scripts.debug;
|
||||
|
@ -100,7 +101,7 @@ public partial class CharacterTemplate : CharacterBody2D
|
|||
//角色创建后的初始血量
|
||||
private int _initialHp;
|
||||
|
||||
protected int MaxHp;
|
||||
public int MaxHp;
|
||||
|
||||
/// <summary>
|
||||
/// <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>();
|
||||
|
||||
/// <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>
|
||||
/// <para>Find the nearest item within the pick up area(Does not include items currently held)</para>
|
||||
/// <para>在拾捡范围内查找距离最近的物品(不包括当前持有的物品)</para>
|
||||
|
@ -433,7 +462,7 @@ public partial class CharacterTemplate : CharacterBody2D
|
|||
/// <para>处理角色死亡的事件</para>
|
||||
/// </summary>
|
||||
/// <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
|
||||
//如果攻击者不为空,且角色名不为空,那么打印角色死亡信息
|
||||
|
@ -451,6 +480,7 @@ public partial class CharacterTemplate : CharacterBody2D
|
|||
}
|
||||
|
||||
QueueFree();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
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;
|
||||
|
@ -153,6 +155,11 @@ 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)
|
||||
|
@ -315,6 +322,11 @@ public partial class Player : CharacterTemplate
|
|||
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
if (!Visible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AimTheCurrentItemAtAPoint(GetGlobalMousePosition());
|
||||
var itemMarker2DPosition = Vector2.Zero;
|
||||
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
|
||||
{
|
||||
DeathInfo = "\"白纸\"失手将自己杀死。"
|
||||
};
|
||||
EventManager.GameOverEvent(gameOverEvent);
|
||||
return;
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
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
|
||||
{
|
||||
private Label? _deathInfoLabel;
|
||||
private Button? _restartButton;
|
||||
|
||||
public override void InitializeUi()
|
||||
{
|
||||
|
@ -19,11 +20,25 @@ 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,6 +2,7 @@ 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;
|
||||
|
@ -38,6 +39,7 @@ 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
|
||||
|
|
|
@ -18,21 +18,26 @@ public partial class PlayerSpawn : Marker2D
|
|||
base._Ready();
|
||||
_playerPackedScene = GD.Load<PackedScene>("res://prefab/entitys/Character.tscn");
|
||||
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)
|
||||
{
|
||||
//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;
|
||||
|
@ -57,9 +62,24 @@ 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;
|
||||
}
|
||||
}
|
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,14 +177,19 @@ public partial class WeaponTemplate : RigidBody2D, IItem
|
|||
public void Fire(Node2D? owner, Vector2 enemyGlobalPosition)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
|
@ -200,12 +205,9 @@ 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