当前位置: 首页 > news >正文

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 增加枚举类型变量

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

相关文章:

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

1 将用到的图标找好&#xff0c;放一起 DataTable里对应好图标 测试一下能正确获取&#xff1a; 2 装备增强属性思路 给FMyItemInfo添加一个枚举变量记录类型&#xff08;物品&#xff0c;道具&#xff0c;装备&#xff0c;饰品&#xff0c;武器&#xff09;--> 扩展DataT…...

C++泛型编程指南09 类模板实现和使用友元

文章目录 第2章 类模板 Stack 的实现2.1 类模板 Stack 的实现 (Implementation of Class Template Stack)2.1.1 声明类模板 (Declaration of Class Templates)2.1.2 成员函数实现 (Implementation of Member Functions) 2.2 使用类模板 Stack脚注改进后的叙述总结脚注2.3 类模板…...

使用MATLAB进行雷达数据采集可视化

本文使用轮趣科技N10雷达&#xff0c;需要源码可在后台私信或者资源自取 1. 项目概述 本项目旨在通过 MATLAB 读取 N10 激光雷达 的数据&#xff0c;并进行 实时 3D 点云可视化。数据通过 串口 传输&#xff0c;并经过解析后转换为 三维坐标点&#xff0c;最终使用 pcplayer 进…...

【Elasticsearch】allow_no_indices

- **allow_no_indices 参数的作用**&#xff1a; 该参数用于控制当请求的目标索引&#xff08;通过通配符、别名或 _all 指定&#xff09;不存在或已关闭时&#xff0c;Elasticsearch 的行为。 - **默认行为**&#xff1a; 如果未显式设置该参数&#xff0c;默认值为 …...

54【ip+端口+根目录通信】

上节课讲到&#xff0c;根目录起到定位作用&#xff0c;比如我们搭建一个php网站后&#xff0c;注册系统是由根目录的register.php文件执行&#xff0c;那么我们给这个根目录绑定域名https://127.0.0.1&#xff0c;当我们浏览器访问https://127.0.0.1/register.php时&#xff0…...

python算法和数据结构刷题[3]:哈希表、滑动窗口、双指针、回溯算法、贪心算法

回溯算法 「所有可能的结果」&#xff0c;而不是「结果的个数」&#xff0c;一般情况下&#xff0c;我们就知道需要暴力搜索所有的可行解了&#xff0c;可以用「回溯法」。 回溯算法关键在于:不合适就退回上一步。在回溯算法中&#xff0c;递归用于深入到所有可能的分支&…...

DeepSeek横空出世,AI格局或将改写?

引言 这几天&#xff0c;国产AI大模型DeepSeek R1&#xff0c;一飞冲天&#xff0c;在全球AI圈持续引爆热度&#xff0c;DeepSeek R1 已经是世界上最先进的 AI 模型之一&#xff0c;可与 OpenAI 的新 o1 和 Meta 的 Llama AI 模型相媲美。 DeepSeek-V3模型发布后&#xff0c;在…...

聚簇索引、哈希索引、覆盖索引、索引分类、最左前缀原则、判断索引使用情况、索引失效条件、优化查询性能

聚簇索引 聚簇索引像一本按目录排版的书&#xff0c;用空间换时间&#xff0c;适合读多写少的场景。设计数据库时&#xff0c;主键的选择&#xff08;如自增ID vs 随机UUID&#xff09;会直接影响聚簇索引的性能。 什么是聚簇索引&#xff1f; 数据即索引&#xff1a;聚簇索引…...

OpenAI 实战进阶教程 - 第四节: 结合 Web 服务:构建 Flask API 网关

目标 学习将 OpenAI 接入 Web 应用&#xff0c;构建交互式 API 网关理解 Flask 框架的基本用法实现 GPT 模型的 API 集成并返回结果 内容与实操 一、环境准备 安装必要依赖&#xff1a; 打开终端或命令行&#xff0c;执行以下命令安装 Flask 和 OpenAI SDK&#xff1a; pip i…...

python的pre-commit库的使用

在软件开发过程中&#xff0c;保持代码的一致性和高质量是非常重要的。pre-commit 是一个强大的工具&#xff0c;它可以帮助我们在提交代码到版本控制系统&#xff08;如 Git&#xff09;之前自动运行一系列的代码检查和格式化操作。通过这种方式&#xff0c;我们可以确保每次提…...

