---@class BP_WeaponPawnBase_C:APawn ---@field Sphere USphereComponent ---@field DefaultRoot USceneComponent ---@field StaticMesh1 UStaticMeshComponent ---@field StaticMesh4 UStaticMeshComponent ---@field StaticMesh3 UStaticMeshComponent ---@field StaticMesh2 UStaticMeshComponent ---@field MuzzleParticle UParticleSystem --Edit Below-- local BP_WeaponPawnBase = { Activated = false, HasBegunPlay = false, InRangeMonsters = {}, -- 检测区域中的 Monster TargetMonster = nil, -- 目标 Monster MarkPendingInitialized = false, Weapons = {}, --所有的武器 数组类型 CurrentWeaponId = 0, -- 这个是 武器表中的 Id OwnerCharacter = nil, OwningPlayerState = nil, -- 拥有的PlayerState OwningPlayerController = nil, -- 拥有的 PlayerController DefaultShootCountPerSecond = 1, -- 默认每秒射击次数 TimeTemp = 0, -- 射击的定时器 DefaultSphereRadius = 1200, -- 默认球体半径 TempSphereRadius = 0, IsPlayerInArena = false; -- 玩家是否在场内,因为玩家默认不在场内 -- Client IsAttackNearestMonster = true; -- 是否攻击离得最近的怪物 }; BP_WeaponPawnBase.OnFireDelegate = Delegate.New() --设置同步的属性 function BP_WeaponPawnBase:GetReplicatedProperties() return "Activated", "OwnerCharacter", "TargetMonster", "CurrentWeaponId" end function BP_WeaponPawnBase:ReceiveBeginPlay() BP_WeaponPawnBase.SuperClass.ReceiveBeginPlay(self) self.MainMesh = self.StaticMesh1 self.PartStaticMeshes = { self.StaticMesh2, self.StaticMesh3, self.StaticMesh4 } self.MonsterBaseClass = UE.LoadClass(BPClassPath.MonsterBase) self.InRangeMonsters = {} self.HasBegunPlay = true if self:HasAuthority() then self:LoadPlayerState() self:LoadPlayerController() --self:SetFireTimer() self.OnFireDelegate:Add(BP_WeaponPawnBase.MulticastPlayMuzzleEffectAndSound, self) else self.Sphere.OnComponentBeginOverlap:Add(BP_WeaponPawnBase.Sphere_OnComponentBeginOverlap, self) self.Sphere.OnComponentEndOverlap:Add(BP_WeaponPawnBase.Sphere_OnComponentEndOverlap, self) EventSystem:AddListener(EventType.AsyncLoadWeaponMeshesCompleted, BP_WeaponPawnBase.OnPreLoadAccessable, self) EventSystem:AddListener(EventType.AttackRangeChanged, BP_WeaponPawnBase.SetSphereSizeRadius, self) self:OnCreateWeapons() end end function BP_WeaponPawnBase:ReceiveEndPlay() self.HasBegunPlay = false self.MainMesh = nil self.PartStaticMeshes = nil self.MonsterBaseClass = nil self.InRangeMonsters = nil if self:HasAuthority() then self:ClearFireTimer() self.OnFireDelegate:Remove(BP_WeaponPawnBase.MulticastPlayMuzzleEffectAndSound, self) else self.Sphere.OnComponentBeginOverlap:Remove(BP_WeaponPawnBase.Sphere_OnComponentBeginOverlap, self) self.Sphere.OnComponentEndOverlap:Remove(BP_WeaponPawnBase.Sphere_OnComponentEndOverlap, self) EventSystem:RemoveListener(EventType.AsyncLoadWeaponMeshesCompleted, BP_WeaponPawnBase.OnPreLoadAccessable, self) EventSystem:RemoveListener(EventType.AttackRangeChanged, BP_WeaponPawnBase.SetSphereSizeRadius, self) end BP_WeaponPawnBase.SuperClass.ReceiveEndPlay(self) end function BP_WeaponPawnBase:ReceiveTick(DeltaTime) BP_WeaponPawnBase.SuperClass.ReceiveTick(self, DeltaTime) if not self.HasBegunPlay then return end if self:HasAuthority() then -- 获取次数 if self.OwnerCharacter == nil or not UE.IsValid(self.OwnerCharacter) then return end if self.OwnerCharacter:IsSelfAlive() then self:TickFire(DeltaTime) end else if self.MarkPendingInitialized then self:ChangeWeaponId(self.CurrentWeaponId) end -- 每帧获取对应位置和旋转 if UE.IsValid(self.OwnerCharacter) then self:UpdateTargetMonster() if UE.IsValid(self.TargetMonster) then local SocketPos = VectorHelper.Add(self.OwnerCharacter:K2_GetActorLocation(), { X = 0, Y = 0, Z = 110 }) local MonsterPos = VectorHelper.Add(self.TargetMonster:K2_GetActorLocation(), { X = 0, Y = 0, Z = 80 }) self.StaticMesh1:K2_SetWorldRotation(KismetMathLibrary.FindLookAtRotation(SocketPos, MonsterPos), false) else self.StaticMesh1:K2_SetWorldRotation(self.OwnerCharacter:K2_GetActorRotation(), false) end end self.TimeTemp = self.TimeTemp + DeltaTime if self.TimeTemp > 1 then -- print(string.format('[BP_WeaponPawnBase:ReceiveTick] 开始打印怪物名称')) if #self.InRangeMonsters > 0 then for i, v in pairs(self.InRangeMonsters) do -- print(string.format('[BP_WeaponPawnBase:ReceiveTick] MonsterName = %s', KismetSystemLibrary.GetObjectName(v))) end end -- print(string.format('[BP_WeaponPawnBase:ReceiveTick] 结束打印, Target Monster Name = %s', KismetSystemLibrary.GetObjectName(self.TargetMonster))) self.TimeTemp = self.TimeTemp - 1 end end end function BP_WeaponPawnBase:OnCreateWeapons() if not self.OwnerCharacter then return end -- 先关闭 local ObjectTypes = {} local ActorClassFilter = UE.LoadClass(BPClassPath.MonsterBase) local ActorsToIgnore = { } local SphereLoc = self.OwnerCharacter:K2_GetActorLocation() local Radius = self.Sphere.SphereRadius local OutArrs = {} local RetVal, OutActors = KismetSystemLibrary.SphereOverlapActors(self.OwnerCharacter, SphereLoc, Radius, ObjectTypes, ActorClassFilter, ActorsToIgnore, OutArrs) --STExtraGameplayStatics.ClientDrawDebugSphere(SphereLoc, Radius, 6, {R = 1, G = 0, B = 0, A = 1}, 10, 1) --print(string.format('[BP_WeaponPawnBase:OnCreateWeapons] OutArrs Len = %d', #OutArrs)) if RetVal then --print(string.format('[BP_WeaponPawnBase:OnCreateWeapons] 进来了是进来了,有多少值呢:%d, Radius = %d', table.getCount(OutActors), Radius)) if table.getCount(OutActors) > 0 then for i = 1, #OutActors do table.insert(self.InRangeMonsters, OutActors[i]) end self:UpdateTargetMonster() end else print(string.format('[BP_WeaponPawnBase:OnCreateWeapons] 没有用呀~~')) end -- 先关闭 --self.TempSphereRadius = self.Sphere.SphereRadius --self.Sphere:SetActive(false, true) ----self.Sphere:SetSphereRadius(5) --EventSystem.SetTimer(self, function() -- --self.Sphere:SetSphereRadius(self.TempSphereRadius, true) -- self.Sphere:SetActive(true, true) --end, 0.2) end function BP_WeaponPawnBase:PlayerInArena(IsInArena) -- print(string.format('[BP_WeaponPawnBase:PlayerInArena] '.. tostring(IsInArena))) self.IsPlayerInArena = IsInArena end function BP_WeaponPawnBase:TickFire(DeltaTime) local ShootTime = self:GetShootTime() self.TimeTemp = self.TimeTemp + DeltaTime if self.TimeTemp > ShootTime then -- print(string.format("[BP_WeaponPawnBase:TickFire] 隔 %f 秒进行第二次射击", ShootTime)) self.TimeTemp = self.TimeTemp - ShootTime self:Fire() end end function BP_WeaponPawnBase:LoadPlayerController() if self.OwnerCharacter ~= nil then self.OwningPlayerController = self.OwnerCharacter:GetPlayerControllerSafety() end end function BP_WeaponPawnBase:LoadPlayerState() if self.OwningPlayerState == nil then if self.OwnerCharacter ~= nil then self.OwningPlayerState = UGCGameSystem.GetPlayerStateByPlayerKey(self.OwnerCharacter.PlayerKey) end end end function BP_WeaponPawnBase:Fire() print(string.format("[BP_WeaponPawnBase:Fire] 开始开火")) if not self.Activated then return end if UE.IsValid(self.TargetMonster) == false then return end if UE.IsValid(self.OwnerCharacter) == false then return end if not self.TargetMonster:IsAlive() then return end self:LoadPlayerState() if self.OwningPlayerController == nil then self:LoadPlayerController() end if self.OwningPlayerController == nil then print(string.format("[BP_WeaponPawnBase:Fire] 玩家控制器设置出错,请检查")) return end -- 造成的伤害 local Damage = self.OwningPlayerState:MakeDamage(self.TargetMonster) self.OnFireDelegate(self, Damage) local RealDamage = UGCGameSystem.ApplyDamage(self.TargetMonster, Damage, self.OwningPlayerController, self.OwnerCharacter, EDamageType.ShootDamage) -- 在这进行判断 if self.TargetMonster then GameDataManager.GetMonsterTypeByID(self.TargetMonster.ID) end --调用PlayerState 射击生命值 和 射击威力值 self.OwningPlayerState:OnShot() UE.Log("[BP_WeaponPawnBase:Fire] RealDamage = %f, Player Key = %d", RealDamage, self.OwnerCharacter.PlayerKey) end function BP_WeaponPawnBase:MulticastPlayMuzzleEffectAndSound() local SoundConfigId = Tables.WeaponSoundConfig[self.CurrentWeaponId] if SoundConfigId then UnrealNetwork.CallUnrealRPC_Multicast_Unreliable(self, "Client_MulticastRPC_PlayMuzzleEffectAndSound", SoundConfigId) end end -- Client function BP_WeaponPawnBase:ChangeWeaponId(ID) if not self.HasBegunPlay then UE.LogError("[BP_WeaponPawnBase:ChangeWeaponId] Has not BegunPlay, Mark Pending Initialized") self.MarkPendingInitialized = true return end self.MarkPendingInitialized = false if ID <= 0 then self.MainMesh:SetHiddenInGame(true, false) for _, StaticMeshComp in pairs(self.PartStaticMeshes) do StaticMeshComp:SetHiddenInGame(true, false) end return end local RowData = GameDataManager.GetWeaponConstructDataByID(ID) local MeshInfo = GameDataManager.GetWeaponMeshInfo(ID) if RowData == nil or MeshInfo == nil then self.MainMesh:SetHiddenInGame(true, false) for _, PartMesh in pairs(self.PartStaticMeshes) do PartMesh:SetHiddenInGame(true, false) end UE.Log("[BP_WeaponPawnBase:ChangeWeaponId] RowData or MeshInfo is nil") return end local MainStaticMesh = MeshInfo.MainMesh local PartStaticMeshes = MeshInfo.PartMeshes if MainStaticMesh then self.MainMesh:SetStaticMesh(MainStaticMesh) end for i, PartMesh in pairs(self.PartStaticMeshes) do local PartStaticMesh = PartStaticMeshes[i] if PartStaticMesh then local SocketName = PartStaticMesh.SocketName local Mesh = PartStaticMesh.PartMesh PartMesh:SetHiddenInGame(false, false) PartMesh:SetStaticMesh(Mesh) PartMesh:K2_AttachTo(self.MainMesh, SocketName, EAttachLocation.SnapToTarget, false) else PartMesh:SetHiddenInGame(true, false) end end local Trans = MeshInfo.RelativeTransform self.MainMesh:K2_SetRelativeTransform(Trans, false, nil, false) end function BP_WeaponPawnBase:OnRep_Activated() ---TODO end function BP_WeaponPawnBase:OnRep_OwnerCharacter() -- UE.Log("[BP_WeaponPawnBase:OnRep_OwnerCharacter]") if self.OwnerCharacter then -- 武器绑定到人物头上 self:K2_AttachToComponent(self.OwnerCharacter.WeaponActorSocket, "", EAttachmentRule.SnapToTarget, EAttachmentRule.KeepRelative, EAttachmentRule.SnapToTarget, true) end end ---Server function BP_WeaponPawnBase:SetWeaponID(ID) print(string.format("[BP_WeaponPawnBase:SetWeaponID] 设置 Weapon Id = %d", ID)) self.CurrentWeaponId = ID self.Activated = ID > 0 end ---S function BP_WeaponPawnBase:SetOwnerCharacter(InCharacter) if InCharacter == nil then return end self.OwnerCharacter = InCharacter self:SetOwner(InCharacter) end function BP_WeaponPawnBase:SetFireTimer() if self.OwningPlayerState == nil then self.OwningPlayerState = UGCGameSystem.GetPlayerStateByPlayerKey(self.PlayerKey) end KismetSystemLibrary.K2_ClearTimerHandle(self, self.TimerHandle) if self.FireTimerDelegate then ObjectExtend.DestroyDelegate(self.FireTimerDelegate) end self.FireTimerDelegate = ObjectExtend.CreateDelegate(self, function() if self.Activated and UE.IsValid(self.TargetMonster) and UE.IsValid(self.OwnerCharacter) and self.TargetMonster:IsAlive() then local PC = self.OwnerCharacter:GetPlayerControllerSafety() if PC then -- 造成的伤害 local Damage = self.OwningPlayerState:MakeDamage(self.TargetMonster) local RealDamage = UGCGameSystem.ApplyDamage(self.TargetMonster, Damage, PC, self.OwnerCharacter, EDamageType.ShootDamage) -- 在这进行判断 if self.TargetMonster then GameDataManager.GetMonsterTypeByID(self.TargetMonster.ID) end UE.Log("[BP_WeaponPawnBase:FireTimerDelegate] RealDamage = %f", RealDamage) end end end) -- 获取一下默认属性 self:RefreshShootSpeed() end function BP_WeaponPawnBase:RefreshShootSpeed() local bIsActive = KismetSystemLibrary.K2_IsTimerActiveDelegate(self.TimerHandle) if bIsActive then KismetSystemLibrary.K2_ClearTimerDelegate(self.TimerHandle) end if self.OwningPlayerState == nil then self.OwningPlayerState = UGCGameSystem.GetPlayerStateByPlayerKey(self.PlayerKey) end local ShootRate = self.OwningPlayerState:ShootTimeEverSecond() --这个 0.5 是一个基础射击数值 local TimeDelta = 0.5 / ShootRate self.TimerHandle = KismetSystemLibrary.K2_SetTimerDelegateForLua(self.FireTimerDelegate, self, TimeDelta, true) end -- server 获取射击间隔(s) function BP_WeaponPawnBase:GetShootTime() if self.OwningPlayerState == nil or self.OwnerCharacter == nil then -- 默认情况下攻速 return 1 / 1.30 end local ShootRate = self.OwningPlayerState:ShootTimeEverSecond() --print(string.format("[BP_WeaponPawnBase:GetShootTime] Shoot Rate = %f", ShootRate)) return 1 / ShootRate end function BP_WeaponPawnBase:ClearFireTimer() KismetSystemLibrary.K2_ClearTimerHandle(self, self.TimerHandle) ObjectExtend.DestroyDelegate(self.FireTimerDelegate) end function BP_WeaponPawnBase:GetWeaponTypeByWeaponId(InWeaponId) return GameDataManager.GetWeaponType(InWeaponId) end ---C function BP_WeaponPawnBase:OnPreLoadAccessable() self:OnRep_OwnerCharacter() end function BP_WeaponPawnBase:Sphere_OnComponentBeginOverlap(OverlappedComponent, OtherActor, OtherComp, OtherBodyIndex, bFromSweep, SweepResult) if UE.IsValid(OtherActor) and UE.IsA(OtherActor, self.MonsterBaseClass) then self:UpdateMonsterInRange(OtherActor, true) end end function BP_WeaponPawnBase:Sphere_OnComponentEndOverlap(OverlappedComponent, OtherActor, OtherComp, OtherBodyIndex) if UE.IsValid(OtherActor) and UE.IsA(OtherActor, self.MonsterBaseClass) then self:UpdateMonsterInRange(OtherActor, false) end end function BP_WeaponPawnBase:UpdateMonsterInRange(InMonster, IsAdd) if not self.OwnerCharacter then return end if IsAdd and InMonster:IsAlive() then InMonster.OnDeath:Add(self.OnOverlappedMonsterDeath, self) table.insert(self.InRangeMonsters, InMonster) else InMonster.OnDeath:Remove(self.OnOverlappedMonsterDeath, self) table.removeValue(self.InRangeMonsters, InMonster) end self:UpdateTargetMonster() end function BP_WeaponPawnBase:UpdateTargetMonster() if (not UE.IsValid(self.OwnerCharacter)) or (not self.Sphere) then return end local MinDist = self.Sphere:GetScaledSphereRadius() local PawnLocation = self.OwnerCharacter:K2_GetActorLocation() local CurTarget = nil local Func = function(InMinDist, InMonster, InPawnLoc, InCurr) if UE.IsValid(InMonster) and InMonster:IsAlive() then local MonsterLocation = InMonster:K2_GetActorLocation() local Dist = VectorHelper.GetDistance(InPawnLoc, MonsterLocation) if Dist < InMinDist then InMinDist = Dist InCurr = InMonster end end return InCurr, InMinDist end -- 选择最近的怪物 if self.IsAttackNearestMonster then for _, Monster in pairs(self.InRangeMonsters) do if UE.IsValid(Monster) then local IsInArenaMonster = Monster:GetMonsterType() == EMonsterType.Boss or Monster:GetMonsterType() == EMonsterType.Common if self.IsPlayerInArena then if IsInArenaMonster then CurTarget, MinDist = Func(MinDist, Monster, PawnLocation, CurTarget) end else CurTarget, MinDist = Func(MinDist, Monster, PawnLocation, CurTarget) end end end else -- 按照权重进行设置,找到 BOSS local NiuBiGuai = {} for _, Monster in pairs(self.InRangeMonsters) do if UE.IsValid(Monster) and Monster:IsAlive() then local MonsterType = Tables.MonsterBaseConfig[Monster.ID].Type if MonsterType == EMonsterType.Default or MonsterType == EMonsterType.Common or MonsterType == EMonsterType.HangupRoom then else table.insert(NiuBiGuai, Monster) end end end if table.getCount(NiuBiGuai) > 0 then for _, Monster in pairs(NiuBiGuai) do CurTarget, MinDist = Func(MinDist, Monster, PawnLocation, CurTarget) end end if CurTarget == nil then for _, Monster in pairs(self.InRangeMonsters) do CurTarget, MinDist = Func(MinDist, Monster, PawnLocation, CurTarget) end end end if CurTarget ~= self.TargetMonster then self.TargetMonster = CurTarget -- print(string.format('[BP_WeaponPawnBase:UpdateTargetMonster] 设置Target Monster = %s', KismetSystemLibrary.GetObjectName(CurTarget))) UnrealNetwork.CallUnrealRPC(self, self, "ServerRPC_SetTargetMonster", CurTarget) end end function BP_WeaponPawnBase:ServerRPC_SetTargetMonster(InMonster) -- print(string.format('[BP_WeaponPawnBase:ServerRPC_SetTargetMonster] 服务端设置 TargetMonster:%s', KismetSystemLibrary.GetObjectName(InMonster))) if UE.IsValid(InMonster) and InMonster:IsAlive() then self.TargetMonster = InMonster else self.TargetMonster = nil end end function BP_WeaponPawnBase:GetAvailableServerRPCs() return -- "Client_MulticastRPC_PlayMuzzleEffectAndSound" "ServerRPC_SetTargetMonster" end function BP_WeaponPawnBase:OnOverlappedMonsterDeath(DeadMonster, KillerController, DamageCauser, KillingHitInfo, KillingHitImpulseDir, KillingHitDamageTypeID, DamageTypeClass, IsHeadShotDamage) if DeadMonster and UE.IsA(DeadMonster, self.MonsterBaseClass) then self:UpdateMonsterInRange(DeadMonster, false) end end function BP_WeaponPawnBase:GetPlayerState() if UGCGameSystem.IsServer() then local PlayerKey = self.OwnerCharacter.PlayerKey local PlayerState = UGCGameSystem.GetPlayerStateByPlayerKey(PlayerKey) return PlayerState else local PlayerState = GameDataManager.GetLocalPlayerState() return PlayerState end end function BP_WeaponPawnBase:FindWeaponById(InWeaponId) -- 找到 PS return self:GetPlayerState():FindWeaponById(InWeaponId) end function BP_WeaponPawnBase:GetWeaponByFittingItemId(InFittingItemId) local WeaponType = GetItemWeaponTypeByItemId(InFittingItemId) for i = 1, #self.Weapons do local Weapon = self.Weapons[i] if Weapon.Type == WeaponType then return Weapon end end return nil end -- 查找配件的武器是否存在 function BP_WeaponPawnBase:FindWeaponExist(InFittingItemId) local WeaponType = GetItemWeaponTypeByItemId(InFittingItemId) return self:FindWeaponByWeaponType(WeaponType) end function BP_WeaponPawnBase:FindWeaponByWeaponType(InWeaponType) for i = 1, #self.Weapons do if self.Weapons[i].Type == InWeaponType then return self.Weapons[i] end end return nil end --Server 获取当前武器的属性,这是一个表:{ { Type = "", Value = 0 },{ Type = "", Value = 0 } } function BP_WeaponPawnBase:GetOutProps() -- 需要获取手枪属性 local OutTable = {} local TheTable = DropItemMap.WeaponTable[EWeaponClassType.WT_Pistol].Props OutTable = TableHelper.DeepCopyTable(TheTable) if self.CurrentWeaponId == 0 then -- 说明当前是手枪,不进行处理 return self:MergeOutTable(OutTable) end print(string.format("[BP_WeaponPawnBase:GetOutProps] 当前武器 Id = %d", self.CurrentWeaponId)) -- NativeProps local Weapon = self:FindWeaponById(self.CurrentWeaponId) local SpecialItems = {} --print(string.format("[BP_WeaponPawnBase:GetOutProps] 开始打印武器高级属性,数量为:%d", table.getCount(Weapon.NativeProps.Plus))) -- 高级属性 for i = 1, table.getCount(Weapon.NativeProps.Plus) do local Val = Weapon.NativeProps.Plus[i] --print(string.format("[BP_WeaponPawnBase:GetOutProps] MainType: %s,类型是:%s", tostring(Val.MainType), type(Val.MainType))) local Name = Tables.WeaponPropertyConfig[Val.MainType].PropName local ItemData = { Type = Name, Value = Val.Value } --print(string.format("[BP_WeaponPawnBase:GetOutProps] 武器高级属性:Name:%s, Value: %s", Name, tostring(Val.Value))) table.insert(OutTable, ItemData) end -- 添加 Properties local Properties = Weapon.Properties --print(string.format("[BP_WeaponPawnBase:GetOutProps] 开始打印武器属性,数量:%d", table.getCount(Properties))) for i = 1, #Properties do local Prop = Properties[i] local ItemData = { Type = Tables.WeaponPropertyConfig[Prop.MainType].PropName, Value = Prop.Value } --print(string.format("[BP_WeaponPawnBase:GetOutProps] 武器属性:Name: %s, Value: %s", ItemData.Type, tostring(Prop.Value))) table.insert(OutTable, ItemData) end -- 处理武器自带属性 local FittingLevel = Weapon.FittingLevel if FittingLevel > 0 then local Val = DropItemMap.WeaponTable[Weapon.Type].PlusProps[FittingLevel] local ItemData = { Type = Val.Type, Value = Val.Value } table.insert(OutTable, ItemData) end -- FittingItems local FittingList = Weapon.Fittings for i = 1, #FittingList do local FittingItemId = FittingList[i] local FittingProps = DropItemMap.FittingItemMap[FittingItemId].Props for j = 1, #FittingProps do if FittingProps[j].Unit ~= 'Special' then local ItemData = { Type = FittingProps[j].Type, Value = FittingProps[j].Value } table.insert(OutTable, ItemData) else local ItemData = { ItemId = FittingItemId, } table.insert(SpecialItems, ItemData) end end end -- OutTable 是不包含特殊词条属性的,SpecialItems 里面是词条属性 return self:MergeOutTable(OutTable), SpecialItems end -- Server 设置当前的武器,当点击页面上的武器的时候执行这个 function BP_WeaponPawnBase:SetCurrentWeapon(InId) -- 重复点击无效 if InId == self.CurrentWeaponId then print(string.format("[BP_WeaponPawnBase:SetCurrentWeapon] 当前选择的Id与原先的Id相同")) return end if self:FindWeaponById(InId) == nil then print(string.format("[BP_WeaponPawnBase:SetCurrentWeapon] 无法找到对应Id")) return end self.CurrentWeaponId = InId -- 通知进行改变 print(string.format("[BP_WeaponPawnBase:SetCurrentWeapon] WeaponId = %d", self.CurrentWeaponId)) local PlayerState = UGCGameSystem.GetPlayerStateByPlayerKey(self.OwnerCharacter.PlayerKey) PlayerState:OnWeaponAttributeChanged(self.CurrentWeaponId) end -- 每操作一下就执行该方法进行检测 FittingLevel,然后刷新全部属性 function BP_WeaponPawnBase:GetWeaponFittingLevel(InWeaponId) if not self:FindWeaponExist(InWeaponId) then print(string.format('[BP_WeaponPawnBase:GetWeaponFittingLevel] 找不到对应武器,请检查')) return -1 end print(string.format('[BP_WeaponPawnBase:GetWeaponFittingLevel] 找到了对应武器,数量是: %d', InWeaponId)) return self:FindWeaponById(InWeaponId).FittingLevel end function BP_WeaponPawnBase:OnRep_CurrentWeaponId() if self.OwnerCharacter == nil or UE.IsValid(self.OwnerCharacter) == false then return end EventSystem:SendEvent(EventType.ClientUpdateWeapon, self.CurrentWeaponId, self.OwnerCharacter.PlayerKey) if self.CurrentWeaponId > 0 then self:ChangeWeaponId(self.CurrentWeaponId) end end function BP_WeaponPawnBase:GetWeaponFittingsById(InItemId) print(string.format("[BP_WeaponPawnBase:GetWeaponFittingsById] 开始输入Ids")) if self:FindWeaponById(InItemId) == nil then for i, v in pairs(self.Weapons) do print(i) end end print(string.format("[BP_WeaponPawnBase:GetWeaponFittingsById] 结束输入Ids")) return self:FindWeaponById(InItemId).Fittings end function BP_WeaponPawnBase:GetWeaponCount() return #self:GetWeapons() end function BP_WeaponPawnBase:FindWeaponIndexById(InWeaponId) local PSWeapons = self:GetWeapons() for i = 1, #PSWeapons do if PSWeapons[i].WeaponId == InWeaponId then return i end end return -1 end function BP_WeaponPawnBase:GetWeapons() return self:GetPlayerState().OwnerWeapons end function BP_WeaponPawnBase:FindWeaponIdByIndex(InIndex) if InIndex <= 0 or InIndex > self:GetWeaponCount() then return end return self:GetWeapons()[InIndex].WeaponId end function BP_WeaponPawnBase:GetCurrentWeaponIndex() return self:FindWeaponIndexById(self.CurrentWeaponId) end -- SC function BP_WeaponPawnBase:SetSphereSizeRadius(InAddNum) self.Sphere:SetSphereRadius(self.DefaultSphereRadius + InAddNum, true) end --获取武器基础属性 function BP_WeaponPawnBase:GetWeaponBaseAttribute() local OutTable = {} local TheTable = DropItemMap.WeaponTable[EWeaponClassType.WT_Pistol].Props OutTable = TableHelper.DeepCopyTable(TheTable) if self.CurrentWeaponId == 0 then -- 说明当前是手枪,不进行处理 return self:MergeOutTable(OutTable) end local Weapon = self:FindWeaponById(self.CurrentWeaponId) --武器基础属性 local FittingLevel = Weapon.FittingLevel if FittingLevel > 0 then local Val = DropItemMap.WeaponTable[Weapon.Type].PlusProps[FittingLevel] local ItemData = { Type = Val.Type, Value = Val.Value } table.insert(OutTable, ItemData) end -- FittingItems local FittingList = Weapon.Fittings for i = 1, #FittingList do local FittingItemId = FittingList[i] local FittingProps = DropItemMap.FittingItemMap[FittingItemId].Props for j = 1, #FittingProps do if FittingProps[j].Unit ~= 'Special' then local ItemData = { Type = FittingProps[j].Type, Value = FittingProps[j].Value } table.insert(OutTable, ItemData) end end end return self:MergeOutTable(OutTable) end --获取武器高级属性 function BP_WeaponPawnBase:GetWeaponSeniorAttribute() local OutTable = {} if self.CurrentWeaponId == 0 then return {} end local Weapon = self:FindWeaponById(self.CurrentWeaponId) local Properties = Weapon.Properties for i = 1, #Properties do local Prop = Properties[i] local ItemData = { Type = Tables.WeaponPropertyConfig[Prop.MainType].PropName, Value = Prop.Value } table.insert(OutTable, ItemData) end for i = 1, table.getCount(Weapon.NativeProps.Plus) do local Val = Weapon.NativeProps.Plus[i] local Name = Tables.WeaponPropertyConfig[Val.MainType].PropName local ItemData = { Type = Name, Value = Val.Value } table.insert(OutTable, ItemData) end return self:MergeOutTable(OutTable) end -- 叠加属性 function BP_WeaponPawnBase:MergeOutTable(InOutTable) local Items = {} for i = 1, table.getCount(InOutTable) do local Name = InOutTable[i].Type local Value = InOutTable[i].Value if Items[Name] == nil then Items[Name] = Value else Items[Name] = Items[Name] + Value end end local OutTable = {} for i, v in pairs(Items) do if string.len(i) < 10 then local ItemData = { Type = i, Value = v } table.insert(OutTable, ItemData) end end return OutTable end function BP_WeaponPawnBase:Client_MulticastRPC_PlayMuzzleEffectAndSound(SoundConfigId) if self.OwnerCharacter then SoundManager.PlaySoundAtLocation(SoundConfigId, self.OwnerCharacter:K2_GetActorLocation(), self.OwnerCharacter:K2_GetActorRotation()) end if self.MuzzleParticle and self.MainMesh then GameplayStatics.SpawnEmitterAttached(self.MuzzleParticle, self.MainMesh, "MuzzleEffect", VectorHelper.VectorZero(), VectorHelper.RotZero(), VectorHelper.Scale(0.5), EAttachLocation.SnapToTarget, true) end end return BP_WeaponPawnBase;