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.
 
 
 
 

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