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

news/2025/2/3 11:57:11 标签: c++, unreal engine, 笔记, 游戏引擎

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)
				{
					//要保证没用到的值为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 测试

测试调用:

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就行了 


http://www.niftyadmin.cn/n/5840772.html

相关文章

XML DOM - 导航节点

可通过使用节点间的关系对节点进行导航。 导航 DOM 节点 通过节点间的关系访问节点树中的节点&#xff0c;通常称为导航节点&#xff08;"navigating nodes"&#xff09;。 在 XML DOM 中&#xff0c;节点的关系被定义为节点的属性&#xff1a; parentNodechildNo…

面试题-消失的数字-异或

消失的数字 数组nums包含从0到n的所有整数&#xff0c;但其中缺了一个。请编写代码找出那个缺失的整数。你有办法在 O(n) 时间内完成吗&#xff1f; 示例&#xff1a; 输入&#xff1a;[3,0,1] 输出&#xff1a;2 int missingNumber(int* nums, int numsSize) {}分析 本题对…

25寒假算法刷题 | Day1 | LeetCode 240. 搜索二维矩阵 II,148. 排序链表

目录 240. 搜索二维矩阵 II题目描述题解 148. 排序链表题目描述题解 240. 搜索二维矩阵 II 点此跳转题目链接 题目描述 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性&#xff1a; 每行的元素从左到右升序排列。每列的元素从上到…

Vue3.0实战:大数据平台可视化(附完整项目源码)

文章目录 创建vue3.0项目项目初始化项目分辨率响应式设置项目顶部信息条创建页面主体创建全局引入echarts和axios后台接口创建express销售总量图实现完整项目下载项目任何问题都可在评论区,或者直接私信即可。 创建vue3.0项目 创建项目: vue create vueecharts选择第三项:…

【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】2.13 零拷贝技巧:as_strided的魔法与风险

2.13 零拷贝技巧&#xff1a;as_strided的魔法与风险 目录 #mermaid-svg-ieI7OVDIdPJxsrfJ {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-ieI7OVDIdPJxsrfJ .error-icon{fill:#552222;}#mermaid-svg-ieI7OVDIdPJx…

w186格障碍诊断系统spring boot设计与实现

&#x1f64a;作者简介&#xff1a;多年一线开发工作经验&#xff0c;原创团队&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取&#xff0c;记得注明来意哦~&#x1f339;赠送计算机毕业设计600个选题excel文…

使用 Numpy 自定义数据集,使用pytorch框架实现逻辑回归并保存模型,然后保存模型后再加载模型进行预测,对预测结果计算精确度和召回率及F1分数

1. 导入必要的库 首先&#xff0c;导入我们需要的库&#xff1a;Numpy、Pytorch 和相关工具包。 import numpy as np import torch import torch.nn as nn import torch.optim as optim from sklearn.metrics import accuracy_score, recall_score, f1_score2. 自定义数据集 …

无法将“mklink”项识别为 cmdlet、函数、脚本文件或可运行程序的名称

mklink : 无法将“mklink”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写&#xff0c;如果包括路径&#xff0c;请确保路径正确&#xff0c;然后再试一次。 所在位置 行:1 字符: 1这是因为 在老版本系统中可以是用mklink来创建软连接&#xff0c;但在最…