Super Knight : Enter the Dungeon
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.

357 lines
11 KiB

using DG.Tweening;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Serialization;
public class Skill : MonoBehaviour
{
public Character character;
public Motion motion;
public List<ItemData> items = new List<ItemData>();//장착 아이템이 스킬을 보유하기에 Skill.cs 에서 기록중
/// <summary>
/// 착용중인 아이템중에 같은것이 있는지 확인합니다.
/// </summary>
/// <param name="idx">아이템 번호</param>
/// <returns></returns>
public bool HoldingItemCheck(string idx)
{
return items.Find(a => a.idx.Equals(idx)) != null;
}
public System.Action<List<ItemData>> OnChangedInstall;
/// <summary>
/// 장비가 장착되어 이를 적용합니다.
/// </summary>
/// <param name="item">아이템 번호</param>
public void Install(ItemData item)
{
items.Add(item);//아이템 장착
for (int i = 0; i < item.skills.Count; i++)
SkillAdd(item.skills[i]);
if (OnChangedInstall != null)
OnChangedInstall(items);
}
/// <summary>
/// 장비가 해제되어 이를 적용합니다.
/// </summary>
/// <param name="item">아이템 번호</param>
public void UnInstall(ItemData item)
{
items.Remove(item);//아이템 해제
for (int i = 0; i < item.skills.Count; i++)
SkillDelete(item.skills[i]);
if (OnChangedInstall != null)
OnChangedInstall(items);
}
public List<SkillData> skills = new List<SkillData>();
public void OnInitialized()
{
for (int i = 0; i < skills.Count; i++)
skills[i].cntUse = 0;//스킬 사용 횟수 제한 초기화
}
/// <summary>
/// 스킬을 추가합니다.
/// </summary>
/// <param name="data"></param>
/// <param name="OVERLAP"></param>
void SkillAdd(SkillData data, bool OVERLAP = false)
{
skills.Add(data);
if (data.trigger.Equals("Install"))
Motion_Start(data, null);
}
/// <summary>
/// 스킬을 삭제합니다.
/// </summary>
/// <param name="data"></param>
void SkillDelete(SkillData data)
{
if (skills.Contains(data))
{
skills.Remove(data);
if (data.trigger.Equals("Install"))
{
data.value = -data.value;
Motion_Start(data, null);
data.value = -data.value;
}
}
else
Debug.LogError($"Skill.Add : {data.trigger}-{data.work}-{data.value} 이미 적용 되어 있지 않은 스킬");
}
/// <summary>
/// 해당 조건에 만족하는 스킬이 있는지 확인합니다.
/// Skill.cs 가 아닌 다른 스크립트에서 적용해야 하는 경우 사용합니다.
/// </summary>
/// <param name="trigger">발동 조건</param>
/// <param name="work">하는 일</param>
/// <returns></returns>
public SkillData Active(string trigger, string work)
{
List<SkillData> checks = skills.FindAll(a => a.trigger.Equals(trigger) && a.work.Equals(work));
for (int i = 0; i < checks.Count; i++)
{
if (checks[i].Activate(trigger))
return checks[i];
}
return null;
}
/// <summary>
/// 연출이 필요한 스킬의 발동을 위해 사용
/// </summary>
/// <param name="trigger"></param>
/// <param name="owner"></param>
/// <param name="OnEnd"></param>
/// <returns></returns>
public bool Active(string trigger, object value, System.Action<SkillData> OnEnd)
{
for (int i = 0; i < skills.Count; i++)
{
if (skills[i].Activate(trigger))
{
character.OnLocked(true);
SkillData active = skills[i];
Motion_Start(active, value, OnEnd);
if (skills[i].motion == null)
{
character.OnLocked(false);
if (OnEnd != null)
OnEnd(active);
}
else
{
motion.Play_Force(skills[i].motion, () =>
{
Motion_End(active, value, OnEnd);
}, data =>
{
Motion_Event(active, value, data);
});
}
return true;
}
}
return false;
}
public List<SkillData> SkillList_IDX(string idx)
{
return skills.FindAll(a => a.IDX.Equals(idx));
}
public List<SkillData> SkillList_Trigger(string trigger)
{
return skills.FindAll(a => a.trigger.Equals(trigger));
}
void Motion_Start(SkillData active, object value, System.Action<SkillData> OnEnd = null)
{
switch (active.work)
{
case "Resurrection":
{
if (character.CompareTag("Enemy"))
character.map.blkCurrent.Monster_Resurrection(character);//부활
}
break;
case "RaiseShield":
{
character.OnDefense = delegate (Character attacker)
{
character.OnDefense = null;
character.motion.Play_Force(active.motion2, () =>
{
if (OnEnd != null)
OnEnd(active);
}, null);
};
}
break;
case "HPRestore":
{
character.Restore((int)active.value);
skills.Remove(active);
}
break;
case "HPMax":
{
character.Restore((int)active.value);
}
break;
case "AH":
{
if (-1 < active.value)
character.OnChanged_ArmorHeart((int)active.value);
}
break;
case "AHRestore":
{
character.OnAdded_ArmorHeart((int)active.value);
skills.Remove(active);
}
break;
case "ATK":
{
//character.ATK += (int)active.value;
character.ATKChanged((int)active.value, true);//캐릭터의 공격력 상승
}
break;
case "ATKRate":
{
//character.ATK_PER += active.value;
character.ATKRateChanged(active.value, true);//캐릭터의 공격력 % 상승
}
break;
case "RANGE"://사거리
{
character.RangeChanged(active.value, true);
}
break;
case "SPDMOVE"://이동속도
{
character.SpeedMoveChanged(active.value);
}
break;
case "SPDATK"://공격모션 속도
{
character.SpeedAttackChanged(active.value, true);
}
break;
case "DLAATKRate":
{
character.DelayAttackChanged(active.value, true);
}
break;
case "DLAATK":
{
character.DelayAttackChanged(active.value, false);
}
break;
case "DropItem":
{
for (int i = 0; i < active.value; i++)
character.map.blkCurrent.OnDropItem_Create(value == null ? transform : ((Character)value).transform, active.work2);
}
break;
}
}
void Motion_Event(SkillData active, object value, Spine.Event data)
{
//Debug.LogWarning($"{name} : {active.IDX} {data.Data.Name} 이벤트 발생");
switch (active.work)
{
case "Clone":
{
Character mob = character.map.blkCurrent.Monster_Create(character, transform.position);//복제
mob.OnWarp(transform.position);
mob.OnLocked(true);
mob.transform.DOMove(Util.PointCreate(mob.transform.position, 2f), 0.5f);
mob.motion.Play_Force(active.motion2, () =>
{
mob.OnInitialized(character.HP, character.HP_Max);//몬스터 생성 : 스킬-클론
mob.OnLocked(false);
}, null);
}
break;
case "GuidedProjectile":
{
Transform target = (Transform)value;
List<object> datas = new List<object>();
datas.Add(target);
Vector3 dir = target != null ? (target.position - transform.position).normalized : motion.LookDir().normalized;
datas.Add(dir);
motion.LookSet(dir.x < 0 ? 1 : -1);
datas.Add(active.prefab);
datas.Add(active.value2);
datas.Add(active.value);
active.onConnect.Invoke(0, datas);
}
break;
case "RockProjectile":
{
Transform target = (Transform)value;
List<object> datas = new List<object>();
datas.Add(target);
Vector3 dir = target != null ? (target.position - transform.position) : motion.LookDir();
datas.Add(dir);
motion.LookSet(dir.x < 0 ? 1 : -1);
datas.Add(active.prefab);
datas.Add(active.value2);
datas.Add(active.value);
active.onConnect.Invoke(0, datas);
}
break;
case "GiantySkill1":
{
Debug.LogWarning($"{active.work} : {data.Data.Name}");
}
break;
}
}
void Motion_End(SkillData active, object value, System.Action<SkillData> OnEnd)
{
switch (active.work)
{
//case "Resurrection":
// {
// //character.Restore_MaxRate(active.value);
// //character.OnInitialized();
// if (OnEnd != null)
// OnEnd(active);
// }
// break;
case "RaiseShield":
{
character.OnDefense = null;
if (OnEnd != null)
OnEnd(active);
}
break;
case "RockProjectile":
{
character.motion.Play_Force(active.motion2, () =>
{
if (OnEnd != null)
OnEnd(active);
}, data =>
{
Motion_Event(active, value, data);
});
}
break;
default:
{
if (OnEnd != null)
OnEnd(active);
}
break;
}
}
}