UE5学习笔记24-添加武器弹药

news2024/12/24 19:37:39

一、给角色的武器添加弹药

        1.创建界面,根据笔记23的界面中添加

        2.绑定界面控件

	UPROPERTY(meta = (Bindwidget))
	UTextBlock* WeaponAmmoAmount;

	UPROPERTY(meta = (Bindwidget))
	UTextBlock* CarriedAmmoAmount;

        3.添加武器类型枚举

        3.1创建武器类型枚举头文件

         3.2创建文件时,默认添加的路径是在Intermediate/ProjectFiles文件夹中,通过#include 包含头文件时会找不到对应的头文件,需要更改路径,我是将所有武器类的C++文件放到Weapon文件夹中,所以我将武器类型头文件放到了Weapon文件夹中。

        3.3创建枚举

#pragma once

UENUM(BlueprintType)
enum class EWeapoType : uint8
{
	EWT_AssaultRifle UMETA(DisplayName = "Assault Rifle"),

	EWT_MAX UMETA(DisplayName = "DefaultMAX"),
};

         3.4创建武器弹药数量,捡起武器的声音

	/**
	*	弹药数量 
	*/

	UPROPERTY(EditAnywhere, ReplicatedUsing = OnRep_Ammo)
	int32 Ammo;//弹药数量

	UFUNCTION()
	void OnRep_Ammo();

	UPROPERTY(EditAnywhere)
	int32 MagCapacity;//最大弹药数量
	
	void SpendRound();

	void SetHUDAmmo();

	UPROPERTY()
	class ABlasterCharacter* BlasterOwnerCharacter; // 当前持有武器的角色

	UPROPERTY()
	class ABlasterPlayerController* BlasterOwnerController; // 当前持有武器的角色控制器

	UPROPERTY()
	EWeapoType WeaponType;

	/**
	*	武器的声音
	*/
	UPROPERTY(EditAnywhere)
	class USoundCue* EquipSound;


bool IsEmpty();
FORCEINLINE EWeapoType GetWeaponType() const { return WeaponType; }
FORCEINLINE int32 GetAmmo() const { return Ammo; }
FORCEINLINE int32 GetMagCapacity() const { return MagCapacity; }
bool AWeapon::IsEmpty()
{
	return Ammo <= 0;
}

void AWeapon::OnRep_Ammo()
{
	//BlasterOwnerCharacter = BlasterOwnerCharacter == nullptr ? Cast<ABlasterCharacter>(GetOwner()) : BlasterOwnerCharacter;
	SetHUDAmmo();
}

void AWeapon::SpendRound()
{
	Ammo = FMath::Clamp(Ammo - 1,0,MagCapacity);
	SetHUDAmmo();
}

void AWeapon::SetHUDAmmo()
{
	BlasterOwnerCharacter = BlasterOwnerCharacter == nullptr ? Cast<ABlasterCharacter>(GetOwner()) : BlasterOwnerCharacter;
	if (BlasterOwnerCharacter)
	{
		BlasterOwnerController = BlasterOwnerController == nullptr ? Cast<ABlasterPlayerController>(BlasterOwnerCharacter->Controller) : BlasterOwnerController;
		if (BlasterOwnerController)
		{
			BlasterOwnerController->SetHUDWeaponAmmo(Ammo);
		}
	}
}

        3.5.因为新添加了两个显示弹药数量的地方,所以给PlayerController添加设置界面的函数

	void SetHUDWeaponAmmo(int32 Ammo);
	void SetHUDCarriedAmmo(int32 Ammo);
void ABlasterPlayerController::SetHUDWeaponAmmo(int32 Ammo)
{
	BlasterHUD = BlasterHUD == nullptr ? Cast<AABasterHUD>(GetHUD()) : BlasterHUD;
	bool bHUDValid = BlasterHUD &&
		BlasterHUD->CharacterOverlay &&
		BlasterHUD->CharacterOverlay->WeaponAmmoAmount;
	if (bHUDValid)
	{
		FString AmmoText = FString::Printf(TEXT("%d"), Ammo); // FloorToInt 向下取整
		BlasterHUD->CharacterOverlay->WeaponAmmoAmount->SetText(FText::FromString(AmmoText));
	}
}