架构技能(四):需求分析

需求分析&#xff0c;即分析需求&#xff0c;分析软件用户需要解决的问题。 需求分析的下一环节是软件的整体架构设计&#xff0c;需求是输入&#xff0c;架构是输出&#xff0c;需求决定了架构。 决定架构的是软件的所有需求吗&#xff1f;肯定不是&#xff0c;真正决定架构…...

Linux环境下的Java项目部署技巧:安装 Nginx

Nginx 的简介&#xff1a; Nginx 是一个高性能的 HTTP 和反向代理服务器&#xff0c;也是一个 IMAP / POP3 / SMTP 代理服务器。它可以作为网站静态资源的 web 服务器&#xff0c;也可以作为其他应用服务器的反向代理服务器。同时&#xff0c; Nginx 还具有负载均衡的功能。 N…...

前端 Vue 性能提升策略

一、引言 前端性能优化是确保 Web 应用快速响应和流畅用户体验的关键。对于使用 Vue.js 构建的应用,性能优化不仅涉及通用的前端技术,还包括针对 Vue 特性的特定优化措施。本文将从多个方面探讨如何全面提升前端和 Vue 应用的性能。 二、前端性能优化基础 1. 减少初始加载…...

深入理解linux中的文件(上)

1.前置知识&#xff1a; &#xff08;1&#xff09;文章 内容 属性 &#xff08;2&#xff09;访问文件之前&#xff0c;都必须打开它&#xff08;打开文件&#xff0c;等价于把文件加载到内存中&#xff09; 如果不打开文件&#xff0c;文件就在磁盘中 &#xff08;3&am…...

Unity特效插件GodFX

2022Unity安装使用方法​​,将MinDrawer.cs文件MinAttribute改成UnityEngine.PostProcessing.MinAttribute 参考链接: Unity3D特效插件GodFX使用教程_哔哩哔哩_bilibili...

从 C 到 C++:理解结构体中字符串的存储与操作

对于刚入门 C/C 的程序员来说&#xff0c;字符串的存储和操作可能是个容易混淆的知识点。在 C 中&#xff0c;std::string 提供了非常友好的接口&#xff0c;我们可以轻松地在结构体中使用字符串类型&#xff0c;无需关注底层细节。然而&#xff0c;在 C 语言中&#xff0c;字符…...

Linux进阶——时间服务器

NTP是网络时间协议&#xff08;network time protocol&#xff09;的简称&#xff08;应用层的协议&#xff09;&#xff0c;通过UDP123端口进行网络时钟同步。 Chrony是一个开源自由的网络时间协议NTP的客户端和服务器软件。它能让计算机保持系统时钟与时钟服务器&#xff08…...

力扣 295. 数据流的中位数

&#x1f517; https://leetcode.cn/problems/find-median-from-data-stream/ 题目 数据流中不断有数添加进来&#xff0c;add 表示添加数据&#xff0c;find 返回数据流中的中位数 思路 大根堆存储数据流中偏小的数据小根堆存储数据流中偏大的数据若当前的 num 比大根堆的…...

【Linux】进程状态和优先级

个人主页~ 进程状态和优先级 一、进程状态1、操作系统进程状态&#xff08;一&#xff09;运行态&#xff08;二&#xff09;阻塞态&#xff08;三&#xff09;挂起态 2、Linux进程状态&#xff08;一&#xff09;R-运行状态并发执行 &#xff08;二&#xff09;S-浅度睡眠状态…...

携程Java开发面试题及参考答案 (200道-上)

说说四层模型、七层模型。 七层模型(OSI 参考模型) 七层模型,即 OSI(Open System Interconnection)参考模型,是一种概念模型,用于描述网络通信的架构。它将计算机网络从下到上分为七层,各层的功能和作用如下: 物理层:物理层是计算机网络的最底层,主要负责传输比特流…...

基于Koopman算子的四旋翼无人机MPC控制开发:一种创新的数据驱动方法

