Files
Net.Like.Xue.Tokyo/Packages-Local/Com.Project.B.Unity/Feel/PlayerHealthFeel.cs
2025-06-24 23:49:13 +08:00

140 lines
3.6 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using BITKit;
using BITKit.Entities;
using BITKit.Tween;
using Cysharp.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Net.Project.B.Damage;
using Net.Project.B.Health;
using Project.B.Entities;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.UI;
namespace Net.Project.B.Feel
{
public class PlayerHealthFeel : MonoBehaviour
{
[SerializeField] private Image bloodyScreen;
[SerializeField] private Volume volume;
[SerializeField] private Volume hitVolume;
private IEntity _entity;
private CancellationTokenSource _hitCts;
private Color _initialColor;
private async void Start()
{
if (hitVolume)
{
hitVolume.weight = 0;
}
if(bloodyScreen)
_initialColor = bloodyScreen.color;
SetValue(0);
await BITApp.WalkUntilInitialize.Task;
var playerFactory = BITApp.ServiceProvider.GetRequiredService<IPlayerFactory>();
var healthService = BITApp.ServiceProvider.GetRequiredService<IHealthService>();
var damageService = BITApp.ServiceProvider.GetRequiredService<IDamageService>();
playerFactory.OnEntityCreated += OnEntityCreated;
healthService.OnHealthChanged += OnHealthChanged;
if (hitVolume)
{
damageService.OnDamaged += OnDamaged;
}
await destroyCancellationToken.WaitUntilCanceled();
healthService.OnHealthChanged -= OnHealthChanged;
playerFactory.OnEntityCreated -= OnEntityCreated;
damageService.OnDamaged -= OnDamaged;
}
private async void OnDamaged(IDamageReport obj)
{
if(_entity is null || obj.Target!=_entity.Id)return;
_hitCts?.Cancel();
_hitCts = new();
try
{
await BITween.Lerp(x => hitVolume.weight = x, 0f, 1, 0.1f, Mathf.Lerp, _hitCts.Token)
.AttachExternalCancellation(destroyCancellationToken);
await BITween.Lerp(x => hitVolume.weight = x, 1f, 0, 0.24f, Mathf.Lerp, _hitCts.Token)
.AttachExternalCancellation(destroyCancellationToken);
}
catch (OperationCanceledException)
{
}
}
private void OnHealthChanged(int arg1, int arg2, int arg3, object arg4)
{
if(_entity is null || arg1!=_entity.Id)return;
var t = Mathf.Clamp01(1 - arg3 * 0.01f);
SetValue(t);
}
private UniTask OnEntityCreated(string arg1, IEntity arg2)
{
_entity = arg2;
if(bloodyScreen)
bloodyScreen.color = Color.clear;
_entity.CancellationToken.Register(DisposeEntity);
return UniTask.CompletedTask;
void DisposeEntity()
{
SetValue(0);
}
}
private void SetValue(float t)
{
if(!volume)return;
if (volume)
{
volume.weight = t;
}
_initialColor.a = t;
if (bloodyScreen)
{
bloodyScreen.color = _initialColor;
}
}
}
}