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.
356 lines
11 KiB
356 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; |
|
} |
|
} |
|
}
|
|
|