You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

148 lines
4.6 KiB

using System;
using System.Collections.Generic;
using System.Numerics;
using UnityEngine;
namespace Skill_V2
{
public class Skill : Entity
{
[SerializeField] CircleCollider2D castDistanceIndicator;
StatData castDistance;
StatData coolTime;
int currentSequenceIndex = -1;
float elapsedCoolTime;
Bitset32.Mask targetTags;
BIValue damageCalculator = new BIValue();
ContactFilter2D layerFilter;
List<Collider2D> castSkillDistOverlaped = new();
public Entity Caster { get; private set; }
public Bitset32.Mask TargetTags => targetTags;
public SkillData Data { get; private set; }
public float CastDistance => castDistance != null ? castDistance.Value : 0f;
public SkillSequence CurrentSequence => currentSequenceIndex >= 0 ? Data.Sequences[currentSequenceIndex] : null;
public bool IsInCoolTime => coolTime != null ? elapsedCoolTime < (float)coolTime.Value : false;
public float CoolTimeRemainTime => coolTime != null ? Mathf.Clamp((float)coolTime.Value - elapsedCoolTime, 0, (float)coolTime.Value) : 0f;
public float ElapsedCoolTimeRate => coolTime != null ? Mathf.Clamp01(elapsedCoolTime / (float)coolTime.Value) : 1f;
private void Awake()
{
AddTags(EntityTag.Skill);
}
private void Update()
{
var currentState = CurrentSequence;
if (currentState != null)
{
if (currentState.IsDone)
{
currentSequenceIndex++;
if (currentSequenceIndex < Data.Sequences.Count)
{
currentState.Exit();
CurrentSequence.Enter();
}
else
{
currentSequenceIndex = -1;
}
}
else
{
currentState.Excute();
}
}
}
public void SetSkillData(SkillData skillData)
{
Debug.Assert(skillData != null, Logger.LogMessage(LogType.Assert, nameof(SetSkillData), "SkillData is null"));
Data = skillData;
for (int i = 0; i < skillData.Sequences.Count; i++)
{
skillData.Sequences[i].Initialize(this);
}
Data.TryGetStat(StatID.CastDistance, out castDistance);
Data.TryGetStat(StatID.CoolTime, out coolTime);
}
public void UpdateSkillCoolTime()
{
if (!IsInCoolTime) return;
elapsedCoolTime += Time.fixedUnscaledDeltaTime;
elapsedCoolTime = Mathf.Min(elapsedCoolTime, coolTime.Value);
}
public void SetTargetTags(LayerMask mask, params EntityTag[] tags)
{
layerFilter.SetLayerMask(mask);
targetTags = Bitset32.GetMask(Array.ConvertAll(tags, (t) => (Enum)t));
}
public void Cast(Entity caster, BigInteger atk)
{
Caster = caster;
damageCalculator.ClearModifiers();
damageCalculator.DefaultValue = atk;
if (Data.TryGetStat(StatID.SkillDamage, out var stat))
{
damageCalculator.AddModifiers(new ValueModifier(ValueModifier.Type.Percent, stat.Value));
}
Stop();
if(Data.Sequences.Count > 0)
{
currentSequenceIndex = 0;
transform.position = caster.CenterPivot;
ChangeLookDirection(caster.LookDirection);
CurrentSequence.Enter();
}
}
public BigInteger GetSkillDamage() => damageCalculator.ModifiedValue;
public void StartCoolTime()
{
elapsedCoolTime = 0f;
}
public void Stop()
{
CurrentSequence?.Stop();
currentSequenceIndex = -1;
}
public bool IsTargetExistInCastRange()
{
if (castDistanceIndicator is null) return false;
castDistanceIndicator.radius = CastDistance;
castSkillDistOverlaped.Clear();
castDistanceIndicator.OverlapCollider(layerFilter, castSkillDistOverlaped);
for (int i = 0; i < castSkillDistOverlaped.Count; i++)
{
var overlapped = castSkillDistOverlaped[i];
if(overlapped.TryGetComponent(out IBattleEntity entity) && (entity as Entity).HasTagsAny(TargetTags) && entity.IsBattleAvail())
{
return true;
}
}
return false;
}
}
}