void ABlasterPlayerController::SetHUDCarriedAmmo(int32 Ammo)
{
	BlasterHUD = BlasterHUD == nullptr ? Cast<AABasterHUD>(GetHUD()) : BlasterHUD;
	bool bHUDValid = BlasterHUD &&
		BlasterHUD->CharacterOverlay &&
		BlasterHUD->CharacterOverlay->CarriedAmmoAmount;
	if (bHUDValid)
	{
		FString CarriedAmmoText = FString::Printf(TEXT("%d"), Ammo); // FloorToInt 向下取整
		BlasterHUD->CharacterOverlay->CarriedAmmoAmount->SetText(FText::FromString(CarriedAmmoText));
	}
}

        3.6添加重新加载弹药功能,当前武器弹药的数量,播放换弹动画的功能

	/* 换弹 */
	UFUNCTION(Server, Reliable)
	void ServerReload();
	/* 换弹 */
	/* 处理换弹 */
	void HandleReload();
	/* 处理换弹 */

	/** 重新加载弹药函数 */
	void Reload();

	/** 处理设置完成战斗状态 */
	UFUNCTION(BlueprintCallable)
	void FinishReloading();

	/** 计算重新加载弹药的数量 */
	int32 AmountToReload();

    //当前装备的武器弹药
    UPROPERTY(ReplicatedUsing = OnRep_CarriedAmmo)
    int32 CarriedAmmo;

    UFUNCTION()
    void OnRep_CarriedAmmo();

	bool CanFire();// 是否可以开火函数

	UPROPERTY(ReplicatedUsing = OnRep_CombatState)
	ECombatState CombatState = ECombatState::ECS_Unoccupied;
	
	UFUNCTION()
	void OnRep_CombatState();

	void InitializeCarriedAmmo();

    TMap<EWeapoType, int32> CarriedAmmoMap;
void UCombatComponent::OnRep_CarriedAmmo()
{
	Controller = Controller == nullptr ? Cast<ABlasterPlayerController>(Character->Controller) : Controller;
	if (Controller)
	{
		Controller->SetHUDCarriedAmmo(CarriedAmmo);
	}
}

bool UCombatComponent::CanFire()
{
	if (EquippedWeapon == nullptr) return false;
	return !EquippedWeapon->IsEmpty() && bCanFire && CombatState == ECombatState::ECS_Unoccupied;
}

void UCombatComponent::OnRep_CombatState()
{
	switch (CombatState)
	{
	case ECombatState::ECS_Reloading:
		HandleReload();
		break;
	case ECombatState::ECS_Unoccupied:
		if (bFireButtonPressed)
		{
			Fire();
		}
		break;
	}
}

void UCombatComponent::FinishReloading()
{
	if (Character == nullptr) return;
	if (Character->HasAuthority())
	{
		CombatState = ECombatState::ECS_Unoccupied;
		UpdateAmmoValues();
	}
	if (bFireButtonPressed)
	{
		Fire();
	}
}

void UCombatComponent::HandleReload()
{
	Character->PlayReloadMontage();
}

void UCombatComponent::Reload()
{
	if (CarriedAmmo > 0 && CombatState != ECombatState::ECS_Reloading)
	{
		ServerReload();
	}
}


void UCombatComponent::ServerReload_Implementation()
{
	if (Character == nullptr || EquippedWeapon == nullptr) return;
	
	
	CombatState = ECombatState::ECS_Reloading;
	HandleReload();
}

int32 UCombatComponent::AmountToReload()
{
	if (EquippedWeapon == nullptr) return 0;
	int32 RoomInMag = EquippedWeapon->GetMagCapacity() - EquippedWeapon->GetAmmo();

	if (CarriedAmmoMap.Contains(EquippedWeapon->GetWeaponType()))
	{
		int32 AmountCarried = CarriedAmmoMap[EquippedWeapon->GetWeaponType()];
		int32 Least = FMath::Min(RoomInMag,AmountCarried);
		return FMath::Clamp(RoomInMag, 0, Least);
	}

	return 0;
}

