Inveotry System Update - Equipment Craft System

김민오·2022년 9월 24일
0
post-thumbnail

#pragma once

#include "CoreMinimal.h"

#include "GameFramework/Actor.h"
#include "Engine/DataTable.h"
#include "Inventory/InventoryAction/InventoryActionBase.h"
#include "ItemCraftRecipe.generated.h"

/**
 * 
 */

USTRUCT(BlueprintType)
struct FItemCraftRecipe : public FTableRowBase
{
	GENERATED_BODY()

public:
	FItemCraftRecipe();

	UPROPERTY(Category = RecipeInfo, EditAnywhere, BlueprintReadWrite)
	int32 RecipeID;

	UPROPERTY(Category = RecipeInfo, EditAnywhere, BlueprintReadWrite)
	TMap<FName, int32> needs;

	UPROPERTY(Category = RecipeInfo, EditAnywhere, BlueprintReadWrite)
	TSubclassOf<AActor> target_item;

	UPROPERTY(Category = RecipeInfo, EditAnywhere, BlueprintReadWrite)
	UTexture2D* Thumbnail;

	UPROPERTY(Category = RecipeInfo, EditAnywhere, BlueprintReadWrite)
	FText Name;
};

아이템을 제작하기 위한 레시피의 구조체이다.
needs는 target_item을 만들기위한(=스폰) 재료들에 대한 맵인데, 재료의 이름을 키로 제작에 필요한 수량을 Value로 두었다.

아이템 제작 시스템 구현을 위해서 Inventory Action Component를 수정했다.

Inventory Action Component 헤더
class SCIFICOMBAT_API UItemActionComponent : public UActorComponent
{
	. . . . .
    public:
	// Item Craft
	UFUNCTION(BlueprintCallable)
	void SelectRecipe(const FItemCraftRecipe& recipe_info);
	UFUNCTION(Server, Reliable)
	void ServerSelectRecipe(TSubclassOf<AActor> item_class);
	UFUNCTION(NetMulticast, Reliable)
	void MulticastSelectRecipe(TSubclassOf<AActor> item_class);

	UFUNCTION(BlueprintCallable)
	bool CheckItemCraftCondition();

	UFUNCTION(BlueprintCallable)
	void ManufactureIngredient();

	UFUNCTION(BlueprintCallable)
	void UseIngredient(int32 need_quantity, int32 inventory_idx);
	UFUNCTION(Server, Reliable)
	void ServerUseIngredient(int32 need_quantity, int32 inventory_idx);
	UFUNCTION(NetMulticast, Reliable)
	void MulticastUseIngredient(int32 need_quantity, int32 inventory_idx);

	UFUNCTION(BlueprintCallable)
	void CraftItem(const FVector& create_loc);
	UFUNCTION(Server, Reliable)
	void ServerCraftItem(const FVector& create_loc);
	UFUNCTION(NetMulticast, Reliable)
	void MulticastCraftItem(const FVector& create_loc);
}
아이템 제작 핵심 함수들 구현부분
bool UItemActionComponent::CheckItemCraftCondition()
{
	// 현재 아이템이 제작 가능한지를 체크하는 함수이다.
	int check_count = 0;

	// 장비 제작을 위해서 필요한 재료들이 현재 인벤토리 내부에 존재하는지 확인한다.
	for (auto& elem : selected_recipe.needs)
	{
		for (int i = 0; i < inventory_owner->inventory_component->inventory.Num(); i++)
		{
        // 재료를 가지고 있다면
			if (inventory_owner->inventory_component->inventory[i].Name.ToString() == elem.Key.ToString())
			{
            // 그리고 가지고 있는 재료가 레시피의 요구량 만큼 가지고 있다면
				if (inventory_owner->inventory_component->inventory[i].Quantity >= elem.Value)
				{
					check_count++;
					//IngredientUpdate(i, elem.Value);
					//selected_ingredient_idxs.Add(i);
					//selected_ingredient_qauntities.Add(elem.Value);
				}
			}
		}
	}
	if (check_count == selected_recipe.needs.Num())
	{
    // check_count가 레시피의 재료 종류 수와 일치한다면 제작 조건을 만족함.
		return true;
	}
	else
	{
		IngredientReset();
		//selected_ingredient_idxs.Empty();
		//selected_ingredient_qauntities.Empty();
	}
	return false;
}

// 레시피의 요구량 만큼 인벤토리 내부의 재료들을 감소시키는 함수
void UItemActionComponent::ManufactureIngredient()
{
// 레시피 내부를 돌면서
	for (auto& Elem : selected_recipe.needs)
	{
		for (int i = 0; i < inventory_owner->inventory_component->inventory.Num(); i++)
		{
        // 레시피의 요구량만큼 재료수를 삭감
			if (inventory_owner->inventory_component->inventory[i].Name.ToString() == Elem.Key.ToString())
			{
				int32 need_qanty = Elem.Value;
				int32 result = inventory_owner->inventory_component->inventory[i].Quantity - need_qanty;
				inventory_owner->inventory_component->inventory[i].Quantity = result;
			}
		}
	}
    // 인벤토리 내부를 돌면서 0보다 적은 재료수가 있다면 해당 아이템을 Remove함
	for (int i = 0; i < inventory_owner->inventory_component->inventory.Num(); i++)
	{
		if (inventory_owner->inventory_component->inventory[i].Quantity <= 0)
		{
			inventory_owner->inventory_component->inventory.RemoveAt(i);
		}
	}
}

// 아이템 제작 로직 중 가장 마지막에 실행된다.

void UItemActionComponent::CraftItem(const FVector& create_loc)
{
	ServerCraftItem(create_loc);
}

void UItemActionComponent::ServerCraftItem_Implementation(const FVector& create_loc)
{
	MulticastCraftItem(create_loc);
}

void UItemActionComponent::MulticastCraftItem_Implementation(const FVector& create_loc)
{
// 제작된 아이템을 스폰한다.
	if (inventory_owner->HasAuthority())
	{
		UWorld* world = GetWorld();
		FRotator spawn_rot = FRotator(0.f, 0.f, 0.f);
		if (world)
		{
			world->SpawnActor<AActor>(
				craft_item_class,
				create_loc,
				spawn_rot
				);
		}
	}
}

테이블 데이터로 보는 FItemCraftRecipe

target_item을 제작하기 위해 추가한 재료들

아이템 제작과 관련된정보들, 함수들은 Blueprint에서도 읽을 수 있게 UFUNCTION 옵션을 설정한다음 User Widget에 바인딩하여 사용했다.

profile
https://github.com/gimhema, https://gimhema.tistory.com/

0개의 댓글