92 lines
3.1 KiB
C#
92 lines
3.1 KiB
C#
using System;
|
|
using SepCore.Definition;
|
|
using SepCore.Entity;
|
|
using UnityEngine;
|
|
|
|
namespace SepCore.Components
|
|
{
|
|
public class AbsorbComponent : MonoBehaviour
|
|
{
|
|
[SerializeField] private int _maxDetectCount = 64;
|
|
|
|
private Player _player;
|
|
private Transform _target;
|
|
private StatComponent _statComponent;
|
|
private Collider[] _buffer;
|
|
|
|
private StatProperty _absorbRangeStat;
|
|
private Action<modifier, bool> _absorbRangeStatCallback;
|
|
|
|
private float AbsorbRangeBase => GameEntry.Luban.Global.DefaultAbsorbRange / 1000f;
|
|
private float AbsorbSpeed => GameEntry.Luban.Global.AbsorbSpeed / 1000f;
|
|
private float CollectDistance => GameEntry.Luban.Global.CollectDistance / 1000f;
|
|
|
|
private float AbsorbRange => Mathf.Max(0f, (AbsorbRangeBase + _absorbRangeStat.Value) * _absorbRangeStat.Percent);
|
|
|
|
public void OnInit(Player player, StatComponent statComponent)
|
|
{
|
|
_player = player;
|
|
_target = player.CachedTransform;
|
|
_statComponent = statComponent;
|
|
_buffer = new Collider[Mathf.Max(1, _maxDetectCount)];
|
|
|
|
_absorbRangeStat = _statComponent.GetStat(StatType.AbsorbRange);
|
|
_absorbRangeStatCallback = (modifier, isApply) =>
|
|
_statComponent.UpdateStat(_absorbRangeStat, modifier, isApply);
|
|
_statComponent.Subscribe(StatType.AbsorbRange, _absorbRangeStatCallback);
|
|
}
|
|
|
|
public void OnUpdate(float elapseSeconds, float realElapseSeconds)
|
|
{
|
|
if (!_player.Available) return;
|
|
|
|
int hitCount = Physics.OverlapSphereNonAlloc(
|
|
_target.position,
|
|
AbsorbRange,
|
|
_buffer,
|
|
Constant.Layer.DropLayerMask
|
|
);
|
|
|
|
for (int i = 0; i < hitCount; i++)
|
|
{
|
|
Collider hit = _buffer[i];
|
|
if (hit == null) continue;
|
|
|
|
CoinEntity coin = hit.GetComponent<CoinEntity>();
|
|
if (coin != null && coin.Available)
|
|
{
|
|
AbsorbDrop(coin.CachedTransform, elapseSeconds);
|
|
coin.TryCollect(_player, CollectDistance);
|
|
continue;
|
|
}
|
|
|
|
ExpEntity exp = hit.GetComponent<ExpEntity>();
|
|
if (exp != null && exp.Available)
|
|
{
|
|
AbsorbDrop(exp.CachedTransform, elapseSeconds);
|
|
exp.TryCollect(_player, CollectDistance);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void OnReset()
|
|
{
|
|
if (_statComponent != null)
|
|
{
|
|
_statComponent.Unsubscribe(StatType.AbsorbRange, _absorbRangeStatCallback);
|
|
_absorbRangeStatCallback = null;
|
|
}
|
|
|
|
_statComponent = null;
|
|
_target = null;
|
|
_player = null;
|
|
_buffer = null;
|
|
}
|
|
|
|
private void AbsorbDrop(Transform drop, float deltaTime)
|
|
{
|
|
drop.position = Vector3.MoveTowards(drop.position, _target.position, AbsorbSpeed * deltaTime);
|
|
}
|
|
}
|
|
}
|