318-一种基于Koopman算子的模型预测控制MPC控制四旋翼无人机开发 简介&#xff1a; 一种基于Koopman算子和扩展动态模式分解(EDMD)的四旋翼无人机学习和控制的新型数据驱动方法。 基于欧拉角(表示方向)等传统方法构建EDMD的观测器已知涉及奇异性。 为了解决这个问题&#xff0c…...

虚拟机异常断电后卡在initramfs阶段?手把手教你用xfs_repair修复系统分区

1. 虚拟机异常断电的常见后果 最近在调试一个基于KVM的虚拟机集群时&#xff0c;遇到了一个典型问题&#xff1a;机房突然断电后&#xff0c;几台虚拟机重启时卡在了initramfs阶段&#xff0c;屏幕上不断刷出"generating /run/initramfs/rdsosreport.txt"的提示。这种…...

为什么你的USB摄像头总掉帧?深入UVC协议Alternate Setting配置避坑指南

为什么你的USB摄像头总掉帧&#xff1f;深入UVC协议Alternate Setting配置避坑指南 工业视觉检测线上&#xff0c;一台标称30fps的USB摄像头突然掉到15帧&#xff0c;导致传送带上的缺陷品漏检&#xff1b;手术内窥镜画面在关键时刻出现卡顿&#xff0c;医生不得不暂停操作——…...

CLaMP技术深度解析:对比学习如何实现语言与音乐的完美融合

CLaMP技术深度解析&#xff1a;对比学习如何实现语言与音乐的完美融合 【免费下载链接】muzic 这是一个微软研究院开发的音乐生成AI项目。适合对音乐、音频处理以及AI应用感兴趣的开发者、学生和研究者。特点是使用深度学习技术生成音乐&#xff0c;具有较高的创作质量和听觉体…...

Win10 22H2多合一版本实测:家庭版/专业版/企业版到底有什么区别?

Win10 22H2多合一版本深度解析&#xff1a;如何根据需求选择最佳系统版本 当你面对一个包含家庭版、专业版、企业版等多个版本的Win10 22H2多合一ISO镜像时&#xff0c;是否曾感到困惑&#xff1a;这些版本之间究竟有什么区别&#xff1f;哪个版本最适合我的使用场景&#xff1…...

解决Qt中使用qmqtt连接ONENet MQTT服务端的版本兼容性问题

1. 问题背景&#xff1a;当qmqtt遇上ONENet 最近在做一个物联网项目&#xff0c;需要用Qt开发一个MQTT客户端连接ONENet平台。按照官方文档&#xff0c;我选择了emqx/qmqtt这个第三方库&#xff0c;结果连接时直接报错。代码明明照着示例写的&#xff0c;参数也都检查过&#x…...

【单片机实战】中断服务程序编写精要:从现场保护到中断返回

1. 中断服务程序的核心作用与基本结构 第一次接触单片机中断时&#xff0c;我盯着开发板上的按键发愣——明明没有循环检测IO口状态&#xff0c;按下按键却能立即触发LED亮灭。这种"随叫随到"的响应机制&#xff0c;就是中断服务程序&#xff08;ISR&#xff09;的魔…...

如何一站式管理Mac周边所有设备的电池电量:AirBattery终极指南

如何一站式管理Mac周边所有设备的电池电量&#xff1a;AirBattery终极指南 【免费下载链接】AirBattery Get the battery level of all your devices on your Mac and put them on the Dock / Status Bar / Widget! && 在Mac上获取你所有设备的电量信息并显示在Dock / …...

开源TeslaMate:重新定义特斯拉数据监控与分析体验

开源TeslaMate&#xff1a;重新定义特斯拉数据监控与分析体验 【免费下载链接】teslamate teslamate-org/teslamate: TeslaMate 是一个开源项目&#xff0c;用于收集特斯拉电动汽车的实时数据&#xff0c;并存储在数据库中以便进一步分析和可视化。该项目支持监控车辆状态、行驶…...

Illustrator脚本大全:30个免费工具彻底改变你的设计工作流

Illustrator脚本大全&#xff1a;30个免费工具彻底改变你的设计工作流 【免费下载链接】illustrator-scripts Adobe Illustrator scripts 项目地址: https://gitcode.com/gh_mirrors/il/illustrator-scripts 如果你是一名Adobe Illustrator用户&#xff0c;每天重复着相…...