|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|