void UCombatComponent::InitializeCarriedAmmo() beginplay中调用需要检查HasAuthority()
{
	CarriedAmmoMap.Emplace(EWeapoType::EWT_AssaultRifle, StartingARAmmo);
}

         3.7.在装备武器时调用


	if (CarriedAmmoMap.Contains(EquippedWeapon->GetWeaponType()))
	{
		CarriedAmmo = CarriedAmmoMap[EquippedWeapon->GetWeaponType()];
	}

	Controller = Controller == nullptr ? Cast<ABlasterPlayerController>(Character->Controller) : Controller;
	if (Controller)
	{
		Controller->SetHUDCarriedAmmo(CarriedAmmo);
	}

	if (EquippedWeapon->EquipSound)
	{
		UGameplayStatics::PlaySoundAtLocation(
			this,
			EquippedWeapon->EquipSound,
			Character->GetActorLocation()
		);
	}

	if (EquippedWeapon->IsEmpty())
	{
		Reload();
	}

        3.8.蓝图设置

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2211479.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++容器:map

1.铺垫 1.1map和unorder_map&#xff0c;两者的实现思想不同&#xff0c;但是用法是相同的&#xff1b;map的思想是平衡二叉树&#xff1b;unorder_map的思想是哈希&#xff1b; 1.2在现实及做题中&#xff0c;百分之99&#xff0c;都在使用unorder_map&#xff0c;接下来的讲…

2024 第一次周赛

A: 题目大意 骑士每连续 i 天每天会得到 i 个金币&#xff0c;&#xff08;i 1&#xff0c; 2&#xff0c; 3 &#xff0c; …&#xff09;,那么展开看每一天可以得到的金币数&#xff1a;1 2 2 3 3 3 4 4 4 5 5 5 5 5 … 可以发现就是1个1 &#xff0c;2个2, 3个3…,那么我…

P20机型HW睡眠省电-调研

摘要 AI睡眠场景识别 不激进的智能管控 睡眠省电 UI 以前有单独的睡眠开关选项&#xff0c;现在没有了&#xff0c;但是智能充电模式是使用AI睡眠模式 睡眠识别 华为专利上提到的论文《BTP-A Bedtime Predicting Algorithm》 各种事件状态&#xff08;亮灭屏、alarm、主动…

《数字信号处理》学习08-围线积分法(留数法)计算z 逆变换

目录 一&#xff0c;z逆变换相关概念 二&#xff0c;留数定理相关概念 三&#xff0c;习题 一&#xff0c;z逆变换相关概念 接下来开始学习z变换的反变换-z逆变换&#xff08;z反变化&#xff09;。 由象函数 求它的原序列 的过程就称为 逆变换。即 。 求z逆变换…

RTR-Chapter8

第八章 光与颜色 光量辐射度量学光度学色度学使用RGB颜色进行渲染 从场景到屏幕HDR显示编码色调映射色调再现变换曝光 颜色分级 光量 辐射度量学 辐射度量学&#xff08;radiometry&#xff09;研究的是对电磁辐射&#xff08;electromagnetic radiation&#xff09;的测量&am…

linux线程 | 线程的控制(二)

前言&#xff1a; 本节内容是线程的控制部分的第二个小节。 主要是列出我们的线程控制部分的几个细节性问题以及我们的线程分离。这些都是需要大量的代码去进行实验的。所以&#xff0c; 准备好接受新知识的友友们请耐心观看。 现在开始我们的学习吧。 ps:本节内容适合了解线程…

开源情报(OSINT)入门:初学者指南

欢迎来到令人兴奋的开源情报 (OSINT) 世界&#xff01;如果您是该领域的新手&#xff0c;OSINT 就是收集和分析公开信息以获取见解并制作情报产品。 无论您是安全爱好者、记者还是只是对 OSINT 感兴趣&#xff0c;本入门指南都将带您了解基础知识&#xff0c;让您开始第一次&a…

MySQL进阶学习一(2024.10.07版)

2024-10-06 -------------------------------------------------------------------------------------------------------------------------------- 1.一条SQL语句是如何执行的 单进程的多线程模型 MySQL的物理目录 show global variables like "%basedir%"; …

初学Vue(3)(内置指令)

文章目录 十四、内置指令v-textv-htmlv-cloak&#xff08;没有值&#xff09;v-oncev-pre自定义指令一、定义语法二、配置对象中常用的3个问题三、备注 十四、内置指令 回顾&#xff1a; v-bind &#xff1a;单向绑定解析表达式&#xff0c;可简写为 :xxx v-model : 双向数据绑…

