using System; using ColdMint.scripts.camp; using ColdMint.scripts.character; using ColdMint.scripts.damage; using ColdMint.scripts.inventory; using Godot; namespace ColdMint.scripts.weapon; /// /// WeaponTemplate /// 武器模板 /// public partial class WeaponTemplate : RigidBody2D, IItem { private float _gravity = ProjectSettings.GetSetting("physics/2d/default_gravity").AsSingle(); public string? Id { get; set; } public int Quantity { get; set; } public int MaxStackQuantity { get; set; } public Texture2D? Icon { get; set; } public new string? Name { get; set; } public string? Description { get; set; } public Action? OnUse { get; set; } public Func? OnInstantiation { get; set; } /// /// Whether the weapon is currently picked up /// 当前武器是否被捡起了 /// public bool Picked { get; set; } /// /// Owner /// 主人 /// public new Node2D? Owner { get; set; } /// /// Enabled contact injury /// 启用接触伤害 /// public bool EnableContactInjury; private int _minContactInjury; private int _maxContactInjury; private DateTime? _lastFiringTime; /// /// Firing interval /// 开火间隔 /// private TimeSpan _firingInterval; /// /// The recoil of the weapon /// 武器的后坐力 /// /// ///When the weapon is fired, how much recoil is applied to the user, in units: the number of cells, and the X direction of the force is automatically inferred. ///武器开火,要对使用者施加多大的后坐力,单位:格数,力的X方向是自动推断的。 /// private Vector2 _recoil; /// /// This area represents the collision range of the weapon, and when other nodes enter this area, they will deal damage. /// 这个区域表示武器的碰撞范围,当其他节点进入此区域时,会造成伤害。 /// private Area2D? _damageArea2D; /// /// The number of tile maps in contact with this weapon /// 与此武器接触的瓦片地图数量 /// private int _tileMapNumber; public override void _Ready() { _damageArea2D = GetNode("DamageArea2D"); _damageArea2D.BodyEntered += OnBodyEnter; _damageArea2D.BodyExited += OnBodyExited; Id = GetMeta("ID", "1").AsString(); Quantity = GetMeta("Quantity", "1").AsInt32(); MaxStackQuantity = GetMeta("MaxStackQuantity", Config.MaxStackQuantity).AsInt32(); Icon = GetMeta("Icon", "").As(); Name = GetMeta("Name", "").AsString(); Description = GetMeta("Description", "").AsString(); _firingInterval = TimeSpan.FromMilliseconds(GetMeta("FiringInterval", "100").AsInt64()); _minContactInjury = GetMeta("MinContactInjury", "1").AsInt32(); _maxContactInjury = GetMeta("MaxContactInjury", "2").AsInt32(); _recoil = GetMeta("Recoil", Vector2.Zero).AsVector2(); } private void OnBodyExited(Node node) { if (Picked) { return; } //If it leaves the ground or walls. //如果离开了地面或墙壁。 if (node is TileMap tileMap) { _tileMapNumber--; if (_tileMapNumber == 0) { //No longer in contact with any shingles can cause injury //不再与任何瓦片接触后,可以造成伤害 EnableContactInjury = true; SetCollisionMaskValue(Config.LayerNumber.Player, false); } } } /// /// Use weapons against the enemy /// 使用武器砸敌人 /// /// private void OnBodyEnter(Node node) { if (Picked) { return; } if (node is TileMap tileMap) { _tileMapNumber++; EnableContactInjury = false; //Items can be pushed by the player when they are on the ground //当物品在地面上时,可被玩家推动 SetCollisionMaskValue(Config.LayerNumber.Player, true); } else if (node is CharacterTemplate characterTemplate) { if (!EnableContactInjury) { return; } if (Owner is not CharacterTemplate ownerCharacterTemplate) { return; } //Determine if your side can cause damage //判断所属的阵营是否可以造成伤害 var canCauseHarm = CampManager.CanCauseHarm(CampManager.GetCamp(ownerCharacterTemplate.CampId), CampManager.GetCamp(characterTemplate.CampId)); if (!canCauseHarm) { return; } //If allowed to cause harm //如果允许造成伤害 var damage = new Damage { MaxDamage = Math.Abs(_maxContactInjury), MinDamage = Math.Abs(_minContactInjury), Attacker = ownerCharacterTemplate }; damage.CreateDamage(); damage.MoveLeft = LinearVelocity.X < 0; damage.Type = Config.DamageType.Physical; characterTemplate.Damage(damage); //Reduce speed after hitting enemies. //击中敌人后减少速度。 LinearVelocity *= 1 - Config.ThrownItemsHitEnemiesReduceSpeedByPercentage; } } /// /// 翻转武器 /// /// public void Flip(bool facingLeft) { } /// /// Discharge of the weapon /// 武器开火 /// /// /// ///owner ///武器所有者 /// /// ///enemyGlobalPosition ///敌人所在位置 /// /// 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) { 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) { //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; } /// /// Execute fire /// 执行开火 /// protected virtual void DoFire(Node2D? owner, Vector2 enemyGlobalPosition) { } }