1 将用到的图标找好,放一起
DataTable里对应好图标
测试一下能正确获取:
2 装备增强属性思路
给FMyItemInfo添加一个枚举变量记录类型(物品,道具,装备,饰品,武器)-->
扩展DataTable,新建行结构继承FMyItemData,增加属性增强数组(数组元素为Struct,其中的属性为FString,bool isPercent增强百分比或加数值,float value)和GA数组(待完善,赋予的能力)-->
用属性初始化AS时-->(倍率属性不参与)(读取的是固定增幅,额外增幅应该记录在FMyItemInfo中)
获取基础属性-->临时的结构体数组记录每个属性增强的百分比和数值
遍历装备列表-->
读取并计算装备增幅-->获取并赋予GA-->
遍历装备列表-->
读取并计算饰品增幅-->获取并赋予GA-->
获取武器id-->
读取并计算武器增幅-->获取并赋予GA-->
每个属性最终先+总数值,再*总百分比(1+总增幅百分比)
最终属性赋予AS
3 实现过程
3.1 增加枚举类型变量
UENUM(BlueprintType)
enum class EMyItemType : uint8
{None=0,Item UMETA(DisplayName = "Item"),Prop UMETA(DisplayName = "Prop"),Arm UMETA(DisplayName = "Arm"),Accessory UMETA(DisplayName = "Accessory"),Weapon UMETA(DisplayName = "Weapon"),
};
结构体里增加表示类型的变量:
struct ARPG_CPLUS_API FMyItemInfo
{GENERATED_USTRUCT_BODY()UPROPERTY(EditAnywhere, BlueprintReadOnly)int32 ItemId;UPROPERTY(EditAnywhere, BlueprintReadOnly)int64 CurrentOwnedCnt;UPROPERTY(EditAnywhere, BlueprintReadOnly)FString DisplayName;UPROPERTY(EditAnywhere, BlueprintReadOnly)EMyItemType ItemType{EMyItemType::Item};FMyItemInfo(int32 ItemId,int64 CurrentOwnedCnt,FString DisplayName) : ItemId(ItemId), CurrentOwnedCnt(CurrentOwnedCnt), DisplayName(DisplayName){}FMyItemInfo(){ItemId = 0;CurrentOwnedCnt=0;DisplayName=FString("Default");}
};
3.2 添加修改器的结构体并创建要使用的行结构,继承FMyItemData
USTRUCT(BlueprintType)
struct ARPG_CPLUS_API FAttributeModifier
{GENERATED_USTRUCT_BODY()UPROPERTY(EditAnywhere, BlueprintReadWrite)FString AttributeName;UPROPERTY(EditAnywhere, BlueprintReadWrite)bool bIsPercent;UPROPERTY(EditAnywhere, BlueprintReadWrite)float PercentValue;UPROPERTY(EditAnywhere, BlueprintReadWrite)float AddedValue;
};
USTRUCT(BlueprintType)
struct ARPG_CPLUS_API FAttrModItemData:public FMyItemData
{GENERATED_USTRUCT_BODY()UPROPERTY(EditAnywhere, BlueprintReadWrite)TArray<FAttributeModifier> AttributeMods;UPROPERTY(EditAnywhere, BlueprintReadWrite)TArray<TSubclassOf<UGameplayAbility>> GAsToAdd;
};
3.3 MyPlayerAttributeSet里的计算逻辑
话不多说了(逻辑太长了)
核心逻辑:
传入的是要检查的所有装备,饰品等的Id
考虑所有物品的所有属性的修改幅值,最后应用修改器
void UMyPlayerAttributeSet::ModAttribute(TArray<int> ItemsId)
{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();
}
以下是功能的具体实现:
void UMyPlayerAttributeSet::CalModMagnitude(int ItemId,TArray<FAttributeModifier>& Modifiers)
{if(!BuffItemsDataTable)return;// 获取DataTable的所有行TArray<FName> RowNames= BuffItemsDataTable->GetRowNames();// 遍历找到ItemId对应的装备for (const auto& RowName : RowNames){FAttrModItemData* RowData = BuffItemsDataTable->FindRow<FAttrModItemData>(RowName,FString(""),true);if (RowData->ItemId == ItemId){for(FAttributeModifier ModifierToCal:RowData->AttributeMods)//遍历ItemId对应的装备的所有增强属性{//对于每一个要增强的属性bool bIsFind{false};//先记录最终修改器里有没有这个属性for(FAttributeModifier& Modifier:Modifiers){if(Modifier.AttributeName.Equals(ModifierToCal.AttributeName))//找到了对应的属性{bIsFind=true;//标记为找到了if(ModifierToCal.bIsPercent)//根据是否百分比增幅累加对应值{Modifier.PercentValue+=ModifierToCal.PercentValue;UE_LOG(LogTemp,Warning,TEXT("Percent==%f"),Modifier.PercentValue);}else{Modifier.AddedValue+=ModifierToCal.AddedValue;}//UE_LOG(LogTemp,Warning,TEXT("ModName=%s PercentValue=%f AddedValue=%f"),*Modifier.AttributeName,Modifier.PercentValue,Modifier.AddedValue);break;}}if(!bIsFind){//要保证没用到的值为0Modifiers.Add(ModifierToCal);}//UE_LOG(LogTemp,Warning,TEXT("ModToCal-->ModName=%s PercentValue=%f AddedValue=%f"),*ModifierToCal.AttributeName,ModifierToCal.PercentValue,ModifierToCal.AddedValue);//UE_LOG(LogTemp,Warning,TEXT("OnEveryModAttribute"));}//TODO:赋予能力}}
}void UMyPlayerAttributeSet::ApplyModifier(FAttributeModifier& Modifier)
{if(Modifier.AttributeName.Equals(FString("MaxHealth"))){FinalModAttribute(Modifier,MaxHealth);return;}if(Modifier.AttributeName.Equals(FString("MaxStamina"))){FinalModAttribute(Modifier,MaxStamina);return;}if(Modifier.AttributeName.Equals(FString("BaseAttack"))){FinalModAttribute(Modifier,BaseAttack);return;}if(Modifier.AttributeName.Equals(FString("BaseStagger"))){FinalModAttribute(Modifier,BaseStagger);return;}if(Modifier.AttributeName.Equals(FString("BaseResistance"))){FinalModAttribute(Modifier,BaseResistance);return;}if(Modifier.AttributeName.Equals(FString("CRT"))){FinalModAttribute(Modifier,CRT);return;}if(Modifier.AttributeName.Equals(FString("CriticalDamage"))){FinalModAttribute(Modifier,CriticalDamage);return;}UE_LOG(LogTemp,Warning,TEXT("ApplyModifier-->Attribute is mistake"));
}void UMyPlayerAttributeSet::FinalModAttribute(const FAttributeModifier& Modifier,FGameplayAttributeData& Attribute)
{//UE_LOG(LogTemp,Warning,TEXT("FinalModAttribute-->ModName=%s PercentValue=%f AddedValue=%f"),*Modifier.AttributeName,Modifier.PercentValue,Modifier.AddedValue);Attribute.SetBaseValue((Attribute.GetBaseValue()+Modifier.AddedValue)*(1+Modifier.PercentValue));Attribute.SetCurrentValue(Attribute.GetBaseValue());
}
3.4 测试
测试调用:
ModAttribute(TArray<int> {100});
对应的测试数值:
修改前后属性变化:
4 背包模块中添加装备栏
暂定三个装备栏(头,胸甲,鞋)(先不管设定)
还是FMyItemInfo类型的数组,0,1,2记录
先把组件创建在脚本里:
//MyPlayer.h
UPROPERTY(EditAnywhere, BlueprintReadWrite)
UBagManager* BagManager;
//MyPlayer.cpp
AMyPlayer::AMyPlayer(){......BagManager=CreateDefaultSubobject<UBagManager>(TEXT("BagManager"));//......
}
更新以下Bag保存相关的函数,例如:
Save->SetItemsInBag(ItemsInBag,Armor);
BeginPlay里调用计算并修改属性逻辑:
TArray<int> ModsId{};
for(FMyItemInfo info:BagManager->Armor)
{ModsId.Add(info.ItemId);
}
Cast<UMyPlayerAttributeSet>(AttributeSet)->ModAttribute(ModsId);
BagUI里添加一个栏位显示相关信息:
运行测试:
还好没啥问题,属性也对,不然今天不知道要调到啥时候了,之后的装备和卸下装备的操作和逻辑就简单了,只要修改Armor数组然后重新调用ModAtrribute就行了