2023-08-27 02:58:19 +08:00
|
|
|
using System;
|
|
|
|
using System.Collections;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Linq;
|
2023-11-15 23:54:54 +08:00
|
|
|
using BITFALL.Combat;
|
2023-08-27 02:58:19 +08:00
|
|
|
using BITKit;
|
|
|
|
using BITKit.Entities;
|
|
|
|
using BITKit.Entities.Melee;
|
|
|
|
using Cysharp.Threading.Tasks;
|
|
|
|
using Cysharp.Threading.Tasks.Triggers;
|
|
|
|
using Unity.Collections;
|
|
|
|
using UnityEngine;
|
|
|
|
using UnityEngine.VFX;
|
|
|
|
|
|
|
|
namespace BITFALL.Melee
|
|
|
|
{
|
|
|
|
[Serializable]
|
|
|
|
public class MeleeServiceSingleton : IMeleeService
|
|
|
|
{
|
|
|
|
public void Melee(MeleeCommand command) => MeleeService.Melee(command);
|
|
|
|
}
|
2023-11-15 23:54:54 +08:00
|
|
|
|
2023-08-27 02:58:19 +08:00
|
|
|
public class MeleeService : MonoBehaviour,IMeleeService
|
|
|
|
{
|
|
|
|
internal static MeleeService Singleton;
|
|
|
|
[RuntimeInitializeOnLoadMethod]
|
|
|
|
private static void Initialize()
|
|
|
|
{
|
|
|
|
Queue.Clear();
|
|
|
|
}
|
|
|
|
private static readonly Queue<MeleeCommand> Queue = new();
|
|
|
|
public static void Melee(MeleeCommand command)=>Queue.Enqueue(command);
|
|
|
|
[SerializeField] private LayerMask detectLayer;
|
2023-10-24 23:37:59 +08:00
|
|
|
[SerializeReference, SubclassSelector] private IDamageService damageService;
|
2023-08-27 02:58:19 +08:00
|
|
|
private void Awake()
|
|
|
|
{
|
|
|
|
Singleton = this;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void FixedUpdate()
|
|
|
|
{
|
|
|
|
if (Queue.TryDequeue(out var command) is false) return;
|
|
|
|
|
|
|
|
var colliders = Physics.OverlapSphere(command.Position, command.Range,detectLayer);
|
2023-11-15 23:54:54 +08:00
|
|
|
var _damaged = new Dictionary<ulong, IUnityEntity>();
|
|
|
|
var hits = colliders
|
|
|
|
.Where(x => x.GetComponent<IDamagable>() is not null)
|
|
|
|
.Where(x => MathV.IsForward(command.Position, command.Forward, x.transform.position))
|
|
|
|
.Select(x => x.GetComponent<IDamagable>())
|
|
|
|
.Where(damageable =>damageable.UnityEntity?.Id != command.PlayerId)
|
|
|
|
.Where(damageable =>
|
|
|
|
{
|
|
|
|
if (command.IgnoreTags is null
|
|
|
|
|| !(command.IgnoreTags?.Length > 0)
|
|
|
|
|| damageable.UnityEntity is null
|
|
|
|
|| !damageable.UnityEntity.TryGetComponent<ITag>(out var iTags)) return true;
|
|
|
|
return !MathE.Contains(iTags.GetTags(), command.IgnoreTags);
|
|
|
|
})
|
|
|
|
.Where(x => x.UnityEntity is null || _damaged.TryAdd(x.UnityEntity.Id, x.UnityEntity))
|
|
|
|
;
|
|
|
|
if (command.Limit is not 0)
|
|
|
|
{
|
|
|
|
hits = hits.Take(command.Limit);
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach (var x in hits)
|
2023-08-27 02:58:19 +08:00
|
|
|
{
|
2023-10-20 19:31:12 +08:00
|
|
|
try
|
2023-08-27 02:58:19 +08:00
|
|
|
{
|
2023-11-15 23:54:54 +08:00
|
|
|
var damageable = x;
|
2023-10-30 01:25:53 +08:00
|
|
|
|
2023-11-15 23:54:54 +08:00
|
|
|
if (command.ForceHitStun)
|
2023-08-27 02:58:19 +08:00
|
|
|
{
|
2023-11-15 23:54:54 +08:00
|
|
|
if (damageable is not null && damageable.UnityEntity is not null && damageable.UnityEntity.TryGetComponent<IMeleeCombat>(out var combat))
|
|
|
|
{
|
|
|
|
combat.HitStun();
|
|
|
|
}
|
2023-10-20 19:31:12 +08:00
|
|
|
}
|
2023-11-15 23:54:54 +08:00
|
|
|
|
2023-10-24 23:37:59 +08:00
|
|
|
var damageMsg =
|
|
|
|
new DamageMessage()
|
2023-10-20 19:31:12 +08:00
|
|
|
{
|
2023-10-30 01:25:53 +08:00
|
|
|
Initiator = UnityEntitiesService.Get(command.PlayerId) as IUnityEntity,
|
2023-10-24 23:37:59 +08:00
|
|
|
DamageType = new MeleeDamageMessage
|
2023-10-20 19:31:12 +08:00
|
|
|
{
|
|
|
|
|
|
|
|
},
|
2023-10-30 01:25:53 +08:00
|
|
|
Target = damageable.UnityEntity,
|
2023-10-24 23:37:59 +08:00
|
|
|
Damage = command.Damage is 0 ? 64 : command.Damage,
|
|
|
|
Hit = damageable,
|
|
|
|
};
|
|
|
|
if (command.PlayerId !=default)
|
|
|
|
{
|
2023-10-30 01:25:53 +08:00
|
|
|
damageMsg.Initiator = UnityEntitiesService.Get(command.PlayerId) as IUnityEntity;
|
2023-10-24 23:37:59 +08:00
|
|
|
}
|
|
|
|
damageService.Execute(damageMsg);
|
|
|
|
|
2023-10-20 19:31:12 +08:00
|
|
|
damageable.Rigidbody.AddForceAtPositionAsync(command.Force, command.Position, ForceMode.Impulse)
|
|
|
|
.Forget();
|
|
|
|
|
2023-11-15 23:54:54 +08:00
|
|
|
if ((x as MonoBehaviour)!.TryGetComponent<ITag>(out var _tag))
|
2023-08-27 02:58:19 +08:00
|
|
|
{
|
2023-10-20 19:31:12 +08:00
|
|
|
DI.Get<VFXService>().Spawn(new Location
|
|
|
|
{
|
2023-11-15 23:54:54 +08:00
|
|
|
position = x.Rigidbody.position,
|
2023-10-20 19:31:12 +08:00
|
|
|
//rotation = Quaternion.identity,
|
|
|
|
}, _tag.GetTags());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (UnassignedReferenceException e)
|
|
|
|
{
|
2023-11-15 23:54:54 +08:00
|
|
|
Debug.LogWarning(x);
|
2023-10-20 19:31:12 +08:00
|
|
|
Debug.LogException(e);
|
2023-08-27 02:58:19 +08:00
|
|
|
}
|
2023-10-20 19:31:12 +08:00
|
|
|
|
2023-08-27 02:58:19 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void IMeleeService.Melee(MeleeCommand command) => Melee(command);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|