HTML快速入门--第一节--五个基本标签

一、网络编程的三大基石 1.1 url 统一资源定位符&#xff1a; 网址:整个互联网中可以唯一且准确的确定一个资源的位置 (url项目外) 网址:https://www.baidu.com/ https://www.baidu.com/ 协议://ip端口/项目名/页面名 协议:交通法规获取资源 ip端口 &#xff08;域名&…

安全企业邮箱优势与局限,密码策略反馈

密码策略是什么呢&#xff1f;如何设置出安全可靠的密码策略呢&#xff1f;企业邮箱安全始于密码策略&#xff0c;包括复杂性、长度、更新频率、重用限制和两步验证。实施需全员培训、密码管理工具、审计与监控。一文为你详细介绍密码策略。 一、如何设置好的密码策略&#xff…

【JavaScript】JavaScript开篇基础(3)

1.❤️❤️前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; Hello, Hello~ 亲爱的朋友们&#x1f44b;&#x1f44b;&#xff0c;这里是E绵绵呀✍️✍️。 如果你喜欢这篇文章&#xff0c;请别吝啬你的点赞❤️❤️和收藏&#x1f4d6;&#x1f4d6;。如果你对我的…

【微信小程序_11_全局配置】

摘要:本文介绍了微信小程序全局配置文件 app.json 中的常用配置项,重点阐述了 window 节点的各项配置,包括导航栏标题文字、背景色、标题颜色,窗口背景色、下拉刷新样式以及上拉触底距离等。通过这些配置可实现小程序窗口外观的个性化设置,提升用户体验。 微信小程序_11_全…

总看别人写贪吃蛇,自己也来写一个吧

贪吃蛇是一个流行度非常高的游戏&#xff0c;玩法十分简单&#xff0c;从最初的方块机上就有这个游戏了&#xff0c;后来出现的手机中也是加入了这个游戏&#xff0c;无聊的时候可以打发时间玩一会。这个游戏可谓是非常的简单&#xff0c;容易上手&#xff0c;所以直到现在&…

番外篇 | 常用的激活函数汇总 | 20+种激活函数介绍及其公式、图像等

前言:Hello大家好,我是小哥谈。激活函数(Activation Function)是神经网络中的一种重要概念,用于控制神经网络中神经元的激活方式。在传统的神经网络中,激活函数被用来将神经元的输出从数值转换为可以被神经网络其他部分理解的非数值形式。激活函数通常被定义为神经元的输…

电能表预付费系统-标准传输规范(STS)(2)

5. 标准传输规格参考模型 5.1 一般付费电表功能参考图 In a single-device payment meter all the essential functions are located in a single enclosure as depicted in Figure 1 above, while in a multi-device payment meter it is possible for the TokenCarrierToMe…

Pagehelper获取total错误

前言 在使用若依框架的pagehelper时&#xff0c;给分页表设置数据的时候前端只收到了分页的那一页的数据&#xff0c;总记录数不符合要求 我想要的效果如下&#xff0c;可以实现分页&#xff0c;和显示总记录数 但是实际情况为 但是我的数据库有11条记录&#xff0c;他这里明…

【python学习】1-2 配置python系统环境变量

1.点击“我的电脑”右键&#xff0c;点击属性&#xff0c;点击“高级系统设置”&#xff0c;再点击环境变量。 2.选择“系统变量”中的Path后&#xff0c;点击编辑。 3.点击新建&#xff0c;添加如图两个路径&#xff0c;即是python安装的路径位置后&#xff0c;点击确定。

前端脚手架插件安装总结(axios,element-ui,bootstrap,echarts等)

1.打开前端项目终端 输入命令 vue ui 进入图形化界面 a.选择插件 b.选择添加插件 c.安装插件 d.完成安装

手写mybatis之完善ORM框架,增删改查操作

前言 目前这个框架中所提供的 SQL 处理仅有一个 select 查询操作&#xff0c;还没有其他我们日常常用的 insert、update、delete&#xff0c;以及 select 查询返回的集合类型数据。 其实这一部分新增处理 SQL 的内容&#xff0c;也就是在 SqlSession 需要定义新的接口&#xff…