1 创建一个人物信息显示的面板,方便测试
简单弄一下:
UpdateInfo函数:
就是获取ASC后用属性更新,就不细看了
2 实现思路
在操作目标为装备栏,或者操作起点为装备栏时,交换前先判断能否交换(只有操作目标为装备栏时需要判断,即穿上装备时),交换完物品要重新计算属性,并更新属性。
3 实现过程
3.1 添加判断函数
bool UBagManager::JudgeCanArm(FMyItemInfo item,int ArmArrayIndex)const
{
if(!(item.ItemType==EMyItemType::Arm||item.ItemType==EMyItemType::Accessory||item.ItemType==EMyItemType::Weapon))return false;
if(item.ItemType==EMyItemType::Arm)
{
if(item.ArmType==EMyArmType::Helmet&&ArmArrayIndex==0)return true;
if(item.ArmType==EMyArmType::Chestplate&&ArmArrayIndex==1)return true;
if(item.ArmType==EMyArmType::Boots&&ArmArrayIndex==2)return true;
}
//TODO:完善所有条件判断
return false;
}
3.2 Mod函数最前重新读取文件中的数据,以此为基础重新计算增益后的数值
void UMyPlayerAttributeSet::ModAttribute(TArray<int> ItemsId)
{
UMyPlayerData* LoadedPlayerData= Cast<UMyPlayerData>(UGameplayStatics::LoadGameFromSlot(FString("PlayerAttributes"), 0));
InitPlayerAttributeSet(LoadedPlayerData->GetSavedAttributes());
LogBaseValueMes();
TArray<FAttributeModifier> Sum{};//不受bIsPercent限制
for(int i:ItemsId)
{
CalModMagnitude(i,Sum);
}
//UE_LOG(LogTemp,Warning,TEXT("Sum[0]-->ModName=%s PercentValue=%f AddedValue=%f"),*Sum[0].AttributeName,Sum[0].PercentValue,Sum[0].AddedValue);
for(FAttributeModifier Modifier:Sum)
{
//UE_LOG(LogTemp,Warning,TEXT("Sum-->ModName=%s PercentValue=%f AddedValue=%f"),*Modifier.AttributeName,Modifier.PercentValue,Modifier.AddedValue);
ApplyModifier(Modifier);
}
LogBaseValueMes();
}
3.3 Player里的调用接口
void AMyPlayer::UpdateModifiedPlayerAS()
{
TArray<int> ModsId{};
for(FMyItemInfo info:BagManager->Armor)
{
ModsId.Add(info.ItemId);
}
Cast<UMyPlayerAttributeSet>(AttributeSet)->ModAttribute(ModsId);
}
3.4 蓝图里把更新UI包装在函数里方便调用
3.5 在涉及到装备的地方加上判断
3.6 修改完数据后重新计算属性并更新
4 测试
分别测试穿脱装备到背包、仓库,其他属性道具能否检查成功,互换装备是否检查成功
同时观察属性变化是否成功
5 任务系统实现设计
看了一些教程决定自己实现一个简单的系统,最容易扩展的我觉得应该是按照树形结构存储信息,每个节点记录前置任务节点,一个总体任务来管理其中的任务节点,遇到末尾节点完成整个任务。而总体任务也存在前置触发条件,而主线就可以时总体线性,即前置触发条件就是前一个任务完成。
接下来细化任务节点的结构,USTRUCT,不是持久数据,用于总体任务结构里
{
TArray<int>记录前置节点id,
bool区分检查前置条件类型,(任意一个完成或全部完成)
int 记录唯一后置节点id,(所有并列情况检查放在TArray<struct>里)
int 记录当前节点id,//id用来查表
bool标记是否完成
}
任务节点数据 ,继承DataTableRow
{
FString任务提示文本,
enum类型表示任务条件检查类型(待扩展,主要用于区分UI表现)
结构数组TArray<struct>//这几个变量用于扩展,只要满足currentValue>neededValue就通过,判定条件固定全部检查
struct { float currentValue , float neededValue,int itemid,FString描述文本(可以为空) }
}
然后就是整个任务的结构,继承DataTableRow
{
int 当前正在执行的任务节点id
TArray<任务节点>;
TArray<int>结尾任务节点id;(任意一个完成即整个任务完成)
}