1 实现思路设计
定义一个结构体记录技能树一个单元的信息,命名为FStrengthenCellInfo,一个TArray记录技能树整体信息,需要以下信息:
1.TArray前置技能index
2.FString 描述文本
3.TArray<FMyItemInfo>激活需要的物品ID和数量
4.bool 是否已经激活
一个新的Save类记录技能树信息
强化条件:所有前置技能激活,消耗物品全部都够
强化时:扣除消耗物品-->修改属性-->保存属性-->更新技能树信息-->保存技能树信息-->更新UI显示
设计一个道具用来测试,ID:1 DisplayName:源能结晶 CurrentOwnedCnt:1000
2 实现过程
2.1 UStrengthenInfoSave
用来保存数据的类,实现了GetSet
.cpp:
// Fill out your copyright notice in the Description page of Project Settings.
#include "StrengthenSystem/StrengthenInfoSave.h"
TArray<FStrengthenCellInfo> UStrengthenInfoSave::GetStrengthenTreeInfo()
{
return StrengthenTreeInfo;
}
void UStrengthenInfoSave::SetStrengthenTreeInfo(TArray<FStrengthenCellInfo> InStrengthenTreeInfo)
{
StrengthenTreeInfo = InStrengthenTreeInfo;
}
.h:
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/SaveGame.h"
#include "Items/WarehouseManager.h"
#include "StrengthenInfoSave.generated.h"
USTRUCT(BlueprintType)
struct ARPG_CPLUS_API FStrengthenCellInfo
{
GENERATED_USTRUCT_BODY()
UPROPERTY(EditAnywhere, BlueprintReadOnly)
TArray<int32> PreIndex;
UPROPERTY(EditAnywhere, BlueprintReadOnly)
FString DescriptionText;
UPROPERTY(EditAnywhere, BlueprintReadOnly)
TArray<FMyItemInfo> NeededItems;
UPROPERTY(EditAnywhere, BlueprintReadOnly)
bool bIsActive=false;
FStrengthenCellInfo()
{
PreIndex=TArray<int32>();
NeededItems=TArray<FMyItemInfo>();
DescriptionText = FString("Default");
bIsActive=false;
}
};
/**
*
*/
UCLASS()
class ARPG_CPLUS_API UStrengthenInfoSave : public USaveGame
{
GENERATED_BODY()
private:
TArray<FStrengthenCellInfo> StrengthenTreeInfo;
public:
UFUNCTION(BlueprintCallable)
TArray<FStrengthenCellInfo> GetStrengthenTreeInfo();
UFUNCTION(BlueprintCallable)
void SetStrengthenTreeInfo(TArray<FStrengthenCellInfo> InStrengthenTreeInfo);
};
呜呜出现了一个难以解决的bug,正在努力找。。。,改完回来更新
(1.22补充)2.2 UStrengthenManager
继承的UObject
实现了下边这几个函数:
Save、Load读取和保存到文件里
GetStrengthedCellInfo是按照index读取技能树里的一个单位的信息,这里暂时只有一个技能树,就是这个StrengthedTree_1
UPROPERTY(EditDefaultsOnly)
TArray<FStrengthenCellInfo> StrengthenTree_1;
UFUNCTION(BlueprintCallable)
void Save();
UFUNCTION(BlueprintCallable)
void Load();
UFUNCTION(BlueprintCallable)
FStrengthenCellInfo GetStrengthenCellInfo(int index);
具体实现:
void UStrengthenManager::Save()
{
UStrengthenInfoSave* SaveData=Cast<UStrengthenInfoSave>(UGameplayStatics::CreateSaveGameObject(UStrengthenInfoSave::StaticClass()));
SaveData->SetStrengthenTreeInfo(StrengthenTree_1);
UGameplayStatics::SaveGameToSlot(SaveData,FString("StrengthenInfo"), 0);
}
void UStrengthenManager::Load()
{
UStrengthenInfoSave* SaveData=Cast<UStrengthenInfoSave>(UGameplayStatics::LoadGameFromSlot(FString("StrengthenInfo"), 0));
StrengthenTree_1=SaveData->GetStrengthenTreeInfo();
}
FStrengthenCellInfo UStrengthenManager::GetStrengthenCellInfo(int index)
{
if(index>=0&&index<StrengthenTree_1.Num())
{
return StrengthenTree_1[index];
}
return FStrengthenCellInfo();
}
还有就是测试用的技能树在构造的时候初始化了:
FStrengthenCellInfo SCI_1=FStrengthenCellInfo();
SCI_1.bIsActive = false;
SCI_1.DescriptionText=FString("BaseAttack+10");
TArray<FMyItemInfo>NeededItems;
NeededItems.Add(FMyItemInfo(1,10,FString("源能结晶")));
SCI_1.NeededItems=NeededItems;
SCI_1.PreIndex=TArray<int32>();
StrengthenTree_1.Add(SCI_1);
SCI_1.bIsActive = false;
SCI_1.DescriptionText=FString("MaxHealth+100");
NeededItems.Empty();
NeededItems.Add(FMyItemInfo(1,15,FString("源能结晶")));
SCI_1.NeededItems=NeededItems;
SCI_1.PreIndex={0};
StrengthenTree_1.Add(SCI_1);
SCI_1.bIsActive = false;
SCI_1.DescriptionText=FString("BaseResistance+10");
NeededItems.Empty();
NeededItems.Add(FMyItemInfo(1,15,FString("源能结晶")));
SCI_1.NeededItems=NeededItems;
SCI_1.PreIndex={0};
StrengthenTree_1.Add(SCI_1);
(1.22补充)2.3 UUserWidget_StrengthenPad中的修改
添加了一个接口函数来调用Manager里的Get:
FStrengthenCellInfo UUserWidget_StrengthenPad::GetStrengthenCellInfoInterface(int index)
{
if(!StrengthenManager)StrengthenManager=NewObject<UStrengthenManager>();
if(StrengthenManager!=nullptr)
{
return StrengthenManager->GetStrengthenCellInfo(index);
}
return FStrengthenCellInfo();
}
强化的核心是这个函数:
所有的需要物品的数量都够了才能进行强化
强化属性
移除消耗物品
更新UI信息
保存数据
//TODO:前置技能条件检查
bool UUserWidget_StrengthenPad::TryStrengthenByCellIndex(int index)
{
if(!WarehouseManager)
{
UE_LOG(LogTemp,Warning,TEXT("WarehouseManager ptr in UUserWidget_StrengthenPad is Not Valid"));
return false;
}
FStrengthenCellInfo temp=StrengthenManager->GetStrengthenCellInfo(index);
bool bCanStrengthen=true;
for(int i=0;i<temp.NeededItems.Num();i++)
{
int OwnedCnt=WarehouseManager->GetItemInfoByItemId(temp.NeededItems[i].ItemId).CurrentOwnedCnt;
if(temp.NeededItems[i].CurrentOwnedCnt>OwnedCnt)//需要的比有的大,则不能强化
{
bCanStrengthen=false;
}
}
if(bCanStrengthen)
{
//这里处理强化逻辑,注意不要错
if(index==0)
{
StrengthenByName(FString("BaseAttack"),10);
for(int i=0;i<temp.NeededItems.Num();i++)
{
WarehouseManager->RemoveItemFromWarehouse(temp.NeededItems[i].ItemId,temp.NeededItems[i].CurrentOwnedCnt);
}
WarehouseManager->SaveData();
UpdatePadInfo();
SaveToSlot();
return true;
}
if(index==1)
{
StrengthenByName(FString("MaxHealth"),100);
for(int i=0;i<temp.NeededItems.Num();i++)
{
WarehouseManager->RemoveItemFromWarehouse(temp.NeededItems[i].ItemId,temp.NeededItems[i].CurrentOwnedCnt);
}
WarehouseManager->SaveData();
UpdatePadInfo();
SaveToSlot();
return true;
}
if(index==2)
{
StrengthenByName(FString("BaseResistance"),10);
for(int i=0;i<temp.NeededItems.Num();i++)
{
WarehouseManager->RemoveItemFromWarehouse(temp.NeededItems[i].ItemId,temp.NeededItems[i].CurrentOwnedCnt);
}
WarehouseManager->SaveData();
UpdatePadInfo();
SaveToSlot();
return true;
}
return false;
}
return false;
}
3 测试
在UI蓝图里把更新信息绑定好,终于行辣!
对比一下这俩图,相关的参数变化都对(其实调了挺久的)