UE求职Demo开发日志#19 给物品找图标,实现装备增加属性,背包栏UI显示装备

1 将用到的图标找好,放一起

DataTable里对应好图标

测试一下能正确获取:

2 装备增强属性思路

给FMyItemInfo添加一个枚举变量记录类型(物品,道具,装备,饰品,武器)-->

扩展DataTable,新建行结构继承FMyItemData,增加属性增强数组(数组元素为Struct,其中的属性为FString,bool isPercent增强百分比或加数值,float value)和GA数组(待完善,赋予的能力)-->

用属性初始化AS时-->(倍率属性不参与)(读取的是固定增幅,额外增幅应该记录在FMyItemInfo中)

获取基础属性-->临时的结构体数组记录每个属性增强的百分比和数值

遍历装备列表-->

读取并计算装备增幅-->获取并赋予GA-->

遍历装备列表-->

读取并计算饰品增幅-->获取并赋予GA-->

获取武器id-->

读取并计算武器增幅-->获取并赋予GA-->

每个属性最终先+总数值,再*总百分比(1+总增幅百分比)

最终属性赋予AS

3 实现过程

3.1 增加枚举类型变量

cpp 复制代码
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"),
};

结构体里增加表示类型的变量:

cpp 复制代码
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

cpp 复制代码
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

考虑所有物品的所有属性的修改幅值,最后应用修改器

cpp 复制代码
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();
}

以下是功能的具体实现:

cpp 复制代码
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)
				{
					//要保证没用到的值为0
					Modifiers.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 测试

测试调用:

cpp 复制代码
ModAttribute(TArray<int> {100});

对应的测试数值:

修改前后属性变化:

4 背包模块中添加装备栏

暂定三个装备栏(头,胸甲,鞋)(先不管设定)

还是FMyItemInfo类型的数组,0,1,2记录

先把组件创建在脚本里:

cpp 复制代码
//MyPlayer.h
UPROPERTY(EditAnywhere, BlueprintReadWrite)
UBagManager* BagManager;
//MyPlayer.cpp
AMyPlayer::AMyPlayer(){
	......
    BagManager=CreateDefaultSubobject<UBagManager>(TEXT("BagManager"));//
    ......
}

更新以下Bag保存相关的函数,例如:

cpp 复制代码
Save->SetItemsInBag(ItemsInBag,Armor);

BeginPlay里调用计算并修改属性逻辑:

cpp 复制代码
TArray<int> ModsId{};
for(FMyItemInfo info:BagManager->Armor)
{
    ModsId.Add(info.ItemId);
}
Cast<UMyPlayerAttributeSet>(AttributeSet)->ModAttribute(ModsId);

BagUI里添加一个栏位显示相关信息:

运行测试:

还好没啥问题,属性也对,不然今天不知道要调到啥时候了,之后的装备和卸下装备的操作和逻辑就简单了,只要修改Armor数组然后重新调用ModAtrribute就行了

相关推荐
Petrichorzncu33 分钟前
Games104——网络游戏的进阶架构
游戏引擎
iqay1 小时前
【C语言】填空题/程序填空题1
c语言·开发语言·数据结构·c++·算法·c#
程序猿编码1 小时前
自定义命令执行器:C++中命令封装的深度探索(C/C++实现)
linux·c语言·c++·网络安全·shell·命令行
想拿高薪的韭菜1 小时前
人工智能第2章-知识点与学习笔记
人工智能·笔记·学习
一只码代码的章鱼2 小时前
计算机网络 应用层 笔记 (电子邮件系统,SMTP,POP3,MIME,IMAP,万维网,HTTP,html)
笔记·计算机网络·microsoft
qq_428639612 小时前
虚幻基础11:坐标计算&旋转计算
游戏引擎·虚幻
wen__xvn2 小时前
每日一题洛谷B3865 [GESP202309 二级] 小杨的 X 字矩阵c++
c++·算法·矩阵
makabaka_T_T2 小时前
25寒假算法刷题 | Day1 | LeetCode 240. 搜索二维矩阵 II,148. 排序链表
数据结构·c++·算法·leetcode·链表·矩阵
qq_428639612 小时前
虚幻基础09:帧运算
游戏引擎·虚幻