2 분 소요

Intro

이번 포스팅에서는 캐릭터 정보창을 구현하기전에, 먼저 포션아이템을 손봤습니다.

현재는 포션을 사용했을 때 별다른 동작없이 포션의 갯수만 차감되도록 되어있습니다.

이제 포션을 사용하면 체력과 마나를 회복할수있도록 기능을 추가해보았습니다.

포션을 사용하는것의 순서는 아래와같습니다.

  1. 인벤토리에서 사용자가 포션아이템슬롯을 우클릭

  2. Inventory 클래스에 포션 사용 요청

  3. Inventory 클래스의 Use() 함수에서 사용가능한 아이템인지여부 판별후 PortionItem 클래스의 Use 함수 호출

  4. PortionItem 클래스에서 PlayerData에 접근하고, 포션데이터를 매개변수로 PlayerData의 UsePortion() 호출

  5. PlayerData 클래스에서 UsePortion() 실행

image

PortionData.json

PortionData.json 파일에 포션타입을 추가했습니다.

{
    "Portion": [
      {
        "id": 2001,
        "itemName": "엘릭서",
        "itemToolTip": "Hp를 일정량 회복시켜준다.",
        "itemIcon": "Item_PortionItem_Elixir.png",
        "maxAmount": 99,
        "PortionType": "Health",
        "value": 30.0
      },
      {
        "id": 2002,
        "itemName": "마나 엘릭서",
        "itemToolTip": "Mp를 일정량 회복시켜준다.",
        "itemIcon": "Item_PortionItem_ManaElixir.png",
        "maxAmount": 99,
        "PortionType": "Mana",
        "value": 30.0
      }
    ]
  }

타입은 String으로, “Health” “Mana” 두가지 종류의 포션이 있습니다.

PortionItemDTO.cs

PortionItemDTO 클래스에 포션타입 필드를 추가했습니다.

[System.Serializable]
public class PortionItemDTO 
{
    public int id;                      // 아이템 id
    public string itemName;             // 아이템 이름
    public string itemToolTip;          // 아이템 툴팁
    public string itemIcon;             // 아이템 아이콘 이름
    public int maxAmount;               // 최대 소지량
    public string portionType;          // 포션 종류
    public float value;                 // 회복량
}

이제 DataManager 에서 포션데이터를 가져올 때 포션타입도 가져오게되었습니다.

PortionItemData.cs

PortionItemData 클래스에 포션타입 필드를 추가했습니다.

public class PortionItemData : CountableItemData
{
    [SerializeField] private float value;              // 회복량
    [SerializeField] private string portionType;       // 포션 종류
    public float Value => value;
    public string PortionType => portionType;

    public PortionItemData(PortionItemDTO dto)
    {
        this.id = dto.id;
        this.itemName = dto.itemName;
        this.itemToolTip = dto.itemToolTip;
        this.itemIcon = dto.itemIcon;
        this.maxAmount = dto.maxAmount;
        this.value = dto.value;
        this.portionType = dto.portionType;
    }

    public override Item CreateItem()
    {
        return new PortionItem(this);
    }
}

DTO 클래스의 portionType으로 초기화하고, 프로퍼티를 추가하여 포션타입을 읽을수 있도록 했습니다.

PortionItem.cs

PortionItem 클래스에서 PortionItemData를 가지고 초기화하고,

IUsableItem 인터페이스를 구현하는 부분에서, PlayerData 클래스의 UsePortion 함수를 호출하도록 했습니다.

public class PortionItem : CountableItem, IUsableItem
{
    public PortionItemData PortionData { get; private set; }
    public PortionItem(PortionItemData data, int amount = 1) : base(data, amount) 
    {
        PortionData = data;
    }

    // 아이템 사용
    public bool Use()
    {
        Amount--;

        DataManager.Instance.GetPlayerData().UsePortion(PortionData.Value, PortionData.PortionType);

        return true;
    }
}

PlayerData.cs

PlayerData 클래스에서 포션 사용에따른 플레이어의 체력과 마나를 회복하도록하는 함수를 만들었습니다.

// PlayerData.cs
    // 포션 회복
    public void UsePortion(float value, string type)
    {
        switch(type)
        {
            case "Health":
                curHp += value;
                break;
            case "Mana":
                curMp += value;
                break;
        }
    }

Inventory.cs

Inventory 클래스의 UpdateSlot, Use 함수를 수정했습니다.

이후 포션아이템뿐만아니라 장비아이템 착용도 Use 함수에서 처리되도록 조건을 나누었습니다.

    // 해당 인덱스 슬롯 갱신
    private void UpdateSlot(int index)
    {
        // 유효한 슬롯만
        if (!IsValidIndex(index)) return;

        // 해당 아이템
        Item item = items[index];

        // 슬롯에 아이템 존재
        if(item != null)
        {
            // 1. 수량이 있는 아이템인 경우
            if(item is CountableItem ci)
            {
                // 수량이 없을 때 아이템 제거
                if(ci.IsEmpty)
                {
                    items[index] = null;
                    RemoveIcon();
                    return;
                }
                // 아이콘 및 수량 표시
                else
                {
                    inventoryUI.SetItemIconAndAmountText(index, item.Data.ItemIcon, ci.Amount);
                }
            }
            // 2. 장비 아이템(임시)
            else if(item is EquipmentItem ei)
            {
                // 아이콘 표시
                inventoryUI.SetItemIconAndAmountText(index, item.Data.ItemIcon);
            }
            // 3. 그 외
            else
            {
                // 아이콘 표시
                inventoryUI.SetItemIconAndAmountText(index, item.Data.ItemIcon);
            }
        }
        // 슬롯에 아이템이 없을 때
        else
        {
            RemoveIcon();
        }

        // 아이콘 제거 함수
        void RemoveIcon()
        {
            inventoryUI.RemoveItem(index);
            inventoryUI.HideItemAmountText(index);
        }
    }

    // 해당 슬롯 인덱스의 아이템 사용
    public void Use(int index)
    {
        if (!IsValidIndex(index)) return;
        if (items[index] == null) return;

        // 1. 소모 아이템일 때
        if(items[index] is IUsableItem usable)
        {
            // 사용
            bool success = usable.Use();

            // 성공
            if(success)
            {
                UpdateSlot(index);
            }
        }
        // 2. 장비 아이템일 때
        else if(items[index] is IEquipableItem equipable)
        {
            // 착용구현..
        }
    }

댓글남기기