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.
404 lines
13 KiB
404 lines
13 KiB
using Spine; |
|
using Spine.Unity; |
|
using Spine.Unity.AttachmentTools; |
|
using System.Collections; |
|
using System.Collections.Generic; |
|
using UnityEngine; |
|
using UnityEngine.Events; |
|
using UnityEngine.Serialization; |
|
|
|
public enum EquipType { None, Armor, Weapon, Accessory } |
|
|
|
[System.Serializable] |
|
public class EquipData |
|
{ |
|
public EquipType type; |
|
public string type2; |
|
public Sprite sprite; |
|
[Space(10)] |
|
public ItemData item; |
|
|
|
public Attachment attachment; |
|
public Texture texture; |
|
public Material matOrigin; |
|
public Material matHit; |
|
public Material matResist; |
|
} |
|
|
|
[System.Serializable] |
|
public class EquipHook |
|
{ |
|
public EquipType type; |
|
public string type2; |
|
[Space(10)] |
|
[SpineSlot] |
|
public string slot; |
|
[SpineAttachment(skinField: "templateSkin")] |
|
public string templateAttachment; |
|
} |
|
|
|
public class Equipment : ResourcePool |
|
{ |
|
void Start() |
|
{ |
|
Skin(skinName); |
|
InstallApply(); |
|
|
|
Install(ItemData.Copy(DataManager.Instance.dataItem.Search($"spear1"))); |
|
//Install(ItemData.Copy(DataManager.Instance.dataItem.Search($"gold_01"))); |
|
} |
|
|
|
public Character character; |
|
[Space(10)] |
|
public SkeletonAnimation skeletonAnimation; |
|
[Space(10)] |
|
public SkeletonDataAsset skeletonDataAsset; |
|
public Material sourceMaterial; |
|
public bool applyPMA = true; |
|
/// <summary> |
|
/// 캐릭터의 아틀라스(스킨 및 장비아이템)를 갱신합니다. |
|
/// </summary> |
|
void RefreshSkeletonAttachments() |
|
{ |
|
skeletonAnimation.Skeleton.SetSlotsToSetupPose(); |
|
skeletonAnimation.AnimationState.Apply(skeletonAnimation.Skeleton); //skeletonAnimation.Update(0); |
|
} |
|
Dictionary<string, Attachment> attachments = new Dictionary<string, Attachment>(); |
|
/// <summary> |
|
/// 장비의 이미지를 적용합니다. |
|
/// </summary> |
|
/// <param name="key">풀링 키</param> |
|
/// <param name="sprite">장비의 이미지</param> |
|
/// <param name="slotIndex">슬롯 번호</param> |
|
/// <param name="templateSkinName">현재 스킨 이름</param> |
|
/// <param name="templateAttachmentName">바꿔야할 어태치먼트의 이름</param> |
|
/// <returns></returns> |
|
Attachment AtlasAttachment(string key, Sprite sprite, int slotIndex, string templateSkinName, string templateAttachmentName) |
|
{ |
|
Attachment attachment = null; |
|
|
|
if (attachments.ContainsKey(key)) |
|
{ |
|
attachment = attachments[key]; |
|
} |
|
else |
|
{ |
|
var templateSkin = skeletonDataAsset.GetSkeletonData(true).FindSkin(templateSkinName); |
|
attachment = templateSkin.GetAttachment(slotIndex, templateAttachmentName).GetRemappedClone(sprite, sourceMaterial, premultiplyAlpha: this.applyPMA); |
|
|
|
attachments.Add(key, attachment); |
|
} |
|
|
|
return attachment; |
|
} |
|
|
|
[Space(10)] |
|
[SpineSkin] |
|
public string skinName;//현재 선택된 스킨(아머) |
|
Skin equipsSkin;//현재 장착하고 있는 스킨(아머) |
|
Dictionary<string, Skin> skins = new Dictionary<string, Skin>(); |
|
/// <summary> |
|
/// 캐릭터의 스킨을 변경 합니다. |
|
/// </summary> |
|
/// <param name="name"></param> |
|
public void Skin(string name) |
|
{ |
|
skinName = name; |
|
|
|
if (skins.ContainsKey($"{skinName}")) |
|
{ |
|
equipsSkin = skins[$"{skinName}"]; |
|
} |
|
else |
|
{ |
|
equipsSkin = new Skin($"{skinName}"); |
|
|
|
var templateSkin = skeletonAnimation.Skeleton.Data.FindSkin(skinName); |
|
if (templateSkin != null) |
|
equipsSkin.AddAttachments(templateSkin); |
|
|
|
skins.Add($"{skinName}", equipsSkin); |
|
} |
|
|
|
skeletonAnimation.Skeleton.Skin = equipsSkin; |
|
RefreshSkeletonAttachments(); |
|
} |
|
|
|
[Space(10)] |
|
public List<EquipHook> equips;//스파인 내의 장비 목록 |
|
/// <summary> |
|
/// 장착 아이템을 장착합니다. |
|
/// </summary> |
|
/// <param name="item"></param> |
|
/// <returns></returns> |
|
public bool Install(ItemData item, bool EQUIP = true) |
|
{ |
|
EquipData data = new EquipData(); |
|
|
|
if (item.type.CompareTo($"{EquipType.Armor}") == 0) |
|
{ |
|
character.ec.Remove(OnChanged_ArmorHeart); |
|
|
|
data.type = Util.EnumUtil<EquipType>.Parse($"{item.type}"); |
|
data.item = item; |
|
|
|
Skin(item.idx); |
|
|
|
//character.ec.Add(OnChanged_ArmorHeart); |
|
} |
|
else if (item.type.CompareTo($"{EquipType.Weapon}") == 0 || item.type.CompareTo($"{EquipType.Accessory}") == 0) |
|
{ |
|
data.sprite = SpriteManager.Instance.SpriteGet($"{item.idx}"); |
|
|
|
data.type = Util.EnumUtil<EquipType>.Parse($"{item.type}"); |
|
data.item = item; |
|
} |
|
else |
|
return false; |
|
|
|
bool INSTALL = InstallEquip(data); |
|
if (INSTALL && EQUIP) |
|
{ |
|
INSTALL = InstallApply(); |
|
|
|
EquipHook hook = equips.Find(a => a.type == data.type && data.item.idx.Contains(a.type2)); |
|
if (hook != null) |
|
data.type2 = hook.type2; |
|
|
|
if (data.type == EquipType.Weapon) |
|
onWeaponChanged.Invoke(data);//바뀐 무기의 연동이 필요 |
|
else if (data.type == EquipType.Armor) |
|
character.ec.Add(OnChanged_ArmorHeart); |
|
} |
|
|
|
return INSTALL; |
|
} |
|
Dictionary<EquipType, EquipData> installs = new Dictionary<EquipType, EquipData>(); |
|
public System.Action<Transform, ItemData> OnUnInstall; |
|
/// <summary> |
|
/// 해당 아이템 의 부위를 확인 |
|
/// 이미 장착되어 있는 부위 라면 장착하고 잇던 아이템을 드랍 처리합니다. |
|
/// </summary> |
|
/// <param name="data"></param> |
|
/// <returns></returns> |
|
public bool InstallEquip(EquipData data) |
|
{ |
|
if (installs.ContainsKey(data.type)) |
|
{ |
|
EquipData before = installs[data.type]; |
|
|
|
if (data.type == EquipType.Armor || before.item.idx != data.item.idx) |
|
{ |
|
installs[data.type] = data; |
|
//이전 장착 아이템 드랍 처리 |
|
//character.map.blkCurrent.OnDropItem_Create(transform, before.item); |
|
//장비가 보유중인 스킬 해제 |
|
character.skill.UnInstall(before.item); |
|
} |
|
else |
|
return false; |
|
} |
|
else |
|
installs.Add(data.type, data);//빈 슬롯에 장착 |
|
|
|
//장비가 보유중인 스킬 적용 |
|
character.skill.Install(data.item); |
|
|
|
return true; |
|
} |
|
/// <summary> |
|
/// 착용한 장비 중 같은 아이템이 있는지 확인합니다. |
|
/// </summary> |
|
/// <param name="data">확인할 아이템</param> |
|
/// <returns></returns> |
|
public bool InstallCheck_Item(ItemData data) |
|
{ |
|
EquipType type = Util.EnumUtil<EquipType>.Parse($"{data.type}"); |
|
if (installs.ContainsKey(type)) |
|
{ |
|
EquipData before = installs[type]; |
|
|
|
if (type == EquipType.Armor || before.item.idx != data.idx) |
|
return true; |
|
else |
|
return false; |
|
} |
|
|
|
return true; |
|
} |
|
/// <summary> |
|
/// 해당 부위에 착용중인 아이템이 있는지 확인 |
|
/// </summary> |
|
/// <param name="type">확인할 부위</param> |
|
/// <returns></returns> |
|
public bool InstallCheck_Part(EquipType type) |
|
{ |
|
return installs.ContainsKey(type); |
|
} |
|
[Space(10)] |
|
public Sprite spriteAlpha; |
|
/// <summary> |
|
/// 장착 부위를 적용합니다. |
|
/// </summary> |
|
bool InstallApply() |
|
{ |
|
for (int i = 0; i < equips.Count; i++) |
|
{ |
|
var skeletonData = skeletonDataAsset.GetSkeletonData(true); |
|
var slotIndex = skeletonData.FindSlotIndex(equips[i].slot); |
|
//var attachment = AtlasAttachment($"{slotIndex}{spriteAlpha}", spriteAlpha, slotIndex, skinName, equips[i].templateAttachment); |
|
|
|
//Equip(slotIndex, equips[i].templateAttachment, attachment); |
|
equipsSkin.RemoveAttachment(slotIndex, equips[i].templateAttachment); |
|
} |
|
|
|
EquipData data = null; |
|
var list = new List<EquipData>(installs.Values); |
|
for (int h = 0; h < list.Count; h++) |
|
{ |
|
data = list[h]; |
|
if (data.type == EquipType.Armor) |
|
continue; |
|
|
|
List<EquipHook> hooks = equips.FindAll(a => a.type == data.type && data.item.idx.Contains(a.type2)); |
|
//if (hooks.Count == 0) |
|
// return false; |
|
|
|
EquipHook equip = null; |
|
for (int i = 0; i < hooks.Count; i++) |
|
{ |
|
equip = hooks[i]; |
|
|
|
var skeletonData = skeletonDataAsset.GetSkeletonData(true); |
|
var slotIndex = skeletonData.FindSlotIndex(equip.slot); |
|
var attachment = AtlasAttachment($"{slotIndex}{equip.slot}{data.sprite}", data.sprite, slotIndex, skinName, equip.templateAttachment); |
|
|
|
if (attachment != null) |
|
{ |
|
data.attachment = attachment; |
|
data.matOrigin = (Material)data.attachment.GetRegion().page.rendererObject; |
|
data.texture = data.matOrigin.mainTexture; |
|
|
|
data.matHit = new Material(matHit); |
|
data.matHit.mainTexture = data.texture; |
|
|
|
data.matResist = new Material(matResist); |
|
data.matResist.mainTexture = data.texture; |
|
} |
|
|
|
Equip(slotIndex, equip.templateAttachment, attachment); |
|
} |
|
} |
|
|
|
return true; |
|
} |
|
/// <summary> |
|
/// 장비의 이미지를 적용합니다. |
|
/// </summary> |
|
/// <param name="slotIndex"></param> |
|
/// <param name="attachmentName"></param> |
|
/// <param name="attachment"></param> |
|
void Equip(int slotIndex, string attachmentName, Attachment attachment) |
|
{ |
|
equipsSkin.SetAttachment(slotIndex, attachmentName, attachment); |
|
|
|
skeletonAnimation.Skeleton.SetSkin(equipsSkin); |
|
RefreshSkeletonAttachments(); |
|
} |
|
|
|
[System.Serializable] |
|
public class WeaponChangEvent : UnityEvent<EquipData> { } |
|
[FormerlySerializedAs("onWeaponChanged")] |
|
[SerializeField] |
|
[Space(10)] |
|
private WeaponChangEvent onWeaponChanged = new WeaponChangEvent(); |
|
|
|
[Space(10)] |
|
public TileCameraEvent tiltEvent; |
|
public GameObject particleArmorDestroy; |
|
public Transform targetArmorDestroy; |
|
/// <summary> |
|
/// 캐릭터의 AH 가 변경되어 이를 적용합니다. |
|
/// </summary> |
|
/// <param name="type"></param> |
|
/// <param name="value"></param> |
|
public void OnChanged_ArmorHeart(int type, object value) |
|
{ |
|
if (installs.ContainsKey(EquipType.Armor)) |
|
{ |
|
ItemData item = installs[EquipType.Armor].item; |
|
SkillData skill = item.skills.Find(a => a.work.Equals("AH")); |
|
skill.value = character.AH; |
|
|
|
//AH 가 0 이 되면 착용중인 갑옷을 파괴 |
|
if (skill.value < 1) |
|
{ |
|
//장비가 보유중인 스킬 해제 |
|
for (int i = 0; i < item.skills.Count; i++) |
|
character.skill.skills.Remove(item.skills[i]); |
|
character.skill.items.Remove(item); |
|
|
|
Skin("base_01"); |
|
installs.Remove(EquipType.Armor); |
|
InstallApply(); |
|
|
|
tiltEvent.Shake(); |
|
ObjectCreateLocalPos(particleArmorDestroy, targetArmorDestroy, Vector3.one, Vector3.zero); |
|
} |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// 캐릭터의 히트 등의 효과로 스파인에 Material 이 변경 될 경우, 장비의 이미지는 따로 적용해야함(어태치먼트 적용시 장비템 마다 아틀라스가 새로생성됨) |
|
/// </summary> |
|
[Space(5)] |
|
public Material matHit; |
|
public void Hit_Start(float duration) |
|
{ |
|
if (0 == installs.Count || duration == 0) |
|
return; |
|
|
|
CancelInvoke("Hit_End"); |
|
|
|
foreach (KeyValuePair<EquipType, EquipData> value in installs) |
|
{ |
|
if (value.Value.matHit != null) |
|
value.Value.attachment.GetRegion().page.rendererObject = value.Value.matHit; |
|
} |
|
|
|
Invoke("Hit_End", duration); |
|
} |
|
void Hit_End() |
|
{ |
|
foreach (KeyValuePair<EquipType, EquipData> value in installs) |
|
{ |
|
if (value.Value.matHit != null) |
|
value.Value.attachment.GetRegion().page.rendererObject = value.Value.matOrigin; |
|
} |
|
} |
|
|
|
public Material matResist; |
|
public void Resist_Start(float duration) |
|
{ |
|
if (0 == installs.Count || duration == 0) |
|
return; |
|
|
|
CancelInvoke("Hit_End"); |
|
|
|
foreach (KeyValuePair<EquipType, EquipData> value in installs) |
|
{ |
|
if (value.Value.matResist != null) |
|
value.Value.attachment.GetRegion().page.rendererObject = value.Value.matResist; |
|
} |
|
|
|
Invoke("Hit_End", duration); |
|
} |
|
void Resist_End() |
|
{ |
|
foreach (KeyValuePair<EquipType, EquipData> value in installs) |
|
{ |
|
if (value.Value.matResist != null) |
|
value.Value.attachment.GetRegion().page.rendererObject = value.Value.matOrigin; |
|
} |
|
} |
|
}
|
|
|